summaryrefslogtreecommitdiffstats
path: root/panels
diff options
context:
space:
mode:
Diffstat (limited to 'panels')
-rw-r--r--panels/applications/applications.gresource.xml10
-rw-r--r--panels/applications/cc-applications-panel.c1902
-rw-r--r--panels/applications/cc-applications-panel.h30
-rw-r--r--panels/applications/cc-applications-panel.ui465
-rw-r--r--panels/applications/cc-applications-row.c108
-rw-r--r--panels/applications/cc-applications-row.h36
-rw-r--r--panels/applications/cc-applications-row.ui28
-rw-r--r--panels/applications/cc-info-row.c187
-rw-r--r--panels/applications/cc-info-row.h37
-rw-r--r--panels/applications/cc-info-row.ui20
-rw-r--r--panels/applications/cc-snap-row.c314
-rw-r--r--panels/applications/cc-snap-row.h36
-rw-r--r--panels/applications/cc-snap-row.ui36
-rw-r--r--panels/applications/cc-toggle-row.c130
-rw-r--r--panels/applications/cc-toggle-row.h37
-rw-r--r--panels/applications/cc-toggle-row.ui12
-rw-r--r--panels/applications/globs.c62
-rw-r--r--panels/applications/globs.h29
-rw-r--r--panels/applications/gnome-applications-panel.desktop.in.in16
-rw-r--r--panels/applications/icons/meson.build4
-rw-r--r--panels/applications/icons/scalable/org.gnome.Settings-applications-symbolic.svg4
-rw-r--r--panels/applications/meson.build58
-rw-r--r--panels/applications/search.c133
-rw-r--r--panels/applications/search.h29
-rw-r--r--panels/applications/utils.c266
-rw-r--r--panels/applications/utils.h57
-rw-r--r--panels/background/background-selected-symbolic.svg1
-rw-r--r--panels/background/background.gresource.xml14
-rw-r--r--panels/background/bg-colors-source.c219
-rw-r--r--panels/background/bg-colors-source.h38
-rw-r--r--panels/background/bg-recent-source.c459
-rw-r--r--panels/background/bg-recent-source.h39
-rw-r--r--panels/background/bg-source.c213
-rw-r--r--panels/background/bg-source.h46
-rw-r--r--panels/background/bg-wallpapers-source.c164
-rw-r--r--panels/background/bg-wallpapers-source.h34
-rw-r--r--panels/background/cc-background-chooser.c337
-rw-r--r--panels/background/cc-background-chooser.h32
-rw-r--r--panels/background/cc-background-chooser.ui64
-rw-r--r--panels/background/cc-background-item.c1062
-rw-r--r--panels/background/cc-background-item.h88
-rw-r--r--panels/background/cc-background-paintable.c314
-rw-r--r--panels/background/cc-background-paintable.h35
-rw-r--r--panels/background/cc-background-panel.c455
-rw-r--r--panels/background/cc-background-panel.h30
-rw-r--r--panels/background/cc-background-panel.ui134
-rw-r--r--panels/background/cc-background-preview.c351
-rw-r--r--panels/background/cc-background-preview.h36
-rw-r--r--panels/background/cc-background-preview.ui55
-rw-r--r--panels/background/cc-background-xml.c669
-rw-r--r--panels/background/cc-background-xml.h46
-rw-r--r--panels/background/gnome-background-panel.desktop.in.in14
-rw-r--r--panels/background/icons/meson.build4
-rw-r--r--panels/background/icons/scalable/org.gnome.Settings-appearance-symbolic.svg9
-rw-r--r--panels/background/meson.build99
-rw-r--r--panels/background/noise-texture-light.pngbin0 -> 69136 bytes
-rw-r--r--panels/background/preview.css96
-rw-r--r--panels/background/slideshow-symbolic.svg1
-rwxr-xr-xpanels/bluetooth/bluetooth-panel-scenario-tester.py226
-rw-r--r--panels/bluetooth/bluetooth.gresource.xml6
-rw-r--r--panels/bluetooth/cc-bluetooth-panel.c269
-rw-r--r--panels/bluetooth/cc-bluetooth-panel.h34
-rw-r--r--panels/bluetooth/cc-bluetooth-panel.ui69
-rw-r--r--panels/bluetooth/dbusmock-templates/gsd_rfkill.py75
-rw-r--r--panels/bluetooth/gnome-bluetooth-panel.desktop.in.in18
-rw-r--r--panels/bluetooth/icons/meson.build4
-rw-r--r--panels/bluetooth/icons/scalable/org.gnome.Settings-bluetooth-symbolic.svg4
-rw-r--r--panels/bluetooth/meson.build41
-rw-r--r--panels/camera/camera.gresource.xml6
-rw-r--r--panels/camera/cc-camera-panel.c416
-rw-r--r--panels/camera/cc-camera-panel.h30
-rw-r--r--panels/camera/cc-camera-panel.ui75
-rw-r--r--panels/camera/gnome-camera-panel.desktop.in.in19
-rw-r--r--panels/camera/icons/meson.build4
-rw-r--r--panels/camera/icons/scalable/org.gnome.Settings-camera-symbolic.svg4
-rw-r--r--panels/camera/meson.build41
-rw-r--r--panels/color/cc-color-calibrate.c993
-rw-r--r--panels/color/cc-color-calibrate.h54
-rw-r--r--panels/color/cc-color-calibrate.ui89
-rw-r--r--panels/color/cc-color-cell-renderer-text.c132
-rw-r--r--panels/color/cc-color-cell-renderer-text.h32
-rw-r--r--panels/color/cc-color-common.c116
-rw-r--r--panels/color/cc-color-common.h32
-rw-r--r--panels/color/cc-color-device.c309
-rw-r--r--panels/color/cc-color-device.h38
-rw-r--r--panels/color/cc-color-panel.c2208
-rw-r--r--panels/color/cc-color-panel.h30
-rw-r--r--panels/color/cc-color-panel.ui707
-rw-r--r--panels/color/cc-color-profile.c475
-rw-r--r--panels/color/cc-color-profile.h43
-rw-r--r--panels/color/color.gresource.xml7
-rw-r--r--panels/color/gnome-color-panel.desktop.in.in20
-rw-r--r--panels/color/icons/meson.build4
-rw-r--r--panels/color/icons/scalable/org.gnome.Settings-color-symbolic.svg9
-rw-r--r--panels/color/meson.build56
-rw-r--r--panels/common/cc-common-language.c304
-rw-r--r--panels/common/cc-common-language.h58
-rw-r--r--panels/common/cc-hostname-entry.c265
-rw-r--r--panels/common/cc-hostname-entry.h33
-rw-r--r--panels/common/cc-language-chooser.c343
-rw-r--r--panels/common/cc-language-chooser.h37
-rw-r--r--panels/common/cc-language-chooser.ui99
-rw-r--r--panels/common/cc-language-row.c184
-rw-r--r--panels/common/cc-language-row.h46
-rw-r--r--panels/common/cc-language-row.ui41
-rw-r--r--panels/common/cc-list-row.c283
-rw-r--r--panels/common/cc-list-row.h47
-rw-r--r--panels/common/cc-list-row.ui37
-rw-r--r--panels/common/cc-permission-infobar.c112
-rw-r--r--panels/common/cc-permission-infobar.h37
-rw-r--r--panels/common/cc-permission-infobar.ui71
-rw-r--r--panels/common/cc-time-editor.c372
-rw-r--r--panels/common/cc-time-editor.h45
-rw-r--r--panels/common/cc-time-editor.ui168
-rw-r--r--panels/common/cc-time-entry.c660
-rw-r--r--panels/common/cc-time-entry.h47
-rw-r--r--panels/common/cc-util.c210
-rw-r--r--panels/common/cc-util.h27
-rw-r--r--panels/common/common.gresource.xml10
-rw-r--r--panels/common/gnome-control-center.rules.in13
-rw-r--r--panels/common/gnome-settings-bus.h14
-rw-r--r--panels/common/gsd-device-manager.c688
-rw-r--r--panels/common/gsd-device-manager.h86
-rw-r--r--panels/common/gsd-input-helper.c108
-rw-r--r--panels/common/gsd-input-helper.h31
-rw-r--r--panels/common/hostname-helper.c204
-rw-r--r--panels/common/hostname-helper.h23
-rw-r--r--panels/common/meson.build126
-rw-r--r--panels/datetime/backward128
-rw-r--r--panels/datetime/cc-datetime-panel.c1098
-rw-r--r--panels/datetime/cc-datetime-panel.h30
-rw-r--r--panels/datetime/cc-datetime-panel.ui263
-rw-r--r--panels/datetime/cc-timezone-map.c530
-rw-r--r--panels/datetime/cc-timezone-map.h39
-rw-r--r--panels/datetime/data/bg.pngbin0 -> 85309 bytes
-rw-r--r--panels/datetime/data/bg_dim.pngbin0 -> 62521 bytes
-rw-r--r--panels/datetime/data/pin.pngbin0 -> 447 bytes
-rw-r--r--panels/datetime/date-endian.c188
-rw-r--r--panels/datetime/date-endian.h32
-rw-r--r--panels/datetime/datetime.gresource.xml10
-rw-r--r--panels/datetime/gnome-datetime-panel.desktop.in.in16
-rw-r--r--panels/datetime/icons/meson.build4
-rw-r--r--panels/datetime/icons/scalable/org.gnome.Settings-time-symbolic.svg7
-rw-r--r--panels/datetime/meson.build112
-rw-r--r--panels/datetime/org.gnome.controlcenter.datetime.policy.in21
-rw-r--r--panels/datetime/po-timezones/LINGUAS69
-rw-r--r--panels/datetime/po-timezones/README3
-rw-r--r--panels/datetime/po-timezones/am.po3350
-rw-r--r--panels/datetime/po-timezones/ar.po3254
-rw-r--r--panels/datetime/po-timezones/as.po3273
-rw-r--r--panels/datetime/po-timezones/ast.po3250
-rw-r--r--panels/datetime/po-timezones/bg.po3275
-rw-r--r--panels/datetime/po-timezones/bn.po3340
-rw-r--r--panels/datetime/po-timezones/bn_IN.po3259
-rw-r--r--panels/datetime/po-timezones/bs.po3283
-rw-r--r--panels/datetime/po-timezones/ca.po3300
-rw-r--r--panels/datetime/po-timezones/cs.po3227
-rw-r--r--panels/datetime/po-timezones/cy.po3333
-rw-r--r--panels/datetime/po-timezones/da.po3250
-rw-r--r--panels/datetime/po-timezones/de.po3722
-rw-r--r--panels/datetime/po-timezones/el.po3272
-rw-r--r--panels/datetime/po-timezones/en_GB.po3262
-rw-r--r--panels/datetime/po-timezones/es.po3252
-rw-r--r--panels/datetime/po-timezones/et.po3351
-rw-r--r--panels/datetime/po-timezones/fa.po3304
-rw-r--r--panels/datetime/po-timezones/fi.po3272
-rw-r--r--panels/datetime/po-timezones/fr.po3263
-rw-r--r--panels/datetime/po-timezones/gl.po3348
-rw-r--r--panels/datetime/po-timezones/gu.po3241
-rw-r--r--panels/datetime/po-timezones/he.po3274
-rw-r--r--panels/datetime/po-timezones/hi.po3247
-rw-r--r--panels/datetime/po-timezones/hr.po3281
-rw-r--r--panels/datetime/po-timezones/hu.po3258
-rw-r--r--panels/datetime/po-timezones/id.po3332
-rw-r--r--panels/datetime/po-timezones/ilo.po3232
-rw-r--r--panels/datetime/po-timezones/is.po3251
-rw-r--r--panels/datetime/po-timezones/it.po3242
-rw-r--r--panels/datetime/po-timezones/ja.po3264
-rw-r--r--panels/datetime/po-timezones/ka.po3280
-rw-r--r--panels/datetime/po-timezones/kn.po3244
-rw-r--r--panels/datetime/po-timezones/ko.po3246
-rw-r--r--panels/datetime/po-timezones/ku.po3237
-rw-r--r--panels/datetime/po-timezones/lo.po3237
-rw-r--r--panels/datetime/po-timezones/lt.po3351
-rw-r--r--panels/datetime/po-timezones/lv.po3287
-rw-r--r--panels/datetime/po-timezones/mai.po3274
-rw-r--r--panels/datetime/po-timezones/meson.build1
-rw-r--r--panels/datetime/po-timezones/mk.po3350
-rw-r--r--panels/datetime/po-timezones/ml.po3240
-rw-r--r--panels/datetime/po-timezones/mr.po3242
-rw-r--r--panels/datetime/po-timezones/ms.po3277
-rw-r--r--panels/datetime/po-timezones/nb.po3234
-rw-r--r--panels/datetime/po-timezones/nds.po3725
-rw-r--r--panels/datetime/po-timezones/nl.po3288
-rw-r--r--panels/datetime/po-timezones/nn.po3238
-rw-r--r--panels/datetime/po-timezones/or.po3250
-rw-r--r--panels/datetime/po-timezones/pa.po3239
-rw-r--r--panels/datetime/po-timezones/pl.po3259
-rw-r--r--panels/datetime/po-timezones/pt.po3298
-rw-r--r--panels/datetime/po-timezones/pt_BR.po3252
-rw-r--r--panels/datetime/po-timezones/ro.po3284
-rw-r--r--panels/datetime/po-timezones/ru.po3250
-rw-r--r--panels/datetime/po-timezones/si.po3283
-rw-r--r--panels/datetime/po-timezones/sk.po3293
-rw-r--r--panels/datetime/po-timezones/sl.po3350
-rw-r--r--panels/datetime/po-timezones/sq.po3278
-rw-r--r--panels/datetime/po-timezones/sr.po3255
-rw-r--r--panels/datetime/po-timezones/sr@latin.po3255
-rw-r--r--panels/datetime/po-timezones/sv.po3221
-rw-r--r--panels/datetime/po-timezones/ta.po3246
-rw-r--r--panels/datetime/po-timezones/te.po3245
-rw-r--r--panels/datetime/po-timezones/tr.po3246
-rw-r--r--panels/datetime/po-timezones/uk.po3239
-rw-r--r--panels/datetime/po-timezones/ur.po3237
-rw-r--r--panels/datetime/po-timezones/vi.po3349
-rw-r--r--panels/datetime/po-timezones/zh_CN.po3244
-rw-r--r--panels/datetime/po-timezones/zh_TW.po3243
-rw-r--r--panels/datetime/timedated1-interface.xml28
-rw-r--r--panels/datetime/tz.c492
-rw-r--r--panels/datetime/tz.h90
-rw-r--r--panels/default-apps/cc-default-apps-panel.c198
-rw-r--r--panels/default-apps/cc-default-apps-panel.h31
-rw-r--r--panels/default-apps/cc-default-apps-panel.ui159
-rw-r--r--panels/default-apps/default-apps.gresource.xml6
-rw-r--r--panels/default-apps/gnome-default-apps-panel.desktop.in.in18
-rw-r--r--panels/default-apps/icons/meson.build4
-rw-r--r--panels/default-apps/icons/scalable/org.gnome.Settings-default-apps-symbolic.svg4
-rw-r--r--panels/default-apps/meson.build43
-rw-r--r--panels/diagnostics/cc-diagnostics-panel.c143
-rw-r--r--panels/diagnostics/cc-diagnostics-panel.h32
-rw-r--r--panels/diagnostics/cc-diagnostics-panel.ui29
-rw-r--r--panels/diagnostics/diagnostics.gresource.xml6
-rw-r--r--panels/diagnostics/gnome-diagnostics-panel.desktop.in.in19
-rw-r--r--panels/diagnostics/icons/meson.build4
-rw-r--r--panels/diagnostics/icons/scalable/org.gnome.Settings-diagnostics-symbolic.svg8
-rw-r--r--panels/diagnostics/meson.build41
-rw-r--r--panels/display/TODO837
-rw-r--r--panels/display/cc-display-arrangement.c978
-rw-r--r--panels/display/cc-display-arrangement.h47
-rw-r--r--panels/display/cc-display-config-dbus.c2116
-rw-r--r--panels/display/cc-display-config-dbus.h40
-rw-r--r--panels/display/cc-display-config-manager-dbus.c241
-rw-r--r--panels/display/cc-display-config-manager-dbus.h34
-rw-r--r--panels/display/cc-display-config-manager.c73
-rw-r--r--panels/display/cc-display-config-manager.h49
-rw-r--r--panels/display/cc-display-config.c665
-rw-r--r--panels/display/cc-display-config.h272
-rw-r--r--panels/display/cc-display-panel.c1140
-rw-r--r--panels/display/cc-display-panel.h30
-rw-r--r--panels/display/cc-display-panel.ui316
-rw-r--r--panels/display/cc-display-settings.c919
-rw-r--r--panels/display/cc-display-settings.h48
-rw-r--r--panels/display/cc-display-settings.ui101
-rw-r--r--panels/display/cc-night-light-page.c746
-rw-r--r--panels/display/cc-night-light-page.h32
-rw-r--r--panels/display/cc-night-light-page.ui438
-rw-r--r--panels/display/display-arrangement.css33
-rw-r--r--panels/display/display.gresource.xml10
-rw-r--r--panels/display/gnome-display-panel.desktop.in.in18
-rw-r--r--panels/display/icons/meson.build4
-rw-r--r--panels/display/icons/scalable/org.gnome.Settings-display-symbolic.svg4
-rw-r--r--panels/display/meson.build64
-rw-r--r--panels/display/night-light.css28
-rw-r--r--panels/firmware-security/cc-firmware-security-boot-dialog.c113
-rw-r--r--panels/firmware-security/cc-firmware-security-boot-dialog.h37
-rw-r--r--panels/firmware-security/cc-firmware-security-boot-dialog.ui63
-rw-r--r--panels/firmware-security/cc-firmware-security-dialog.c442
-rw-r--r--panels/firmware-security/cc-firmware-security-dialog.h38
-rw-r--r--panels/firmware-security/cc-firmware-security-dialog.ui271
-rw-r--r--panels/firmware-security/cc-firmware-security-panel.c717
-rw-r--r--panels/firmware-security/cc-firmware-security-panel.h34
-rw-r--r--panels/firmware-security/cc-firmware-security-panel.ui176
-rw-r--r--panels/firmware-security/cc-firmware-security-utils.c373
-rw-r--r--panels/firmware-security/cc-firmware-security-utils.h133
-rw-r--r--panels/firmware-security/firmware-security.gresource.xml9
-rw-r--r--panels/firmware-security/gnome-firmware-security-panel.desktop.in.in19
-rw-r--r--panels/firmware-security/meson.build44
-rw-r--r--panels/firmware-security/security-level.css119
-rw-r--r--panels/info-overview/cc-info-overview-panel.c993
-rw-r--r--panels/info-overview/cc-info-overview-panel.h31
-rw-r--r--panels/info-overview/cc-info-overview-panel.ui232
-rw-r--r--panels/info-overview/gnome-control-center-print-renderer.c65
-rw-r--r--panels/info-overview/gnome-info-overview-panel.desktop.in.in22
-rw-r--r--panels/info-overview/gnome-logo-text-dark.svg137
-rw-r--r--panels/info-overview/gnome-logo-text.svg134
-rw-r--r--panels/info-overview/icons/meson.build4
-rw-r--r--panels/info-overview/icons/scalable/org.gnome.Settings-about-symbolic.svg4
-rw-r--r--panels/info-overview/info-cleanup.c130
-rw-r--r--panels/info-overview/info-cleanup.h23
-rw-r--r--panels/info-overview/info-overview.gresource.xml6
-rw-r--r--panels/info-overview/meson.build76
-rw-r--r--panels/keyboard/00-multimedia.xml.in27
-rw-r--r--panels/keyboard/01-input-sources.xml.in15
-rw-r--r--panels/keyboard/01-launchers.xml.in19
-rw-r--r--panels/keyboard/01-system.xml.in9
-rw-r--r--panels/keyboard/50-accessibility.xml.in20
-rw-r--r--panels/keyboard/cc-ibus-utils.c43
-rw-r--r--panels/keyboard/cc-ibus-utils.h26
-rw-r--r--panels/keyboard/cc-input-chooser.c1087
-rw-r--r--panels/keyboard/cc-input-chooser.h41
-rw-r--r--panels/keyboard/cc-input-chooser.ui102
-rw-r--r--panels/keyboard/cc-input-list-box.c821
-rw-r--r--panels/keyboard/cc-input-list-box.h43
-rw-r--r--panels/keyboard/cc-input-list-box.ui47
-rw-r--r--panels/keyboard/cc-input-row.c306
-rw-r--r--panels/keyboard/cc-input-row.h41
-rw-r--r--panels/keyboard/cc-input-row.ui60
-rw-r--r--panels/keyboard/cc-input-source-ibus.c155
-rw-r--r--panels/keyboard/cc-input-source-ibus.h46
-rw-r--r--panels/keyboard/cc-input-source-xkb.c134
-rw-r--r--panels/keyboard/cc-input-source-xkb.h39
-rw-r--r--panels/keyboard/cc-input-source.c84
-rw-r--r--panels/keyboard/cc-input-source.h49
-rw-r--r--panels/keyboard/cc-keyboard-item.c881
-rw-r--r--panels/keyboard/cc-keyboard-item.h112
-rw-r--r--panels/keyboard/cc-keyboard-manager.c1050
-rw-r--r--panels/keyboard/cc-keyboard-manager.h54
-rw-r--r--panels/keyboard/cc-keyboard-panel.c266
-rw-r--r--panels/keyboard/cc-keyboard-panel.h32
-rw-r--r--panels/keyboard/cc-keyboard-panel.ui116
-rw-r--r--panels/keyboard/cc-keyboard-shortcut-dialog.c877
-rw-r--r--panels/keyboard/cc-keyboard-shortcut-dialog.h35
-rw-r--r--panels/keyboard/cc-keyboard-shortcut-dialog.ui227
-rw-r--r--panels/keyboard/cc-keyboard-shortcut-editor.c985
-rw-r--r--panels/keyboard/cc-keyboard-shortcut-editor.h52
-rw-r--r--panels/keyboard/cc-keyboard-shortcut-editor.ui288
-rw-r--r--panels/keyboard/cc-keyboard-shortcut-row.c139
-rw-r--r--panels/keyboard/cc-keyboard-shortcut-row.h38
-rw-r--r--panels/keyboard/cc-keyboard-shortcut-row.ui38
-rw-r--r--panels/keyboard/cc-xkb-modifier-dialog.c355
-rw-r--r--panels/keyboard/cc-xkb-modifier-dialog.h49
-rw-r--r--panels/keyboard/cc-xkb-modifier-dialog.ui73
-rw-r--r--panels/keyboard/enter-keyboard-shortcut.svg245
-rw-r--r--panels/keyboard/gnome-keybindings.pc.in10
-rw-r--r--panels/keyboard/gnome-keyboard-panel.desktop.in.in18
-rw-r--r--panels/keyboard/icons/meson.build4
-rw-r--r--panels/keyboard/icons/scalable/org.gnome.Settings-keyboard-symbolic.svg4
-rw-r--r--panels/keyboard/keyboard-shortcuts.c450
-rw-r--r--panels/keyboard/keyboard-shortcuts.h84
-rw-r--r--panels/keyboard/keyboard.gresource.xml14
-rw-r--r--panels/keyboard/meson.build106
-rw-r--r--panels/location/cc-location-panel.c427
-rw-r--r--panels/location/cc-location-panel.h30
-rw-r--r--panels/location/cc-location-panel.ui77
-rw-r--r--panels/location/gnome-location-panel.desktop.in.in19
-rw-r--r--panels/location/icons/meson.build4
-rw-r--r--panels/location/icons/scalable/org.gnome.Settings-location-symbolic.svg4
-rw-r--r--panels/location/location.gresource.xml6
-rw-r--r--panels/location/meson.build41
-rw-r--r--panels/meson.build56
-rw-r--r--panels/microphone/cc-microphone-panel.c413
-rw-r--r--panels/microphone/cc-microphone-panel.h30
-rw-r--r--panels/microphone/cc-microphone-panel.ui74
-rw-r--r--panels/microphone/gnome-microphone-panel.desktop.in.in19
-rw-r--r--panels/microphone/icons/meson.build4
-rw-r--r--panels/microphone/icons/scalable/org.gnome.Settings-microphone-symbolic.svg4
-rw-r--r--panels/microphone/meson.build41
-rw-r--r--panels/microphone/microphone.gresource.xml6
-rw-r--r--panels/mouse/cc-mouse-caps-helper.c148
-rw-r--r--panels/mouse/cc-mouse-caps-helper.h33
-rw-r--r--panels/mouse/cc-mouse-panel.c414
-rw-r--r--panels/mouse/cc-mouse-panel.h30
-rw-r--r--panels/mouse/cc-mouse-panel.ui219
-rw-r--r--panels/mouse/cc-mouse-test.c389
-rw-r--r--panels/mouse/cc-mouse-test.h32
-rw-r--r--panels/mouse/cc-mouse-test.ui69
-rw-r--r--panels/mouse/gnome-mouse-panel.desktop.in.in18
-rw-r--r--panels/mouse/icons/meson.build4
-rw-r--r--panels/mouse/icons/scalable/org.gnome.Settings-mouse-symbolic.svg4
-rw-r--r--panels/mouse/meson.build70
-rw-r--r--panels/mouse/mouse.gresource.xml9
-rw-r--r--panels/mouse/scroll-test-gegl.svg1
-rw-r--r--panels/mouse/scroll-test.svg1
-rw-r--r--panels/mouse/test-gnome-mouse-test.c24
-rw-r--r--panels/multitasking/assets/active-screen-edges-rtl.svg1
-rw-r--r--panels/multitasking/assets/active-screen-edges.svg1
-rw-r--r--panels/multitasking/assets/hot-corner-rtl.svg1
-rw-r--r--panels/multitasking/assets/hot-corner.svg1
-rw-r--r--panels/multitasking/assets/workspaces-primary-display.svg1
-rw-r--r--panels/multitasking/assets/workspaces-span-displays.svg1
-rw-r--r--panels/multitasking/cc-multitasking-panel.c161
-rw-r--r--panels/multitasking/cc-multitasking-panel.h30
-rw-r--r--panels/multitasking/cc-multitasking-panel.ui229
-rw-r--r--panels/multitasking/cc-multitasking-row.c572
-rw-r--r--panels/multitasking/cc-multitasking-row.h66
-rw-r--r--panels/multitasking/cc-multitasking-row.ui100
-rw-r--r--panels/multitasking/gnome-multitasking-panel.desktop.in.in14
-rw-r--r--panels/multitasking/icons/meson.build4
-rw-r--r--panels/multitasking/icons/scalable/org.gnome.Settings-multitasking-symbolic.svg4
-rw-r--r--panels/multitasking/meson.build48
-rw-r--r--panels/multitasking/multitasking.gresource.xml15
-rw-r--r--panels/network/cc-network-panel.c806
-rw-r--r--panels/network/cc-network-panel.h30
-rw-r--r--panels/network/cc-network-panel.ui94
-rw-r--r--panels/network/cc-qr-code.c186
-rw-r--r--panels/network/cc-qr-code.h43
-rw-r--r--panels/network/cc-wifi-connection-list.c799
-rw-r--r--panels/network/cc-wifi-connection-list.h41
-rw-r--r--panels/network/cc-wifi-connection-row.c678
-rw-r--r--panels/network/cc-wifi-connection-row.h54
-rw-r--r--panels/network/cc-wifi-connection-row.ui73
-rw-r--r--panels/network/cc-wifi-hotspot-dialog.c553
-rw-r--r--panels/network/cc-wifi-hotspot-dialog.h44
-rw-r--r--panels/network/cc-wifi-hotspot-dialog.ui140
-rw-r--r--panels/network/cc-wifi-panel.c1079
-rw-r--r--panels/network/cc-wifi-panel.h32
-rw-r--r--panels/network/cc-wifi-panel.ui326
-rw-r--r--panels/network/connection-editor/8021x-security-page.ui45
-rw-r--r--panels/network/connection-editor/ce-ip-address-entry.c99
-rw-r--r--panels/network/connection-editor/ce-ip-address-entry.h36
-rw-r--r--panels/network/connection-editor/ce-netmask-entry.c137
-rw-r--r--panels/network/connection-editor/ce-netmask-entry.h38
-rw-r--r--panels/network/connection-editor/ce-page-8021x-security.c202
-rw-r--r--panels/network/connection-editor/ce-page-8021x-security.h34
-rw-r--r--panels/network/connection-editor/ce-page-details.c571
-rw-r--r--panels/network/connection-editor/ce-page-details.h38
-rw-r--r--panels/network/connection-editor/ce-page-ethernet.c224
-rw-r--r--panels/network/connection-editor/ce-page-ethernet.h34
-rw-r--r--panels/network/connection-editor/ce-page-ip4.c846
-rw-r--r--panels/network/connection-editor/ce-page-ip4.h34
-rw-r--r--panels/network/connection-editor/ce-page-ip6.c817
-rw-r--r--panels/network/connection-editor/ce-page-ip6.h34
-rw-r--r--panels/network/connection-editor/ce-page-security.c553
-rw-r--r--panels/network/connection-editor/ce-page-security.h33
-rw-r--r--panels/network/connection-editor/ce-page-vpn.c227
-rw-r--r--panels/network/connection-editor/ce-page-vpn.h33
-rw-r--r--panels/network/connection-editor/ce-page-wifi.c212
-rw-r--r--panels/network/connection-editor/ce-page-wifi.h32
-rw-r--r--panels/network/connection-editor/ce-page.c417
-rw-r--r--panels/network/connection-editor/ce-page.h79
-rw-r--r--panels/network/connection-editor/connection-editor.gresource.xml14
-rw-r--r--panels/network/connection-editor/connection-editor.ui75
-rw-r--r--panels/network/connection-editor/details-page.ui458
-rw-r--r--panels/network/connection-editor/ethernet-page.ui121
-rw-r--r--panels/network/connection-editor/ip4-page.ui339
-rw-r--r--panels/network/connection-editor/ip6-page.ui349
-rw-r--r--panels/network/connection-editor/meson.build48
-rw-r--r--panels/network/connection-editor/net-connection-editor.c830
-rw-r--r--panels/network/connection-editor/net-connection-editor.h40
-rw-r--r--panels/network/connection-editor/security-page.ui45
-rw-r--r--panels/network/connection-editor/vpn-helpers.c358
-rw-r--r--panels/network/connection-editor/vpn-helpers.h39
-rw-r--r--panels/network/connection-editor/vpn-page.ui41
-rw-r--r--panels/network/connection-editor/wifi-page.ui109
-rw-r--r--panels/network/gnome-network-panel.desktop.in.in18
-rw-r--r--panels/network/gnome-wifi-panel.desktop.in.in18
-rw-r--r--panels/network/icons/meson.build4
-rw-r--r--panels/network/icons/scalable/org.gnome.Settings-network-symbolic.svg7
-rw-r--r--panels/network/lock-small-symbolic.svg1
-rw-r--r--panels/network/meson.build85
-rw-r--r--panels/network/net-device-bluetooth.c201
-rw-r--r--panels/network/net-device-bluetooth.h38
-rw-r--r--panels/network/net-device-ethernet.c540
-rw-r--r--panels/network/net-device-ethernet.h37
-rw-r--r--panels/network/net-device-mobile.c912
-rw-r--r--panels/network/net-device-mobile.h40
-rw-r--r--panels/network/net-device-wifi.c1303
-rw-r--r--panels/network/net-device-wifi.h47
-rw-r--r--panels/network/net-proxy.c372
-rw-r--r--panels/network/net-proxy.h32
-rw-r--r--panels/network/net-vpn.c228
-rw-r--r--panels/network/net-vpn.h37
-rw-r--r--panels/network/network-bluetooth.ui27
-rw-r--r--panels/network/network-dialogs.c499
-rw-r--r--panels/network/network-dialogs.h38
-rw-r--r--panels/network/network-ethernet.ui70
-rw-r--r--panels/network/network-mobile.ui334
-rw-r--r--panels/network/network-proxy.ui404
-rw-r--r--panels/network/network-vpn.ui29
-rw-r--r--panels/network/network-wifi.ui153
-rw-r--r--panels/network/network.gresource.xml24
-rw-r--r--panels/network/panel-common.c449
-rw-r--r--panels/network/panel-common.h39
-rw-r--r--panels/network/qrcodegen.c1009
-rw-r--r--panels/network/qrcodegen.h311
-rw-r--r--panels/network/ui-helpers.c38
-rw-r--r--panels/network/ui-helpers.h27
-rw-r--r--panels/network/warning-small-symbolic.svg1
-rw-r--r--panels/network/wifi-panel.css5
-rw-r--r--panels/network/wireless-security/eap-method-fast.c399
-rw-r--r--panels/network/wireless-security/eap-method-fast.h34
-rw-r--r--panels/network/wireless-security/eap-method-fast.ui151
-rw-r--r--panels/network/wireless-security/eap-method-leap.c266
-rw-r--r--panels/network/wireless-security/eap-method-leap.h34
-rw-r--r--panels/network/wireless-security/eap-method-leap.ui63
-rw-r--r--panels/network/wireless-security/eap-method-peap.c400
-rw-r--r--panels/network/wireless-security/eap-method-peap.h34
-rw-r--r--panels/network/wireless-security/eap-method-peap.ui167
-rw-r--r--panels/network/wireless-security/eap-method-simple.c356
-rw-r--r--panels/network/wireless-security/eap-method-simple.h52
-rw-r--r--panels/network/wireless-security/eap-method-simple.ui68
-rw-r--r--panels/network/wireless-security/eap-method-tls.c557
-rw-r--r--panels/network/wireless-security/eap-method-tls.h34
-rw-r--r--panels/network/wireless-security/eap-method-tls.ui139
-rw-r--r--panels/network/wireless-security/eap-method-ttls.c415
-rw-r--r--panels/network/wireless-security/eap-method-ttls.h34
-rw-r--r--panels/network/wireless-security/eap-method-ttls.ui160
-rw-r--r--panels/network/wireless-security/eap-method.c588
-rw-r--r--panels/network/wireless-security/eap-method.h108
-rw-r--r--panels/network/wireless-security/helpers.c60
-rw-r--r--panels/network/wireless-security/helpers.h45
-rw-r--r--panels/network/wireless-security/meson.build73
-rw-r--r--panels/network/wireless-security/wireless-security.c101
-rw-r--r--panels/network/wireless-security/wireless-security.gresource.xml17
-rw-r--r--panels/network/wireless-security/wireless-security.h53
-rw-r--r--panels/network/wireless-security/ws-dynamic-wep.c262
-rw-r--r--panels/network/wireless-security/ws-dynamic-wep.h34
-rw-r--r--panels/network/wireless-security/ws-dynamic-wep.ui89
-rw-r--r--panels/network/wireless-security/ws-file-chooser-button.c268
-rw-r--r--panels/network/wireless-security/ws-file-chooser-button.h44
-rw-r--r--panels/network/wireless-security/ws-leap.c211
-rw-r--r--panels/network/wireless-security/ws-leap.h34
-rw-r--r--panels/network/wireless-security/ws-leap.ui63
-rw-r--r--panels/network/wireless-security/ws-sae.c225
-rw-r--r--panels/network/wireless-security/ws-sae.h33
-rw-r--r--panels/network/wireless-security/ws-sae.ui63
-rw-r--r--panels/network/wireless-security/ws-wep-key.c369
-rw-r--r--panels/network/wireless-security/ws-wep-key.h35
-rw-r--r--panels/network/wireless-security/ws-wep-key.ui141
-rw-r--r--panels/network/wireless-security/ws-wpa-eap.c313
-rw-r--r--panels/network/wireless-security/ws-wpa-eap.h37
-rw-r--r--panels/network/wireless-security/ws-wpa-eap.ui93
-rw-r--r--panels/network/wireless-security/ws-wpa-psk.c237
-rw-r--r--panels/network/wireless-security/ws-wpa-psk.h34
-rw-r--r--panels/network/wireless-security/ws-wpa-psk.ui72
-rw-r--r--panels/notifications/cc-app-notifications-dialog.c399
-rw-r--r--panels/notifications/cc-app-notifications-dialog.h35
-rw-r--r--panels/notifications/cc-app-notifications-dialog.ui97
-rw-r--r--panels/notifications/cc-notifications-panel.c476
-rw-r--r--panels/notifications/cc-notifications-panel.h31
-rw-r--r--panels/notifications/cc-notifications-panel.ui48
-rw-r--r--panels/notifications/gnome-notifications-panel.desktop.in.in19
-rw-r--r--panels/notifications/icons/meson.build4
-rw-r--r--panels/notifications/icons/scalable/org.gnome.Settings-notifications-symbolic.svg4
-rw-r--r--panels/notifications/meson.build45
-rw-r--r--panels/notifications/notifications.gresource.xml7
-rw-r--r--panels/online-accounts/cc-online-account-provider-row.c135
-rw-r--r--panels/online-accounts/cc-online-account-provider-row.h32
-rw-r--r--panels/online-accounts/cc-online-account-provider-row.ui12
-rw-r--r--panels/online-accounts/cc-online-account-row.c140
-rw-r--r--panels/online-accounts/cc-online-account-row.h35
-rw-r--r--panels/online-accounts/cc-online-account-row.ui17
-rw-r--r--panels/online-accounts/cc-online-accounts-panel.c947
-rw-r--r--panels/online-accounts/cc-online-accounts-panel.h31
-rw-r--r--panels/online-accounts/cc-online-accounts-panel.ui115
-rw-r--r--panels/online-accounts/gnome-control-center-goa-helper.c505
-rw-r--r--panels/online-accounts/gnome-online-accounts-panel.desktop.in.in21
-rw-r--r--panels/online-accounts/icons/meson.build4
-rw-r--r--panels/online-accounts/icons/scalable/org.gnome.Settings-online-accounts-symbolic.svg4
-rw-r--r--panels/online-accounts/meson.build84
-rw-r--r--panels/online-accounts/online-accounts.css6
-rw-r--r--panels/online-accounts/online-accounts.gresource.xml9
-rw-r--r--panels/panel-app-icons.svg1246
-rw-r--r--panels/power/battery-levels.css14
-rw-r--r--panels/power/cc-battery-row.c357
-rw-r--r--panels/power/cc-battery-row.h49
-rw-r--r--panels/power/cc-battery-row.ui82
-rw-r--r--panels/power/cc-power-panel.c1539
-rw-r--r--panels/power/cc-power-panel.h29
-rw-r--r--panels/power/cc-power-panel.ui364
-rw-r--r--panels/power/cc-power-profile-info-row.c67
-rw-r--r--panels/power/cc-power-profile-info-row.h36
-rw-r--r--panels/power/cc-power-profile-info-row.ui42
-rw-r--r--panels/power/cc-power-profile-row.c180
-rw-r--r--panels/power/cc-power-profile-row.h51
-rw-r--r--panels/power/cc-power-profile-row.ui76
-rw-r--r--panels/power/gnome-power-panel.desktop.in.in20
-rw-r--r--panels/power/icons/info-symbolic.svg1
-rw-r--r--panels/power/icons/meson.build10
-rw-r--r--panels/power/icons/scalable/org.gnome.Settings-power-symbolic.svg4
-rw-r--r--panels/power/meson.build52
-rwxr-xr-xpanels/power/power-panel-scenario-tester.py311
-rw-r--r--panels/power/power-profiles.css7
-rw-r--r--panels/power/power.gresource.xml11
-rw-r--r--panels/printers/cc-printers-panel.c1340
-rw-r--r--panels/printers/cc-printers-panel.h28
-rw-r--r--panels/printers/gnome-printers-panel.desktop.in.in17
-rw-r--r--panels/printers/icons/meson.build4
-rw-r--r--panels/printers/icons/scalable/org.gnome.Settings-printers-symbolic.svg8
-rw-r--r--panels/printers/meson.build76
-rw-r--r--panels/printers/new-printer-dialog.ui378
-rw-r--r--panels/printers/pp-cups.c313
-rw-r--r--panels/printers/pp-cups.h76
-rw-r--r--panels/printers/pp-details-dialog.c399
-rw-r--r--panels/printers/pp-details-dialog.h41
-rw-r--r--panels/printers/pp-details-dialog.ui235
-rw-r--r--panels/printers/pp-host.c747
-rw-r--r--panels/printers/pp-host.h80
-rw-r--r--panels/printers/pp-ipp-option-widget.c524
-rw-r--r--panels/printers/pp-ipp-option-widget.h39
-rw-r--r--panels/printers/pp-job-row.c190
-rw-r--r--panels/printers/pp-job-row.h36
-rw-r--r--panels/printers/pp-job-row.ui62
-rw-r--r--panels/printers/pp-job.c485
-rw-r--r--panels/printers/pp-job.h90
-rw-r--r--panels/printers/pp-jobs-dialog.c539
-rw-r--r--panels/printers/pp-jobs-dialog.h35
-rw-r--r--panels/printers/pp-jobs-dialog.ui234
-rw-r--r--panels/printers/pp-maintenance-command.c390
-rw-r--r--panels/printers/pp-maintenance-command.h52
-rw-r--r--panels/printers/pp-new-printer-dialog.c1929
-rw-r--r--panels/printers/pp-new-printer-dialog.h38
-rw-r--r--panels/printers/pp-new-printer.c1300
-rw-r--r--panels/printers/pp-new-printer.h42
-rw-r--r--panels/printers/pp-options-dialog.c940
-rw-r--r--panels/printers/pp-options-dialog.h34
-rw-r--r--panels/printers/pp-options-dialog.ui75
-rw-r--r--panels/printers/pp-ppd-option-widget.c535
-rw-r--r--panels/printers/pp-ppd-option-widget.h35
-rw-r--r--panels/printers/pp-ppd-selection-dialog.c378
-rw-r--r--panels/printers/pp-ppd-selection-dialog.h40
-rw-r--r--panels/printers/pp-print-device.c450
-rw-r--r--panels/printers/pp-print-device.h48
-rw-r--r--panels/printers/pp-printer-entry.c1022
-rw-r--r--panels/printers/pp-printer-entry.h45
-rw-r--r--panels/printers/pp-printer.c562
-rw-r--r--panels/printers/pp-printer.h80
-rw-r--r--panels/printers/pp-samba.c414
-rw-r--r--panels/printers/pp-samba.h47
-rw-r--r--panels/printers/pp-utils.c3645
-rw-r--r--panels/printers/pp-utils.h263
-rw-r--r--panels/printers/ppd-selection-dialog.ui106
-rw-r--r--panels/printers/printer-entry.ui319
-rw-r--r--panels/printers/printers.gresource.xml13
-rw-r--r--panels/printers/printers.ui242
-rw-r--r--panels/region/.indent.pro2
-rw-r--r--panels/region/cc-format-chooser.c541
-rw-r--r--panels/region/cc-format-chooser.h36
-rw-r--r--panels/region/cc-format-chooser.ui262
-rw-r--r--panels/region/cc-format-preview.c257
-rw-r--r--panels/region/cc-format-preview.h38
-rw-r--r--panels/region/cc-format-preview.ui120
-rw-r--r--panels/region/cc-region-panel.c879
-rw-r--r--panels/region/cc-region-panel.h30
-rw-r--r--panels/region/cc-region-panel.ui132
-rw-r--r--panels/region/gnome-region-panel.desktop.in.in18
-rw-r--r--panels/region/icons/meson.build4
-rw-r--r--panels/region/icons/scalable/org.gnome.Settings-region-symbolic.svg4
-rw-r--r--panels/region/meson.build59
-rw-r--r--panels/region/region.gresource.xml11
-rw-r--r--panels/region/view-layout-symbolic.svg1
-rw-r--r--panels/removable-media/cc-removable-media-panel.c511
-rw-r--r--panels/removable-media/cc-removable-media-panel.h29
-rw-r--r--panels/removable-media/cc-removable-media-panel.ui304
-rw-r--r--panels/removable-media/gnome-removable-media-panel.desktop.in.in18
-rw-r--r--panels/removable-media/icons/meson.build4
-rw-r--r--panels/removable-media/icons/scalable/org.gnome.Settings-removable-media-symbolic.svg4
-rw-r--r--panels/removable-media/meson.build47
-rw-r--r--panels/removable-media/removable-media.gresource.xml6
-rw-r--r--panels/screen/cc-screen-panel.c387
-rw-r--r--panels/screen/cc-screen-panel.h55
-rw-r--r--panels/screen/cc-screen-panel.ui129
-rw-r--r--panels/screen/gnome-screen-panel.desktop.in.in19
-rw-r--r--panels/screen/icons/meson.build4
-rw-r--r--panels/screen/icons/scalable/org.gnome.Settings-screen-symbolic.svg4
-rw-r--r--panels/screen/meson.build46
-rw-r--r--panels/screen/screen.gresource.xml6
-rw-r--r--panels/search/cc-search-locations-dialog.c787
-rw-r--r--panels/search/cc-search-locations-dialog.h30
-rw-r--r--panels/search/cc-search-locations-dialog.ui85
-rw-r--r--panels/search/cc-search-panel-row.c233
-rw-r--r--panels/search/cc-search-panel-row.h38
-rw-r--r--panels/search/cc-search-panel-row.ui61
-rw-r--r--panels/search/cc-search-panel.c683
-rw-r--r--panels/search/cc-search-panel.h30
-rw-r--r--panels/search/cc-search-panel.ui57
-rw-r--r--panels/search/gnome-search-panel.desktop.in.in18
-rw-r--r--panels/search/icons/meson.build4
-rw-r--r--panels/search/icons/scalable/org.gnome.Settings-search-symbolic.svg4
-rw-r--r--panels/search/meson.build50
-rw-r--r--panels/search/search.gresource.xml8
-rw-r--r--panels/sharing/cc-gnome-remote-desktop.c124
-rw-r--r--panels/sharing/cc-gnome-remote-desktop.h36
-rw-r--r--panels/sharing/cc-media-sharing.c146
-rw-r--r--panels/sharing/cc-media-sharing.h27
-rw-r--r--panels/sharing/cc-remote-login-helper.c68
-rw-r--r--panels/sharing/cc-remote-login.c306
-rw-r--r--panels/sharing/cc-remote-login.h30
-rw-r--r--panels/sharing/cc-sharing-networks.c520
-rw-r--r--panels/sharing/cc-sharing-networks.h39
-rw-r--r--panels/sharing/cc-sharing-networks.ui31
-rw-r--r--panels/sharing/cc-sharing-panel.c1600
-rw-r--r--panels/sharing/cc-sharing-panel.h33
-rw-r--r--panels/sharing/cc-sharing-panel.ui537
-rw-r--r--panels/sharing/cc-systemd-service.c236
-rw-r--r--panels/sharing/cc-systemd-service.h33
-rw-r--r--panels/sharing/cc-tls-certificate.c511
-rw-r--r--panels/sharing/cc-tls-certificate.h63
-rw-r--r--panels/sharing/file-share-properties.c55
-rw-r--r--panels/sharing/file-share-properties.h22
-rw-r--r--panels/sharing/gnome-sharing-panel.desktop.in.in15
-rw-r--r--panels/sharing/gsd-sharing-enums.h31
-rw-r--r--panels/sharing/icons/meson.build4
-rw-r--r--panels/sharing/icons/scalable/org.gnome.Settings-sharing-symbolic.svg9
-rw-r--r--panels/sharing/meson.build114
-rw-r--r--panels/sharing/org.gnome.SettingsDaemon.Sharing.xml19
-rw-r--r--panels/sharing/org.gnome.controlcenter.remote-login-helper.policy.in.in22
-rw-r--r--panels/sharing/sharing.css4
-rw-r--r--panels/sharing/sharing.gresource.xml8
-rw-r--r--panels/sound/cc-alert-chooser.c306
-rw-r--r--panels/sound/cc-alert-chooser.h28
-rw-r--r--panels/sound/cc-alert-chooser.ui41
-rw-r--r--panels/sound/cc-balance-slider.c119
-rw-r--r--panels/sound/cc-balance-slider.h33
-rw-r--r--panels/sound/cc-balance-slider.ui30
-rw-r--r--panels/sound/cc-device-combo-box.c213
-rw-r--r--panels/sound/cc-device-combo-box.h36
-rw-r--r--panels/sound/cc-device-combo-box.ui33
-rw-r--r--panels/sound/cc-fade-slider.c119
-rw-r--r--panels/sound/cc-fade-slider.h33
-rw-r--r--panels/sound/cc-fade-slider.ui30
-rw-r--r--panels/sound/cc-level-bar.c290
-rw-r--r--panels/sound/cc-level-bar.h36
-rw-r--r--panels/sound/cc-output-test-dialog.c160
-rw-r--r--panels/sound/cc-output-test-dialog.h34
-rw-r--r--panels/sound/cc-output-test-dialog.ui163
-rw-r--r--panels/sound/cc-profile-combo-box.c135
-rw-r--r--panels/sound/cc-profile-combo-box.h37
-rw-r--r--panels/sound/cc-profile-combo-box.ui22
-rw-r--r--panels/sound/cc-sound-enums.h30
-rw-r--r--panels/sound/cc-sound-panel.c318
-rw-r--r--panels/sound/cc-sound-panel.h28
-rw-r--r--panels/sound/cc-sound-panel.ui351
-rw-r--r--panels/sound/cc-speaker-test-button.c241
-rw-r--r--panels/sound/cc-speaker-test-button.h36
-rw-r--r--panels/sound/cc-speaker-test-button.ui30
-rw-r--r--panels/sound/cc-stream-list-box.c248
-rw-r--r--panels/sound/cc-stream-list-box.h38
-rw-r--r--panels/sound/cc-stream-list-box.ui15
-rw-r--r--panels/sound/cc-stream-row.c142
-rw-r--r--panels/sound/cc-stream-row.h43
-rw-r--r--panels/sound/cc-stream-row.ui39
-rw-r--r--panels/sound/cc-subwoofer-slider.c135
-rw-r--r--panels/sound/cc-subwoofer-slider.h37
-rw-r--r--panels/sound/cc-subwoofer-slider.ui21
-rw-r--r--panels/sound/cc-volume-slider.c263
-rw-r--r--panels/sound/cc-volume-slider.h45
-rw-r--r--panels/sound/cc-volume-slider.ui34
-rw-r--r--panels/sound/gnome-sound-panel.desktop.in.in19
-rw-r--r--panels/sound/gvc-mixer-stream-private.h30
-rw-r--r--panels/sound/icons/audio-speaker-center-back-testing.svg1
-rw-r--r--panels/sound/icons/audio-speaker-center-back.svg1
-rw-r--r--panels/sound/icons/audio-speaker-center-testing.svg1
-rw-r--r--panels/sound/icons/audio-speaker-center.svg1
-rw-r--r--panels/sound/icons/audio-speaker-left-back-testing.svg1
-rw-r--r--panels/sound/icons/audio-speaker-left-back.svg1
-rw-r--r--panels/sound/icons/audio-speaker-left-side-testing.svg1
-rw-r--r--panels/sound/icons/audio-speaker-left-side.svg1
-rw-r--r--panels/sound/icons/audio-speaker-left-testing.svg1
-rw-r--r--panels/sound/icons/audio-speaker-left.svg1
-rw-r--r--panels/sound/icons/audio-speaker-mono-testing.svg1
-rw-r--r--panels/sound/icons/audio-speaker-mono.svg1
-rw-r--r--panels/sound/icons/audio-speaker-right-back-testing.svg1
-rw-r--r--panels/sound/icons/audio-speaker-right-back.svg1
-rw-r--r--panels/sound/icons/audio-speaker-right-side-testing.svg1
-rw-r--r--panels/sound/icons/audio-speaker-right-side.svg1
-rw-r--r--panels/sound/icons/audio-speaker-right-testing.svg1
-rw-r--r--panels/sound/icons/audio-speaker-right.svg1
-rw-r--r--panels/sound/icons/audio-speaker-testing.svg1
-rw-r--r--panels/sound/icons/audio-subwoofer-testing.svg1
-rw-r--r--panels/sound/icons/audio-subwoofer.svg1
-rw-r--r--panels/sound/icons/org.gnome.Settings-sound-symbolic.svg1
-rw-r--r--panels/sound/meson.build112
-rw-r--r--panels/sound/sound.gresource.xml40
-rw-r--r--panels/sound/sounds/click.oggbin0 -> 10510 bytes
-rw-r--r--panels/sound/sounds/hum.oggbin0 -> 12632 bytes
-rw-r--r--panels/sound/sounds/string.oggbin0 -> 18245 bytes
-rw-r--r--panels/sound/sounds/swing.oggbin0 -> 11445 bytes
-rw-r--r--panels/thunderbolt/bolt-client.c1054
-rw-r--r--panels/thunderbolt/bolt-client.h143
-rw-r--r--panels/thunderbolt/bolt-device.c604
-rw-r--r--panels/thunderbolt/bolt-device.h87
-rw-r--r--panels/thunderbolt/bolt-enums.c397
-rw-r--r--panels/thunderbolt/bolt-enums.h249
-rw-r--r--panels/thunderbolt/bolt-error.c99
-rw-r--r--panels/thunderbolt/bolt-error.h55
-rw-r--r--panels/thunderbolt/bolt-names.c48
-rw-r--r--panels/thunderbolt/bolt-names.h73
-rw-r--r--panels/thunderbolt/bolt-proxy.c514
-rw-r--r--panels/thunderbolt/bolt-proxy.h97
-rw-r--r--panels/thunderbolt/bolt-str.c117
-rw-r--r--panels/thunderbolt/bolt-str.h43
-rw-r--r--panels/thunderbolt/bolt-time.c44
-rw-r--r--panels/thunderbolt/bolt-time.h32
-rw-r--r--panels/thunderbolt/cc-bolt-device-dialog.c515
-rw-r--r--panels/thunderbolt/cc-bolt-device-dialog.h47
-rw-r--r--panels/thunderbolt/cc-bolt-device-dialog.ui325
-rw-r--r--panels/thunderbolt/cc-bolt-device-entry.c223
-rw-r--r--panels/thunderbolt/cc-bolt-device-entry.h36
-rw-r--r--panels/thunderbolt/cc-bolt-device-entry.ui13
-rw-r--r--panels/thunderbolt/cc-bolt-panel.c960
-rw-r--r--panels/thunderbolt/cc-bolt-panel.h30
-rw-r--r--panels/thunderbolt/cc-bolt-panel.ui361
-rw-r--r--panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in18
-rw-r--r--panels/thunderbolt/icons/meson.build4
-rw-r--r--panels/thunderbolt/icons/scalable/org.gnome.Settings-thunderbolt-symbolic.svg4
-rw-r--r--panels/thunderbolt/meson.build70
-rw-r--r--panels/thunderbolt/thunderbolt.gresource.xml9
-rwxr-xr-xpanels/thunderbolt/update-from-bolt.sh50
-rw-r--r--panels/universal-access/cc-cursor-blinking-dialog.c83
-rw-r--r--panels/universal-access/cc-cursor-blinking-dialog.h29
-rw-r--r--panels/universal-access/cc-cursor-blinking-dialog.ui103
-rw-r--r--panels/universal-access/cc-cursor-size-dialog.c121
-rw-r--r--panels/universal-access/cc-cursor-size-dialog.h29
-rw-r--r--panels/universal-access/cc-cursor-size-dialog.ui40
-rw-r--r--panels/universal-access/cc-pointing-dialog.c123
-rw-r--r--panels/universal-access/cc-pointing-dialog.h29
-rw-r--r--panels/universal-access/cc-pointing-dialog.ui306
-rw-r--r--panels/universal-access/cc-repeat-keys-dialog.c108
-rw-r--r--panels/universal-access/cc-repeat-keys-dialog.h29
-rw-r--r--panels/universal-access/cc-repeat-keys-dialog.ui179
-rw-r--r--panels/universal-access/cc-typing-dialog.c185
-rw-r--r--panels/universal-access/cc-typing-dialog.h29
-rw-r--r--panels/universal-access/cc-typing-dialog.ui381
-rw-r--r--panels/universal-access/cc-ua-panel.c574
-rw-r--r--panels/universal-access/cc-ua-panel.h31
-rw-r--r--panels/universal-access/cc-ua-panel.ui308
-rw-r--r--panels/universal-access/cc-visual-alerts-dialog.c144
-rw-r--r--panels/universal-access/cc-visual-alerts-dialog.h29
-rw-r--r--panels/universal-access/cc-visual-alerts-dialog.ui101
-rw-r--r--panels/universal-access/cc-zoom-options-dialog.c553
-rw-r--r--panels/universal-access/cc-zoom-options-dialog.h31
-rw-r--r--panels/universal-access/cc-zoom-options-dialog.ui686
-rw-r--r--panels/universal-access/gnome-universal-access-panel.desktop.in.in18
-rw-r--r--panels/universal-access/icons/meson.build4
-rw-r--r--panels/universal-access/icons/scalable/org.gnome.Settings-accessibility-symbolic.svg7
-rw-r--r--panels/universal-access/left_ptr_24px.pngbin0 -> 762 bytes
-rw-r--r--panels/universal-access/left_ptr_32px.pngbin0 -> 1081 bytes
-rw-r--r--panels/universal-access/left_ptr_48px.pngbin0 -> 1766 bytes
-rw-r--r--panels/universal-access/left_ptr_64px.pngbin0 -> 2447 bytes
-rw-r--r--panels/universal-access/left_ptr_96px.pngbin0 -> 3995 bytes
-rw-r--r--panels/universal-access/meson.build64
-rw-r--r--panels/universal-access/universal-access.gresource.xml18
-rw-r--r--panels/usage/cc-usage-panel.c362
-rw-r--r--panels/usage/cc-usage-panel.h50
-rw-r--r--panels/usage/cc-usage-panel.ui140
-rw-r--r--panels/usage/gnome-usage-panel.desktop.in.in19
-rw-r--r--panels/usage/icons/meson.build4
-rw-r--r--panels/usage/icons/scalable/org.gnome.Settings-file-history-symbolic.svg4
-rw-r--r--panels/usage/meson.build45
-rw-r--r--panels/usage/usage.gresource.xml6
-rw-r--r--panels/user-accounts/cc-add-user-dialog.c1717
-rw-r--r--panels/user-accounts/cc-add-user-dialog.h34
-rw-r--r--panels/user-accounts/cc-add-user-dialog.ui411
-rw-r--r--panels/user-accounts/cc-avatar-chooser.c452
-rw-r--r--panels/user-accounts/cc-avatar-chooser.h39
-rw-r--r--panels/user-accounts/cc-avatar-chooser.ui41
-rw-r--r--panels/user-accounts/cc-crop-area.c717
-rw-r--r--panels/user-accounts/cc-crop-area.h42
-rw-r--r--panels/user-accounts/cc-fingerprint-dialog.c1527
-rw-r--r--panels/user-accounts/cc-fingerprint-dialog.h37
-rw-r--r--panels/user-accounts/cc-fingerprint-dialog.ui346
-rw-r--r--panels/user-accounts/cc-fingerprint-manager.c597
-rw-r--r--panels/user-accounts/cc-fingerprint-manager.h74
-rw-r--r--panels/user-accounts/cc-login-history-dialog.c346
-rw-r--r--panels/user-accounts/cc-login-history-dialog.h33
-rw-r--r--panels/user-accounts/cc-login-history-dialog.ui66
-rw-r--r--panels/user-accounts/cc-password-dialog.c530
-rw-r--r--panels/user-accounts/cc-password-dialog.h34
-rw-r--r--panels/user-accounts/cc-password-dialog.ui184
-rw-r--r--panels/user-accounts/cc-realm-manager.c788
-rw-r--r--panels/user-accounts/cc-realm-manager.h97
-rw-r--r--panels/user-accounts/cc-user-panel.c1603
-rw-r--r--panels/user-accounts/cc-user-panel.h29
-rw-r--r--panels/user-accounts/cc-user-panel.ui407
-rw-r--r--panels/user-accounts/data/cc-fingerprint-dialog.css83
-rw-r--r--panels/user-accounts/data/faces/bicycle.jpgbin0 -> 164797 bytes
-rw-r--r--panels/user-accounts/data/faces/book.jpgbin0 -> 107001 bytes
-rw-r--r--panels/user-accounts/data/faces/calculator.jpgbin0 -> 71432 bytes
-rw-r--r--panels/user-accounts/data/faces/cat.jpgbin0 -> 84614 bytes
-rw-r--r--panels/user-accounts/data/faces/coffee2.jpgbin0 -> 59609 bytes
-rw-r--r--panels/user-accounts/data/faces/flower2.jpgbin0 -> 37545 bytes
-rw-r--r--panels/user-accounts/data/faces/gamepad.jpgbin0 -> 48885 bytes
-rw-r--r--panels/user-accounts/data/faces/guitar2.jpgbin0 -> 39121 bytes
-rw-r--r--panels/user-accounts/data/faces/headphones.jpgbin0 -> 50165 bytes
-rw-r--r--panels/user-accounts/data/faces/hummingbird.jpgbin0 -> 44924 bytes
-rw-r--r--panels/user-accounts/data/faces/legacy/astronaut.jpgbin0 -> 3034 bytes
-rw-r--r--panels/user-accounts/data/faces/legacy/baseball.pngbin0 -> 12985 bytes
-rw-r--r--panels/user-accounts/data/faces/legacy/butterfly.pngbin0 -> 17171 bytes
-rw-r--r--panels/user-accounts/data/faces/legacy/cat-eye.jpgbin0 -> 5495 bytes
-rw-r--r--panels/user-accounts/data/faces/legacy/chess.jpgbin0 -> 3346 bytes
-rw-r--r--panels/user-accounts/data/faces/legacy/coffee.jpgbin0 -> 3467 bytes
-rw-r--r--panels/user-accounts/data/faces/legacy/dice.jpgbin0 -> 2807 bytes
-rw-r--r--panels/user-accounts/data/faces/legacy/energy-arc.jpgbin0 -> 2041 bytes
-rw-r--r--panels/user-accounts/data/faces/legacy/fish.jpgbin0 -> 3225 bytes
-rw-r--r--panels/user-accounts/data/faces/legacy/flake.jpgbin0 -> 4216 bytes
-rw-r--r--panels/user-accounts/data/faces/legacy/flower.jpgbin0 -> 3572 bytes
-rw-r--r--panels/user-accounts/data/faces/legacy/grapes.jpgbin0 -> 4045 bytes
-rw-r--r--panels/user-accounts/data/faces/legacy/guitar.jpgbin0 -> 2281 bytes
-rw-r--r--panels/user-accounts/data/faces/legacy/launch.jpgbin0 -> 3121 bytes
-rw-r--r--panels/user-accounts/data/faces/legacy/leaf.jpgbin0 -> 2627 bytes
-rw-r--r--panels/user-accounts/data/faces/legacy/lightning.jpgbin0 -> 2621 bytes
-rw-r--r--panels/user-accounts/data/faces/legacy/penguin.jpgbin0 -> 2192 bytes
-rw-r--r--panels/user-accounts/data/faces/legacy/puppy.jpgbin0 -> 3461 bytes
-rw-r--r--panels/user-accounts/data/faces/legacy/sky.jpgbin0 -> 2964 bytes
-rw-r--r--panels/user-accounts/data/faces/legacy/soccerball.pngbin0 -> 9267 bytes
-rw-r--r--panels/user-accounts/data/faces/legacy/sunflower.jpgbin0 -> 4105 bytes
-rw-r--r--panels/user-accounts/data/faces/legacy/sunset.jpgbin0 -> 2752 bytes
-rw-r--r--panels/user-accounts/data/faces/legacy/tennis-ball.pngbin0 -> 13432 bytes
-rw-r--r--panels/user-accounts/data/faces/legacy/yellow-rose.jpgbin0 -> 2727 bytes
-rw-r--r--panels/user-accounts/data/faces/mountain.jpgbin0 -> 42261 bytes
-rw-r--r--panels/user-accounts/data/faces/plane.jpgbin0 -> 65115 bytes
-rw-r--r--panels/user-accounts/data/faces/surfer.jpgbin0 -> 101022 bytes
-rw-r--r--panels/user-accounts/data/faces/tomatoes.jpgbin0 -> 103768 bytes
-rw-r--r--panels/user-accounts/data/faces/tree.jpgbin0 -> 99009 bytes
-rw-r--r--panels/user-accounts/data/gnome-user-accounts-panel.desktop.in.in19
-rw-r--r--panels/user-accounts/data/icons/fingerprint-detection-complete-symbolic.svg1
-rw-r--r--panels/user-accounts/data/icons/fingerprint-detection-symbolic.svg1
-rw-r--r--panels/user-accounts/data/icons/fingerprint-detection-warning-symbolic.svg1
-rw-r--r--panels/user-accounts/data/icons/left-index-finger.svg1
-rw-r--r--panels/user-accounts/data/icons/left-little-finger.svg1
-rw-r--r--panels/user-accounts/data/icons/left-middle-finger.svg1
-rw-r--r--panels/user-accounts/data/icons/left-ring-finger.svg1
-rw-r--r--panels/user-accounts/data/icons/left-thumb.svg1
-rw-r--r--panels/user-accounts/data/icons/print_error.svg1
-rw-r--r--panels/user-accounts/data/icons/print_ok.svg1
-rw-r--r--panels/user-accounts/data/icons/right-index-finger.svg1
-rw-r--r--panels/user-accounts/data/icons/right-little-finger.svg1
-rw-r--r--panels/user-accounts/data/icons/right-middle-finger.svg1
-rw-r--r--panels/user-accounts/data/icons/right-ring-finger.svg1
-rw-r--r--panels/user-accounts/data/icons/right-thumb.svg1
-rw-r--r--panels/user-accounts/data/join-dialog.ui166
-rw-r--r--panels/user-accounts/data/net.reactivated.Fprint.Device.xml585
-rw-r--r--panels/user-accounts/data/net.reactivated.Fprint.Manager.xml50
-rw-r--r--panels/user-accounts/data/org.freedesktop.realmd.xml666
-rw-r--r--panels/user-accounts/data/user-accounts-dialog.css23
-rw-r--r--panels/user-accounts/fingerprint-strings.h172
-rw-r--r--panels/user-accounts/icons/meson.build4
-rw-r--r--panels/user-accounts/icons/scalable/org.gnome.Settings-users-symbolic.svg4
-rw-r--r--panels/user-accounts/meson.build199
-rw-r--r--panels/user-accounts/org.gnome.controlcenter.user-accounts.policy.in21
-rw-r--r--panels/user-accounts/pw-utils.c177
-rw-r--r--panels/user-accounts/pw-utils.h31
-rw-r--r--panels/user-accounts/run-passwd.c737
-rw-r--r--panels/user-accounts/run-passwd.h54
-rw-r--r--panels/user-accounts/user-accounts.gresource.xml20
-rw-r--r--panels/user-accounts/user-utils.c471
-rw-r--r--panels/user-accounts/user-utils.h52
-rw-r--r--panels/wacom/button-mapping.ui78
-rw-r--r--panels/wacom/calibrator/COPYING27
-rw-r--r--panels/wacom/calibrator/calibrator-gui.c429
-rw-r--r--panels/wacom/calibrator/calibrator-gui.h63
-rw-r--r--panels/wacom/calibrator/calibrator.c183
-rw-r--r--panels/wacom/calibrator/calibrator.css47
-rw-r--r--panels/wacom/calibrator/calibrator.h99
-rw-r--r--panels/wacom/calibrator/calibrator.ui146
-rw-r--r--panels/wacom/calibrator/cc-clock.c289
-rw-r--r--panels/wacom/calibrator/cc-clock.h41
-rw-r--r--panels/wacom/calibrator/main.c421
-rw-r--r--panels/wacom/calibrator/meson.build35
-rw-r--r--panels/wacom/calibrator/target.svg93
-rw-r--r--panels/wacom/cc-drawing-area.c182
-rw-r--r--panels/wacom/cc-drawing-area.h31
-rw-r--r--panels/wacom/cc-tablet-tool-map.c398
-rw-r--r--panels/wacom/cc-tablet-tool-map.h44
-rw-r--r--panels/wacom/cc-wacom-button-row.c280
-rw-r--r--panels/wacom/cc-wacom-button-row.h43
-rw-r--r--panels/wacom/cc-wacom-device.c437
-rw-r--r--panels/wacom/cc-wacom-device.h66
-rw-r--r--panels/wacom/cc-wacom-ekr-page.c195
-rw-r--r--panels/wacom/cc-wacom-ekr-page.h34
-rw-r--r--panels/wacom/cc-wacom-ekr-page.ui32
-rw-r--r--panels/wacom/cc-wacom-page.c865
-rw-r--r--panels/wacom/cc-wacom-page.h39
-rw-r--r--panels/wacom/cc-wacom-page.ui89
-rw-r--r--panels/wacom/cc-wacom-panel.c753
-rw-r--r--panels/wacom/cc-wacom-panel.h42
-rw-r--r--panels/wacom/cc-wacom-panel.ui88
-rw-r--r--panels/wacom/cc-wacom-stylus-page.c274
-rw-r--r--panels/wacom/cc-wacom-stylus-page.h35
-rw-r--r--panels/wacom/cc-wacom-stylus-page.ui140
-rw-r--r--panels/wacom/cc-wacom-tool.c330
-rw-r--r--panels/wacom/cc-wacom-tool.h46
-rw-r--r--panels/wacom/gnome-wacom-panel.desktop.in.in18
-rw-r--r--panels/wacom/gsd-enums.h7
-rw-r--r--panels/wacom/gsd-wacom-key-shortcut-button.c535
-rw-r--r--panels/wacom/gsd-wacom-key-shortcut-button.h40
-rw-r--r--panels/wacom/icons/meson.build4
-rw-r--r--panels/wacom/icons/scalable/org.gnome.Settings-wacom-symbolic.svg4
-rw-r--r--panels/wacom/meson.build106
-rw-r--r--panels/wacom/test-wacom.c155
-rwxr-xr-xpanels/wacom/wacom-panel-scenario-tester.py75
-rw-r--r--panels/wacom/wacom-stylus-3btn-no-eraser.svg110
-rw-r--r--panels/wacom/wacom-stylus-3btn.svg106
-rw-r--r--panels/wacom/wacom-stylus-airbrush.svg73
-rw-r--r--panels/wacom/wacom-stylus-art-pen.svg94
-rw-r--r--panels/wacom/wacom-stylus-classic.svg83
-rw-r--r--panels/wacom/wacom-stylus-inking.svg79
-rw-r--r--panels/wacom/wacom-stylus-no-eraser.svg101
-rw-r--r--panels/wacom/wacom-stylus.svg100
-rw-r--r--panels/wacom/wacom-tablet-cintiq.svg86
-rw-r--r--panels/wacom/wacom-tablet-pc.svg80
-rw-r--r--panels/wacom/wacom-tablet.svg84
-rw-r--r--panels/wacom/wacom.gresource.xml24
-rw-r--r--panels/wwan/cc-wwan-apn-dialog.c428
-rw-r--r--panels/wwan/cc-wwan-apn-dialog.h40
-rw-r--r--panels/wwan/cc-wwan-apn-dialog.ui209
-rw-r--r--panels/wwan/cc-wwan-data.c1502
-rw-r--r--panels/wwan/cc-wwan-data.h93
-rw-r--r--panels/wwan/cc-wwan-details-dialog.c256
-rw-r--r--panels/wwan/cc-wwan-details-dialog.h40
-rw-r--r--panels/wwan/cc-wwan-details-dialog.ui274
-rw-r--r--panels/wwan/cc-wwan-device-page.c650
-rw-r--r--panels/wwan/cc-wwan-device-page.h42
-rw-r--r--panels/wwan/cc-wwan-device-page.ui190
-rw-r--r--panels/wwan/cc-wwan-device.c1481
-rw-r--r--panels/wwan/cc-wwan-device.h152
-rw-r--r--panels/wwan/cc-wwan-errors-private.h107
-rw-r--r--panels/wwan/cc-wwan-mode-dialog.c335
-rw-r--r--panels/wwan/cc-wwan-mode-dialog.h40
-rw-r--r--panels/wwan/cc-wwan-mode-dialog.ui52
-rw-r--r--panels/wwan/cc-wwan-network-dialog.c432
-rw-r--r--panels/wwan/cc-wwan-network-dialog.h40
-rw-r--r--panels/wwan/cc-wwan-network-dialog.ui128
-rw-r--r--panels/wwan/cc-wwan-panel.c836
-rw-r--r--panels/wwan/cc-wwan-panel.h36
-rw-r--r--panels/wwan/cc-wwan-panel.ui198
-rw-r--r--panels/wwan/cc-wwan-sim-lock-dialog.c309
-rw-r--r--panels/wwan/cc-wwan-sim-lock-dialog.h40
-rw-r--r--panels/wwan/cc-wwan-sim-lock-dialog.ui249
-rw-r--r--panels/wwan/gnome-wwan-panel.desktop.in.in15
-rw-r--r--panels/wwan/icons/meson.build4
-rw-r--r--panels/wwan/icons/scalable/org.gnome.Settings-mobile-network-symbolic.svg4
-rw-r--r--panels/wwan/meson.build61
-rw-r--r--panels/wwan/wwan.gresource.xml12
1025 files changed, 389185 insertions, 0 deletions
diff --git a/panels/applications/applications.gresource.xml b/panels/applications/applications.gresource.xml
new file mode 100644
index 0000000..9163349
--- /dev/null
+++ b/panels/applications/applications.gresource.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/applications">
+ <file preprocess="xml-stripblanks">cc-applications-panel.ui</file>
+ <file preprocess="xml-stripblanks">cc-applications-row.ui</file>
+ <file preprocess="xml-stripblanks">cc-info-row.ui</file>
+ <file preprocess="xml-stripblanks">cc-snap-row.ui</file>
+ <file preprocess="xml-stripblanks">cc-toggle-row.ui</file>
+ </gresource>
+</gresources>
diff --git a/panels/applications/cc-applications-panel.c b/panels/applications/cc-applications-panel.c
new file mode 100644
index 0000000..9d2d521
--- /dev/null
+++ b/panels/applications/cc-applications-panel.c
@@ -0,0 +1,1902 @@
+/* cc-applications-panel.c
+ *
+ * Copyright 2018 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "cc-applications-panel"
+
+#include <config.h>
+#include <glib/gi18n.h>
+#ifdef HAVE_SNAP
+#include <snapd-glib/snapd-glib.h>
+#endif
+#ifdef HAVE_MALCONTENT
+#include <libmalcontent/malcontent.h>
+#endif
+
+#include <gio/gdesktopappinfo.h>
+
+#include "cc-applications-panel.h"
+#include "cc-applications-row.h"
+#include "cc-toggle-row.h"
+#include "cc-info-row.h"
+#include "cc-applications-resources.h"
+#include "cc-util.h"
+#ifdef HAVE_SNAP
+#include "cc-snap-row.h"
+#endif
+#include "globs.h"
+#include "search.h"
+#include "utils.h"
+
+#define MASTER_SCHEMA "org.gnome.desktop.notifications"
+#define APP_SCHEMA MASTER_SCHEMA ".application"
+#define APP_PREFIX "/org/gnome/desktop/notifications/application/"
+
+#define PORTAL_SNAP_PREFIX "snap."
+
+struct _CcApplicationsPanel
+{
+ CcPanel parent;
+
+ GtkBox *sidebar_box;
+ GtkListBox *sidebar_listbox;
+ GtkEntry *sidebar_search_entry;
+ AdwWindowTitle *header_title;
+ GAppInfoMonitor *monitor;
+ gulong monitor_id;
+#ifdef HAVE_MALCONTENT
+ GCancellable *cancellable;
+
+ MctAppFilter *app_filter;
+ MctManager *manager;
+ guint app_filter_id;
+#endif
+
+ gchar *current_app_id;
+ GAppInfo *current_app_info;
+ gchar *current_portal_app_id;
+
+ GHashTable *globs;
+ GHashTable *search_providers;
+
+ GtkImage *app_icon_image;
+ GtkLabel *app_name_label;
+ GtkButton *launch_button;
+ GtkButton *view_details_button;
+
+ GDBusProxy *perm_store;
+ GSettings *notification_settings;
+ GSettings *location_settings;
+ GSettings *privacy_settings;
+ GSettings *search_settings;
+
+ GtkStack *stack;
+ GtkWidget *empty_box;
+ GtkWidget *settings_box;
+ GtkButton *install_button;
+
+ AdwPreferencesGroup *integration_section;
+ CcToggleRow *notification;
+ CcToggleRow *background;
+ CcToggleRow *wallpaper;
+ CcToggleRow *screenshot;
+ CcToggleRow *sound;
+ CcInfoRow *no_sound;
+ CcToggleRow *search;
+ CcInfoRow *no_search;
+ CcToggleRow *camera;
+ CcInfoRow *no_camera;
+ CcToggleRow *location;
+ CcInfoRow *no_location;
+ CcToggleRow *shortcuts;
+ CcToggleRow *microphone;
+ CcInfoRow *no_microphone;
+ CcInfoRow *builtin;
+ GtkDialog *builtin_dialog;
+ AdwPreferencesGroup *builtin_group;
+ GtkListBox *builtin_list;
+#ifdef HAVE_SNAP
+ GList *snap_permission_rows;
+#endif
+
+ GtkButton *handler_reset;
+ GtkDialog *handler_dialog;
+ CcInfoRow *handler_row;
+ GtkLabel *handler_title_label;
+ AdwPreferencesGroup *handler_file_group;
+ AdwPreferencesGroup *handler_link_group;
+ GList *file_handler_rows;
+ GList *link_handler_rows;
+
+ GtkWidget *usage_section;
+ CcInfoRow *storage;
+ GtkDialog *storage_dialog;
+ CcInfoRow *app;
+ CcInfoRow *data;
+ CcInfoRow *cache;
+ CcInfoRow *total;
+ GtkButton *clear_cache_button;
+
+ guint64 app_size;
+ guint64 cache_size;
+ guint64 data_size;
+};
+
+static void select_app (CcApplicationsPanel *self,
+ const gchar *app_id);
+
+G_DEFINE_TYPE (CcApplicationsPanel, cc_applications_panel, CC_TYPE_PANEL)
+
+enum
+{
+ PROP_0,
+ PROP_PARAMETERS
+};
+
+static gboolean
+gnome_software_is_installed (void)
+{
+ g_autofree gchar *path = g_find_program_in_path ("gnome-software");
+ return path != NULL;
+}
+
+/* Callbacks */
+
+static gboolean
+privacy_link_cb (CcApplicationsPanel *self)
+{
+ CcShell *shell = cc_panel_get_shell (CC_PANEL (self));
+ g_autoptr(GError) error = NULL;
+
+ if (!cc_shell_set_active_panel_from_id (shell, "location", NULL, &error))
+ g_warning ("Failed to switch to privacy panel: %s", error->message);
+
+ return TRUE;
+}
+
+static void
+open_software_cb (CcApplicationsPanel *self)
+{
+ const gchar *argv[] = { "gnome-software", "--details", "appid", NULL };
+
+ if (self->current_app_id == NULL)
+ argv[1] = NULL;
+ else
+ argv[2] = self->current_app_id;
+
+ g_spawn_async (NULL, (char **)argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL);
+}
+
+/* --- portal permissions and utilities --- */
+
+static gchar **
+get_portal_permissions (CcApplicationsPanel *self,
+ const gchar *table,
+ const gchar *id,
+ const gchar *app_id)
+{
+ g_autoptr(GVariant) ret = NULL;
+ g_autoptr(GVariantIter) iter = NULL;
+ const gchar *key = NULL;
+ GStrv val;
+ GStrv result = NULL;
+
+ ret = g_dbus_proxy_call_sync (self->perm_store,
+ "Lookup",
+ g_variant_new ("(ss)", table, id),
+ 0, G_MAXINT, NULL, NULL);
+ if (ret == NULL)
+ return NULL;
+
+ g_variant_get (ret, "(a{sas}v)", &iter, NULL);
+
+ while (g_variant_iter_loop (iter, "{&s^a&s}", &key, &val))
+ {
+ if (strcmp (key, app_id) == 0 && result == NULL)
+ result = g_strdupv (val);
+ }
+
+ return result;
+}
+
+static void
+set_portal_permissions (CcApplicationsPanel *self,
+ const gchar *table,
+ const gchar *id,
+ const gchar *app_id,
+ const gchar * const *permissions)
+{
+ g_autoptr(GError) error = NULL;
+
+ g_dbus_proxy_call_sync (self->perm_store,
+ "SetPermission",
+ g_variant_new ("(sbss^as)", table, TRUE, id, app_id, permissions),
+ 0,
+ G_MAXINT,
+ NULL,
+ &error);
+ if (error)
+ g_warning ("Error setting portal permissions: %s", error->message);
+}
+
+static gchar *
+get_portal_app_id (GAppInfo *info)
+{
+ if (G_IS_DESKTOP_APP_INFO (info))
+ {
+ g_autofree gchar *snap_name = NULL;
+ gchar *flatpak_id;
+
+ flatpak_id = g_desktop_app_info_get_string (G_DESKTOP_APP_INFO (info), "X-Flatpak");
+ if (flatpak_id != NULL)
+ return flatpak_id;
+
+ snap_name = g_desktop_app_info_get_string (G_DESKTOP_APP_INFO (info), "X-SnapInstanceName");
+ if (snap_name != NULL)
+ return g_strdup_printf ("%s%s", PORTAL_SNAP_PREFIX, snap_name);
+ }
+
+ return NULL;
+}
+
+static GFile *
+get_flatpak_app_dir (const gchar *app_id,
+ const gchar *subdir)
+{
+ g_autofree gchar *path = NULL;
+ g_autoptr(GFile) appdir = NULL;
+
+ path = g_build_filename (g_get_home_dir (), ".var", "app", app_id, NULL);
+ appdir = g_file_new_for_path (path);
+
+ return g_file_get_child (appdir, subdir);
+}
+
+/* --- search settings --- */
+
+static void
+set_search_enabled (CcApplicationsPanel *self,
+ const gchar *app_id,
+ gboolean enabled)
+{
+ g_autoptr(GPtrArray) new_apps = NULL;
+ g_autofree gchar *desktop_id = NULL;
+ g_auto(GStrv) apps = NULL;
+ gpointer key, value;
+ gboolean default_disabled;
+ gint i;
+
+ desktop_id = g_strconcat (app_id, ".desktop", NULL);
+
+ if (!g_hash_table_lookup_extended (self->search_providers, app_id, &key, &value))
+ {
+ g_warning ("Trying to configure search for a provider-less app - this shouldn't happen");
+ return;
+ }
+
+ default_disabled = GPOINTER_TO_INT (value);
+
+ new_apps = g_ptr_array_new_with_free_func (g_free);
+ if (default_disabled)
+ {
+ apps = g_settings_get_strv (self->search_settings, "enabled");
+ for (i = 0; apps[i]; i++)
+ {
+ if (strcmp (apps[i], desktop_id) != 0)
+ g_ptr_array_add (new_apps, g_strdup (apps[i]));
+ }
+ if (enabled)
+ g_ptr_array_add (new_apps, g_strdup (desktop_id));
+ g_ptr_array_add (new_apps, NULL);
+ g_settings_set_strv (self->search_settings, "enabled", (const gchar * const *)new_apps->pdata);
+ }
+ else
+ {
+ apps = g_settings_get_strv (self->search_settings, "disabled");
+ for (i = 0; apps[i]; i++)
+ {
+ if (strcmp (apps[i], desktop_id) != 0)
+ g_ptr_array_add (new_apps, g_strdup (apps[i]));
+ }
+ if (!enabled)
+ g_ptr_array_add (new_apps, g_strdup (desktop_id));
+ g_ptr_array_add (new_apps, NULL);
+ g_settings_set_strv (self->search_settings, "disabled", (const gchar * const *)new_apps->pdata);
+ }
+}
+
+static gboolean
+search_contains_string_for_app (CcApplicationsPanel *self,
+ const gchar *app_id,
+ const gchar *setting)
+{
+ g_autofree gchar *desktop_id = NULL;
+ g_auto(GStrv) apps = NULL;
+
+ desktop_id = g_strconcat (app_id, ".desktop", NULL);
+ apps = g_settings_get_strv (self->search_settings, setting);
+
+ return g_strv_contains ((const gchar * const *)apps, desktop_id);
+}
+
+static gboolean
+search_enabled_for_app (CcApplicationsPanel *self,
+ const gchar *app_id)
+{
+ return search_contains_string_for_app (self, app_id, "enabled");
+}
+
+static gboolean
+search_disabled_for_app (CcApplicationsPanel *self,
+ const gchar *app_id)
+{
+ return search_contains_string_for_app (self, app_id, "disabled");
+}
+
+static void
+get_search_enabled (CcApplicationsPanel *self,
+ const gchar *app_id,
+ gboolean *set,
+ gboolean *enabled)
+{
+ gpointer key, value;
+
+ *enabled = FALSE;
+ *set = g_hash_table_lookup_extended (self->search_providers, app_id, &key, &value);
+ if (!*set)
+ return;
+
+ if (search_enabled_for_app (self, app_id))
+ *enabled = TRUE;
+ else if (search_disabled_for_app (self, app_id))
+ *enabled = FALSE;
+ else
+ *enabled = !GPOINTER_TO_INT (value);
+}
+
+static void
+search_cb (CcApplicationsPanel *self)
+{
+ if (self->current_app_id)
+ set_search_enabled (self,
+ self->current_app_id,
+ cc_toggle_row_get_allowed (self->search));
+}
+
+/* --- notification permissions (flatpaks and non-flatpak) --- */
+
+static void
+get_notification_allowed (CcApplicationsPanel *self,
+ const gchar *app_id,
+ gboolean *set,
+ gboolean *allowed)
+{
+ if (self->notification_settings)
+ {
+ /* FIXME */
+ *set = TRUE;
+ *allowed = g_settings_get_boolean (self->notification_settings, "enable");
+ }
+ else
+ {
+ g_auto(GStrv) perms = get_portal_permissions (self, "notifications", "notification", app_id);
+ *set = perms != NULL;
+ /* FIXME: needs unreleased xdg-desktop-portals to write permissions on use */
+ *set = TRUE;
+ *allowed = perms == NULL || strcmp (perms[0], "no") != 0;
+ }
+}
+
+static void
+set_notification_allowed (CcApplicationsPanel *self,
+ gboolean allowed)
+{
+ if (self->notification_settings)
+ {
+ g_settings_set_boolean (self->notification_settings, "enable", allowed);
+ }
+ else
+ {
+ const gchar *perms[2] = { NULL, NULL };
+
+ perms[0] = allowed ? "yes" : "no";
+ set_portal_permissions (self, "notifications", "notification", self->current_portal_app_id, perms);
+ }
+}
+
+static void
+notification_cb (CcApplicationsPanel *self)
+{
+ if (self->current_app_id)
+ set_notification_allowed (self, cc_toggle_row_get_allowed (self->notification));
+}
+
+static gchar *
+munge_app_id (const gchar *app_id)
+{
+ gchar *id = g_strdup (app_id);
+ gint i;
+
+ g_strcanon (id,
+ "0123456789"
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "-",
+ '-');
+ for (i = 0; id[i] != '\0'; i++)
+ id[i] = g_ascii_tolower (id[i]);
+
+ return id;
+}
+
+static GSettings *
+get_notification_settings (const gchar *app_id)
+{
+ g_autofree gchar *munged_app_id = munge_app_id (app_id);
+ g_autofree gchar *path = g_strconcat (APP_PREFIX, munged_app_id, "/", NULL);
+ return g_settings_new_with_path (APP_SCHEMA, path);
+}
+
+
+/* --- background --- */
+
+static void
+get_background_allowed (CcApplicationsPanel *self,
+ const gchar *app_id,
+ gboolean *set,
+ gboolean *allowed)
+{
+ g_auto(GStrv) perms = get_portal_permissions (self, "background", "background", app_id);
+ *set = TRUE;
+ *allowed = perms == NULL || strcmp (perms[0], "no") != 0;
+}
+
+static void
+set_background_allowed (CcApplicationsPanel *self,
+ gboolean allowed)
+{
+ const gchar *perms[2] = { NULL, NULL };
+
+ perms[0] = allowed ? "yes" : "no";
+ set_portal_permissions (self, "background", "background", self->current_portal_app_id, perms);
+}
+
+static void
+background_cb (CcApplicationsPanel *self)
+{
+ if (self->current_app_id)
+ set_background_allowed (self, cc_toggle_row_get_allowed (self->background));
+}
+
+/* --- wallpaper --- */
+
+static void
+get_wallpaper_allowed (CcApplicationsPanel *self,
+ const gchar *app_id,
+ gboolean *set,
+ gboolean *allowed)
+{
+ g_auto(GStrv) perms = get_portal_permissions (self, "wallpaper", "wallpaper", app_id);
+
+ *set = perms != NULL;
+ *allowed = perms == NULL || strcmp (perms[0], "no") != 0;
+}
+
+static void
+set_wallpaper_allowed (CcApplicationsPanel *self,
+ gboolean allowed)
+{
+ const gchar *perms[2] = { NULL, NULL };
+
+ perms[0] = allowed ? "yes" : "no";
+ set_portal_permissions (self, "wallpaper", "wallpaper", self->current_app_id, perms);
+}
+
+static void
+wallpaper_cb (CcApplicationsPanel *self)
+{
+ if (self->current_app_id)
+ set_wallpaper_allowed (self, cc_toggle_row_get_allowed (self->wallpaper));
+}
+
+/* --- screenshot --- */
+
+static void
+get_screenshot_allowed (CcApplicationsPanel *self,
+ const gchar *app_id,
+ gboolean *set,
+ gboolean *allowed)
+{
+ g_auto(GStrv) perms = get_portal_permissions (self, "screenshot", "screenshot", app_id);
+
+ *set = perms != NULL;
+ *allowed = perms == NULL || strcmp (perms[0], "no") != 0;
+}
+
+static void
+set_screenshot_allowed (CcApplicationsPanel *self,
+ gboolean allowed)
+{
+ const gchar *perms[2] = { NULL, NULL };
+
+ perms[0] = allowed ? "yes" : "no";
+ set_portal_permissions (self, "screenshot", "screenshot", self->current_app_id, perms);
+}
+
+static void
+screenshot_cb (CcApplicationsPanel *self)
+{
+ if (self->current_app_id)
+ set_screenshot_allowed (self, cc_toggle_row_get_allowed (self->screenshot));
+}
+
+/* --- shortcuts permissions (flatpak) --- */
+
+static void
+get_shortcuts_allowed (CcApplicationsPanel *self,
+ const gchar *app_id,
+ gboolean *set,
+ gboolean *granted)
+{
+ g_auto(GStrv) perms = NULL;
+
+ perms = get_portal_permissions (self, "gnome", "shortcuts-inhibitor", app_id);
+
+ /* GNOME Shell's "inhibit shortcut dialog" sets the permission to "GRANTED" if
+ * the user allowed for the keyboard shortcuts to be inhibited, check for that
+ * string value here.
+ */
+ *set = perms != NULL;
+ *granted = (perms != NULL) && g_ascii_strcasecmp (perms[0], "GRANTED") == 0;
+}
+
+static void
+set_shortcuts_allowed (CcApplicationsPanel *self,
+ gboolean granted)
+{
+ const gchar *perms[2];
+ g_autofree gchar *desktop_id = g_strconcat (self->current_app_id, ".desktop", NULL);
+
+ /* "GRANTED" and "DENIED" here match the values set by the "inhibit shortcut
+ * dialog" is GNOME Shell:
+ * https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/inhibitShortcutsDialog.js
+ */
+ perms[0] = granted ? "GRANTED" : "DENIED";
+ perms[1] = NULL;
+
+ set_portal_permissions (self, "gnome", "shortcuts-inhibitor", desktop_id, perms);
+}
+
+static void
+shortcuts_cb (CcApplicationsPanel *self)
+{
+ if (self->current_app_id)
+ set_shortcuts_allowed (self, cc_toggle_row_get_allowed (self->shortcuts));
+}
+
+/* --- device (microphone, camera, speaker) permissions (flatpak) --- */
+
+static void
+get_device_allowed (CcApplicationsPanel *self,
+ const gchar *device,
+ const gchar *app_id,
+ gboolean *set,
+ gboolean *allowed)
+{
+ g_auto(GStrv) perms = NULL;
+
+ perms = get_portal_permissions (self, "devices", device, app_id);
+
+ *set = perms != NULL;
+ *allowed = perms == NULL || strcmp (perms[0], "no") != 0;
+}
+
+static void
+set_device_allowed (CcApplicationsPanel *self,
+ const gchar *device,
+ gboolean allowed)
+{
+ const gchar *perms[2];
+
+ perms[0] = allowed ? "yes" : "no";
+ perms[1] = NULL;
+
+ set_portal_permissions (self, "devices", device, self->current_portal_app_id, perms);
+}
+
+static void
+microphone_cb (CcApplicationsPanel *self)
+{
+ if (self->current_portal_app_id)
+ set_device_allowed (self, "microphone", cc_toggle_row_get_allowed (self->microphone));
+}
+
+static void
+sound_cb (CcApplicationsPanel *self)
+{
+ if (self->current_portal_app_id)
+ set_device_allowed (self, "speakers", cc_toggle_row_get_allowed (self->sound));
+}
+
+static void
+camera_cb (CcApplicationsPanel *self)
+{
+ if (self->current_portal_app_id)
+ set_device_allowed (self, "camera", cc_toggle_row_get_allowed (self->camera));
+}
+
+/* --- location permissions (flatpak) --- */
+
+static void
+get_location_allowed (CcApplicationsPanel *self,
+ const gchar *app_id,
+ gboolean *set,
+ gboolean *allowed)
+{
+ g_auto(GStrv) perms = NULL;
+
+ perms = get_portal_permissions (self, "location", "location", app_id);
+
+ *set = perms != NULL;
+ *allowed = perms == NULL || strcmp (perms[0], "NONE") != 0;
+}
+
+static void
+set_location_allowed (CcApplicationsPanel *self,
+ gboolean allowed)
+{
+ const gchar *perms[3];
+
+ /* FIXME allow setting accuracy */
+ perms[0] = allowed ? "EXACT" : "NONE";
+ perms[1] = "0";
+ perms[2] = NULL;
+
+ set_portal_permissions (self, "location", "location", self->current_portal_app_id, perms);
+}
+
+static void
+location_cb (CcApplicationsPanel *self)
+{
+ if (self->current_portal_app_id)
+ set_location_allowed (self, cc_toggle_row_get_allowed (self->location));
+}
+
+/* --- permissions section --- */
+
+#ifdef HAVE_SNAP
+static void
+remove_snap_permissions (CcApplicationsPanel *self)
+{
+ GList *l;
+
+ for (l = self->snap_permission_rows; l; l = l->next)
+ adw_preferences_group_remove (self->integration_section, l->data);
+ g_clear_pointer (&self->snap_permission_rows, g_list_free);
+}
+
+static gboolean
+add_snap_permissions (CcApplicationsPanel *self,
+ GAppInfo *info,
+ const gchar *app_id)
+{
+ const gchar *snap_name;
+ g_autoptr(SnapdClient) client = NULL;
+ g_autoptr(GPtrArray) interfaces = NULL;
+ g_autoptr(GPtrArray) plugs = NULL;
+ g_autoptr(GPtrArray) slots = NULL;
+ SnapdInterface *interface = NULL;
+ gint added = 0;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GError) interfaces_error = NULL;
+
+ if (!g_str_has_prefix (app_id, PORTAL_SNAP_PREFIX))
+ return FALSE;
+ snap_name = app_id + strlen (PORTAL_SNAP_PREFIX);
+
+ client = snapd_client_new ();
+
+ interfaces = snapd_client_get_interfaces2_sync (client,
+ SNAPD_GET_INTERFACES_FLAGS_NONE,
+ NULL,
+ NULL, &interfaces_error);
+ if (interfaces == NULL)
+ g_warning ("Failed to get snap interfaces: %s", interfaces_error->message);
+
+ if (!snapd_client_get_connections2_sync (client,
+ SNAPD_GET_CONNECTIONS_FLAGS_SELECT_ALL,
+ NULL, NULL,
+ NULL, NULL,
+ &plugs, &slots,
+ NULL, &error))
+ {
+ g_warning ("Failed to get snap connections: %s", error->message);
+ return FALSE;
+ }
+
+ for (int i = 0; i < plugs->len; i++)
+ {
+ SnapdPlug *plug = g_ptr_array_index (plugs, i);
+ CcSnapRow *row;
+ g_autoptr(GPtrArray) available_slots = NULL;
+ const gchar * const hidden_interfaces[] = { "content",
+ "desktop", "desktop-legacy",
+ "mir",
+ "unity7", "unity8",
+ "wayland",
+ "x11",
+ NULL };
+
+ /* Skip if not relating to this snap */
+ if (g_strcmp0 (snapd_plug_get_snap (plug), snap_name) != 0)
+ continue;
+
+ /* Ignore interfaces that are too low level to make sense to show or disable */
+ if (g_strv_contains (hidden_interfaces, snapd_plug_get_interface (plug)))
+ continue;
+
+ available_slots = g_ptr_array_new_with_free_func (g_object_unref);
+ for (int j = 0; j < slots->len; j++)
+ {
+ SnapdSlot *slot = g_ptr_array_index (slots, j);
+ if (g_strcmp0 (snapd_plug_get_interface (plug), snapd_slot_get_interface (slot)) != 0)
+ continue;
+
+ g_ptr_array_add (available_slots, g_object_ref (slot));
+ }
+
+ if (interfaces != NULL)
+ {
+ for (int j = 0; j < interfaces->len; j++)
+ {
+ SnapdInterface *i = g_ptr_array_index (interfaces, j);
+ if (g_strcmp0 (snapd_interface_get_name (i), snapd_plug_get_interface (plug)) == 0)
+ interface = i;
+ }
+ }
+
+ row = cc_snap_row_new (cc_panel_get_cancellable (CC_PANEL (self)), interface, plug, available_slots);
+ adw_preferences_group_add (self->integration_section, GTK_WIDGET (row));
+ self->snap_permission_rows = g_list_prepend (self->snap_permission_rows, row);
+ added++;
+ }
+
+ return added > 0;
+}
+#endif
+
+static gint
+add_static_permission_row (CcApplicationsPanel *self,
+ const gchar *title,
+ const gchar *subtitle)
+{
+ GtkWidget *row;
+
+ row = g_object_new (CC_TYPE_INFO_ROW,
+ "title", title,
+ "info", subtitle,
+ NULL);
+ gtk_list_box_append (self->builtin_list, row);
+
+ return 1;
+}
+
+static gboolean
+add_static_permissions (CcApplicationsPanel *self,
+ GAppInfo *info,
+ const gchar *app_id)
+{
+ g_autoptr(GKeyFile) keyfile = NULL;
+ g_auto(GStrv) sockets = NULL;
+ g_auto(GStrv) devices = NULL;
+ g_auto(GStrv) shared = NULL;
+ g_auto(GStrv) filesystems = NULL;
+ g_autofree gchar *str = NULL;
+ gint added = 0;
+ g_autofree gchar *text = NULL;
+
+ if (app_id && !g_str_has_prefix (app_id, PORTAL_SNAP_PREFIX))
+ keyfile = get_flatpak_metadata (app_id);
+ if (keyfile == NULL)
+ return FALSE;
+
+ sockets = g_key_file_get_string_list (keyfile, "Context", "sockets", NULL, NULL);
+ if (sockets && g_strv_contains ((const gchar * const*)sockets, "system-bus"))
+ added += add_static_permission_row (self, _("System Bus"), _("Full access"));
+ if (sockets && g_strv_contains ((const gchar * const*)sockets, "session-bus"))
+ added += add_static_permission_row (self, _("Session Bus"), _("Full access"));
+
+ devices = g_key_file_get_string_list (keyfile, "Context", "devices", NULL, NULL);
+ if (devices && g_strv_contains ((const gchar * const*)devices, "all"))
+ added += add_static_permission_row (self, _("Devices"), _("Full access to /dev"));
+
+ shared = g_key_file_get_string_list (keyfile, "Context", "shared", NULL, NULL);
+ if (shared && g_strv_contains ((const gchar * const*)shared, "network"))
+ added += add_static_permission_row (self, _("Network"), _("Has network access"));
+
+ filesystems = g_key_file_get_string_list (keyfile, "Context", "filesystems", NULL, NULL);
+ if (filesystems && (g_strv_contains ((const gchar * const *)filesystems, "home") ||
+ g_strv_contains ((const gchar * const *)filesystems, "home:rw")))
+ added += add_static_permission_row (self, _("Home"), _("Full access"));
+ else if (filesystems && g_strv_contains ((const gchar * const *)filesystems, "home:ro"))
+ added += add_static_permission_row (self, _("Home"), _("Read-only"));
+ if (filesystems && (g_strv_contains ((const gchar * const *)filesystems, "host") ||
+ g_strv_contains ((const gchar * const *)filesystems, "host:rw")))
+ added += add_static_permission_row (self, _("File System"), _("Full access"));
+ else if (filesystems && g_strv_contains ((const gchar * const *)filesystems, "host:ro"))
+ added += add_static_permission_row (self, _("File System"), _("Read-only"));
+
+ str = g_key_file_get_string (keyfile, "Session Bus Policy", "ca.desrt.dconf", NULL);
+ if (str && g_str_equal (str, "talk"))
+ added += add_static_permission_row (self, _("Settings"), _("Can change settings"));
+
+ text = g_strdup_printf (_("%s has the following permissions built-in. These cannot be altered. If you are concerned about these permissions, consider removing this application."), g_app_info_get_display_name (info));
+ adw_preferences_group_set_description (self->builtin_group, text);
+
+ return added > 0;
+}
+
+static void
+remove_static_permissions (CcApplicationsPanel *self)
+{
+ listbox_remove_all (self->builtin_list);
+}
+
+/* --- header section --- */
+
+static void
+update_header_section (CcApplicationsPanel *self,
+ GAppInfo *info)
+{
+ GIcon *icon;
+
+ icon = g_app_info_get_icon (info);
+ gtk_image_set_from_gicon (self->app_icon_image, icon);
+
+ gtk_label_set_label (self->app_name_label,
+ g_app_info_get_display_name (info));
+}
+
+
+/* --- gintegration section --- */
+
+static void
+update_integration_section (CcApplicationsPanel *self,
+ GAppInfo *info)
+{
+ g_autofree gchar *app_id = get_app_id (info);
+ g_autofree gchar *portal_app_id = get_portal_app_id (info);
+ gboolean set, allowed, disabled;
+ gboolean has_any = FALSE;
+
+ disabled = g_settings_get_boolean (self->search_settings, "disable-external");
+ get_search_enabled (self, app_id, &set, &allowed);
+ cc_toggle_row_set_allowed (self->search, allowed);
+ gtk_widget_set_visible (GTK_WIDGET (self->search), set && !disabled);
+ gtk_widget_set_visible (GTK_WIDGET (self->no_search), set && disabled);
+
+ if (app_id != NULL)
+ {
+ g_autofree gchar *desktop_id = g_strconcat (app_id, ".desktop", NULL);
+ get_shortcuts_allowed (self, desktop_id, &set, &allowed);
+ gtk_widget_set_visible (GTK_WIDGET (self->shortcuts), set);
+ cc_toggle_row_set_allowed (self->shortcuts, allowed);
+ }
+ else
+ {
+ gtk_widget_hide (GTK_WIDGET (self->shortcuts));
+ }
+
+#ifdef HAVE_SNAP
+ remove_snap_permissions (self);
+#endif
+
+ if (portal_app_id != NULL)
+ {
+ g_clear_object (&self->notification_settings);
+ get_notification_allowed (self, portal_app_id, &set, &allowed);
+ cc_toggle_row_set_allowed (self->notification, allowed);
+ gtk_widget_set_visible (GTK_WIDGET (self->notification), set);
+ has_any |= set;
+
+ get_background_allowed (self, portal_app_id, &set, &allowed);
+ cc_toggle_row_set_allowed (self->background, allowed);
+ gtk_widget_set_visible (GTK_WIDGET (self->background), set);
+ has_any |= set;
+
+ get_wallpaper_allowed (self, portal_app_id, &set, &allowed);
+ cc_toggle_row_set_allowed (self->wallpaper, allowed);
+ gtk_widget_set_visible (GTK_WIDGET (self->wallpaper), set);
+ has_any |= set;
+
+ get_screenshot_allowed (self, portal_app_id, &set, &allowed);
+ cc_toggle_row_set_allowed (self->screenshot, allowed);
+ gtk_widget_set_visible (GTK_WIDGET (self->screenshot), set);
+ has_any |= set;
+
+ disabled = g_settings_get_boolean (self->privacy_settings, "disable-sound-output");
+ get_device_allowed (self, "speakers", portal_app_id, &set, &allowed);
+ cc_toggle_row_set_allowed (self->sound, allowed);
+ gtk_widget_set_visible (GTK_WIDGET (self->sound), set && !disabled);
+ gtk_widget_set_visible (GTK_WIDGET (self->no_sound), set && disabled);
+
+ disabled = g_settings_get_boolean (self->privacy_settings, "disable-camera");
+ get_device_allowed (self, "camera", portal_app_id, &set, &allowed);
+ cc_toggle_row_set_allowed (self->camera, allowed);
+ gtk_widget_set_visible (GTK_WIDGET (self->camera), set && !disabled);
+ gtk_widget_set_visible (GTK_WIDGET (self->no_camera), set && disabled);
+ has_any |= set;
+
+ disabled = g_settings_get_boolean (self->privacy_settings, "disable-microphone");
+ get_device_allowed (self, "microphone", portal_app_id, &set, &allowed);
+ cc_toggle_row_set_allowed (self->microphone, allowed);
+ gtk_widget_set_visible (GTK_WIDGET (self->microphone), set && !disabled);
+ gtk_widget_set_visible (GTK_WIDGET (self->no_microphone), set && disabled);
+ has_any |= set;
+
+ disabled = !g_settings_get_boolean (self->location_settings, "enabled");
+ get_location_allowed (self, portal_app_id, &set, &allowed);
+ cc_toggle_row_set_allowed (self->location, allowed);
+ gtk_widget_set_visible (GTK_WIDGET (self->location), set && !disabled);
+ gtk_widget_set_visible (GTK_WIDGET (self->no_location), set && disabled);
+ has_any |= set;
+
+ #ifdef HAVE_SNAP
+ has_any |= add_snap_permissions (self, info, portal_app_id);
+ #endif
+ }
+ else
+ {
+ g_set_object (&self->notification_settings, get_notification_settings (app_id));
+ get_notification_allowed (self, app_id, &set, &allowed);
+ cc_toggle_row_set_allowed (self->notification, allowed);
+ gtk_widget_set_visible (GTK_WIDGET (self->notification), set);
+ has_any |= set;
+
+ gtk_widget_hide (GTK_WIDGET (self->background));
+ gtk_widget_hide (GTK_WIDGET (self->wallpaper));
+ gtk_widget_hide (GTK_WIDGET (self->screenshot));
+ gtk_widget_hide (GTK_WIDGET (self->sound));
+ gtk_widget_hide (GTK_WIDGET (self->no_sound));
+ gtk_widget_hide (GTK_WIDGET (self->camera));
+ gtk_widget_hide (GTK_WIDGET (self->no_camera));
+ gtk_widget_hide (GTK_WIDGET (self->microphone));
+ gtk_widget_hide (GTK_WIDGET (self->no_microphone));
+ gtk_widget_hide (GTK_WIDGET (self->location));
+ gtk_widget_hide (GTK_WIDGET (self->no_location));
+ }
+
+ gtk_widget_set_visible (GTK_WIDGET (self->integration_section), has_any);
+}
+
+/* --- handler section --- */
+
+static void
+unset_cb (CcApplicationsPanel *self,
+ GtkButton *button)
+{
+ const gchar *type;
+ GtkListBoxRow *selected;
+ GAppInfo *info;
+
+ selected = gtk_list_box_get_selected_row (self->sidebar_listbox);
+ info = cc_applications_row_get_info (CC_APPLICATIONS_ROW (selected));
+
+ type = (const gchar *)g_object_get_data (G_OBJECT (button), "type");
+
+ g_app_info_remove_supports_type (info, type, NULL);
+}
+
+static void
+add_scheme (CcApplicationsPanel *self,
+ const gchar *type)
+{
+ g_autofree gchar *title = NULL;
+ GtkWidget *button;
+ GtkWidget *row;
+ gchar *scheme;
+
+ scheme = strrchr (type, '/') + 1;
+ title = g_strdup_printf ("%s://", scheme);
+
+ row = adw_action_row_new ();
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row), title);
+
+ button = gtk_button_new_from_icon_name ("edit-delete-symbolic");
+ gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
+ gtk_widget_set_halign (button, GTK_ALIGN_END);
+ gtk_widget_add_css_class (button, "flat");
+ gtk_widget_add_css_class (button, "circular");
+ adw_action_row_add_suffix (ADW_ACTION_ROW (row), button);
+ adw_action_row_set_activatable_widget (ADW_ACTION_ROW (row), button);
+ g_object_set_data_full (G_OBJECT (button), "type", g_strdup (type), g_free);
+ g_signal_connect_object (button, "clicked", G_CALLBACK (unset_cb), self, G_CONNECT_SWAPPED);
+
+ gtk_widget_show (GTK_WIDGET (self->handler_link_group));
+ adw_preferences_group_add (self->handler_link_group, GTK_WIDGET (row));
+
+ self->link_handler_rows = g_list_prepend (self->link_handler_rows, row);
+}
+
+static void
+add_file_type (CcApplicationsPanel *self,
+ const gchar *type)
+{
+ g_autofree gchar *desc = NULL;
+ const gchar *glob;
+ GtkWidget *button;
+ GtkWidget *row;
+
+ glob = g_hash_table_lookup (self->globs, type);
+
+ desc = g_content_type_get_description (type);
+ row = adw_action_row_new ();
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row), desc);
+ adw_action_row_set_subtitle (ADW_ACTION_ROW (row), glob ? glob : "");
+
+ button = gtk_button_new_from_icon_name ("edit-delete-symbolic");
+ gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
+ gtk_widget_set_halign (button, GTK_ALIGN_END);
+ gtk_widget_add_css_class (button, "flat");
+ gtk_widget_add_css_class (button, "circular");
+ adw_action_row_add_suffix (ADW_ACTION_ROW (row), button);
+ adw_action_row_set_activatable_widget (ADW_ACTION_ROW (row), button);
+ g_object_set_data_full (G_OBJECT (button), "type", g_strdup (type), g_free);
+ g_signal_connect_object (button, "clicked", G_CALLBACK (unset_cb), self, G_CONNECT_SWAPPED);
+
+ gtk_widget_show (GTK_WIDGET (self->handler_file_group));
+ adw_preferences_group_add (self->handler_file_group, GTK_WIDGET (row));
+
+ self->file_handler_rows = g_list_prepend (self->file_handler_rows, row);
+}
+
+static void
+add_handler_row (CcApplicationsPanel *self,
+ const gchar *type)
+{
+ gtk_widget_show (GTK_WIDGET (self->handler_row));
+
+ if (g_content_type_is_a (type, "x-scheme-handler/*"))
+ add_scheme (self, type);
+ else
+ add_file_type (self, type);
+}
+
+static gboolean
+app_info_recommended_for (GAppInfo *info,
+ const gchar *type)
+{
+ /* this is horribly inefficient. I blame the mime system */
+ g_autolist(GObject) list = NULL;
+ GList *l;
+ gboolean ret = FALSE;
+
+ list = g_app_info_get_recommended_for_type (type);
+ for (l = list; l; l = l->next)
+ {
+ GAppInfo *ri = l->data;
+
+ if (g_app_info_equal (info, ri))
+ {
+ ret = TRUE;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static void
+handler_reset_cb (CcApplicationsPanel *self)
+{
+ GtkListBoxRow *selected;
+ GAppInfo *info;
+ const gchar **types;
+ gint i;
+
+ selected = gtk_list_box_get_selected_row (self->sidebar_listbox);
+ info = cc_applications_row_get_info (CC_APPLICATIONS_ROW (selected));
+
+ types = g_app_info_get_supported_types (info);
+ if (types == NULL || types[0] == NULL)
+ return;
+
+ g_signal_handler_block (self->monitor, self->monitor_id);
+ for (i = 0; types[i]; i++)
+ {
+ gchar *ctype = g_content_type_from_mime_type (types[i]);
+ g_app_info_add_supports_type (info, ctype, NULL);
+ }
+ g_signal_handler_unblock (self->monitor, self->monitor_id);
+ g_signal_emit_by_name (self->monitor, "changed");
+}
+
+static void
+remove_all_handler_rows (CcApplicationsPanel *self)
+{
+ GList *l;
+
+ for (l = self->file_handler_rows; l; l = l->next)
+ adw_preferences_group_remove (self->handler_file_group, l->data);
+ g_clear_pointer (&self->file_handler_rows, g_list_free);
+
+ for (l = self->link_handler_rows; l; l = l->next)
+ adw_preferences_group_remove (self->handler_link_group, l->data);
+ g_clear_pointer (&self->link_handler_rows, g_list_free);
+}
+
+static void
+update_handler_dialog (CcApplicationsPanel *self,
+ GAppInfo *info)
+{
+ g_autofree gchar *header_title = NULL;
+ g_autoptr(GHashTable) hash = NULL;
+ const gchar **types;
+ guint n_associations = 0;
+ gint i;
+
+ remove_all_handler_rows (self);
+
+ gtk_widget_hide (GTK_WIDGET (self->handler_row));
+ gtk_widget_hide (GTK_WIDGET (self->handler_file_group));
+ gtk_widget_hide (GTK_WIDGET (self->handler_link_group));
+
+ types = g_app_info_get_supported_types (info);
+ if (types == NULL || types[0] == NULL)
+ return;
+
+ hash = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->handler_reset), FALSE);
+ for (i = 0; types[i]; i++)
+ {
+ g_autofree gchar *ctype = g_content_type_from_mime_type (types[i]);
+
+ if (g_hash_table_contains (hash, ctype))
+ continue;
+
+ if (!app_info_recommended_for (info, ctype))
+ {
+ gtk_widget_set_sensitive (GTK_WIDGET (self->handler_reset), TRUE);
+ continue;
+ }
+
+ add_handler_row (self, ctype);
+ g_hash_table_add (hash, g_steal_pointer (&ctype));
+
+ n_associations++;
+ }
+
+ if (n_associations > 0)
+ {
+ g_autofree gchar *subtitle = NULL;
+
+ subtitle = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE,
+ "%u file and link type that is opened by the app",
+ "%u file and link types that are opened by the app",
+ n_associations),
+ n_associations);
+ adw_action_row_set_subtitle (ADW_ACTION_ROW (self->handler_row), subtitle);
+ }
+
+ header_title = g_strdup_printf (_("<b>%s</b> is used to open the following types of files and links."),
+ g_app_info_get_display_name (info));
+ gtk_label_set_markup (self->handler_title_label, header_title);
+}
+
+/* --- usage section --- */
+
+static void
+on_builtin_row_activated_cb (GtkListBoxRow *row,
+ CcApplicationsPanel *self)
+{
+ CcShell *shell = cc_panel_get_shell (CC_PANEL (self));
+
+ gtk_window_set_transient_for (GTK_WINDOW (self->builtin_dialog),
+ GTK_WINDOW (cc_shell_get_toplevel (shell)));
+ gtk_window_present (GTK_WINDOW (self->builtin_dialog));
+}
+
+static void
+on_handler_row_activated_cb (GtkListBoxRow *row,
+ CcApplicationsPanel *self)
+{
+ CcShell *shell = cc_panel_get_shell (CC_PANEL (self));
+
+ gtk_window_set_transient_for (GTK_WINDOW (self->handler_dialog),
+ GTK_WINDOW (cc_shell_get_toplevel (shell)));
+ gtk_window_present (GTK_WINDOW (self->handler_dialog));
+}
+
+static void
+on_storage_row_activated_cb (GtkListBoxRow *row,
+ CcApplicationsPanel *self)
+{
+ CcShell *shell = cc_panel_get_shell (CC_PANEL (self));
+
+ gtk_window_set_transient_for (GTK_WINDOW (self->storage_dialog),
+ GTK_WINDOW (cc_shell_get_toplevel (shell)));
+ gtk_window_present (GTK_WINDOW (self->storage_dialog));
+}
+
+static void
+update_total_size (CcApplicationsPanel *self)
+{
+ g_autofree gchar *formatted_size = NULL;
+ g_autofree gchar *subtitle = NULL;
+ guint64 total;
+
+ total = self->app_size + self->data_size + self->cache_size;
+ formatted_size = g_format_size (total);
+ g_object_set (self->total, "info", formatted_size, NULL);
+
+ /* Translators: '%s' is the formatted size, e.g. "26.2 MB" */
+ subtitle = g_strdup_printf (_("%s of disk space used."), formatted_size);
+ g_object_set (self->storage, "subtitle", subtitle, NULL);
+}
+
+static void
+set_cache_size (GObject *source,
+ GAsyncResult *res,
+ gpointer data)
+{
+ CcApplicationsPanel *self = data;
+ g_autofree gchar *formatted_size = NULL;
+ guint64 size;
+ g_autoptr(GError) error = NULL;
+
+ if (!file_size_finish (G_FILE (source), res, &size, &error))
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to get flatpak cache size: %s", error->message);
+ return;
+ }
+ self->cache_size = size;
+
+ formatted_size = g_format_size (self->cache_size);
+ g_object_set (self->cache, "info", formatted_size, NULL);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->clear_cache_button), self->cache_size > 0);
+
+ update_total_size (self);
+}
+
+static void
+update_cache_row (CcApplicationsPanel *self,
+ const gchar *app_id)
+{
+ g_autoptr(GFile) dir = get_flatpak_app_dir (app_id, "cache");
+ g_object_set (self->cache, "info", "...", NULL);
+ file_size_async (dir, cc_panel_get_cancellable (CC_PANEL (self)), set_cache_size, self);
+}
+
+static void
+set_data_size (GObject *source,
+ GAsyncResult *res,
+ gpointer data)
+{
+ CcApplicationsPanel *self = data;
+ g_autofree gchar *formatted_size = NULL;
+ guint64 size;
+ g_autoptr(GError) error = NULL;
+
+ if (!file_size_finish (G_FILE (source), res, &size, &error))
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to get flatpak data size: %s", error->message);
+ return;
+ }
+ self->data_size = size;
+
+ formatted_size = g_format_size (self->data_size);
+ g_object_set (self->data, "info", formatted_size, NULL);
+
+ update_total_size (self);
+}
+
+static void
+update_data_row (CcApplicationsPanel *self,
+ const gchar *app_id)
+{
+ g_autoptr(GFile) dir = get_flatpak_app_dir (app_id, "data");
+
+ g_object_set (self->data, "info", "...", NULL);
+ file_size_async (dir, cc_panel_get_cancellable (CC_PANEL (self)), set_data_size, self);
+}
+
+static void
+cache_cleared (GObject *source,
+ GAsyncResult *res,
+ gpointer data)
+{
+ CcApplicationsPanel *self = data;
+ g_autoptr(GError) error = NULL;
+
+ if (!file_remove_finish (G_FILE (source), res, &error))
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to remove cache: %s", error->message);
+ return;
+ }
+
+ update_cache_row (self, self->current_app_id);
+}
+
+static void
+clear_cache_cb (CcApplicationsPanel *self)
+{
+ g_autoptr(GFile) dir = NULL;
+
+ if (self->current_app_id == NULL)
+ return;
+
+ dir = get_flatpak_app_dir (self->current_app_id, "cache");
+ file_remove_async (dir, cc_panel_get_cancellable (CC_PANEL (self)), cache_cleared, self);
+}
+
+static void
+update_app_row (CcApplicationsPanel *self,
+ const gchar *app_id)
+{
+ g_autofree gchar *formatted_size = NULL;
+
+ if (g_str_has_prefix (app_id, PORTAL_SNAP_PREFIX))
+ self->app_size = get_snap_app_size (app_id + strlen (PORTAL_SNAP_PREFIX));
+ else
+ self->app_size = get_flatpak_app_size (app_id);
+ formatted_size = g_format_size (self->app_size);
+ g_object_set (self->app, "info", formatted_size, NULL);
+ update_total_size (self);
+}
+
+static void
+update_app_sizes (CcApplicationsPanel *self,
+ const gchar *app_id)
+{
+ gtk_widget_set_sensitive (GTK_WIDGET (self->clear_cache_button), FALSE);
+
+ self->app_size = self->data_size = self->cache_size = 0;
+
+ update_app_row (self, app_id);
+ update_cache_row (self, app_id);
+ update_data_row (self, app_id);
+}
+
+static void
+update_usage_section (CcApplicationsPanel *self,
+ GAppInfo *info)
+{
+ g_autofree gchar *portal_app_id = get_portal_app_id (info);
+ gboolean has_builtin = FALSE;
+
+ if (portal_app_id != NULL)
+ update_app_sizes (self, portal_app_id);
+
+ remove_static_permissions (self);
+ has_builtin = add_static_permissions (self, info, portal_app_id);
+ gtk_widget_set_visible (GTK_WIDGET (self->builtin), has_builtin);
+
+ gtk_widget_set_visible (GTK_WIDGET (self->usage_section), portal_app_id || has_builtin);
+}
+
+/* --- panel setup --- */
+
+static void
+update_panel (CcApplicationsPanel *self,
+ GtkListBoxRow *row)
+{
+ GAppInfo *info;
+
+ if (self->perm_store == NULL)
+ {
+ g_message ("No permissions store proxy yet, come back later");
+ return;
+ }
+
+ if (row == NULL)
+ {
+ adw_window_title_set_title (self->header_title, _("Applications"));
+ gtk_stack_set_visible_child (self->stack, self->empty_box);
+ gtk_widget_hide (GTK_WIDGET (GTK_WIDGET (self->view_details_button)));
+ return;
+ }
+
+ info = cc_applications_row_get_info (CC_APPLICATIONS_ROW (row));
+
+ adw_window_title_set_title (self->header_title, g_app_info_get_display_name (info));
+ gtk_stack_set_visible_child (self->stack, self->settings_box);
+ gtk_widget_set_visible (GTK_WIDGET (self->view_details_button), gnome_software_is_installed ());
+
+ g_clear_pointer (&self->current_app_id, g_free);
+ g_clear_pointer (&self->current_portal_app_id, g_free);
+
+ update_header_section (self, info);
+ update_integration_section (self, info);
+ update_handler_dialog (self, info);
+ update_usage_section (self, info);
+
+ g_set_object (&self->current_app_info, info);
+ self->current_app_id = get_app_id (info);
+ self->current_portal_app_id = get_portal_app_id (info);
+}
+
+static void
+populate_applications (CcApplicationsPanel *self)
+{
+ g_autolist(GObject) infos = NULL;
+ GList *l;
+
+ listbox_remove_all (self->sidebar_listbox);
+#ifdef HAVE_MALCONTENT
+ g_signal_handler_block (self->manager, self->app_filter_id);
+#endif
+
+ infos = g_app_info_get_all ();
+
+ for (l = infos; l; l = l->next)
+ {
+ GAppInfo *info = l->data;
+ GtkWidget *row;
+ g_autofree gchar *id = NULL;
+
+ if (!g_app_info_should_show (info))
+ continue;
+
+#ifdef HAVE_MALCONTENT
+ if (!mct_app_filter_is_appinfo_allowed (self->app_filter, info))
+ continue;
+#endif
+
+ row = GTK_WIDGET (cc_applications_row_new (info));
+ gtk_list_box_insert (self->sidebar_listbox, row, -1);
+
+ id = get_app_id (info);
+ if (g_strcmp0 (id, self->current_app_id) == 0)
+ gtk_list_box_select_row (self->sidebar_listbox, GTK_LIST_BOX_ROW (row));
+ }
+#ifdef HAVE_MALCONTENT
+ g_signal_handler_unblock (self->manager, self->app_filter_id);
+#endif
+}
+
+static gint
+compare_rows (GtkListBoxRow *row1,
+ GtkListBoxRow *row2,
+ gpointer data)
+{
+ const gchar *key1 = cc_applications_row_get_sort_key (CC_APPLICATIONS_ROW (row1));
+ const gchar *key2 = cc_applications_row_get_sort_key (CC_APPLICATIONS_ROW (row2));
+
+ return strcmp (key1, key2);
+}
+
+static gboolean
+filter_sidebar_rows (GtkListBoxRow *row,
+ gpointer data)
+{
+ CcApplicationsPanel *self = CC_APPLICATIONS_PANEL (data);
+ g_autofree gchar *app_name = NULL;
+ g_autofree gchar *search_text = NULL;
+ const gchar *text;
+ GAppInfo *info;
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self->sidebar_search_entry));
+
+ /* Only filter after the second character */
+ if (g_utf8_strlen (text, -1) < 2)
+ return TRUE;
+
+ info = cc_applications_row_get_info (CC_APPLICATIONS_ROW (row));
+ app_name = cc_util_normalize_casefold_and_unaccent (g_app_info_get_name (info));
+ search_text = cc_util_normalize_casefold_and_unaccent (text);
+
+ return g_strstr_len (app_name, -1, search_text) != NULL;
+}
+
+#ifdef HAVE_MALCONTENT
+static void
+app_filter_changed_cb (MctAppFilter *app_filter,
+ uid_t uid,
+ CcApplicationsPanel *self)
+{
+ populate_applications (self);
+}
+#endif
+
+static void
+apps_changed (CcApplicationsPanel *self)
+{
+ populate_applications (self);
+}
+
+static void
+row_activated_cb (CcApplicationsPanel *self,
+ GtkListBoxRow *row)
+{
+ update_panel (self, row);
+ g_signal_emit_by_name (self, "sidebar-activated");
+}
+
+static void
+on_perm_store_ready (GObject *source_object,
+ GAsyncResult *res,
+ gpointer data)
+{
+ CcApplicationsPanel *self = data;
+ GDBusProxy *proxy;
+ g_autoptr(GError) error = NULL;
+
+ proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+ if (proxy == NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to connect to portal permission store: %s",
+ error->message);
+ return;
+ }
+
+ self->perm_store = proxy;
+
+ update_panel (self, gtk_list_box_get_selected_row (self->sidebar_listbox));
+}
+
+static void
+select_app (CcApplicationsPanel *self,
+ const gchar *app_id)
+{
+ GtkWidget *child;
+
+ for (child = gtk_widget_get_first_child (GTK_WIDGET (self->sidebar_listbox));
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ {
+ CcApplicationsRow *row = CC_APPLICATIONS_ROW (child);
+ GAppInfo *info = cc_applications_row_get_info (row);
+ if (g_str_has_prefix (g_app_info_get_id (info), app_id))
+ {
+ gtk_list_box_select_row (self->sidebar_listbox, GTK_LIST_BOX_ROW (row));
+ g_signal_emit_by_name (row, "activate");
+ break;
+ }
+ }
+}
+
+static void
+on_launch_button_clicked_cb (GtkButton *button,
+ CcApplicationsPanel *self)
+{
+ g_autoptr(GdkAppLaunchContext) context = NULL;
+ g_autoptr(GError) error = NULL;
+ GdkDisplay *display;
+
+ if (!self->current_app_info)
+ return;
+
+ display = gtk_widget_get_display (GTK_WIDGET (self));
+ context = gdk_display_get_app_launch_context (display);
+
+ g_app_info_launch (self->current_app_info,
+ NULL,
+ G_APP_LAUNCH_CONTEXT (context),
+ &error);
+
+ if (error)
+ g_warning ("Error launching application: %s", error->message);
+}
+
+static void
+on_sidebar_search_entry_activated_cb (CcApplicationsPanel *self)
+{
+ GtkListBoxRow *row;
+
+ row = gtk_list_box_get_row_at_y (self->sidebar_listbox, 0);
+
+ if (!row)
+ return;
+
+ /* Show the app */
+ gtk_list_box_select_row (self->sidebar_listbox, row);
+ g_signal_emit_by_name (row, "activate");
+
+ /* Cleanup the entry */
+ gtk_editable_set_text (GTK_EDITABLE (self->sidebar_search_entry), "");
+ gtk_widget_grab_focus (GTK_WIDGET (self->sidebar_search_entry));
+}
+
+static void
+on_sidebar_search_entry_search_changed_cb (CcApplicationsPanel *self)
+{
+ gtk_list_box_invalidate_filter (self->sidebar_listbox);
+}
+
+static void
+on_sidebar_search_entry_search_stopped_cb (CcApplicationsPanel *self)
+{
+ gtk_editable_set_text (GTK_EDITABLE (self->sidebar_search_entry), "");
+}
+
+static void
+cc_applications_panel_dispose (GObject *object)
+{
+ CcApplicationsPanel *self = CC_APPLICATIONS_PANEL (object);
+
+ remove_all_handler_rows (self);
+#ifdef HAVE_SNAP
+ remove_snap_permissions (self);
+#endif
+ g_clear_object (&self->monitor);
+ g_clear_object (&self->perm_store);
+
+ G_OBJECT_CLASS (cc_applications_panel_parent_class)->dispose (object);
+}
+
+static void
+cc_applications_panel_finalize (GObject *object)
+{
+ CcApplicationsPanel *self = CC_APPLICATIONS_PANEL (object);
+#ifdef HAVE_MALCONTENT
+ if (self->app_filter != NULL && self->app_filter_id != 0)
+ {
+ g_signal_handler_disconnect (self->manager, self->app_filter_id);
+ self->app_filter_id = 0;
+ }
+ g_clear_pointer (&self->app_filter, mct_app_filter_unref);
+
+ g_clear_object (&self->manager);
+#endif
+ g_clear_object (&self->notification_settings);
+ g_clear_object (&self->location_settings);
+ g_clear_object (&self->privacy_settings);
+ g_clear_object (&self->search_settings);
+
+ g_clear_object (&self->current_app_info);
+ g_clear_pointer (&self->current_app_id, g_free);
+ g_clear_pointer (&self->current_portal_app_id, g_free);
+ g_clear_pointer (&self->globs, g_hash_table_unref);
+ g_clear_pointer (&self->search_providers, g_hash_table_unref);
+
+ G_OBJECT_CLASS (cc_applications_panel_parent_class)->finalize (object);
+}
+
+static void
+cc_applications_panel_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id)
+ {
+ case PROP_PARAMETERS:
+ {
+ GVariant *parameters, *v;
+ const gchar *first_arg = NULL;
+
+ parameters = g_value_get_variant (value);
+ if (parameters == NULL)
+ return;
+
+ if (g_variant_n_children (parameters) > 0)
+ {
+ g_variant_get_child (parameters, 0, "v", &v);
+ if (g_variant_is_of_type (v, G_VARIANT_TYPE_STRING))
+ first_arg = g_variant_get_string (v, NULL);
+ else
+ g_warning ("Wrong type for the second argument GVariant, expected 's' but got '%s'",
+ (gchar *)g_variant_get_type (v));
+ g_variant_unref (v);
+
+ select_app (CC_APPLICATIONS_PANEL (object), first_arg);
+ }
+
+ return;
+ }
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+cc_applications_panel_constructed (GObject *object)
+{
+ CcApplicationsPanel *self = CC_APPLICATIONS_PANEL (object);
+ GtkListBoxRow *row;
+
+ G_OBJECT_CLASS (cc_applications_panel_parent_class)->constructed (object);
+
+ /* Select the first row */
+ row = gtk_list_box_get_row_at_index (self->sidebar_listbox, 0);
+ gtk_list_box_select_row (self->sidebar_listbox, row);
+}
+
+static GtkWidget*
+cc_applications_panel_get_sidebar_widget (CcPanel *panel)
+{
+ CcApplicationsPanel *self = CC_APPLICATIONS_PANEL (panel);
+ return GTK_WIDGET (self->sidebar_box);
+}
+
+static void
+cc_applications_panel_class_init (CcApplicationsPanelClass *klass)
+{
+ CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_applications_panel_dispose;
+ object_class->finalize = cc_applications_panel_finalize;
+ object_class->constructed = cc_applications_panel_constructed;
+ object_class->set_property = cc_applications_panel_set_property;
+
+ panel_class->get_sidebar_widget = cc_applications_panel_get_sidebar_widget;
+
+ g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters");
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/applications/cc-applications-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, app);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, app_icon_image);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, app_name_label);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, builtin);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, builtin_dialog);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, builtin_group);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, builtin_list);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, cache);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, camera);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, clear_cache_button);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, data);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, empty_box);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, handler_dialog);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, handler_file_group);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, handler_link_group);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, handler_row);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, handler_reset);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, handler_title_label);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, header_title);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, install_button);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, integration_section);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, launch_button);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, location);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, microphone);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, no_camera);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, no_location);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, no_microphone);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, no_search);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, no_sound);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, notification);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, background);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, wallpaper);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, screenshot);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, shortcuts);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, sidebar_box);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, sidebar_listbox);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, sidebar_search_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, search);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, settings_box);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, sound);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, stack);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, storage);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, storage_dialog);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, total);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, usage_section);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsPanel, view_details_button);
+
+ gtk_widget_class_bind_template_callback (widget_class, camera_cb);
+ gtk_widget_class_bind_template_callback (widget_class, location_cb);
+ gtk_widget_class_bind_template_callback (widget_class, microphone_cb);
+ gtk_widget_class_bind_template_callback (widget_class, search_cb);
+ gtk_widget_class_bind_template_callback (widget_class, notification_cb);
+ gtk_widget_class_bind_template_callback (widget_class, background_cb);
+ gtk_widget_class_bind_template_callback (widget_class, wallpaper_cb);
+ gtk_widget_class_bind_template_callback (widget_class, screenshot_cb);
+ gtk_widget_class_bind_template_callback (widget_class, shortcuts_cb);
+ gtk_widget_class_bind_template_callback (widget_class, privacy_link_cb);
+ gtk_widget_class_bind_template_callback (widget_class, sound_cb);
+ gtk_widget_class_bind_template_callback (widget_class, clear_cache_cb);
+ gtk_widget_class_bind_template_callback (widget_class, open_software_cb);
+ gtk_widget_class_bind_template_callback (widget_class, handler_reset_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_builtin_row_activated_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_handler_row_activated_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_launch_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_sidebar_search_entry_activated_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_sidebar_search_entry_search_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_sidebar_search_entry_search_stopped_cb);
+
+ gtk_widget_class_bind_template_callback (widget_class, on_storage_row_activated_cb);}
+
+static void
+cc_applications_panel_init (CcApplicationsPanel *self)
+{
+#ifdef HAVE_MALCONTENT
+ g_autoptr(GDBusConnection) system_bus = NULL;
+ g_autoptr(GError) error = NULL;
+#endif
+
+ g_resources_register (cc_applications_get_resource ());
+
+ g_type_ensure(CC_TYPE_TOGGLE_ROW);
+ g_type_ensure(CC_TYPE_INFO_ROW);
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ gtk_widget_set_visible (GTK_WIDGET (self->install_button), gnome_software_is_installed ());
+
+ g_signal_connect_object (self->sidebar_listbox, "row-activated",
+ G_CALLBACK (row_activated_cb), self, G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self->view_details_button,
+ "clicked",
+ G_CALLBACK (open_software_cb),
+ self,
+ G_CONNECT_SWAPPED);
+
+ gtk_list_box_set_sort_func (self->sidebar_listbox,
+ compare_rows,
+ NULL, NULL);
+
+ gtk_list_box_set_filter_func (self->sidebar_listbox,
+ filter_sidebar_rows,
+ self, NULL);
+
+ self->location_settings = g_settings_new ("org.gnome.system.location");
+ self->privacy_settings = g_settings_new ("org.gnome.desktop.privacy");
+ self->search_settings = g_settings_new ("org.gnome.desktop.search-providers");
+#ifdef HAVE_MALCONTENT
+ /* FIXME: should become asynchronous */
+ system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, self->cancellable, &error);
+ if (system_bus == NULL)
+ {
+ g_warning ("Error getting system bus while setting up app permissions: %s", error->message);
+ return;
+ }
+
+ /* Load the user’s parental controls settings too, so we can filter the list. */
+ self->manager = mct_manager_new (system_bus);
+ self->app_filter = mct_manager_get_app_filter (self->manager,
+ getuid (),
+ MCT_GET_APP_FILTER_FLAGS_NONE,
+ self->cancellable,
+ &error);
+ if (error)
+ {
+ g_warning ("Error retrieving app filter: %s", error->message);
+ return;
+ }
+
+ self->app_filter_id = g_signal_connect (self->manager, "app-filter-changed",
+ G_CALLBACK (app_filter_changed_cb), self);
+#endif
+ populate_applications (self);
+
+ self->monitor = g_app_info_monitor_get ();
+ self->monitor_id = g_signal_connect_object (self->monitor, "changed", G_CALLBACK (apps_changed), self, G_CONNECT_SWAPPED);
+
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.freedesktop.impl.portal.PermissionStore",
+ "/org/freedesktop/impl/portal/PermissionStore",
+ "org.freedesktop.impl.portal.PermissionStore",
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ on_perm_store_ready,
+ self);
+
+ self->globs = parse_globs ();
+ self->search_providers = parse_search_providers ();
+}
diff --git a/panels/applications/cc-applications-panel.h b/panels/applications/cc-applications-panel.h
new file mode 100644
index 0000000..c6c8882
--- /dev/null
+++ b/panels/applications/cc-applications-panel.h
@@ -0,0 +1,30 @@
+/* cc-applications-panel.h
+ *
+ * Copyright 2018 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_APPLICATIONS_PANEL (cc_applications_panel_get_type())
+G_DECLARE_FINAL_TYPE (CcApplicationsPanel, cc_applications_panel, CC, APPLICATIONS_PANEL, CcPanel)
+
+G_END_DECLS
diff --git a/panels/applications/cc-applications-panel.ui b/panels/applications/cc-applications-panel.ui
new file mode 100644
index 0000000..f054fbf
--- /dev/null
+++ b/panels/applications/cc-applications-panel.ui
@@ -0,0 +1,465 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcApplicationsPanel" parent="CcPanel">
+
+ <child type="titlebar">
+ <object class="AdwHeaderBar">
+ <property name="show-end-title-buttons">True</property>
+ <property name="show-start-title-buttons">False</property>
+ <child type="start">
+ <object class="GtkButton">
+ <property name="visible" bind-source="CcApplicationsPanel" bind-property="folded" bind-flags="default|sync-create" />
+ <property name="icon-name">go-previous-symbolic</property>
+ <property name="action-name">window.navigate</property>
+ <property name="action-target">0</property> <!-- 0: ADW_NAVIGATION_DIRECTION_BACK -->
+ </object>
+ </child>
+ <property name="title-widget">
+ <object class="AdwWindowTitle" id="header_title">
+ <property name="title" translatable="yes">Applications</property>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child type="content">
+ <object class="GtkStack" id="stack">
+
+ <child>
+ <object class="AdwStatusPage" id="empty_box">
+ <property name="icon-name">org.gnome.Software-symbolic</property>
+ <property name="title" translatable="yes">No applications</property>
+ <child>
+ <object class="GtkButton" id="install_button">
+ <property name="label" translatable="yes">Install some…</property>
+ <property name="halign">center</property>
+ <signal name="clicked" handler="open_software_cb" object="CcApplicationsPanel" swapped="yes"/>
+ <style>
+ <class name="pill" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesPage" id="settings_box">
+
+ <!-- App icon & buttons -->
+ <child>
+ <object class="AdwPreferencesGroup">
+
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">18</property>
+ <child>
+ <object class="GtkImage" id="app_icon_image">
+ <property name="icon-name">org.gnome.Software</property>
+ <property name="pixel-size">96</property>
+ <style>
+ <class name="icon-dropshadow" />
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="app_name_label">
+ <property name="wrap">True</property>
+ <style>
+ <class name="title" />
+ <class name="title-1" />
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkBox">
+ <property name="halign">center</property>
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="spacing">18</property>
+ <child>
+ <object class="GtkButton" id="launch_button">
+ <property name="label" translatable="yes">Open</property>
+ <signal name="clicked" handler="on_launch_button_clicked_cb" object="CcApplicationsPanel" swapped="no" />
+ <style>
+ <class name="pill" />
+ <class name="suggested-action" />
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="view_details_button">
+ <property name="label" translatable="yes">View Details</property>
+ <style>
+ <class name="pill" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup" id="integration_section">
+ <child>
+ <object class="CcToggleRow" id="search">
+ <property name="title" translatable="yes">Search</property>
+ <property name="subtitle" translatable="yes">Receive system searches and send results.</property>
+ <signal name="notify::allowed" handler="search_cb" object="CcApplicationsPanel" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="CcInfoRow" id="no_search">
+ <property name="title" translatable="yes">Search</property>
+ <property name="subtitle" translatable="yes">Receive system searches and send results.</property>
+ <property name="info" translatable="yes">Disabled</property>
+ </object>
+ </child>
+ <child>
+ <object class="CcToggleRow" id="notification">
+ <property name="title" translatable="yes">Notifications</property>
+ <property name="subtitle" translatable="yes">Show system notifications.</property>
+ <signal name="notify::allowed" handler="notification_cb" object="CcApplicationsPanel" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="CcToggleRow" id="background">
+ <property name="title" translatable="yes">Run in Background</property>
+ <property name="subtitle" translatable="yes">Allow activity when the app is closed.</property>
+ <signal name="notify::allowed" handler="background_cb" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="CcToggleRow" id="screenshot">
+ <property name="title" translatable="yes">Screenshots</property>
+ <property name="subtitle" translatable="yes">Take pictures of the screen at any time.</property>
+ <signal name="notify::allowed" handler="screenshot_cb" object="CcApplicationsPanel" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="CcToggleRow" id="wallpaper">
+ <property name="title" translatable="yes">Change Wallpaper</property>
+ <property name="subtitle" translatable="yes">Change the desktop wallpaper.</property>
+ <signal name="notify::allowed" handler="wallpaper_cb" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="CcToggleRow" id="sound">
+ <property name="title" translatable="yes">Sounds</property>
+ <property name="subtitle" translatable="yes">Reproduce sounds.</property>
+ <signal name="notify::allowed" handler="sound_cb" object="CcApplicationsPanel" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="CcInfoRow" id="no_sound">
+ <property name="title" translatable="yes">Sounds</property>
+ <property name="subtitle" translatable="yes">Reproduce sounds.</property>
+ <property name="info" translatable="yes">Disabled</property>
+ </object>
+ </child>
+ <child>
+ <object class="CcToggleRow" id="shortcuts">
+ <property name="title" translatable="yes">Inhibit Shortcuts</property>
+ <property name="subtitle" translatable="yes">Block standard keyboard shortcuts.</property>
+ <signal name="notify::allowed" handler="shortcuts_cb" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="CcToggleRow" id="camera">
+ <property name="title" translatable="yes">Camera</property>
+ <property name="subtitle" translatable="yes">Take pictures with the camera.</property>
+ <signal name="notify::allowed" handler="camera_cb" object="CcApplicationsPanel" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="CcInfoRow" id="no_camera">
+ <property name="title" translatable="yes">Camera</property>
+ <property name="subtitle" translatable="yes">Take pictures with the camera.</property>
+ <property name="info" translatable="yes">Disabled</property>
+ </object>
+ </child>
+ <child>
+ <object class="CcToggleRow" id="microphone">
+ <property name="title" translatable="yes">Microphone</property>
+ <property name="subtitle" translatable="yes">Record audio with the microphone.</property>
+ <signal name="notify::allowed" handler="microphone_cb" object="CcApplicationsPanel" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="CcInfoRow" id="no_microphone">
+ <property name="title" translatable="yes">Microphone</property>
+ <property name="subtitle" translatable="yes">Record audio with the microphone.</property>
+ <property name="info" translatable="yes">Disabled</property>
+ </object>
+ </child>
+ <child>
+ <object class="CcToggleRow" id="location">
+ <property name="title" translatable="yes">Location Services</property>
+ <property name="subtitle" translatable="yes">Access device location data.</property>
+ <signal name="notify::allowed" handler="location_cb" object="CcApplicationsPanel" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="CcInfoRow" id="no_location">
+ <property name="title" translatable="yes">Location Services</property>
+ <property name="subtitle" translatable="yes">Access device location data.</property>
+ <property name="info" translatable="yes">Disabled</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup" id="usage_section">
+ <child>
+ <object class="CcInfoRow" id="builtin">
+ <property name="title" translatable="yes">Built-in Permissions</property>
+ <property name="subtitle" translatable="yes">System access that is required by the app</property>
+ <property name="has-expander">True</property>
+ <property name="is-link">True</property>
+ <signal name="activated" handler="on_builtin_row_activated_cb" object="CcApplicationsPanel" swapped="no" />
+ </object>
+ </child>
+ <child>
+ <object class="CcInfoRow" id="handler_row">
+ <property name="title" translatable="yes">File &amp;amp; Link Associations</property>
+ <property name="has-expander">True</property>
+ <property name="is-link">True</property>
+ <signal name="activated" handler="on_handler_row_activated_cb" object="CcApplicationsPanel" swapped="no" />
+ </object>
+ </child>
+ <child>
+ <object class="CcInfoRow" id="storage">
+ <property name="title" translatable="yes">Storage</property>
+ <property name="has-expander">1</property>
+ <property name="is-link">1</property>
+ <signal name="activated" handler="on_storage_row_activated_cb" object="CcApplicationsPanel" swapped="no" />
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+
+ <!-- Sidebar -->
+ <object class="GtkBox" id="sidebar_box">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkSearchEntry" id="sidebar_search_entry">
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <signal name="activate" handler="on_sidebar_search_entry_activated_cb" object="CcApplicationsPanel" swapped="yes" />
+ <signal name="search-changed" handler="on_sidebar_search_entry_search_changed_cb" object="CcApplicationsPanel" swapped="yes" />
+ <signal name="stop-search" handler="on_sidebar_search_entry_search_stopped_cb" object="CcApplicationsPanel" swapped="yes" />
+ </object>
+ </child>
+ <child>
+ <object class="GtkListBox" id="sidebar_listbox">
+ <property name="vexpand">True</property>
+ <property name="selection-mode">browse</property>
+ <style>
+ <class name="navigation-sidebar" />
+ </style>
+
+ <child type="placeholder">
+ <object class="GtkBox" id="empty_search_placeholder">
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="margin-top">18</property>
+ <property name="margin-bottom">18</property>
+ <property name="margin-start">18</property>
+ <property name="margin-end">18</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkImage">
+ <property name="can_focus">False</property>
+ <property name="pixel_size">64</property>
+ <property name="icon_name">edit-find-symbolic</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">No results found</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ <attribute name="scale" value="1.44"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Try a different search</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+
+ <!-- Built-in Permissions dialog -->
+ <object class="GtkDialog" id="builtin_dialog">
+ <property name="title" translatable="yes">Built-in Permissions</property>
+ <property name="modal">1</property>
+ <property name="use-header-bar">1</property>
+ <property name="resizable">True</property>
+ <property name="hide-on-close">True</property>
+ <child>
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup" id="builtin_group">
+ <child>
+ <object class="GtkListBox" id="builtin_list">
+ <property name="selection-mode">none</property>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+
+ <!-- File & Link handlers dialog -->
+ <object class="GtkDialog" id="handler_dialog">
+ <property name="title" translatable="yes">File &amp; Link Associations</property>
+ <property name="modal">1</property>
+ <property name="use-header-bar">1</property>
+ <property name="resizable">True</property>
+ <property name="hide-on-close">True</property>
+ <property name="default-width">500</property>
+ <property name="default-height">400</property>
+ <child>
+ <object class="AdwPreferencesPage">
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="GtkLabel" id="handler_title_label">
+ <property name="wrap">True</property>
+ <property name="xalign">0.0</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup" id="handler_file_group">
+ <property name="title" translatable="yes">File Types</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup" id="handler_link_group">
+ <property name="title" translatable="yes">Link Types</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="GtkButton" id="handler_reset">
+ <property name="valign">center</property>
+ <property name="margin-top">12</property>
+ <property name="label" translatable="yes">Reset</property>
+ <signal name="clicked" handler="handler_reset_cb" object="CcApplicationsPanel" swapped="yes"/>
+ <style>
+ <class name="destructive-action" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+
+ <!-- Storage dialog -->
+ <object class="GtkDialog" id="storage_dialog">
+ <property name="title" translatable="yes">Storage</property>
+ <property name="modal">1</property>
+ <property name="use-header-bar">1</property>
+ <property name="resizable">True</property>
+ <property name="hide-on-close">True</property>
+ <property name="default-width">420</property>
+ <property name="default-height">420</property>
+ <child>
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="description" translatable="yes">How much disk space this application is occupying with app data and caches.</property>
+ <child>
+ <object class="CcInfoRow" id="app">
+ <property name="title" translatable="yes">Application</property>
+ <property name="info">Unknown</property>
+ </object>
+ </child>
+ <child>
+ <object class="CcInfoRow" id="data">
+ <property name="title" translatable="yes">Data</property>
+ <property name="info">Unknown</property>
+ </object>
+ </child>
+ <child>
+ <object class="CcInfoRow" id="cache">
+ <property name="title" translatable="yes">Cache</property>
+ <property name="info">Unknown</property>
+ </object>
+ </child>
+ <child>
+ <object class="CcInfoRow" id="total">
+ <property name="title" translatable="yes">&lt;b&gt;Total&lt;/b&gt;</property>
+ <property name="info">Unknown</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="GtkButton" id="clear_cache_button">
+ <property name="label" translatable="yes">Clear Cache…</property>
+ <signal name="clicked" handler="clear_cache_cb" object="CcApplicationsPanel" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+
+ <object class="GtkSizeGroup">
+ <property name="mode">horizontal</property>
+ <widgets>
+ <widget name="launch_button" />
+ <widget name="view_details_button" />
+ </widgets>
+ </object>
+</interface>
diff --git a/panels/applications/cc-applications-row.c b/panels/applications/cc-applications-row.c
new file mode 100644
index 0000000..db1d4b5
--- /dev/null
+++ b/panels/applications/cc-applications-row.c
@@ -0,0 +1,108 @@
+/* cc-applications-row.c
+ *
+ * Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+
+#include "cc-applications-row.h"
+#include "cc-applications-resources.h"
+
+struct _CcApplicationsRow
+{
+ GtkListBoxRow parent;
+
+ GAppInfo *info;
+ gchar *sortkey;
+
+ GtkWidget *box;
+ GtkWidget *image;
+ GtkWidget *label;
+};
+
+G_DEFINE_TYPE (CcApplicationsRow, cc_applications_row, GTK_TYPE_LIST_BOX_ROW)
+
+static void
+cc_applications_row_finalize (GObject *object)
+{
+ CcApplicationsRow *self = CC_APPLICATIONS_ROW (object);
+
+ g_object_unref (self->info);
+ g_free (self->sortkey);
+
+ G_OBJECT_CLASS (cc_applications_row_parent_class)->finalize (object);
+}
+
+static void
+cc_applications_row_class_init (CcApplicationsRowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = cc_applications_row_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/applications/cc-applications-row.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsRow, box);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsRow, image);
+ gtk_widget_class_bind_template_child (widget_class, CcApplicationsRow, label);
+}
+
+static void
+cc_applications_row_init (CcApplicationsRow *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+CcApplicationsRow *
+cc_applications_row_new (GAppInfo *info)
+{
+ CcApplicationsRow *self;
+ g_autofree gchar *key = NULL;
+ GIcon *icon;
+
+ self = g_object_new (CC_TYPE_APPLICATIONS_ROW, NULL);
+
+ self->info = g_object_ref (info);
+
+ key = g_utf8_casefold (g_app_info_get_display_name (info), -1);
+ self->sortkey = g_utf8_collate_key (key, -1);
+
+ icon = g_app_info_get_icon (info);
+ if (icon != NULL)
+ gtk_image_set_from_gicon (GTK_IMAGE (self->image), g_app_info_get_icon (info));
+ else
+ gtk_image_set_from_icon_name (GTK_IMAGE (self->image), "application-x-executable");
+
+ gtk_label_set_label (GTK_LABEL (self->label), g_app_info_get_display_name (info));
+
+ return self;
+}
+
+GAppInfo *
+cc_applications_row_get_info (CcApplicationsRow *self)
+{
+ return self->info;
+}
+
+const gchar *
+cc_applications_row_get_sort_key (CcApplicationsRow *self)
+{
+ return self->sortkey;
+}
diff --git a/panels/applications/cc-applications-row.h b/panels/applications/cc-applications-row.h
new file mode 100644
index 0000000..7ca44e1
--- /dev/null
+++ b/panels/applications/cc-applications-row.h
@@ -0,0 +1,36 @@
+/* cc-applications-row.h
+ *
+ * Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_APPLICATIONS_ROW (cc_applications_row_get_type())
+G_DECLARE_FINAL_TYPE (CcApplicationsRow, cc_applications_row, CC, APPLICATIONS_ROW, GtkListBoxRow)
+
+CcApplicationsRow* cc_applications_row_new (GAppInfo *info);
+
+GAppInfo* cc_applications_row_get_info (CcApplicationsRow *row);
+
+const gchar* cc_applications_row_get_sort_key (CcApplicationsRow *row);
+
+G_END_DECLS
diff --git a/panels/applications/cc-applications-row.ui b/panels/applications/cc-applications-row.ui
new file mode 100644
index 0000000..5bd6e09
--- /dev/null
+++ b/panels/applications/cc-applications-row.ui
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcApplicationsRow" parent="GtkListBoxRow">
+ <child>
+ <object class="GtkBox" id="box">
+ <property name="margin-top">6</property>
+ <property name="margin-bottom">6</property>
+ <property name="margin-start">6</property>
+ <property name="margin-end">6</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkImage" id="image">
+ <property name="pixel-size">32</property>
+ <style>
+ <class name="lowres-icon"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label">
+ <property name="xalign">0</property>
+ <property name="ellipsize">end</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/applications/cc-info-row.c b/panels/applications/cc-info-row.c
new file mode 100644
index 0000000..6dcff98
--- /dev/null
+++ b/panels/applications/cc-info-row.c
@@ -0,0 +1,187 @@
+/* cc-info-row.c
+ *
+ * Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+
+#include "cc-info-row.h"
+#include "cc-applications-resources.h"
+
+struct _CcInfoRow
+{
+ AdwActionRow parent;
+
+ GtkWidget *info;
+ GtkWidget *expander;
+
+ gboolean expanded;
+ gboolean link;
+};
+
+G_DEFINE_TYPE (CcInfoRow, cc_info_row, ADW_TYPE_ACTION_ROW)
+
+enum
+{
+ PROP_0,
+ PROP_INFO,
+ PROP_HAS_EXPANDER,
+ PROP_IS_LINK,
+ PROP_EXPANDED
+};
+
+static void
+cc_info_row_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcInfoRow *row = CC_INFO_ROW (object);
+
+ switch (prop_id)
+ {
+ case PROP_INFO:
+ g_value_set_string (value, gtk_label_get_label (GTK_LABEL (row->info)));
+ break;
+ case PROP_HAS_EXPANDER:
+ g_value_set_boolean (value, gtk_widget_get_visible (row->expander));
+ break;
+ case PROP_IS_LINK:
+ g_value_set_boolean (value, row->link);
+ break;
+ case PROP_EXPANDED:
+ g_value_set_boolean (value, cc_info_row_get_expanded (row));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+update_expander (CcInfoRow *row)
+{
+ if (row->link)
+ gtk_image_set_from_icon_name (GTK_IMAGE (row->expander), "go-next-symbolic");
+ else if (row->expanded)
+ gtk_image_set_from_icon_name (GTK_IMAGE (row->expander), "pan-down-symbolic");
+ else
+ gtk_image_set_from_icon_name (GTK_IMAGE (row->expander), "pan-end-symbolic");
+}
+
+static void
+cc_info_row_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcInfoRow *row = CC_INFO_ROW (object);
+
+ switch (prop_id)
+ {
+ case PROP_INFO:
+ gtk_label_set_label (GTK_LABEL (row->info), g_value_get_string (value));
+ break;
+
+ case PROP_HAS_EXPANDER:
+ gtk_widget_set_visible (row->expander, g_value_get_boolean (value));
+ gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), g_value_get_boolean (value));
+ break;
+
+ case PROP_IS_LINK:
+ row->link = g_value_get_boolean (value);
+ update_expander (row);
+ break;
+
+ case PROP_EXPANDED:
+ cc_info_row_set_expanded (row, g_value_get_boolean (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_info_row_class_init (CcInfoRowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->get_property = cc_info_row_get_property;
+ object_class->set_property = cc_info_row_set_property;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/applications/cc-info-row.ui");
+
+ g_object_class_install_property (object_class,
+ PROP_INFO,
+ g_param_spec_string ("info", "info", "info",
+ NULL, G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_HAS_EXPANDER,
+ g_param_spec_boolean ("has-expander", "has-expander", "has-expander",
+ FALSE, G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_EXPANDED,
+ g_param_spec_boolean ("expanded", "expanded", "expanded",
+ FALSE, G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_IS_LINK,
+ g_param_spec_boolean ("is-link", "is-link", "is-link",
+ FALSE, G_PARAM_READWRITE));
+
+ gtk_widget_class_bind_template_child (widget_class, CcInfoRow, info);
+ gtk_widget_class_bind_template_child (widget_class, CcInfoRow, expander);
+}
+
+static void
+cc_info_row_init (CcInfoRow *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+CcInfoRow *
+cc_info_row_new (void)
+{
+ return CC_INFO_ROW (g_object_new (CC_TYPE_INFO_ROW, NULL));
+}
+
+gboolean
+cc_info_row_get_expanded (CcInfoRow *row)
+{
+ return row->expanded;
+}
+
+void
+cc_info_row_set_expanded (CcInfoRow *row,
+ gboolean expanded)
+{
+ if (row->expanded == expanded)
+ return;
+
+ row->expanded = expanded;
+ update_expander (row);
+
+ g_object_notify (G_OBJECT (row), "expanded");
+}
+
diff --git a/panels/applications/cc-info-row.h b/panels/applications/cc-info-row.h
new file mode 100644
index 0000000..f1376dc
--- /dev/null
+++ b/panels/applications/cc-info-row.h
@@ -0,0 +1,37 @@
+/* cc-info-row.h
+ *
+ * Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <adwaita.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_INFO_ROW (cc_info_row_get_type())
+G_DECLARE_FINAL_TYPE (CcInfoRow, cc_info_row, CC, INFO_ROW, AdwActionRow)
+
+CcInfoRow* cc_info_row_new (void);
+
+void cc_info_row_set_expanded (CcInfoRow *row,
+ gboolean expanded);
+
+gboolean cc_info_row_get_expanded (CcInfoRow *row);
+
+G_END_DECLS
diff --git a/panels/applications/cc-info-row.ui b/panels/applications/cc-info-row.ui
new file mode 100644
index 0000000..d5c9215
--- /dev/null
+++ b/panels/applications/cc-info-row.ui
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcInfoRow" parent="AdwActionRow">
+ <child>
+ <object class="GtkLabel" id="info">
+ <property name="valign">center</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage" id="expander">
+ <property name="visible">False</property>
+ <property name="valign">center</property>
+ <property name="icon-name">pan-end-symbolic</property>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/applications/cc-snap-row.c b/panels/applications/cc-snap-row.c
new file mode 100644
index 0000000..5928ad3
--- /dev/null
+++ b/panels/applications/cc-snap-row.c
@@ -0,0 +1,314 @@
+/* cc-snap-row.c
+ *
+ * Copyright 2019 Canonical Ltd.
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+
+#include "cc-snap-row.h"
+#include "cc-applications-resources.h"
+
+struct _CcSnapRow
+{
+ AdwActionRow parent;
+
+ GtkSwitch *slot_toggle;
+ GtkComboBox *slots_combo;
+ GtkListStore *slots_combo_model;
+
+ GCancellable *cancellable;
+
+ SnapdPlug *plug;
+ SnapdSlot *connected_slot;
+ GPtrArray *slots;
+};
+
+G_DEFINE_TYPE (CcSnapRow, cc_snap_row, ADW_TYPE_ACTION_ROW)
+
+typedef struct
+{
+ CcSnapRow *self;
+ SnapdSlot *slot;
+} ConnectData;
+
+static void
+update_state (CcSnapRow *self)
+{
+ gboolean have_single_option;
+ GtkTreeIter iter;
+
+ have_single_option = self->slots->len == 1;
+ gtk_widget_set_visible (GTK_WIDGET (self->slot_toggle), have_single_option);
+ gtk_widget_set_visible (GTK_WIDGET (self->slots_combo), !have_single_option);
+
+ gtk_switch_set_active (self->slot_toggle, self->connected_slot != NULL);
+
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->slots_combo_model), &iter))
+ {
+ do
+ {
+ SnapdSlot *slot;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (self->slots_combo_model), &iter, 0, &slot, -1);
+ if (slot == self->connected_slot)
+ gtk_combo_box_set_active_iter (self->slots_combo, &iter);
+ } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->slots_combo_model), &iter));
+ }
+}
+
+static void
+disable_controls (CcSnapRow *self)
+{
+ gtk_widget_set_sensitive (GTK_WIDGET (self->slot_toggle), FALSE);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->slots_combo), FALSE);
+}
+
+static void
+enable_controls (CcSnapRow *self)
+{
+ gtk_widget_set_sensitive (GTK_WIDGET (self->slot_toggle), TRUE);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->slots_combo), TRUE);
+}
+
+static ConnectData *
+connect_data_new (CcSnapRow *self, SnapdSlot *slot)
+{
+ ConnectData *data;
+
+ data = g_new0 (ConnectData, 1);
+ data->self = self;
+ data->slot = g_object_ref (slot);
+
+ return data;
+}
+
+static void
+connect_data_free (ConnectData *data)
+{
+ g_clear_object (&data->slot);
+ g_free (data);
+}
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (ConnectData, connect_data_free)
+
+static void
+connect_interface_cb (GObject *client, GAsyncResult *result, gpointer user_data)
+{
+ g_autoptr(ConnectData) data = user_data;
+ CcSnapRow *self = data->self;
+ SnapdSlot *slot = data->slot;
+ g_autoptr(GError) error = NULL;
+
+ if (snapd_client_connect_interface_finish (SNAPD_CLIENT (client), result, &error))
+ {
+ g_clear_object (&self->connected_slot);
+ self->connected_slot = g_object_ref (slot);
+ }
+ else
+ {
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+ g_warning ("Failed to connect interface: %s", error->message);
+ }
+
+ update_state (self);
+ enable_controls (self);
+}
+
+static void
+connect_plug (CcSnapRow *self, SnapdSlot *slot)
+{
+ g_autoptr(SnapdClient) client = NULL;
+
+ /* already connected */
+ if (self->connected_slot == slot)
+ return;
+
+ disable_controls (self);
+
+ client = snapd_client_new ();
+ snapd_client_connect_interface_async (client,
+ snapd_plug_get_snap (self->plug), snapd_plug_get_name (self->plug),
+ snapd_slot_get_snap (slot), snapd_slot_get_name (slot),
+ NULL, NULL,
+ self->cancellable,
+ connect_interface_cb, connect_data_new (self, slot));
+}
+
+static void
+disconnect_interface_cb (GObject *client, GAsyncResult *result, gpointer user_data)
+{
+ CcSnapRow *self = user_data;
+ g_autoptr(GError) error = NULL;
+
+ if (snapd_client_disconnect_interface_finish (SNAPD_CLIENT (client), result, &error))
+ {
+ g_clear_object (&self->connected_slot);
+ }
+ else
+ {
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+ g_warning ("Failed to disconnect interface: %s", error->message);
+ }
+
+ update_state (self);
+ enable_controls (self);
+}
+
+static void
+disconnect_plug (CcSnapRow *self)
+{
+ g_autoptr(SnapdClient) client = NULL;
+
+ /* already disconnected */
+ if (self->connected_slot == NULL)
+ return;
+
+ disable_controls (self);
+
+ client = snapd_client_new ();
+ snapd_client_disconnect_interface_async (client,
+ snapd_plug_get_snap (self->plug), snapd_plug_get_name (self->plug),
+ NULL, NULL,
+ NULL, NULL,
+ self->cancellable,
+ disconnect_interface_cb, self);
+}
+
+static void
+switch_changed_cb (CcSnapRow *self)
+{
+ if (gtk_switch_get_active (self->slot_toggle))
+ {
+ if (self->slots->len == 1)
+ connect_plug (self, g_ptr_array_index (self->slots, 0));
+ }
+ else
+ {
+ disconnect_plug (self);
+ }
+}
+
+static void
+combo_changed_cb (CcSnapRow *self)
+{
+ GtkTreeIter iter;
+ SnapdSlot *slot = NULL;
+
+ if (!gtk_combo_box_get_active_iter (self->slots_combo, &iter))
+ return;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (self->slots_combo_model), &iter, 0, &slot, -1);
+ if (slot != NULL)
+ connect_plug (self, slot);
+ else
+ disconnect_plug (self);
+}
+
+static void
+cc_snap_row_finalize (GObject *object)
+{
+ CcSnapRow *self = CC_SNAP_ROW (object);
+
+ g_clear_object (&self->cancellable);
+ g_clear_object (&self->plug);
+ g_clear_pointer (&self->slots, g_ptr_array_unref);
+
+ G_OBJECT_CLASS (cc_snap_row_parent_class)->finalize (object);
+}
+
+static void
+cc_snap_row_class_init (CcSnapRowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = cc_snap_row_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/applications/cc-snap-row.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcSnapRow, slot_toggle);
+ gtk_widget_class_bind_template_child (widget_class, CcSnapRow, slots_combo);
+ gtk_widget_class_bind_template_child (widget_class, CcSnapRow, slots_combo_model);
+
+ gtk_widget_class_bind_template_callback (widget_class, combo_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, switch_changed_cb);
+}
+
+static void
+cc_snap_row_init (CcSnapRow *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+CcSnapRow *
+cc_snap_row_new (GCancellable *cancellable, SnapdInterface *interface, SnapdPlug *plug, GPtrArray *slots)
+{
+ CcSnapRow *self;
+ GPtrArray *connected_slots;
+ g_autofree gchar *label = NULL;
+ GtkTreeIter iter;
+
+ g_return_val_if_fail (SNAPD_IS_PLUG (plug), NULL);
+
+ self = CC_SNAP_ROW (g_object_new (CC_TYPE_SNAP_ROW, NULL));
+
+ self->cancellable = g_object_ref (cancellable);
+ self->plug = g_object_ref (plug);
+ self->slots = g_ptr_array_ref (slots);
+
+ connected_slots = snapd_plug_get_connected_slots (plug);
+ if (connected_slots->len > 0)
+ {
+ SnapdSlotRef *connected_slot_ref = g_ptr_array_index (connected_slots, 0);
+
+ for (int i = 0; i < slots->len; i++)
+ {
+ SnapdSlot *slot = g_ptr_array_index (slots, i);
+
+ if (g_strcmp0 (snapd_slot_get_snap (slot), snapd_slot_ref_get_snap (connected_slot_ref)) == 0 &&
+ g_strcmp0 (snapd_slot_get_name (slot), snapd_slot_ref_get_slot (connected_slot_ref)) == 0)
+ self->connected_slot = slot;
+ }
+ }
+
+ if (interface != NULL)
+ label = snapd_interface_make_label (interface);
+ else
+ label = g_strdup (snapd_plug_get_interface (plug));
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self), label);
+
+ /* Add option into combo box */
+ gtk_list_store_append (self->slots_combo_model, &iter);
+ gtk_list_store_set (self->slots_combo_model, &iter, 1, "--", -1);
+ for (int i = 0; i < slots->len; i++)
+ {
+ SnapdSlot *slot = g_ptr_array_index (slots, i);
+ g_autofree gchar *label = NULL;
+
+ label = g_strdup_printf ("%s:%s", snapd_slot_get_snap (slot), snapd_slot_get_name (slot));
+ gtk_list_store_append (self->slots_combo_model, &iter);
+ gtk_list_store_set (self->slots_combo_model, &iter, 0, slot, 1, label, -1);
+ }
+
+ update_state (self);
+
+ return self;
+}
diff --git a/panels/applications/cc-snap-row.h b/panels/applications/cc-snap-row.h
new file mode 100644
index 0000000..1121413
--- /dev/null
+++ b/panels/applications/cc-snap-row.h
@@ -0,0 +1,36 @@
+/* cc-snap-row.h
+ *
+ * Copyright 2019 Canonical Ltd.
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <adwaita.h>
+#include <snapd-glib/snapd-glib.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_SNAP_ROW (cc_snap_row_get_type())
+G_DECLARE_FINAL_TYPE (CcSnapRow, cc_snap_row, CC, SNAP_ROW, AdwActionRow)
+
+CcSnapRow* cc_snap_row_new (GCancellable *cancellable,
+ SnapdInterface *interface,
+ SnapdPlug *plug,
+ GPtrArray *slots);
+
+G_END_DECLS
diff --git a/panels/applications/cc-snap-row.ui b/panels/applications/cc-snap-row.ui
new file mode 100644
index 0000000..fed545f
--- /dev/null
+++ b/panels/applications/cc-snap-row.ui
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <object class="GtkListStore" id="slots_combo_model">
+ <columns>
+ <!-- column-name slot -->
+ <column type="GObject"/>
+ <!-- column-name label -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <template class="CcSnapRow" parent="AdwActionRow">
+ <property name="can-focus">True</property>
+ <property name="activatable">False</property>
+ <child>
+ <object class="GtkSwitch" id="slot_toggle">
+ <property name="valign">center</property>
+ <signal name="notify::active" handler="switch_changed_cb" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="slots_combo">
+ <property name="valign">center</property>
+ <property name="model">slots_combo_model</property>
+ <signal name="changed" handler="combo_changed_cb" swapped="yes"/>
+ <child>
+ <object class="GtkCellRendererText">
+ <property name="ellipsize">end</property>
+ </object>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/applications/cc-toggle-row.c b/panels/applications/cc-toggle-row.c
new file mode 100644
index 0000000..e51c73c
--- /dev/null
+++ b/panels/applications/cc-toggle-row.c
@@ -0,0 +1,130 @@
+/* cc-toggle-row.c
+ *
+ * Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+
+#include "cc-toggle-row.h"
+#include "cc-applications-resources.h"
+
+struct _CcToggleRow
+{
+ AdwActionRow parent;
+
+ GtkWidget *toggle;
+};
+
+G_DEFINE_TYPE (CcToggleRow, cc_toggle_row, ADW_TYPE_ACTION_ROW)
+
+enum
+{
+ PROP_0,
+ PROP_ALLOWED
+};
+
+static void
+changed_cb (CcToggleRow *row)
+{
+ g_object_notify (G_OBJECT (row), "allowed");
+}
+
+static void
+cc_toggle_row_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcToggleRow *row = CC_TOGGLE_ROW (object);
+
+ switch (prop_id)
+ {
+ case PROP_ALLOWED:
+ g_value_set_boolean (value, cc_toggle_row_get_allowed (row));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_toggle_row_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcToggleRow *row = CC_TOGGLE_ROW (object);
+
+ switch (prop_id)
+ {
+ case PROP_ALLOWED:
+ cc_toggle_row_set_allowed (row, g_value_get_boolean (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_toggle_row_class_init (CcToggleRowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->get_property = cc_toggle_row_get_property;
+ object_class->set_property = cc_toggle_row_set_property;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/applications/cc-toggle-row.ui");
+
+ g_object_class_install_property (object_class,
+ PROP_ALLOWED,
+ g_param_spec_boolean ("allowed", "allowed", "allowed",
+ FALSE, G_PARAM_READWRITE));
+
+ gtk_widget_class_bind_template_child (widget_class, CcToggleRow, toggle);
+
+ gtk_widget_class_bind_template_callback (widget_class, changed_cb);
+}
+
+static void
+cc_toggle_row_init (CcToggleRow *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+CcToggleRow *
+cc_toggle_row_new (void)
+{
+ return CC_TOGGLE_ROW (g_object_new (CC_TYPE_TOGGLE_ROW, NULL));
+}
+
+void
+cc_toggle_row_set_allowed (CcToggleRow *self,
+ gboolean allowed)
+{
+ gtk_switch_set_active (GTK_SWITCH (self->toggle), allowed);
+}
+
+gboolean
+cc_toggle_row_get_allowed (CcToggleRow *self)
+{
+ return gtk_switch_get_active (GTK_SWITCH (self->toggle));
+}
diff --git a/panels/applications/cc-toggle-row.h b/panels/applications/cc-toggle-row.h
new file mode 100644
index 0000000..e7ab497
--- /dev/null
+++ b/panels/applications/cc-toggle-row.h
@@ -0,0 +1,37 @@
+/* cc-toggle-row.h
+ *
+ * Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <adwaita.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_TOGGLE_ROW (cc_toggle_row_get_type())
+G_DECLARE_FINAL_TYPE (CcToggleRow, cc_toggle_row, CC, TOGGLE_ROW, AdwActionRow)
+
+CcToggleRow* cc_toggle_row_new (void);
+
+void cc_toggle_row_set_allowed (CcToggleRow *row,
+ gboolean allowed);
+
+gboolean cc_toggle_row_get_allowed (CcToggleRow *row);
+
+G_END_DECLS
diff --git a/panels/applications/cc-toggle-row.ui b/panels/applications/cc-toggle-row.ui
new file mode 100644
index 0000000..d9a2d6f
--- /dev/null
+++ b/panels/applications/cc-toggle-row.ui
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcToggleRow" parent="AdwActionRow">
+ <property name="activatable-widget">toggle</property>
+ <child>
+ <object class="GtkSwitch" id="toggle">
+ <property name="valign">center</property>
+ <signal name="notify::active" handler="changed_cb" swapped="yes"/>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/applications/globs.c b/panels/applications/globs.c
new file mode 100644
index 0000000..4d2c939
--- /dev/null
+++ b/panels/applications/globs.c
@@ -0,0 +1,62 @@
+/* globs.c
+ *
+ * Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <config.h>
+
+#include "globs.h"
+
+/* parse mime/globs and return a string->string hash table */
+GHashTable *
+parse_globs (void)
+{
+ GHashTable *globs;
+ const gchar * const *dirs;
+ gint i;
+
+ globs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ dirs = g_get_system_data_dirs ();
+
+ for (i = 0; dirs[i]; i++)
+ {
+ g_autofree gchar *file = g_build_filename (dirs[i], "mime", "globs", NULL);
+ g_autofree gchar *contents = NULL;
+
+ if (g_file_get_contents (file, &contents, NULL, NULL))
+ {
+ g_auto(GStrv) strv = NULL;
+ int i;
+
+ strv = g_strsplit (contents, "\n", 0);
+ for (i = 0; strv[i]; i++)
+ {
+ g_auto(GStrv) parts = NULL;
+
+ if (strv[i][0] == '#' || strv[i][0] == '\0')
+ continue;
+
+ parts = g_strsplit (strv[i], ":", 2);
+ g_hash_table_insert (globs, g_strdup (parts[0]), g_strdup (parts[1]));
+ }
+ }
+ }
+
+ return globs;
+}
diff --git a/panels/applications/globs.h b/panels/applications/globs.h
new file mode 100644
index 0000000..0a54588
--- /dev/null
+++ b/panels/applications/globs.h
@@ -0,0 +1,29 @@
+/* globs.h
+ *
+ * Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+GHashTable* parse_globs (void);
+
+G_END_DECLS
diff --git a/panels/applications/gnome-applications-panel.desktop.in.in b/panels/applications/gnome-applications-panel.desktop.in.in
new file mode 100644
index 0000000..1f20521
--- /dev/null
+++ b/panels/applications/gnome-applications-panel.desktop.in.in
@@ -0,0 +1,16 @@
+[Desktop Entry]
+Name=Applications
+Comment=Control various application permissions and settings
+Exec=gnome-control-center applications
+# FIXME
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-applications-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-AccountSettings;
+OnlyShowIn=GNOME;Unity;
+# Translators: Search terms to find the Applications panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=application;flatpak;permission;setting;
+X-GNOME-ControlCenter-HasSidebar=true
diff --git a/panels/applications/icons/meson.build b/panels/applications/icons/meson.build
new file mode 100644
index 0000000..60ee78c
--- /dev/null
+++ b/panels/applications/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-applications-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/applications/icons/scalable/org.gnome.Settings-applications-symbolic.svg b/panels/applications/icons/scalable/org.gnome.Settings-applications-symbolic.svg
new file mode 100644
index 0000000..65f17a8
--- /dev/null
+++ b/panels/applications/icons/scalable/org.gnome.Settings-applications-symbolic.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <path d="m 2 0 c -1.089844 0 -2 0.910156 -2 2 v 3 c 0 1.089844 0.910156 2 2 2 h 3 c 1.089844 0 2 -0.910156 2 -2 v -3 c 0 -1.089844 -0.910156 -2 -2 -2 z m 8 0 c -1.089844 0 -2 0.910156 -2 2 v 3 c 0 1.089844 0.910156 2 2 2 h 3 c 1.089844 0 2 -0.910156 2 -2 v -3 c 0 -1.089844 -0.910156 -2 -2 -2 z m -8 2 h 3 v 3 h -3 z m 8 0 h 3 v 3 h -3 z m -8 6 c -1.089844 0 -2 0.910156 -2 2 v 3 c 0 1.089844 0.910156 2 2 2 h 3 c 1.089844 0 2 -0.910156 2 -2 v -3 c 0 -1.089844 -0.910156 -2 -2 -2 z m 8 0 c -1.089844 0 -2 0.910156 -2 2 v 3 c 0 1.089844 0.910156 2 2 2 h 3 c 1.089844 0 2 -0.910156 2 -2 v -3 c 0 -1.089844 -0.910156 -2 -2 -2 z m -8 2 h 3 v 3 h -3 z m 8 0 h 3 v 3 h -3 z m 0 0" fill="#2e3436"/>
+</svg>
diff --git a/panels/applications/meson.build b/panels/applications/meson.build
new file mode 100644
index 0000000..6a1dd5d
--- /dev/null
+++ b/panels/applications/meson.build
@@ -0,0 +1,58 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input : desktop + '.in.in',
+ output : desktop + '.in',
+ configuration : desktop_conf
+)
+
+i18n.merge_file(
+ type : 'desktop',
+ input : desktop_in,
+ output : desktop,
+ po_dir : po_dir,
+ install : true,
+ install_dir : control_center_desktopdir
+)
+
+sources = files(
+ 'cc-applications-panel.c',
+ 'cc-applications-row.c',
+ 'cc-toggle-row.c',
+ 'cc-info-row.c',
+ 'globs.c',
+ 'search.c',
+ 'utils.c',
+)
+
+resource_data = files('cc-applications-panel.ui')
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name : 'cc_' + cappletname,
+ dependencies : resource_data,
+ export : true
+)
+
+deps = common_deps
+
+if enable_snap
+ deps += snapd_glib_deps
+ sources += files('cc-snap-row.c')
+endif
+
+if enable_malcontent
+ deps += malcontent_dep
+endif
+
+panels_libs += static_library(
+ cappletname,
+ sources : sources,
+ include_directories : [ top_inc, common_inc ],
+ dependencies : deps,
+ c_args : cflags
+)
+
+subdir('icons')
diff --git a/panels/applications/search.c b/panels/applications/search.c
new file mode 100644
index 0000000..448918b
--- /dev/null
+++ b/panels/applications/search.c
@@ -0,0 +1,133 @@
+/* search.c
+ *
+ * Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <config.h>
+
+#include "search.h"
+
+
+#define SHELL_PROVIDER_GROUP "Shell Search Provider"
+
+static void
+add_one_provider (GHashTable *search_providers,
+ GFile *file)
+{
+ g_autoptr(GKeyFile) keyfile = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *app_id = NULL;
+ g_autofree gchar *path = NULL;
+ gboolean default_disabled;
+
+ path = g_file_get_path (file);
+ keyfile = g_key_file_new ();
+ g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, &error);
+
+ if (error != NULL)
+ {
+ g_warning ("Error loading %s: %s - search provider will be ignored",
+ path, error->message);
+ return;
+ }
+
+ if (!g_key_file_has_group (keyfile, SHELL_PROVIDER_GROUP))
+ {
+ g_debug ("Shell search provider group missing from '%s', ignoring", path);
+ return;
+ }
+
+ app_id = g_key_file_get_string (keyfile, SHELL_PROVIDER_GROUP, "DesktopId", &error);
+
+ if (error != NULL)
+ {
+ g_warning ("Unable to read desktop ID from %s: %s - search provider will be ignored",
+ path, error->message);
+ return;
+ }
+
+ if (g_str_has_suffix (app_id, ".desktop"))
+ app_id[strlen (app_id) - strlen (".desktop")] = '\0';
+
+ default_disabled = g_key_file_get_boolean (keyfile, SHELL_PROVIDER_GROUP, "DefaultDisabled", NULL);
+
+ g_hash_table_insert (search_providers, g_strdup (app_id), GINT_TO_POINTER (default_disabled));
+}
+
+static void
+parse_search_providers_one_dir (GHashTable *search_providers,
+ const gchar *system_dir)
+{
+ g_autoptr(GFileEnumerator) enumerator = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GFile) providers_location = NULL;
+ g_autofree gchar *providers_path = NULL;
+
+ providers_path = g_build_filename (system_dir, "gnome-shell", "search-providers", NULL);
+ providers_location = g_file_new_for_path (providers_path);
+
+ enumerator = g_file_enumerate_children (providers_location,
+ "standard::type,standard::name,standard::content-type",
+ G_FILE_QUERY_INFO_NONE,
+ NULL, &error);
+
+ if (error != NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) &&
+ !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Error opening %s: %s - search provider configuration won't be possible",
+ providers_path, error->message);
+ return;
+ }
+
+ while (TRUE)
+ {
+ GFile *provider = NULL;
+
+ if (!g_file_enumerator_iterate (enumerator, NULL, &provider, NULL, &error))
+ {
+ g_warning ("Error while reading %s: %s - search provider configuration won't be possible",
+ providers_path, error->message);
+ return;
+ }
+
+ if (provider == NULL)
+ break;
+
+ add_one_provider (search_providers, provider);
+ }
+}
+
+/* parse gnome-shell/search-provider files and return a string->boolean hash table */
+GHashTable *
+parse_search_providers (void)
+{
+ GHashTable *search_providers;
+ const gchar * const *dirs;
+ gint i;
+
+ search_providers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ dirs = g_get_system_data_dirs ();
+
+ for (i = 0; dirs[i]; i++)
+ parse_search_providers_one_dir (search_providers, dirs[i]);
+
+ return search_providers;
+}
+
diff --git a/panels/applications/search.h b/panels/applications/search.h
new file mode 100644
index 0000000..b7ade82
--- /dev/null
+++ b/panels/applications/search.h
@@ -0,0 +1,29 @@
+/* globs.h
+ *
+ * Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+GHashTable* parse_search_providers (void);
+
+G_END_DECLS
diff --git a/panels/applications/utils.c b/panels/applications/utils.c
new file mode 100644
index 0000000..a952416
--- /dev/null
+++ b/panels/applications/utils.c
@@ -0,0 +1,266 @@
+/* utils.c
+ *
+ * Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE 600
+#endif
+
+#include <config.h>
+#include <glib/gi18n.h>
+#ifdef HAVE_SNAP
+#include <snapd-glib/snapd-glib.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ftw.h>
+
+#include "utils.h"
+
+static gint
+ftw_remove_cb (const gchar *path,
+ const struct stat *sb,
+ gint typeflags,
+ struct FTW *ftwbuf)
+{
+ remove (path);
+ return 0;
+}
+
+static void
+file_remove_thread_func (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ GFile *file = source_object;
+ g_autofree gchar *path = g_file_get_path (file);
+
+ nftw (path, ftw_remove_cb, 20, FTW_PHYS | FTW_DEPTH);
+
+ if (g_task_set_return_on_cancel (task, FALSE))
+ g_task_return_boolean (task, TRUE);
+}
+
+void
+file_remove_async (GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data)
+{
+ g_autoptr(GTask) task = g_task_new (file, cancellable, callback, data);
+ g_task_set_return_on_cancel (task, TRUE);
+ g_task_run_in_thread (task, file_remove_thread_func);
+}
+
+gboolean
+file_remove_finish (GFile *file,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (result, file), FALSE);
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+static GPrivate size_key = G_PRIVATE_INIT (g_free);
+
+static gint
+ftw_size_cb (const gchar *path,
+ const struct stat *sb,
+ gint typeflags,
+ struct FTW *ftwbuf)
+{
+ guint64 *size = (guint64*)g_private_get (&size_key);
+ if (typeflags == FTW_F)
+ *size += sb->st_size;
+ return 0;
+}
+
+static void
+file_size_thread_func (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ GFile *file = source_object;
+ g_autofree gchar *path = g_file_get_path (file);
+ guint64 *total;
+
+ g_private_replace (&size_key, g_new0 (guint64, 1));
+
+ nftw (path, ftw_size_cb, 20, FTW_DEPTH);
+
+ total = g_new0 (guint64, 1);
+ *total = *(guint64*)g_private_get (&size_key);
+
+ if (g_task_set_return_on_cancel (task, FALSE))
+ g_task_return_pointer (task, total, g_free);
+}
+
+void
+file_size_async (GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data)
+{
+ g_autoptr(GTask) task = g_task_new (file, cancellable, callback, data);
+ g_task_set_return_on_cancel (task, TRUE);
+ g_task_run_in_thread (task, file_size_thread_func);
+}
+
+gboolean
+file_size_finish (GFile *file,
+ GAsyncResult *result,
+ guint64 *size,
+ GError **error)
+{
+ g_autofree guint64 *data = NULL;
+
+ g_return_val_if_fail (g_task_is_valid (result, file), FALSE);
+ data = g_task_propagate_pointer (G_TASK (result), error);
+ if (data == NULL)
+ return FALSE;
+ if (size != NULL)
+ *size = *data;
+ return TRUE;
+}
+
+void
+listbox_remove_all (GtkListBox *listbox)
+{
+ GtkWidget *child;
+
+ while ((child = gtk_widget_get_first_child (GTK_WIDGET (listbox))))
+ gtk_list_box_remove (listbox, child);
+}
+
+static gchar *
+get_output_of (const gchar **argv)
+{
+ g_autofree gchar *output = NULL;
+ int status;
+
+ if (!g_spawn_sync (NULL,
+ (gchar**) argv,
+ NULL,
+ G_SPAWN_SEARCH_PATH,
+ NULL, NULL,
+ &output, NULL,
+ &status, NULL))
+ return NULL;
+
+ if (!g_spawn_check_wait_status (status, NULL))
+ return NULL;
+
+ return g_steal_pointer (&output);
+}
+
+GKeyFile *
+get_flatpak_metadata (const gchar *app_id)
+{
+ const gchar *argv[5] = { "flatpak", "info", "-m", "app", NULL };
+ g_autofree gchar *data = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GKeyFile) keyfile = NULL;
+
+ argv[3] = app_id;
+
+ data = get_output_of (argv);
+ if (data == NULL)
+ return NULL;
+
+ keyfile = g_key_file_new ();
+ if (!g_key_file_load_from_data (keyfile, data, -1, 0, &error))
+ {
+ g_warning ("%s", error->message);
+ return NULL;
+ }
+
+ return g_steal_pointer (&keyfile);
+}
+
+guint64
+get_flatpak_app_size (const gchar *app_id)
+{
+ const gchar *argv[5] = { "flatpak", "info", "-s", "app", NULL };
+ g_autofree gchar *data = NULL;
+ guint64 factor;
+ double val;
+
+ argv[3] = app_id;
+
+ data = get_output_of (argv);
+ if (data == NULL)
+ return 0;
+
+ data = g_strstrip (data);
+
+ if (g_str_has_suffix (data, "kB") || g_str_has_suffix (data, "kb"))
+ factor = 1000;
+ else if (g_str_has_suffix (data, "MB") || g_str_has_suffix (data, "Mb"))
+ factor = 1000 * 1000;
+ else if (g_str_has_suffix (data, "GB") || g_str_has_suffix (data, "Gb"))
+ factor = 1000 * 1000 * 1000;
+ else if (g_str_has_suffix (data, "KiB") || g_str_has_suffix (data, "Kib"))
+ factor = 1024;
+ else if (g_str_has_suffix (data, "MiB") || g_str_has_suffix (data, "Mib"))
+ factor = 1024 * 1024;
+ else if (g_str_has_suffix (data, "GiB") || g_str_has_suffix (data, "Gib"))
+ factor = 1024 * 1024 * 1024;
+ else
+ factor = 1;
+
+ val = g_ascii_strtod (data, NULL);
+
+ return (guint64)(val * factor);
+}
+
+guint64
+get_snap_app_size (const gchar *snap_name)
+{
+#ifdef HAVE_SNAP
+ g_autoptr(SnapdClient) client = NULL;
+ g_autoptr(SnapdSnap) snap = NULL;
+ g_autoptr(GError) error = NULL;
+
+ client = snapd_client_new ();
+ snap = snapd_client_get_snap_sync (client, snap_name, NULL, &error);
+ if (snap == NULL)
+ {
+ g_warning ("Failed to get snap size: %s", error->message);
+ return 0;
+ }
+
+ return snapd_snap_get_installed_size (snap);
+#else
+ return 0;
+#endif
+}
+
+char *
+get_app_id (GAppInfo *info)
+{
+ gchar *app_id = g_strdup (g_app_info_get_id (info));
+
+ if (g_str_has_suffix (app_id, ".desktop"))
+ app_id[strlen (app_id) - strlen (".desktop")] = '\0';
+
+ return app_id;
+}
diff --git a/panels/applications/utils.h b/panels/applications/utils.h
new file mode 100644
index 0000000..c3b30f7
--- /dev/null
+++ b/panels/applications/utils.h
@@ -0,0 +1,57 @@
+/* utils.h
+ *
+ * Copyright 2018 Matthias Clasen <matthias.clasen@gmail.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+void file_remove_async (GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data);
+
+gboolean file_remove_finish (GFile *file,
+ GAsyncResult *result,
+ GError **error);
+
+void file_size_async (GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data);
+
+gboolean file_size_finish (GFile *file,
+ GAsyncResult *result,
+ guint64 *size,
+ GError **error);
+
+void listbox_remove_all (GtkListBox *listbox);
+
+GKeyFile* get_flatpak_metadata (const gchar *app_id);
+
+guint64 get_flatpak_app_size (const gchar *app_id);
+
+guint64 get_snap_app_size (const gchar *snap_name);
+
+gchar* get_app_id (GAppInfo *info);
+
+G_END_DECLS
diff --git a/panels/background/background-selected-symbolic.svg b/panels/background/background-selected-symbolic.svg
new file mode 100644
index 0000000..9e820d1
--- /dev/null
+++ b/panels/background/background-selected-symbolic.svg
@@ -0,0 +1 @@
+<svg width="16" height="16" viewBox="0 0 4.233 4.233" xmlns="http://www.w3.org/2000/svg"><path d="M3.843.627a.397.397 0 0 0-.56.034L1.45 2.73l-.775-.763a.397.397 0 0 0-.56.004.397.397 0 0 0 .003.562L1.191 3.59a.397.397 0 0 0 .576-.02l2.11-2.382a.397.397 0 0 0-.034-.56Z" style="fill:#3d3846"/></svg> \ No newline at end of file
diff --git a/panels/background/background.gresource.xml b/panels/background/background.gresource.xml
new file mode 100644
index 0000000..1699244
--- /dev/null
+++ b/panels/background/background.gresource.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/background">
+ <file preprocess="xml-stripblanks">cc-background-chooser.ui</file>
+ <file preprocess="xml-stripblanks">cc-background-panel.ui</file>
+ <file preprocess="xml-stripblanks">cc-background-preview.ui</file>
+ <file>preview.css</file>
+ </gresource>
+
+ <gresource prefix="/org/gnome/Settings/icons/scalable/actions">
+ <file preprocess="xml-stripblanks">background-selected-symbolic.svg</file>
+ <file preprocess="xml-stripblanks">slideshow-symbolic.svg</file>
+ </gresource>
+</gresources>
diff --git a/panels/background/bg-colors-source.c b/panels/background/bg-colors-source.c
new file mode 100644
index 0000000..fbf116a
--- /dev/null
+++ b/panels/background/bg-colors-source.c
@@ -0,0 +1,219 @@
+/* bg-colors-source.c */
+/*
+ * Copyright (C) 2010 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ *
+ */
+
+#include <config.h>
+#include "bg-colors-source.h"
+
+#include "cc-background-item.h"
+
+#include <cairo-gobject.h>
+#include <glib/gi18n-lib.h>
+#include <gdesktop-enums.h>
+
+struct _BgColorsSource
+{
+ BgSource parent_instance;
+};
+
+G_DEFINE_TYPE (BgColorsSource, bg_colors_source, BG_TYPE_SOURCE)
+
+struct {
+ GDesktopBackgroundShading type;
+ int orientation;
+ const char *pcolor;
+} items[] = {
+ { G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#000000" },
+ { G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#db5d33" },
+ { G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#008094" },
+ { G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#5d479d" },
+ { G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#ab2876" },
+ { G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#fad166" },
+ { G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#437740" },
+ { G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#d272c4" },
+ { G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#ed9116" },
+ { G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#ff89a9" },
+ { G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#7a8aa2" },
+ { G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#888888" },
+ { G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#475b52" },
+ { G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#425265" },
+ { G_DESKTOP_BACKGROUND_SHADING_SOLID, -1, "#7a634b" },
+};
+
+static gchar *
+get_colors_path (void)
+{
+ return g_build_filename (g_get_user_config_dir (), "gnome-control-center", "backgrounds", "colors.ini", NULL);
+}
+
+static char *
+get_colors_dir (void)
+{
+ return g_build_filename (g_get_user_config_dir (), "gnome-control-center", "backgrounds", NULL);
+}
+
+static void
+bg_colors_source_add_color (BgColorsSource *self,
+ GListStore *store,
+ const char *color)
+{
+ CcBackgroundItemFlags flags;
+ g_autoptr(CcBackgroundItem) item = NULL;
+
+ item = cc_background_item_new (NULL);
+ flags = CC_BACKGROUND_ITEM_HAS_PCOLOR |
+ CC_BACKGROUND_ITEM_HAS_SCOLOR |
+ CC_BACKGROUND_ITEM_HAS_SHADING |
+ CC_BACKGROUND_ITEM_HAS_PLACEMENT |
+ CC_BACKGROUND_ITEM_HAS_URI;
+ /* It does have a URI, it's "none" */
+
+ g_object_set (G_OBJECT (item),
+ "uri", "file:///" DATADIR "/gnome-control-center/pixmaps/noise-texture-light.png",
+ "primary-color", color,
+ "secondary-color", color,
+ "shading", G_DESKTOP_BACKGROUND_SHADING_SOLID,
+ "placement", G_DESKTOP_BACKGROUND_STYLE_WALLPAPER,
+ "flags", flags,
+ NULL);
+ cc_background_item_load (item, NULL);
+
+ /* insert the item into the liststore */
+ g_list_store_append (store, item);
+}
+
+static void
+bg_colors_source_constructed (GObject *object)
+{
+ BgColorsSource *self = BG_COLORS_SOURCE (object);
+ guint i;
+ GListStore *store;
+ g_autoptr(GKeyFile) keyfile = NULL;
+ g_autofree gchar *path = NULL;
+
+ G_OBJECT_CLASS (bg_colors_source_parent_class)->constructed (object);
+
+ store = bg_source_get_liststore (BG_SOURCE (self));
+
+ for (i = 0; i < G_N_ELEMENTS (items); i++)
+ bg_colors_source_add_color (self, store, items[i].pcolor);
+
+ keyfile = g_key_file_new ();
+ path = get_colors_path ();
+ if (g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, NULL))
+ {
+ g_auto(GStrv) colors = NULL;
+
+ colors = g_key_file_get_string_list (keyfile, "Colors", "custom-colors", NULL, NULL);
+ for (i = 0; colors != NULL && colors[i] != NULL; i++)
+ bg_colors_source_add_color (self, store, colors[i]);
+ }
+}
+
+gboolean
+bg_colors_source_add (BgColorsSource *self,
+ GdkRGBA *rgba,
+ GtkTreeRowReference **ret_row_ref)
+{
+ GListStore *store;
+ g_autofree gchar *c = NULL;
+ g_auto(GStrv) colors = NULL;
+ gsize len;
+ g_autoptr(GKeyFile) keyfile = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *dir = NULL;
+ g_autofree gchar *path = NULL;
+
+ c = g_strdup_printf ("#%02x%02x%02x",
+ (int)(255*rgba->red),
+ (int)(255*rgba->green),
+ (int)(255*rgba->blue));
+
+ store = bg_source_get_liststore (BG_SOURCE (self));
+
+ bg_colors_source_add_color (self, store, c);
+
+ /* Save to the keyfile */
+ dir = get_colors_dir ();
+ g_mkdir_with_parents (dir, 0700);
+
+ path = get_colors_path ();
+ colors = NULL;
+ len = 0;
+
+ keyfile = g_key_file_new ();
+ if (g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, NULL))
+ colors = g_key_file_get_string_list (keyfile, "Colors", "custom-colors", &len, NULL);
+
+ if (len == 0 && colors != NULL)
+ g_clear_pointer (&colors, g_strfreev);
+
+ if (colors == NULL)
+ {
+ colors = g_new0 (char *, 2);
+ colors[0] = g_steal_pointer (&c);
+ len = 1;
+ }
+ else
+ {
+ char **new_colors;
+ guint i;
+
+ new_colors = g_new0 (char *, len + 2);
+ for (i = 0; colors[i] != NULL; i++)
+ {
+ new_colors[i] = colors[i];
+ colors[i] = NULL;
+ }
+
+ new_colors[len] = g_steal_pointer (&c);
+ len++;
+
+ g_strfreev (colors);
+ colors = new_colors;
+ }
+
+ g_key_file_set_string_list (keyfile, "Colors", "custom-colors", (const gchar * const*) colors, len);
+
+ if (!g_key_file_save_to_file (keyfile, path, &error))
+ g_warning ("Could not save custom color: %s", error->message);
+
+ return TRUE;
+}
+
+static void
+bg_colors_source_init (BgColorsSource *self)
+{
+}
+
+static void
+bg_colors_source_class_init (BgColorsSourceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructed = bg_colors_source_constructed;
+}
+
+BgColorsSource *
+bg_colors_source_new (GtkWidget *widget)
+{
+ return g_object_new (BG_TYPE_COLORS_SOURCE, "widget", widget, NULL);
+}
+
diff --git a/panels/background/bg-colors-source.h b/panels/background/bg-colors-source.h
new file mode 100644
index 0000000..8e2575d
--- /dev/null
+++ b/panels/background/bg-colors-source.h
@@ -0,0 +1,38 @@
+/* bg-colors-source.h */
+/*
+ * Copyright (C) 2010 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ *
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include "bg-source.h"
+
+G_BEGIN_DECLS
+
+#define BG_TYPE_COLORS_SOURCE (bg_colors_source_get_type ())
+G_DECLARE_FINAL_TYPE (BgColorsSource, bg_colors_source, BG, COLORS_SOURCE, BgSource)
+
+BgColorsSource *bg_colors_source_new (GtkWidget *widget);
+
+gboolean bg_colors_source_add (BgColorsSource *self,
+ GdkRGBA *rgba,
+ GtkTreeRowReference **ret_row_ref);
+
+G_END_DECLS
diff --git a/panels/background/bg-recent-source.c b/panels/background/bg-recent-source.c
new file mode 100644
index 0000000..32d1854
--- /dev/null
+++ b/panels/background/bg-recent-source.c
@@ -0,0 +1,459 @@
+/* bg-recent-source.c
+ *
+ * Copyright 2019 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "bg-recent-source"
+
+#include "bg-recent-source.h"
+#include "cc-background-item.h"
+
+#define ATTRIBUTES G_FILE_ATTRIBUTE_STANDARD_NAME "," \
+ G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," \
+ G_FILE_ATTRIBUTE_TIME_MODIFIED
+
+struct _BgRecentSource
+{
+ BgSource parent;
+
+ GFile *backgrounds_folder;
+ GFileMonitor *monitor;
+
+ GCancellable *cancellable;
+ GHashTable *items;
+};
+
+G_DEFINE_TYPE (BgRecentSource, bg_recent_source, BG_TYPE_SOURCE)
+
+static int
+sort_func (gconstpointer a,
+ gconstpointer b,
+ gpointer user_data)
+{
+ CcBackgroundItem *item_a;
+ CcBackgroundItem *item_b;
+ guint64 modified_a;
+ guint64 modified_b;
+ int retval;
+
+ item_a = (CcBackgroundItem *) a;
+ item_b = (CcBackgroundItem *) b;
+ modified_a = cc_background_item_get_modified (item_a);
+ modified_b = cc_background_item_get_modified (item_b);
+
+ retval = modified_b - modified_a;
+
+ return retval;
+}
+
+static void
+add_file_from_info (BgRecentSource *self,
+ GFile *file,
+ GFileInfo *info)
+{
+ g_autoptr(CcBackgroundItem) item = NULL;
+ CcBackgroundItemFlags flags = 0;
+ g_autofree gchar *source_uri = NULL;
+ g_autofree gchar *uri = NULL;
+ GListStore *store;
+ const gchar *content_type;
+ guint64 mtime;
+
+ content_type = g_file_info_get_content_type (info);
+ mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
+
+ if (!content_type || !g_content_type_is_a (content_type, "image/*"))
+ return;
+
+ uri = g_file_get_uri (file);
+ item = cc_background_item_new (uri);
+ flags |= CC_BACKGROUND_ITEM_HAS_SHADING | CC_BACKGROUND_ITEM_HAS_PLACEMENT;
+ g_object_set (G_OBJECT (item),
+ "flags", flags,
+ "shading", G_DESKTOP_BACKGROUND_SHADING_SOLID,
+ "placement", G_DESKTOP_BACKGROUND_STYLE_ZOOM,
+ "modified", mtime,
+ "needs-download", FALSE,
+ "source-url", source_uri,
+ NULL);
+
+ store = bg_source_get_liststore (BG_SOURCE (self));
+ g_list_store_insert_sorted (store, item, sort_func, self);
+
+ g_hash_table_insert (self->items, g_strdup (uri), g_object_ref (item));
+}
+
+static void
+remove_item (BgRecentSource *self,
+ CcBackgroundItem *item)
+{
+ GListStore *store;
+ const gchar *uri;
+ guint i;
+
+ g_return_if_fail (BG_IS_RECENT_SOURCE (self));
+ g_return_if_fail (CC_IS_BACKGROUND_ITEM (item));
+
+ uri = cc_background_item_get_uri (item);
+ store = bg_source_get_liststore (BG_SOURCE (self));
+
+ g_debug ("Removing wallpaper %s", uri);
+
+ for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (store)); i++)
+ {
+ g_autoptr(CcBackgroundItem) tmp = NULL;
+
+ tmp = g_list_model_get_item (G_LIST_MODEL (store), i);
+
+ if (tmp == item)
+ {
+ g_list_store_remove (store, i);
+ break;
+ }
+ }
+
+ g_hash_table_remove (self->items, cc_background_item_get_uri (item));
+}
+
+static void
+query_info_finished_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ BgRecentSource *self;
+ g_autoptr(GFileInfo) file_info = NULL;
+ g_autoptr(GError) error = NULL;
+ GFile *file = NULL;
+
+ file = G_FILE (source);
+ file_info = g_file_query_info_finish (file, result, &error);
+ if (error)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Could not get pictures file information: %s", error->message);
+ return;
+ }
+
+ self = BG_RECENT_SOURCE (user_data);
+
+ g_debug ("Adding wallpaper %s (%d)",
+ g_file_info_get_name (file_info),
+ G_IS_FILE (self->backgrounds_folder));
+
+ add_file_from_info (self, file, file_info);
+}
+
+static void
+on_file_changed_cb (BgRecentSource *self,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type)
+{
+ g_autofree gchar *uri = NULL;
+
+ switch (event_type)
+ {
+ case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
+ g_file_query_info_async (file,
+ ATTRIBUTES,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ G_PRIORITY_DEFAULT,
+ self->cancellable,
+ query_info_finished_cb,
+ self);
+ break;
+
+ case G_FILE_MONITOR_EVENT_DELETED:
+ uri = g_file_get_uri (file);
+ remove_item (self, g_hash_table_lookup (self->items, uri));
+ break;
+
+ default:
+ return;
+ }
+}
+
+static int
+file_sort_func (gconstpointer a,
+ gconstpointer b)
+{
+ GFileInfo *file_a = G_FILE_INFO (a);
+ GFileInfo *file_b = G_FILE_INFO (b);
+ guint64 modified_a, modified_b;
+
+ modified_a = g_file_info_get_attribute_uint64 (file_a, G_FILE_ATTRIBUTE_TIME_MODIFIED);
+ modified_b = g_file_info_get_attribute_uint64 (file_b, G_FILE_ATTRIBUTE_TIME_MODIFIED);
+
+ return modified_b - modified_a;
+}
+
+static void
+file_info_async_ready_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ BgRecentSource *self;
+ g_autolist(GFileInfo) file_infos = NULL;
+ g_autoptr(GError) error = NULL;
+ GFile *parent = NULL;
+ GList *l;
+
+ file_infos = g_file_enumerator_next_files_finish (G_FILE_ENUMERATOR (source),
+ result,
+ &error);
+ if (error)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Could not get pictures file information: %s", error->message);
+ return;
+ }
+
+ self = BG_RECENT_SOURCE (user_data);
+ parent = g_file_enumerator_get_container (G_FILE_ENUMERATOR (source));
+
+ file_infos = g_list_sort (file_infos, file_sort_func);
+
+ for (l = file_infos; l; l = l->next)
+ {
+ g_autoptr(GFile) file = NULL;
+ GFileInfo *info;
+
+ info = l->data;
+ file = g_file_get_child (parent, g_file_info_get_name (info));
+
+ g_debug ("Found recent wallpaper %s", g_file_info_get_name (info));
+
+ add_file_from_info (self, file, info);
+ }
+
+ g_file_enumerator_close (G_FILE_ENUMERATOR (source), self->cancellable, &error);
+
+ if (error)
+ g_warning ("Error closing file enumerator: %s", error->message);
+}
+
+static void
+enumerate_children_finished_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ BgRecentSource *self;
+ g_autoptr(GFileEnumerator) enumerator = NULL;
+ g_autoptr(GError) error = NULL;
+
+ enumerator = g_file_enumerate_children_finish (G_FILE (source), result, &error);
+
+ if (error)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Could not fill pictures source: %s", error->message);
+ return;
+ }
+
+ self = BG_RECENT_SOURCE (user_data);
+ g_file_enumerator_next_files_async (enumerator,
+ G_MAXINT,
+ G_PRIORITY_DEFAULT,
+ self->cancellable,
+ file_info_async_ready_cb,
+ self);
+}
+
+static void
+load_backgrounds (BgRecentSource *self)
+{
+ g_autofree gchar *backgrounds_path = NULL;
+ g_autoptr(GError) error = NULL;
+
+ if (!g_file_make_directory_with_parents (self->backgrounds_folder, self->cancellable, &error) &&
+ !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS))
+ {
+ g_critical ("Failed to create local background directory: %s", error->message);
+ return;
+ }
+
+ backgrounds_path = g_file_get_path (self->backgrounds_folder);
+ g_debug ("Enumerating wallpapers under %s", backgrounds_path);
+
+ g_file_enumerate_children_async (self->backgrounds_folder,
+ ATTRIBUTES,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ G_PRIORITY_DEFAULT,
+ self->cancellable,
+ enumerate_children_finished_cb,
+ self);
+
+ self->monitor = g_file_monitor_directory (self->backgrounds_folder,
+ G_FILE_MONITOR_WATCH_MOVES,
+ self->cancellable,
+ &error);
+
+ if (!self->monitor)
+ {
+ g_critical ("Failed to monitor background directory: %s", error->message);
+ return;
+ }
+
+ g_signal_connect_object (self->monitor, "changed", G_CALLBACK (on_file_changed_cb), self, G_CONNECT_SWAPPED);
+}
+
+/* Callbacks */
+
+static void
+on_file_copied_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(BgRecentSource) self = BG_RECENT_SOURCE (user_data);
+ g_autofree gchar *original_file = NULL;
+ g_autoptr(GError) error = NULL;
+
+ g_file_copy_finish (G_FILE (source), result, &error);
+
+ if (error)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_critical ("Failed to copy file: %s", error->message);
+ return;
+ }
+
+ original_file = g_file_get_path (G_FILE (source));
+ g_debug ("Successfully copied wallpaper: %s", original_file);
+}
+
+static void
+on_file_deleted_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(BgRecentSource) self = BG_RECENT_SOURCE (user_data);
+ g_autofree gchar *original_file = NULL;
+ g_autoptr(GError) error = NULL;
+
+ g_file_delete_finish (G_FILE (source), result, &error);
+
+ if (error)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_critical ("Failed to delete wallpaper: %s", error->message);
+ return;
+ }
+
+ original_file = g_file_get_path (G_FILE (source));
+ g_debug ("Successfully deleted wallpaper: %s", original_file);
+}
+
+/* GObject overrides */
+
+static void
+bg_recent_source_finalize (GObject *object)
+{
+ BgRecentSource *self = (BgRecentSource *)object;
+
+ g_cancellable_cancel (self->cancellable);
+ g_clear_object (&self->cancellable);
+ g_clear_object (&self->monitor);
+
+ G_OBJECT_CLASS (bg_recent_source_parent_class)->finalize (object);
+}
+
+static void
+bg_recent_source_class_init (BgRecentSourceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = bg_recent_source_finalize;
+}
+
+static void
+bg_recent_source_init (BgRecentSource *self)
+{
+ g_autofree gchar *backgrounds_path = NULL;
+
+ backgrounds_path = g_build_filename (g_get_user_data_dir (), "backgrounds", NULL);
+
+ self->items = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+ self->cancellable = g_cancellable_new ();
+ self->backgrounds_folder = g_file_new_for_path (backgrounds_path);
+
+ load_backgrounds (self);
+}
+
+BgRecentSource*
+bg_recent_source_new (GtkWidget *widget)
+{
+ return g_object_new (BG_TYPE_RECENT_SOURCE,
+ "widget", widget,
+ NULL);
+}
+
+void
+bg_recent_source_add_file (BgRecentSource *self,
+ const gchar *path)
+{
+ g_autoptr(GDateTime) now = NULL;
+ g_autofree gchar *destination_name = NULL;
+ g_autofree gchar *formatted_now = NULL;
+ g_autofree gchar *basename = NULL;
+ g_autoptr(GFile) destination = NULL;
+ g_autoptr(GFile) file = NULL;
+
+ g_return_if_fail (BG_IS_RECENT_SOURCE (self));
+ g_return_if_fail (path && *path);
+
+ g_debug ("Importing wallpaper %s", path);
+
+ now = g_date_time_new_now_local ();
+ formatted_now = g_date_time_format (now, "%Y-%m-%d-%H-%M-%S");
+
+ file = g_file_new_for_path (path);
+
+ basename = g_file_get_basename (file);
+ destination_name = g_strdup_printf ("%s-%s", formatted_now, basename);
+ destination = g_file_get_child (self->backgrounds_folder, destination_name);
+
+ g_file_copy_async (file,
+ destination,
+ G_FILE_COPY_NONE,
+ G_PRIORITY_DEFAULT,
+ self->cancellable,
+ NULL, NULL,
+ on_file_copied_cb,
+ g_object_ref (self));
+}
+
+void
+bg_recent_source_remove_item (BgRecentSource *self,
+ CcBackgroundItem *item)
+{
+ g_autoptr(GFile) file = NULL;
+ const gchar *uri;
+
+ g_return_if_fail (BG_IS_RECENT_SOURCE (self));
+ g_return_if_fail (CC_IS_BACKGROUND_ITEM (item));
+
+ uri = cc_background_item_get_uri (item);
+ file = g_file_new_for_uri (uri);
+
+ g_file_delete_async (file,
+ G_PRIORITY_DEFAULT,
+ self->cancellable,
+ on_file_deleted_cb,
+ g_object_ref (self));
+}
diff --git a/panels/background/bg-recent-source.h b/panels/background/bg-recent-source.h
new file mode 100644
index 0000000..58d4c04
--- /dev/null
+++ b/panels/background/bg-recent-source.h
@@ -0,0 +1,39 @@
+/* bg-recent-source.h
+ *
+ * Copyright 2019 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include "bg-source.h"
+#include "cc-background-item.h"
+
+G_BEGIN_DECLS
+
+#define BG_TYPE_RECENT_SOURCE (bg_recent_source_get_type())
+G_DECLARE_FINAL_TYPE (BgRecentSource, bg_recent_source, BG, RECENT_SOURCE, BgSource)
+
+BgRecentSource* bg_recent_source_new (GtkWidget *widget);
+
+void bg_recent_source_add_file (BgRecentSource *self,
+ const gchar *path);
+
+void bg_recent_source_remove_item (BgRecentSource *self,
+ CcBackgroundItem *item);
+
+G_END_DECLS
diff --git a/panels/background/bg-source.c b/panels/background/bg-source.c
new file mode 100644
index 0000000..dacf82f
--- /dev/null
+++ b/panels/background/bg-source.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2010 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ *
+ */
+
+#include "bg-source.h"
+#include "cc-background-item.h"
+
+#include <cairo-gobject.h>
+
+#define THUMBNAIL_WIDTH 144
+#define THUMBNAIL_HEIGHT (THUMBNAIL_WIDTH * 3 / 4)
+
+typedef struct
+{
+ GnomeDesktopThumbnailFactory *thumbnail_factory;
+ GListStore *store;
+ GtkWidget *widget;
+ gint thumbnail_height;
+ gint thumbnail_width;
+} BgSourcePrivate;
+
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (BgSource, bg_source, G_TYPE_OBJECT)
+
+enum
+{
+ PROP_LISTSTORE = 1,
+ PROP_WIDGET
+};
+
+
+static void
+bg_source_calculate_thumbnail_dimensions (BgSource *source)
+{
+ BgSourcePrivate *priv = bg_source_get_instance_private (source);
+ gint scale_factor;
+
+ priv->thumbnail_height = THUMBNAIL_HEIGHT;
+ priv->thumbnail_width = THUMBNAIL_WIDTH;
+
+ if (priv->widget == NULL)
+ return;
+
+ scale_factor = gtk_widget_get_scale_factor (priv->widget);
+ if (scale_factor > 1)
+ {
+ priv->thumbnail_height *= scale_factor;
+ priv->thumbnail_width *= scale_factor;
+ }
+}
+
+static void
+bg_source_constructed (GObject *object)
+{
+ G_OBJECT_CLASS (bg_source_parent_class)->constructed (object);
+
+ bg_source_calculate_thumbnail_dimensions (BG_SOURCE (object));
+}
+
+static void
+bg_source_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ BgSource *source = BG_SOURCE (object);
+
+ switch (property_id)
+ {
+ case PROP_LISTSTORE:
+ g_value_set_object (value, bg_source_get_liststore (source));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+bg_source_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ BgSource *source = BG_SOURCE (object);
+ BgSourcePrivate *priv = bg_source_get_instance_private (source);
+
+ switch (property_id)
+ {
+ case PROP_WIDGET:
+ priv->widget = GTK_WIDGET (g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+bg_source_dispose (GObject *object)
+{
+ BgSource *source = BG_SOURCE (object);
+ BgSourcePrivate *priv = bg_source_get_instance_private (source);
+
+ g_clear_object (&priv->thumbnail_factory);
+ g_clear_object (&priv->store);
+
+ G_OBJECT_CLASS (bg_source_parent_class)->dispose (object);
+}
+
+static void
+bg_source_class_init (BgSourceClass *klass)
+{
+ GParamSpec *pspec;
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructed = bg_source_constructed;
+ object_class->get_property = bg_source_get_property;
+ object_class->set_property = bg_source_set_property;
+ object_class->dispose = bg_source_dispose;
+
+ pspec = g_param_spec_object ("liststore",
+ "Liststore",
+ "Liststore used in the source",
+ G_TYPE_LIST_STORE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_LISTSTORE, pspec);
+
+ pspec = g_param_spec_object ("widget",
+ "Widget",
+ "Widget used to view the source",
+ GTK_TYPE_WIDGET,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_WIDGET, pspec);
+}
+
+static void
+bg_source_init (BgSource *self)
+{
+ BgSourcePrivate *priv = bg_source_get_instance_private (self);
+ priv->store = g_list_store_new (CC_TYPE_BACKGROUND_ITEM);
+ priv->thumbnail_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
+}
+
+GListStore*
+bg_source_get_liststore (BgSource *source)
+{
+ BgSourcePrivate *priv;
+
+ g_return_val_if_fail (BG_IS_SOURCE (source), NULL);
+
+ priv = bg_source_get_instance_private (source);
+ return priv->store;
+}
+
+gint
+bg_source_get_scale_factor (BgSource *source)
+{
+ BgSourcePrivate *priv;
+
+ g_return_val_if_fail (BG_IS_SOURCE (source), 1);
+
+ priv = bg_source_get_instance_private (source);
+ return gtk_widget_get_scale_factor (priv->widget);
+}
+
+gint
+bg_source_get_thumbnail_height (BgSource *source)
+{
+ BgSourcePrivate *priv;
+
+ g_return_val_if_fail (BG_IS_SOURCE (source), THUMBNAIL_HEIGHT);
+
+ priv = bg_source_get_instance_private (source);
+ return priv->thumbnail_height;
+}
+
+gint
+bg_source_get_thumbnail_width (BgSource *source)
+{
+ BgSourcePrivate *priv;
+
+ g_return_val_if_fail (BG_IS_SOURCE (source), THUMBNAIL_WIDTH);
+
+ priv = bg_source_get_instance_private (source);
+ return priv->thumbnail_width;
+}
+
+GnomeDesktopThumbnailFactory*
+bg_source_get_thumbnail_factory (BgSource *source)
+{
+ BgSourcePrivate *priv;
+
+ g_return_val_if_fail (BG_IS_SOURCE (source), NULL);
+
+ priv = bg_source_get_instance_private (source);
+ return priv->thumbnail_factory;
+}
diff --git a/panels/background/bg-source.h b/panels/background/bg-source.h
new file mode 100644
index 0000000..ff86a85
--- /dev/null
+++ b/panels/background/bg-source.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2010 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ *
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <libgnome-desktop/gnome-desktop-thumbnail.h>
+
+G_BEGIN_DECLS
+
+#define BG_TYPE_SOURCE (bg_source_get_type ())
+G_DECLARE_DERIVABLE_TYPE (BgSource, bg_source, BG, SOURCE, GObject)
+
+struct _BgSourceClass
+{
+ GObjectClass parent_class;
+};
+
+GListStore* bg_source_get_liststore (BgSource *source);
+
+gint bg_source_get_scale_factor (BgSource *source);
+
+gint bg_source_get_thumbnail_height (BgSource *source);
+
+gint bg_source_get_thumbnail_width (BgSource *source);
+
+GnomeDesktopThumbnailFactory* bg_source_get_thumbnail_factory (BgSource *source);
+
+G_END_DECLS
diff --git a/panels/background/bg-wallpapers-source.c b/panels/background/bg-wallpapers-source.c
new file mode 100644
index 0000000..20ca4b7
--- /dev/null
+++ b/panels/background/bg-wallpapers-source.c
@@ -0,0 +1,164 @@
+/* bg-wallpapers-source.c */
+/*
+ * Copyright (C) 2010 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ *
+ */
+
+#include "bg-wallpapers-source.h"
+
+#include "cc-background-item.h"
+#include "cc-background-xml.h"
+
+#include <cairo-gobject.h>
+#include <gio/gio.h>
+
+struct _BgWallpapersSource
+{
+ BgSource parent_instance;
+ CcBackgroundXml *xml;
+};
+
+G_DEFINE_TYPE (BgWallpapersSource, bg_wallpapers_source, BG_TYPE_SOURCE)
+
+static int
+sort_func (gconstpointer a,
+ gconstpointer b,
+ gpointer user_data)
+{
+ CcBackgroundItem *item_a;
+ CcBackgroundItem *item_b;
+ const char *name_a;
+ const char *name_b;
+
+ item_a = (CcBackgroundItem *) a;
+ item_b = (CcBackgroundItem *) b;
+
+ name_a = cc_background_item_get_name (item_a);
+ name_b = cc_background_item_get_name (item_b);
+
+ if (name_a && strcmp (name_a, "Default Background") == 0)
+ return -1;
+ if (name_b && strcmp (name_b, "Default Background") == 0)
+ return 1;
+
+
+ return strcmp (cc_background_item_get_name (item_a),
+ cc_background_item_get_name (item_b));
+}
+
+static void
+load_wallpapers (gchar *key,
+ CcBackgroundItem *item,
+ BgWallpapersSource *source)
+{
+ GListStore *store = bg_source_get_liststore (BG_SOURCE (source));
+ gboolean deleted;
+
+ g_object_get (G_OBJECT (item), "is-deleted", &deleted, NULL);
+
+ if (deleted)
+ return;
+
+ g_list_store_insert_sorted (store, item, sort_func, NULL);
+}
+
+static void
+list_load_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+ if (!cc_background_xml_load_list_finish (CC_BACKGROUND_XML (source_object), res, &error))
+ g_warning ("Failed to load background list: %s", error->message);
+}
+
+static void
+item_added (BgWallpapersSource *self,
+ CcBackgroundItem *item)
+{
+ load_wallpapers (NULL, item, self);
+}
+
+static void
+load_default_bg (BgWallpapersSource *self)
+{
+ const char * const *system_data_dirs;
+ guint i;
+
+ /* FIXME We could do this nicer if we had the XML source in GSettings */
+
+ system_data_dirs = g_get_system_data_dirs ();
+ for (i = 0; system_data_dirs[i]; i++) {
+ g_autofree gchar *filename = NULL;
+
+ filename = g_build_filename (system_data_dirs[i],
+ "gnome-background-properties",
+ "adwaita.xml",
+ NULL);
+ if (cc_background_xml_load_xml (self->xml, filename))
+ break;
+ }
+}
+
+static void
+bg_wallpapers_source_constructed (GObject *object)
+{
+ BgWallpapersSource *self = BG_WALLPAPERS_SOURCE (object);
+
+ G_OBJECT_CLASS (bg_wallpapers_source_parent_class)->constructed (object);
+
+ g_signal_connect_object (G_OBJECT (self->xml), "added",
+ G_CALLBACK (item_added), self, G_CONNECT_SWAPPED);
+
+ /* Try adding the default background first */
+ load_default_bg (self);
+
+ cc_background_xml_load_list_async (self->xml, NULL, list_load_cb, self);
+}
+
+static void
+bg_wallpapers_source_dispose (GObject *object)
+{
+ BgWallpapersSource *self = BG_WALLPAPERS_SOURCE (object);
+
+ g_clear_object (&self->xml);
+
+ G_OBJECT_CLASS (bg_wallpapers_source_parent_class)->dispose (object);
+}
+
+static void
+bg_wallpapers_source_init (BgWallpapersSource *self)
+{
+ self->xml = cc_background_xml_new ();
+}
+
+static void
+bg_wallpapers_source_class_init (BgWallpapersSourceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructed = bg_wallpapers_source_constructed;
+ object_class->dispose = bg_wallpapers_source_dispose;
+}
+
+BgWallpapersSource *
+bg_wallpapers_source_new (GtkWidget *widget)
+{
+ return g_object_new (BG_TYPE_WALLPAPERS_SOURCE, "widget", widget, NULL);
+}
+
diff --git a/panels/background/bg-wallpapers-source.h b/panels/background/bg-wallpapers-source.h
new file mode 100644
index 0000000..3ca222b
--- /dev/null
+++ b/panels/background/bg-wallpapers-source.h
@@ -0,0 +1,34 @@
+/* bg-wallpapers-source.h */
+/*
+ * Copyright (C) 2010 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ *
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include "bg-source.h"
+
+G_BEGIN_DECLS
+
+#define BG_TYPE_WALLPAPERS_SOURCE (bg_wallpapers_source_get_type ())
+G_DECLARE_FINAL_TYPE (BgWallpapersSource, bg_wallpapers_source, BG, WALLPAPERS_SOURCE, BgSource)
+
+BgWallpapersSource *bg_wallpapers_source_new (GtkWidget *widget);
+
+G_END_DECLS
diff --git a/panels/background/cc-background-chooser.c b/panels/background/cc-background-chooser.c
new file mode 100644
index 0000000..8d24e45
--- /dev/null
+++ b/panels/background/cc-background-chooser.c
@@ -0,0 +1,337 @@
+/* cc-background-chooser.c
+ *
+ * Copyright 2019 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "cc-background-chooser"
+
+#include <glib/gi18n.h>
+#include <libgnome-desktop/gnome-desktop-thumbnail.h>
+
+#include "bg-colors-source.h"
+#include "bg-recent-source.h"
+#include "bg-wallpapers-source.h"
+#include "cc-background-chooser.h"
+#include "cc-background-paintable.h"
+
+struct _CcBackgroundChooser
+{
+ GtkBox parent;
+
+ GtkFlowBox *flowbox;
+ GtkWidget *recent_box;
+ GtkFlowBox *recent_flowbox;
+
+ gboolean recent_selected;
+
+ BgWallpapersSource *wallpapers_source;
+ BgRecentSource *recent_source;
+};
+
+G_DEFINE_TYPE (CcBackgroundChooser, cc_background_chooser, GTK_TYPE_BOX)
+
+enum
+{
+ BACKGROUND_CHOSEN,
+ N_SIGNALS,
+};
+
+static guint signals [N_SIGNALS];
+
+static void
+emit_background_chosen (CcBackgroundChooser *self)
+{
+ g_autoptr(GList) list = NULL;
+ CcBackgroundItem *item;
+ GtkFlowBox *flowbox;
+
+ flowbox = self->recent_selected ? self->recent_flowbox : self->flowbox;
+ list = gtk_flow_box_get_selected_children (flowbox);
+ g_assert (g_list_length (list) == 1);
+
+ item = g_object_get_data (list->data, "item");
+
+ g_signal_emit (self, signals[BACKGROUND_CHOSEN], 0, item);
+}
+
+static void
+on_delete_background_clicked_cb (GtkButton *button,
+ BgRecentSource *source)
+{
+ GtkWidget *parent;
+ CcBackgroundItem *item;
+
+ parent = gtk_widget_get_parent (gtk_widget_get_parent (GTK_WIDGET (button)));
+ g_assert (GTK_IS_FLOW_BOX_CHILD (parent));
+
+ item = g_object_get_data (G_OBJECT (parent), "item");
+
+ bg_recent_source_remove_item (source, item);
+}
+
+static void
+direction_changed_cb (GtkWidget *widget,
+ GtkTextDirection *previous_direction,
+ GdkPaintable *paintable)
+{
+ g_object_set (paintable,
+ "text-direction", gtk_widget_get_direction (widget),
+ NULL);
+}
+
+static GtkWidget*
+create_widget_func (gpointer model_item,
+ gpointer user_data)
+{
+ g_autoptr(CcBackgroundPaintable) paintable = NULL;
+ CcBackgroundItem *item;
+ GtkWidget *overlay;
+ GtkWidget *child;
+ GtkWidget *picture;
+ GtkWidget *icon;
+ GtkWidget *check;
+ GtkWidget *button = NULL;
+ BgSource *source;
+
+ source = BG_SOURCE (user_data);
+ item = CC_BACKGROUND_ITEM (model_item);
+
+ paintable = cc_background_paintable_new (source, item);
+
+ picture = gtk_picture_new_for_paintable (GDK_PAINTABLE (paintable));
+ gtk_picture_set_can_shrink (GTK_PICTURE (picture), FALSE);
+
+ g_object_bind_property (picture, "scale-factor",
+ paintable, "scale-factor", G_BINDING_SYNC_CREATE);
+ g_signal_connect_object (picture, "direction-changed",
+ G_CALLBACK (direction_changed_cb), paintable, 0);
+
+ icon = gtk_image_new_from_icon_name ("slideshow-symbolic");
+ gtk_widget_set_halign (icon, GTK_ALIGN_START);
+ gtk_widget_set_valign (icon, GTK_ALIGN_END);
+ gtk_widget_set_visible (icon, cc_background_item_changes_with_time (item));
+ gtk_widget_add_css_class (icon, "slideshow-icon");
+
+ check = gtk_image_new_from_icon_name ("background-selected-symbolic");
+ gtk_widget_set_halign (check, GTK_ALIGN_END);
+ gtk_widget_set_valign (check, GTK_ALIGN_END);
+ gtk_widget_add_css_class (check, "selected-check");
+
+ if (BG_IS_RECENT_SOURCE (source))
+ {
+ button = gtk_button_new_from_icon_name ("window-close-symbolic");
+ gtk_widget_set_halign (button, GTK_ALIGN_END);
+ gtk_widget_set_valign (button, GTK_ALIGN_START);
+
+ gtk_widget_add_css_class (button, "osd");
+ gtk_widget_add_css_class (button, "circular");
+ gtk_widget_add_css_class (button, "remove-button");
+
+ g_signal_connect (button,
+ "clicked",
+ G_CALLBACK (on_delete_background_clicked_cb),
+ source);
+ }
+
+ overlay = gtk_overlay_new ();
+ gtk_widget_set_overflow (overlay, GTK_OVERFLOW_HIDDEN);
+ gtk_widget_add_css_class (overlay, "background-thumbnail");
+ gtk_overlay_set_child (GTK_OVERLAY (overlay), picture);
+ gtk_overlay_add_overlay (GTK_OVERLAY (overlay), icon);
+ gtk_overlay_add_overlay (GTK_OVERLAY (overlay), check);
+ if (button)
+ gtk_overlay_add_overlay (GTK_OVERLAY (overlay), button);
+ gtk_accessible_update_property (GTK_ACCESSIBLE (overlay),
+ GTK_ACCESSIBLE_PROPERTY_LABEL,
+ cc_background_item_get_name (item),
+ -1);
+
+
+ child = gtk_flow_box_child_new ();
+ gtk_widget_set_halign (child, GTK_ALIGN_CENTER);
+ gtk_widget_set_valign (child, GTK_ALIGN_CENTER);
+ gtk_flow_box_child_set_child (GTK_FLOW_BOX_CHILD (child), overlay);
+
+ g_object_set_data_full (G_OBJECT (child), "item", g_object_ref (item), g_object_unref);
+
+ return child;
+}
+
+static void
+update_recent_visibility (CcBackgroundChooser *self)
+{
+ GListStore *store;
+ gboolean has_items;
+
+ store = bg_source_get_liststore (BG_SOURCE (self->recent_source));
+ has_items = g_list_model_get_n_items (G_LIST_MODEL (store)) != 0;
+
+ gtk_widget_set_visible (self->recent_box, has_items);
+}
+
+static void
+setup_flowbox (CcBackgroundChooser *self)
+{
+ GListStore *store;
+
+ store = bg_source_get_liststore (BG_SOURCE (self->wallpapers_source));
+
+ gtk_flow_box_bind_model (self->flowbox,
+ G_LIST_MODEL (store),
+ create_widget_func,
+ self->wallpapers_source,
+ NULL);
+
+ store = bg_source_get_liststore (BG_SOURCE (self->recent_source));
+
+ gtk_flow_box_bind_model (self->recent_flowbox,
+ G_LIST_MODEL (store),
+ create_widget_func,
+ self->recent_source,
+ NULL);
+
+ update_recent_visibility (self);
+ g_signal_connect_object (store,
+ "items-changed",
+ G_CALLBACK (update_recent_visibility),
+ self,
+ G_CONNECT_SWAPPED);
+}
+
+static void
+on_item_activated_cb (GtkFlowBox *flowbox,
+ GtkFlowBoxChild *child,
+ CcBackgroundChooser *self)
+{
+ self->recent_selected = flowbox == self->recent_flowbox;
+ if (self->recent_selected)
+ gtk_flow_box_unselect_all (self->flowbox);
+ else
+ gtk_flow_box_unselect_all (self->recent_flowbox);
+ emit_background_chosen (self);
+}
+
+static void
+on_file_chooser_response_cb (GtkDialog *filechooser,
+ gint response,
+ CcBackgroundChooser *self)
+{
+ if (response == GTK_RESPONSE_ACCEPT)
+ {
+ g_autoptr(GListModel) files = NULL;
+ guint i;
+
+ files = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (filechooser));
+ for (i = 0; i < g_list_model_get_n_items (files); i++)
+ {
+ g_autoptr(GFile) file = g_list_model_get_item (files, i);
+ g_autofree gchar *filename = g_file_get_path (file);
+
+ bg_recent_source_add_file (self->recent_source, filename);
+ }
+ }
+
+ gtk_window_destroy (GTK_WINDOW (filechooser));
+}
+
+/* GObject overrides */
+
+static void
+cc_background_chooser_finalize (GObject *object)
+{
+ CcBackgroundChooser *self = (CcBackgroundChooser *)object;
+
+ g_clear_object (&self->recent_source);
+ g_clear_object (&self->wallpapers_source);
+
+ G_OBJECT_CLASS (cc_background_chooser_parent_class)->finalize (object);
+}
+
+static void
+cc_background_chooser_class_init (CcBackgroundChooserClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = cc_background_chooser_finalize;
+
+ signals[BACKGROUND_CHOSEN] = g_signal_new ("background-chosen",
+ CC_TYPE_BACKGROUND_CHOOSER,
+ G_SIGNAL_RUN_FIRST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 1,
+ CC_TYPE_BACKGROUND_ITEM);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/background/cc-background-chooser.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcBackgroundChooser, flowbox);
+ gtk_widget_class_bind_template_child (widget_class, CcBackgroundChooser, recent_box);
+ gtk_widget_class_bind_template_child (widget_class, CcBackgroundChooser, recent_flowbox);
+
+ gtk_widget_class_bind_template_callback (widget_class, on_item_activated_cb);
+}
+
+static void
+cc_background_chooser_init (CcBackgroundChooser *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->recent_source = bg_recent_source_new (GTK_WIDGET (self));
+ self->wallpapers_source = bg_wallpapers_source_new (GTK_WIDGET (self));
+ setup_flowbox (self);
+}
+
+void
+cc_background_chooser_select_file (CcBackgroundChooser *self)
+{
+ g_autoptr(GFile) pictures_folder = NULL;
+ GtkFileFilter *filter;
+ GtkWidget *filechooser;
+ GtkWindow *toplevel;
+
+ g_return_if_fail (CC_IS_BACKGROUND_CHOOSER (self));
+
+ toplevel = (GtkWindow*) gtk_widget_get_native (GTK_WIDGET (self));
+ filechooser = gtk_file_chooser_dialog_new (_("Select a picture"),
+ toplevel,
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Open"), GTK_RESPONSE_ACCEPT,
+ NULL);
+ gtk_window_set_modal (GTK_WINDOW (filechooser), TRUE);
+
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_add_pixbuf_formats (filter);
+ gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (filechooser), filter);
+ gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (filechooser), TRUE);
+
+ pictures_folder = g_file_new_for_path (g_get_user_special_dir (G_USER_DIRECTORY_PICTURES));
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (filechooser),
+ pictures_folder,
+ NULL);
+
+ g_signal_connect_object (filechooser,
+ "response",
+ G_CALLBACK (on_file_chooser_response_cb),
+ self,
+ 0);
+
+ gtk_window_present (GTK_WINDOW (filechooser));
+}
diff --git a/panels/background/cc-background-chooser.h b/panels/background/cc-background-chooser.h
new file mode 100644
index 0000000..1751098
--- /dev/null
+++ b/panels/background/cc-background-chooser.h
@@ -0,0 +1,32 @@
+/* cc-background-chooser.h
+ *
+ * Copyright 2019 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_BACKGROUND_CHOOSER (cc_background_chooser_get_type())
+G_DECLARE_FINAL_TYPE (CcBackgroundChooser, cc_background_chooser, CC, BACKGROUND_CHOOSER, GtkBox)
+
+void cc_background_chooser_select_file (CcBackgroundChooser *self);
+
+G_END_DECLS
diff --git a/panels/background/cc-background-chooser.ui b/panels/background/cc-background-chooser.ui
new file mode 100644
index 0000000..edaf1dd
--- /dev/null
+++ b/panels/background/cc-background-chooser.ui
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcBackgroundChooser" parent="GtkBox">
+ <property name="orientation">vertical</property>
+
+ <!-- Recent -->
+ <child>
+ <object class="GtkBox" id="recent_box">
+ <property name="orientation">vertical</property>
+ <property name="halign">center</property>
+
+ <child>
+ <object class="GtkFlowBox" id="recent_flowbox">
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="column-spacing">12</property>
+ <property name="row-spacing">12</property>
+ <property name="homogeneous">True</property>
+ <property name="halign">center</property>
+ <property name="min-children-per-line">1</property>
+ <property name="max-children-per-line">8</property>
+ <property name="activate-on-single-click">True</property>
+ <property name="selection-mode">single</property>
+ <signal name="child-activated" handler="on_item_activated_cb" object="CcBackgroundChooser" swapped="no" />
+ <style>
+ <class name="background-flowbox"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkSeparator">
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkFlowBox" id="flowbox">
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="column-spacing">12</property>
+ <property name="row-spacing">12</property>
+ <property name="homogeneous">True</property>
+ <property name="halign">center</property>
+ <property name="min-children-per-line">1</property>
+ <property name="max-children-per-line">8</property>
+ <property name="activate-on-single-click">True</property>
+ <property name="selection-mode">single</property>
+ <signal name="child-activated" handler="on_item_activated_cb" object="CcBackgroundChooser" swapped="no" />
+ <style>
+ <class name="background-flowbox"/>
+ </style>
+ </object>
+ </child>
+
+ </template>
+</interface>
diff --git a/panels/background/cc-background-item.c b/panels/background/cc-background-item.c
new file mode 100644
index 0000000..e25c8c4
--- /dev/null
+++ b/panels/background/cc-background-item.c
@@ -0,0 +1,1062 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010-2011 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <gtk/gtk.h>
+#include <gio/gio.h>
+#include <glib/gi18n-lib.h>
+
+#include <gnome-bg/gnome-bg.h>
+#include <gdesktop-enums.h>
+
+#include "cc-background-item.h"
+#include "gdesktop-enums-types.h"
+
+typedef struct {
+ int width;
+ int height;
+ int frame;
+ int scale_factor;
+ GdkPixbuf *thumbnail;
+} CachedThumbnail;
+
+struct _CcBackgroundItem
+{
+ GObject parent_instance;
+
+ /* properties */
+ char *name;
+ char *uri;
+ char *uri_dark;
+ char *size;
+ GDesktopBackgroundStyle placement;
+ GDesktopBackgroundShading shading;
+ char *primary_color;
+ char *secondary_color;
+ char *source_url; /* Used by the Flickr source */
+ char *source_xml; /* Used by the Wallpapers source */
+ gboolean is_deleted;
+ gboolean needs_download;
+ CcBackgroundItemFlags flags;
+ guint64 modified;
+
+ /* internal */
+ GnomeBG *bg;
+ char *mime_type;
+ int width;
+ int height;
+
+ GnomeBG *bg_dark;
+
+ CachedThumbnail cached_thumbnail;
+ CachedThumbnail cached_thumbnail_dark;
+};
+
+enum {
+ PROP_0,
+ PROP_NAME,
+ PROP_URI,
+ PROP_URI_DARK,
+ PROP_PLACEMENT,
+ PROP_SHADING,
+ PROP_PRIMARY_COLOR,
+ PROP_SECONDARY_COLOR,
+ PROP_IS_DELETED,
+ PROP_SOURCE_URL,
+ PROP_SOURCE_XML,
+ PROP_FLAGS,
+ PROP_SIZE,
+ PROP_NEEDS_DOWNLOAD,
+ PROP_MODIFIED
+};
+
+static void cc_background_item_finalize (GObject *object);
+
+G_DEFINE_TYPE (CcBackgroundItem, cc_background_item, G_TYPE_OBJECT)
+
+static void
+set_bg_properties (CcBackgroundItem *item)
+{
+ GdkRGBA pcolor = { 0, 0, 0, 0 };
+ GdkRGBA scolor = { 0, 0, 0, 0 };
+
+ if (item->uri) {
+ g_autoptr(GFile) file = NULL;
+ g_autofree gchar *filename = NULL;
+
+ file = g_file_new_for_commandline_arg (item->uri);
+ filename = g_file_get_path (file);
+ gnome_bg_set_filename (item->bg, filename);
+ }
+
+ if (item->uri_dark) {
+ g_autoptr(GFile) file = NULL;
+ g_autofree gchar *filename = NULL;
+
+ file = g_file_new_for_commandline_arg (item->uri_dark);
+ filename = g_file_get_path (file);
+ gnome_bg_set_filename (item->bg_dark, filename);
+ }
+
+ if (item->primary_color != NULL) {
+ gdk_rgba_parse (&pcolor, item->primary_color);
+ }
+ if (item->secondary_color != NULL) {
+ gdk_rgba_parse (&scolor, item->secondary_color);
+ }
+
+ gnome_bg_set_rgba (item->bg, item->shading, &pcolor, &scolor);
+ gnome_bg_set_rgba (item->bg_dark, item->shading, &pcolor, &scolor);
+ gnome_bg_set_placement (item->bg, item->placement);
+ gnome_bg_set_placement (item->bg_dark, item->placement);
+}
+
+
+gboolean
+cc_background_item_changes_with_time (CcBackgroundItem *item)
+{
+ gboolean changes;
+
+ g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), FALSE);
+
+ changes = FALSE;
+ if (item->bg != NULL) {
+ changes = gnome_bg_changes_with_time (item->bg);
+ }
+ if (item->bg_dark != NULL) {
+ changes |= gnome_bg_changes_with_time (item->bg_dark);
+ }
+ return changes;
+}
+
+gboolean
+cc_background_item_has_dark_version (CcBackgroundItem *item)
+{
+ g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), FALSE);
+
+ return item->uri && item->uri_dark;
+}
+
+static void
+update_size (CcBackgroundItem *item)
+{
+ g_clear_pointer (&item->size, g_free);
+
+ if (item->uri == NULL) {
+ item->size = g_strdup ("");
+ } else {
+ if (gnome_bg_has_multiple_sizes (item->bg) || gnome_bg_changes_with_time (item->bg)) {
+ item->size = g_strdup (_("multiple sizes"));
+ } else {
+ /* translators: 100 × 100px
+ * Note that this is not an "x", but U+00D7 MULTIPLICATION SIGN */
+ item->size = g_strdup_printf (_("%d × %d"),
+ item->width,
+ item->height);
+ }
+ }
+}
+
+static GdkPixbuf *
+render_at_size (GnomeBG *bg,
+ gint width,
+ gint height)
+{
+ GdkPixbuf *pixbuf;
+
+ pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height);
+ gnome_bg_draw (bg, pixbuf);
+
+ return pixbuf;
+}
+
+GdkPixbuf *
+cc_background_item_get_frame_thumbnail (CcBackgroundItem *item,
+ GnomeDesktopThumbnailFactory *thumbs,
+ int width,
+ int height,
+ int scale_factor,
+ int frame,
+ gboolean force_size,
+ gboolean dark)
+{
+ g_autoptr(GdkPixbuf) pixbuf = NULL;
+ g_autoptr(GdkPixbuf) retval = NULL;
+ CachedThumbnail *thumbnail;
+ GnomeBG *bg;
+
+ g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
+ g_return_val_if_fail (width > 0 && height > 0, NULL);
+
+ thumbnail = dark ? &item->cached_thumbnail_dark : &item->cached_thumbnail;
+ bg = dark ? item->bg_dark : item->bg;
+
+ /* Use the cached thumbnail if the sizes match */
+ if (thumbnail->thumbnail &&
+ thumbnail->width == width &&
+ thumbnail->height == height &&
+ thumbnail->scale_factor == scale_factor &&
+ thumbnail->frame == frame)
+ return g_object_ref (thumbnail->thumbnail);
+
+ set_bg_properties (item);
+
+ if (force_size) {
+ /* FIXME: this doesn't play nice with slideshow stepping at all,
+ * because it will always render the current slideshow frame, which
+ * might not be what we want.
+ * We're lacking an API to draw a high-res GnomeBG manually choosing
+ * the slideshow frame though, so we can't do much better than this
+ * for now.
+ */
+ pixbuf = render_at_size (bg, width, height);
+ } else {
+ g_autoptr(GdkMonitor) monitor = NULL;
+ GdkDisplay *display;
+ GListModel *monitors;
+ GdkRectangle monitor_layout;
+
+
+ display = gdk_display_get_default ();
+ monitors = gdk_display_get_monitors (display);
+ monitor = g_list_model_get_item (monitors, 0);
+ gdk_monitor_get_geometry (monitor, &monitor_layout);
+
+ if (frame >= 0) {
+ pixbuf = gnome_bg_create_frame_thumbnail (bg,
+ thumbs,
+ &monitor_layout,
+ width,
+ height,
+ frame);
+ } else {
+ pixbuf = gnome_bg_create_thumbnail (bg,
+ thumbs,
+ &monitor_layout,
+ width,
+ height);
+ }
+ }
+
+ retval = g_steal_pointer (&pixbuf);
+
+ gnome_bg_get_image_size (bg,
+ thumbs,
+ width,
+ height,
+ &item->width,
+ &item->height);
+
+ update_size (item);
+
+ /* Cache the new thumbnail */
+ g_set_object (&thumbnail->thumbnail, retval);
+ thumbnail->width = width;
+ thumbnail->height = height;
+ thumbnail->scale_factor = scale_factor;
+ thumbnail->frame = frame;
+
+ return g_steal_pointer (&retval);
+}
+
+
+GdkPixbuf *
+cc_background_item_get_thumbnail (CcBackgroundItem *item,
+ GnomeDesktopThumbnailFactory *thumbs,
+ int width,
+ int height,
+ int scale_factor,
+ gboolean dark)
+{
+ return cc_background_item_get_frame_thumbnail (item, thumbs, width, height, scale_factor, -1, FALSE, dark);
+}
+
+static void
+update_info (CcBackgroundItem *item,
+ GFileInfo *_info)
+{
+ g_autoptr(GFileInfo) info = NULL;
+
+ if (_info == NULL) {
+ g_autoptr(GFile) file = NULL;
+
+ file = g_file_new_for_uri (item->uri);
+
+ info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_STANDARD_NAME ","
+ G_FILE_ATTRIBUTE_STANDARD_SIZE ","
+ G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
+ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME ","
+ G_FILE_ATTRIBUTE_TIME_MODIFIED,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ NULL);
+ } else {
+ info = g_object_ref (_info);
+ }
+
+ g_clear_pointer (&item->mime_type, g_free);
+
+ if (info == NULL
+ || g_file_info_get_content_type (info) == NULL) {
+ if (item->uri == NULL) {
+ item->mime_type = g_strdup ("image/x-no-data");
+ g_free (item->name);
+ item->name = g_strdup (_("No Desktop Background"));
+ }
+ } else {
+ if (item->name == NULL)
+ item->name = g_strdup (g_file_info_get_display_name (info));
+
+ item->mime_type = g_strdup (g_file_info_get_content_type (info));
+ if (item->modified == 0)
+ item->modified = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
+ }
+}
+
+gboolean
+cc_background_item_load (CcBackgroundItem *item,
+ GFileInfo *info)
+{
+ g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), FALSE);
+
+ if (item->uri == NULL)
+ return TRUE;
+
+ update_info (item, info);
+
+ if (item->mime_type != NULL
+ && (g_str_has_prefix (item->mime_type, "image/")
+ || strcmp (item->mime_type, "application/xml") == 0)) {
+ set_bg_properties (item);
+ } else {
+ return FALSE;
+ }
+
+ /* FIXME we should handle XML files as well */
+ if (item->mime_type != NULL &&
+ g_str_has_prefix (item->mime_type, "image/")) {
+ g_autofree gchar *filename = NULL;
+
+ filename = g_filename_from_uri (item->uri, NULL, NULL);
+ gdk_pixbuf_get_file_info (filename,
+ &item->width,
+ &item->height);
+ update_size (item);
+ }
+
+ return TRUE;
+}
+
+static void
+_set_name (CcBackgroundItem *item,
+ const char *value)
+{
+ g_free (item->name);
+ item->name = g_strdup (value);
+}
+
+const char *
+cc_background_item_get_name (CcBackgroundItem *item)
+{
+ g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
+
+ return item->name;
+}
+
+static void
+_set_uri (CcBackgroundItem *item,
+ const char *value)
+{
+ g_free (item->uri);
+ if (value && *value == '\0') {
+ item->uri = NULL;
+ } else {
+ if (value && strstr (value, "://") == NULL)
+ g_warning ("URI '%s' is invalid", value);
+ item->uri = g_strdup (value);
+ }
+}
+
+
+static void
+_set_uri_dark (CcBackgroundItem *item,
+ const char *value)
+{
+ g_free (item->uri_dark);
+ if (value && *value == '\0') {
+ item->uri_dark = NULL;
+ } else {
+ if (value && strstr (value, "://") == NULL)
+ g_warning ("URI '%s' is invalid", value);
+ item->uri_dark = g_strdup (value);
+ }
+}
+
+const char *
+cc_background_item_get_uri (CcBackgroundItem *item)
+{
+ g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
+
+ return item->uri;
+}
+
+const char *
+cc_background_item_get_uri_dark (CcBackgroundItem *item)
+{
+ g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
+
+ return item->uri_dark;
+}
+
+static void
+_set_placement (CcBackgroundItem *item,
+ GDesktopBackgroundStyle value)
+{
+ item->placement = value;
+}
+
+static void
+_set_shading (CcBackgroundItem *item,
+ GDesktopBackgroundShading value)
+{
+ item->shading = value;
+}
+
+static void
+_set_primary_color (CcBackgroundItem *item,
+ const char *value)
+{
+ g_free (item->primary_color);
+ item->primary_color = g_strdup (value);
+}
+
+const char *
+cc_background_item_get_pcolor (CcBackgroundItem *item)
+{
+ g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
+
+ return item->primary_color;
+}
+
+static void
+_set_secondary_color (CcBackgroundItem *item,
+ const char *value)
+{
+ g_free (item->secondary_color);
+ item->secondary_color = g_strdup (value);
+}
+
+const char *
+cc_background_item_get_scolor (CcBackgroundItem *item)
+{
+ g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
+
+ return item->secondary_color;
+}
+
+GDesktopBackgroundStyle
+cc_background_item_get_placement (CcBackgroundItem *item)
+{
+ g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), G_DESKTOP_BACKGROUND_STYLE_SCALED);
+
+ return item->placement;
+}
+
+GDesktopBackgroundShading
+cc_background_item_get_shading (CcBackgroundItem *item)
+{
+ g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), G_DESKTOP_BACKGROUND_SHADING_SOLID);
+
+ return item->shading;
+}
+
+static void
+_set_is_deleted (CcBackgroundItem *item,
+ gboolean value)
+{
+ item->is_deleted = value;
+}
+
+static void
+_set_source_url (CcBackgroundItem *item,
+ const char *value)
+{
+ g_free (item->source_url);
+ item->source_url = g_strdup (value);
+}
+
+const char *
+cc_background_item_get_source_url (CcBackgroundItem *item)
+{
+ g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
+
+ return item->source_url;
+}
+
+static void
+_set_source_xml (CcBackgroundItem *item,
+ const char *value)
+{
+ g_free (item->source_xml);
+ item->source_xml = g_strdup (value);
+}
+
+const char *
+cc_background_item_get_source_xml (CcBackgroundItem *item)
+{
+ g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
+
+ return item->source_xml;
+}
+
+static void
+_set_flags (CcBackgroundItem *item,
+ CcBackgroundItemFlags value)
+{
+ item->flags = value;
+}
+
+CcBackgroundItemFlags
+cc_background_item_get_flags (CcBackgroundItem *item)
+{
+ g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), 0);
+
+ return item->flags;
+}
+
+const char *
+cc_background_item_get_size (CcBackgroundItem *item)
+{
+ g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
+
+ return item->size;
+}
+
+static void
+_set_needs_download (CcBackgroundItem *item,
+ gboolean value)
+{
+ item->needs_download = value;
+}
+
+gboolean
+cc_background_item_get_needs_download (CcBackgroundItem *item)
+{
+ g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), 0);
+
+ return item->needs_download;
+}
+
+static void
+_set_modified (CcBackgroundItem *item,
+ guint64 value)
+{
+ item->modified = value;
+}
+
+guint64
+cc_background_item_get_modified (CcBackgroundItem *item)
+{
+ g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), 0);
+
+ return item->modified;
+}
+
+static void
+cc_background_item_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcBackgroundItem *self;
+
+ self = CC_BACKGROUND_ITEM (object);
+
+ switch (prop_id) {
+ case PROP_NAME:
+ _set_name (self, g_value_get_string (value));
+ break;
+ case PROP_URI:
+ _set_uri (self, g_value_get_string (value));
+ break;
+ case PROP_URI_DARK:
+ _set_uri_dark (self, g_value_get_string (value));
+ break;
+ case PROP_PLACEMENT:
+ _set_placement (self, g_value_get_enum (value));
+ break;
+ case PROP_SHADING:
+ _set_shading (self, g_value_get_enum (value));
+ break;
+ case PROP_PRIMARY_COLOR:
+ _set_primary_color (self, g_value_get_string (value));
+ break;
+ case PROP_SECONDARY_COLOR:
+ _set_secondary_color (self, g_value_get_string (value));
+ break;
+ case PROP_IS_DELETED:
+ _set_is_deleted (self, g_value_get_boolean (value));
+ break;
+ case PROP_SOURCE_URL:
+ _set_source_url (self, g_value_get_string (value));
+ break;
+ case PROP_SOURCE_XML:
+ _set_source_xml (self, g_value_get_string (value));
+ break;
+ case PROP_FLAGS:
+ _set_flags (self, g_value_get_flags (value));
+ break;
+ case PROP_NEEDS_DOWNLOAD:
+ _set_needs_download (self, g_value_get_boolean (value));
+ break;
+ case PROP_MODIFIED:
+ _set_modified (self, g_value_get_uint64 (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_background_item_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcBackgroundItem *self;
+
+ self = CC_BACKGROUND_ITEM (object);
+
+ switch (prop_id) {
+ case PROP_NAME:
+ g_value_set_string (value, self->name);
+ break;
+ case PROP_URI:
+ g_value_set_string (value, self->uri);
+ break;
+ case PROP_URI_DARK:
+ g_value_set_string (value, self->uri_dark);
+ break;
+ case PROP_PLACEMENT:
+ g_value_set_enum (value, self->placement);
+ break;
+ case PROP_SHADING:
+ g_value_set_enum (value, self->shading);
+ break;
+ case PROP_PRIMARY_COLOR:
+ g_value_set_string (value, self->primary_color);
+ break;
+ case PROP_SECONDARY_COLOR:
+ g_value_set_string (value, self->secondary_color);
+ break;
+ case PROP_IS_DELETED:
+ g_value_set_boolean (value, self->is_deleted);
+ break;
+ case PROP_SOURCE_URL:
+ g_value_set_string (value, self->source_url);
+ break;
+ case PROP_SOURCE_XML:
+ g_value_set_string (value, self->source_xml);
+ break;
+ case PROP_FLAGS:
+ g_value_set_flags (value, self->flags);
+ break;
+ case PROP_SIZE:
+ g_value_set_string (value, self->size);
+ break;
+ case PROP_NEEDS_DOWNLOAD:
+ g_value_set_boolean (value, self->needs_download);
+ break;
+ case PROP_MODIFIED:
+ g_value_set_uint64 (value, self->modified);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+cc_background_item_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ CcBackgroundItem *background_item;
+
+ background_item = CC_BACKGROUND_ITEM (G_OBJECT_CLASS (cc_background_item_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (background_item);
+}
+
+static void
+cc_background_item_class_init (CcBackgroundItemClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = cc_background_item_get_property;
+ object_class->set_property = cc_background_item_set_property;
+ object_class->constructor = cc_background_item_constructor;
+ object_class->finalize = cc_background_item_finalize;
+
+ g_object_class_install_property (object_class,
+ PROP_NAME,
+ g_param_spec_string ("name",
+ "name",
+ "name",
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_URI,
+ g_param_spec_string ("uri",
+ "uri",
+ "uri",
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_URI_DARK,
+ g_param_spec_string ("uri-dark",
+ "uri-dark",
+ "uri-dark",
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_PLACEMENT,
+ g_param_spec_enum ("placement",
+ "placement",
+ "placement",
+ G_DESKTOP_TYPE_DESKTOP_BACKGROUND_STYLE,
+ G_DESKTOP_BACKGROUND_STYLE_SCALED,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_SHADING,
+ g_param_spec_enum ("shading",
+ "shading",
+ "shading",
+ G_DESKTOP_TYPE_DESKTOP_BACKGROUND_SHADING,
+ G_DESKTOP_BACKGROUND_SHADING_SOLID,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_PRIMARY_COLOR,
+ g_param_spec_string ("primary-color",
+ "primary-color",
+ "primary-color",
+ "#000000000000",
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_SECONDARY_COLOR,
+ g_param_spec_string ("secondary-color",
+ "secondary-color",
+ "secondary-color",
+ "#000000000000",
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_IS_DELETED,
+ g_param_spec_boolean ("is-deleted",
+ NULL,
+ NULL,
+ FALSE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_SOURCE_URL,
+ g_param_spec_string ("source-url",
+ "source-url",
+ "source-url",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_SOURCE_XML,
+ g_param_spec_string ("source-xml",
+ "source-xml",
+ "source-xml",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_FLAGS,
+ g_param_spec_flags ("flags",
+ "flags",
+ "flags",
+ G_DESKTOP_TYPE_BACKGROUND_ITEM_FLAGS,
+ 0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_SIZE,
+ g_param_spec_string ("size",
+ "size",
+ "size",
+ NULL,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (object_class,
+ PROP_NEEDS_DOWNLOAD,
+ g_param_spec_boolean ("needs-download",
+ NULL,
+ NULL,
+ TRUE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_MODIFIED,
+ g_param_spec_uint64 ("modified",
+ "modified",
+ NULL,
+ 0,
+ G_MAXUINT64,
+ 0,
+ G_PARAM_READWRITE));
+}
+
+static void
+cc_background_item_init (CcBackgroundItem *item)
+{
+ item->bg = gnome_bg_new ();
+ item->bg_dark = gnome_bg_new ();
+
+ item->shading = G_DESKTOP_BACKGROUND_SHADING_SOLID;
+ item->placement = G_DESKTOP_BACKGROUND_STYLE_SCALED;
+ item->primary_color = g_strdup ("#000000000000");
+ item->secondary_color = g_strdup ("#000000000000");
+ item->needs_download = TRUE;
+ item->flags = 0;
+ item->modified = 0;
+}
+
+static void
+cc_background_item_finalize (GObject *object)
+{
+ CcBackgroundItem *item;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (CC_IS_BACKGROUND_ITEM (object));
+
+ item = CC_BACKGROUND_ITEM (object);
+
+ g_return_if_fail (item != NULL);
+
+ g_clear_object (&item->cached_thumbnail.thumbnail);
+ g_clear_object (&item->cached_thumbnail_dark.thumbnail);
+ g_free (item->name);
+ g_free (item->uri);
+ g_free (item->primary_color);
+ g_free (item->secondary_color);
+ g_free (item->mime_type);
+ g_free (item->size);
+ g_free (item->source_url);
+ g_free (item->source_xml);
+
+ g_clear_object (&item->bg);
+ g_clear_object (&item->bg_dark);
+
+ G_OBJECT_CLASS (cc_background_item_parent_class)->finalize (object);
+}
+
+CcBackgroundItem *
+cc_background_item_new (const char *uri)
+{
+ GObject *object;
+
+ object = g_object_new (CC_TYPE_BACKGROUND_ITEM,
+ "uri", uri,
+ NULL);
+
+ return CC_BACKGROUND_ITEM (object);
+}
+
+CcBackgroundItem *
+cc_background_item_copy (CcBackgroundItem *item)
+{
+ CcBackgroundItem *ret;
+
+ ret = cc_background_item_new (item->uri);
+ ret->name = g_strdup (item->name);
+ ret->size = g_strdup (item->size);
+ ret->placement = item->placement;
+ ret->shading = item->shading;
+ ret->primary_color = g_strdup (item->primary_color);
+ ret->secondary_color = g_strdup (item->secondary_color);
+ ret->source_url = g_strdup (item->source_url);
+ ret->source_xml = g_strdup (item->source_xml);
+ ret->is_deleted = item->is_deleted;
+ ret->needs_download = item->needs_download;
+ ret->flags = item->flags;
+
+ return ret;
+}
+
+static const char *
+flags_to_str (CcBackgroundItemFlags flag)
+{
+ GFlagsClass *fclass;
+ GFlagsValue *value;
+
+ fclass = G_FLAGS_CLASS (g_type_class_peek (G_DESKTOP_TYPE_BACKGROUND_ITEM_FLAGS));
+ value = g_flags_get_first_value (fclass, flag);
+
+ g_assert (value);
+
+ return value->value_nick;
+}
+
+static const char *
+enum_to_str (GType type,
+ int v)
+{
+ GEnumClass *eclass;
+ GEnumValue *value;
+
+ eclass = G_ENUM_CLASS (g_type_class_peek (type));
+ value = g_enum_get_value (eclass, v);
+
+ g_assert (value);
+
+ return value->value_nick;
+}
+
+void
+cc_background_item_dump (CcBackgroundItem *item)
+{
+ g_autoptr(GString) flags = NULL;
+ int i;
+
+ g_return_if_fail (CC_IS_BACKGROUND_ITEM (item));
+
+ g_debug ("name:\t\t\t%s", item->name);
+ g_debug ("URI:\t\t\t%s", item->uri ? item->uri : "NULL");
+ if (item->size)
+ g_debug ("size:\t\t\t'%s'", item->size);
+ flags = g_string_new (NULL);
+ for (i = 0; i < 5; i++) {
+ if (item->flags & (1 << i)) {
+ g_string_append (flags, flags_to_str (1 << i));
+ g_string_append_c (flags, ' ');
+ }
+ }
+ if (flags->len == 0)
+ g_string_append (flags, "-none-");
+ g_debug ("flags:\t\t\t%s", flags->str);
+ if (item->primary_color)
+ g_debug ("pcolor:\t\t\t%s", item->primary_color);
+ if (item->secondary_color)
+ g_debug ("scolor:\t\t\t%s", item->secondary_color);
+ g_debug ("placement:\t\t%s", enum_to_str (G_DESKTOP_TYPE_DESKTOP_BACKGROUND_STYLE, item->placement));
+ g_debug ("shading:\t\t%s", enum_to_str (G_DESKTOP_TYPE_DESKTOP_BACKGROUND_SHADING, item->shading));
+ if (item->source_url)
+ g_debug ("source URL:\t\t%s", item->source_url);
+ if (item->source_xml)
+ g_debug ("source XML:\t\t%s", item->source_xml);
+ g_debug ("deleted:\t\t%s", item->is_deleted ? "yes" : "no");
+ if (item->mime_type)
+ g_debug ("mime-type:\t\t%s", item->mime_type);
+ g_debug ("dimensions:\t\t%d x %d", item->width, item->height);
+ g_debug ("modified: %"G_GUINT64_FORMAT, item->modified);
+ g_debug (" ");
+}
+
+static gboolean
+files_equal (const char *a,
+ const char *b)
+{
+ g_autoptr(GFile) file1 = NULL;
+ g_autoptr(GFile) file2 = NULL;
+ gboolean retval;
+
+ if (a == NULL &&
+ b == NULL)
+ return TRUE;
+
+ if (a == NULL ||
+ b == NULL)
+ return FALSE;
+
+ file1 = g_file_new_for_commandline_arg (a);
+ file2 = g_file_new_for_commandline_arg (b);
+ if (g_file_equal (file1, file2) == FALSE)
+ retval = FALSE;
+ else
+ retval = TRUE;
+
+ return retval;
+}
+
+static gboolean
+colors_equal (const char *a,
+ const char *b)
+{
+ GdkRGBA color1, color2;
+
+ gdk_rgba_parse (&color1, a);
+ gdk_rgba_parse (&color2, b);
+
+ return gdk_rgba_equal (&color1, &color2);
+}
+
+gboolean
+cc_background_item_compare (CcBackgroundItem *saved,
+ CcBackgroundItem *configured)
+{
+ CcBackgroundItemFlags flags;
+
+ flags = saved->flags;
+ if (flags == 0)
+ return FALSE;
+
+ if (flags & CC_BACKGROUND_ITEM_HAS_URI) {
+ if (files_equal (saved->uri, configured->uri) == FALSE)
+ return FALSE;
+ }
+ if (flags & CC_BACKGROUND_ITEM_HAS_URI_DARK) {
+ if (files_equal (saved->uri_dark, configured->uri_dark) == FALSE)
+ return FALSE;
+ }
+ if (flags & CC_BACKGROUND_ITEM_HAS_SHADING) {
+ if (saved->shading != configured->shading)
+ return FALSE;
+ }
+ if (flags & CC_BACKGROUND_ITEM_HAS_PLACEMENT) {
+ if (saved->placement != configured->placement)
+ return FALSE;
+ }
+ if (flags & CC_BACKGROUND_ITEM_HAS_PCOLOR) {
+ if (colors_equal (saved->primary_color,
+ configured->primary_color) == FALSE) {
+ return FALSE;
+ }
+ }
+ if (flags & CC_BACKGROUND_ITEM_HAS_SCOLOR) {
+ if (colors_equal (saved->secondary_color,
+ configured->secondary_color) == FALSE) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
diff --git a/panels/background/cc-background-item.h b/panels/background/cc-background-item.h
new file mode 100644
index 0000000..80fd5a2
--- /dev/null
+++ b/panels/background/cc-background-item.h
@@ -0,0 +1,88 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010-2011 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <glib-object.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <libgnome-desktop/gnome-desktop-thumbnail.h>
+#include <gdesktop-enums.h>
+#include <gnome-bg/gnome-bg.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_BACKGROUND_ITEM (cc_background_item_get_type ())
+G_DECLARE_FINAL_TYPE (CcBackgroundItem, cc_background_item, CC, BACKGROUND_ITEM, GObject)
+
+typedef enum {
+ CC_BACKGROUND_ITEM_HAS_SHADING = 1 << 0,
+ CC_BACKGROUND_ITEM_HAS_PLACEMENT = 1 << 1,
+ CC_BACKGROUND_ITEM_HAS_PCOLOR = 1 << 2,
+ CC_BACKGROUND_ITEM_HAS_SCOLOR = 1 << 3,
+ CC_BACKGROUND_ITEM_HAS_URI = 1 << 4,
+ CC_BACKGROUND_ITEM_HAS_URI_DARK = 1 << 5
+} CcBackgroundItemFlags;
+
+#define CC_BACKGROUND_ITEM_HAS_ALL (CC_BACKGROUND_ITEM_HAS_SHADING & \
+ CC_BACKGROUND_ITEM_HAS_PLACEMENT & \
+ CC_BACKGROUND_ITEM_HAS_PCOLOR & \
+ CC_BACKGROUND_ITEM_HAS_SCOLOR & \
+ CC_BACKGROUND_ITEM_HAS_FNAME)
+
+CcBackgroundItem * cc_background_item_new (const char *uri);
+CcBackgroundItem * cc_background_item_copy (CcBackgroundItem *item);
+gboolean cc_background_item_load (CcBackgroundItem *item,
+ GFileInfo *info);
+gboolean cc_background_item_changes_with_time (CcBackgroundItem *item);
+gboolean cc_background_item_has_dark_version (CcBackgroundItem *item);
+
+GdkPixbuf * cc_background_item_get_thumbnail (CcBackgroundItem *item,
+ GnomeDesktopThumbnailFactory *thumbs,
+ int width,
+ int height,
+ int scale_factor,
+ gboolean dark);
+GdkPixbuf * cc_background_item_get_frame_thumbnail (CcBackgroundItem *item,
+ GnomeDesktopThumbnailFactory *thumbs,
+ int width,
+ int height,
+ int scale_factor,
+ int frame,
+ gboolean force_size,
+ gboolean dark);
+
+GDesktopBackgroundStyle cc_background_item_get_placement (CcBackgroundItem *item);
+GDesktopBackgroundShading cc_background_item_get_shading (CcBackgroundItem *item);
+const char * cc_background_item_get_uri (CcBackgroundItem *item);
+const char * cc_background_item_get_uri_dark (CcBackgroundItem *item);
+const char * cc_background_item_get_source_url (CcBackgroundItem *item);
+const char * cc_background_item_get_source_xml (CcBackgroundItem *item);
+CcBackgroundItemFlags cc_background_item_get_flags (CcBackgroundItem *item);
+const char * cc_background_item_get_pcolor (CcBackgroundItem *item);
+const char * cc_background_item_get_scolor (CcBackgroundItem *item);
+const char * cc_background_item_get_name (CcBackgroundItem *item);
+const char * cc_background_item_get_size (CcBackgroundItem *item);
+gboolean cc_background_item_get_needs_download (CcBackgroundItem *item);
+guint64 cc_background_item_get_modified (CcBackgroundItem *item);
+
+gboolean cc_background_item_compare (CcBackgroundItem *saved,
+ CcBackgroundItem *configured);
+void cc_background_item_dump (CcBackgroundItem *item);
+
+G_END_DECLS
diff --git a/panels/background/cc-background-paintable.c b/panels/background/cc-background-paintable.c
new file mode 100644
index 0000000..e510736
--- /dev/null
+++ b/panels/background/cc-background-paintable.c
@@ -0,0 +1,314 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2021 Alexander Mikhaylenko <alexm@gnome.org>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+
+#include "cc-background-paintable.h"
+
+struct _CcBackgroundPaintable
+{
+ GObject parent_instance;
+
+ BgSource *source;
+ CcBackgroundItem *item;
+ int scale_factor;
+ GtkTextDirection text_direction;
+
+ GdkPaintable *texture;
+ GdkPaintable *dark_texture;
+};
+
+enum
+{
+ PROP_0,
+ PROP_SOURCE,
+ PROP_ITEM,
+ PROP_SCALE_FACTOR,
+ PROP_TEXT_DIRECTION,
+ N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+static void cc_background_paintable_paintable_init (GdkPaintableInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (CcBackgroundPaintable, cc_background_paintable, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
+ cc_background_paintable_paintable_init))
+
+static void
+update_cache (CcBackgroundPaintable *self)
+{
+ g_autoptr (GdkPixbuf) pixbuf = NULL;
+ GnomeDesktopThumbnailFactory *factory;
+ int width, height;
+
+ g_clear_object (&self->texture);
+ g_clear_object (&self->dark_texture);
+
+ factory = bg_source_get_thumbnail_factory (self->source);
+ width = bg_source_get_thumbnail_width (self->source);
+ height = bg_source_get_thumbnail_height (self->source);
+
+ pixbuf = cc_background_item_get_thumbnail (self->item,
+ factory,
+ width,
+ height,
+ self->scale_factor,
+ FALSE);
+
+ self->texture = GDK_PAINTABLE (gdk_texture_new_for_pixbuf (pixbuf));
+
+ if (cc_background_item_has_dark_version (self->item))
+ {
+ g_autoptr (GdkPixbuf) dark_pixbuf = NULL;
+
+ dark_pixbuf = cc_background_item_get_thumbnail (self->item,
+ factory,
+ width,
+ height,
+ self->scale_factor,
+ TRUE);
+ self->dark_texture = GDK_PAINTABLE (gdk_texture_new_for_pixbuf (dark_pixbuf));
+ }
+
+ gdk_paintable_invalidate_size (GDK_PAINTABLE (self));
+}
+
+static void
+cc_background_paintable_dispose (GObject *object)
+{
+ CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (object);
+
+ g_clear_object (&self->item);
+ g_clear_object (&self->source);
+ g_clear_object (&self->texture);
+ g_clear_object (&self->dark_texture);
+
+ G_OBJECT_CLASS (cc_background_paintable_parent_class)->dispose (object);
+}
+
+static void
+cc_background_paintable_constructed (GObject *object)
+{
+ CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (object);
+
+ G_OBJECT_CLASS (cc_background_paintable_parent_class)->constructed (object);
+
+ update_cache (self);
+}
+
+static void
+cc_background_paintable_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (object);
+
+ switch (prop_id)
+ {
+ case PROP_SOURCE:
+ g_value_set_object (value, self->source);
+ break;
+
+ case PROP_ITEM:
+ g_value_set_object (value, self->item);
+ break;
+
+ case PROP_SCALE_FACTOR:
+ g_value_set_int (value, self->scale_factor);
+ break;
+
+ case PROP_TEXT_DIRECTION:
+ g_value_set_enum (value, self->text_direction);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_background_paintable_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (object);
+
+ switch (prop_id)
+ {
+ case PROP_SOURCE:
+ g_set_object (&self->source, g_value_get_object (value));
+ break;
+
+ case PROP_ITEM:
+ g_set_object (&self->item, g_value_get_object (value));
+ break;
+
+ case PROP_SCALE_FACTOR:
+ self->scale_factor = g_value_get_int (value);
+ update_cache (self);
+ break;
+
+ case PROP_TEXT_DIRECTION:
+ self->text_direction = g_value_get_enum (value);
+ gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_background_paintable_class_init (CcBackgroundPaintableClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = cc_background_paintable_dispose;
+ object_class->constructed = cc_background_paintable_constructed;
+ object_class->get_property = cc_background_paintable_get_property;
+ object_class->set_property = cc_background_paintable_set_property;
+
+ properties[PROP_SOURCE] =
+ g_param_spec_object ("source",
+ "Source",
+ "Source",
+ BG_TYPE_SOURCE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_ITEM] =
+ g_param_spec_object ("item",
+ "Item",
+ "Item",
+ CC_TYPE_BACKGROUND_ITEM,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_SCALE_FACTOR] =
+ g_param_spec_int ("scale-factor",
+ "Scale Factor",
+ "Scale Factor",
+ 1, G_MAXINT, 1,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_TEXT_DIRECTION] =
+ g_param_spec_enum ("text-direction",
+ "Text Direction",
+ "Text Direction",
+ GTK_TYPE_TEXT_DIRECTION,
+ GTK_TEXT_DIR_LTR,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+cc_background_paintable_init (CcBackgroundPaintable *self)
+{
+ self->scale_factor = 1;
+ self->text_direction = GTK_TEXT_DIR_LTR;
+}
+
+static void
+cc_background_paintable_snapshot (GdkPaintable *paintable,
+ GdkSnapshot *snapshot,
+ double width,
+ double height)
+{
+ CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (paintable);
+ gboolean is_rtl;
+
+ if (!self->dark_texture)
+ {
+ gdk_paintable_snapshot (self->texture, snapshot, width, height);
+ return;
+ }
+
+ is_rtl = self->text_direction == GTK_TEXT_DIR_RTL;
+
+ gtk_snapshot_push_clip (GTK_SNAPSHOT (snapshot),
+ &GRAPHENE_RECT_INIT (is_rtl ? width / 2.0f : 0.0f,
+ 0.0f,
+ width / 2.0f,
+ height));
+ gdk_paintable_snapshot (self->texture, snapshot, width, height);
+ gtk_snapshot_pop (GTK_SNAPSHOT (snapshot));
+
+ gtk_snapshot_push_clip (GTK_SNAPSHOT (snapshot),
+ &GRAPHENE_RECT_INIT (is_rtl ? 0.0f : width / 2.0f,
+ 0.0f,
+ width / 2.0f,
+ height));
+ gdk_paintable_snapshot (self->dark_texture, snapshot, width, height);
+ gtk_snapshot_pop (GTK_SNAPSHOT (snapshot));
+}
+
+static int
+cc_background_paintable_get_intrinsic_width (GdkPaintable *paintable)
+{
+ CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (paintable);
+
+ return gdk_paintable_get_intrinsic_width (self->texture) / self->scale_factor;
+}
+
+static int
+cc_background_paintable_get_intrinsic_height (GdkPaintable *paintable)
+{
+ CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (paintable);
+
+ return gdk_paintable_get_intrinsic_height (self->texture) / self->scale_factor;
+}
+
+static double
+cc_background_paintable_get_intrinsic_aspect_ratio (GdkPaintable *paintable)
+{
+ CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (paintable);
+
+ return gdk_paintable_get_intrinsic_aspect_ratio (self->texture);
+}
+
+static void
+cc_background_paintable_paintable_init (GdkPaintableInterface *iface)
+{
+ iface->snapshot = cc_background_paintable_snapshot;
+ iface->get_intrinsic_width = cc_background_paintable_get_intrinsic_width;
+ iface->get_intrinsic_height = cc_background_paintable_get_intrinsic_height;
+ iface->get_intrinsic_aspect_ratio = cc_background_paintable_get_intrinsic_aspect_ratio;
+}
+
+CcBackgroundPaintable *
+cc_background_paintable_new (BgSource *source,
+ CcBackgroundItem *item)
+{
+ g_return_val_if_fail (BG_IS_SOURCE (source), NULL);
+ g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
+
+ return g_object_new (CC_TYPE_BACKGROUND_PAINTABLE,
+ "source", source,
+ "item", item,
+ NULL);
+}
diff --git a/panels/background/cc-background-paintable.h b/panels/background/cc-background-paintable.h
new file mode 100644
index 0000000..75360dc
--- /dev/null
+++ b/panels/background/cc-background-paintable.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2021 Alexander Mikhaylenko <alexm@gnome.org>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "bg-source.h"
+#include "cc-background-item.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_BACKGROUND_PAINTABLE (cc_background_paintable_get_type ())
+G_DECLARE_FINAL_TYPE (CcBackgroundPaintable, cc_background_paintable, CC, BACKGROUND_PAINTABLE, GObject)
+
+CcBackgroundPaintable * cc_background_paintable_new (BgSource *source,
+ CcBackgroundItem *item);
+
+G_END_DECLS
diff --git a/panels/background/cc-background-panel.c b/panels/background/cc-background-panel.c
new file mode 100644
index 0000000..f748e9a
--- /dev/null
+++ b/panels/background/cc-background-panel.c
@@ -0,0 +1,455 @@
+/*
+ * Copyright (C) 2010 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ *
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <glib/gstdio.h>
+
+#include <gdesktop-enums.h>
+
+#include "cc-background-panel.h"
+
+#include "cc-background-chooser.h"
+#include "cc-background-item.h"
+#include "cc-background-preview.h"
+#include "cc-background-resources.h"
+#include "cc-background-xml.h"
+
+#define WP_PATH_ID "org.gnome.desktop.background"
+#define WP_LOCK_PATH_ID "org.gnome.desktop.screensaver"
+#define WP_URI_KEY "picture-uri"
+#define WP_URI_DARK_KEY "picture-uri-dark"
+#define WP_OPTIONS_KEY "picture-options"
+#define WP_SHADING_KEY "color-shading-type"
+#define WP_PCOLOR_KEY "primary-color"
+#define WP_SCOLOR_KEY "secondary-color"
+
+#define INTERFACE_PATH_ID "org.gnome.desktop.interface"
+#define INTERFACE_COLOR_SCHEME_KEY "color-scheme"
+
+struct _CcBackgroundPanel
+{
+ CcPanel parent_instance;
+
+ GDBusConnection *connection;
+
+ GSettings *settings;
+ GSettings *lock_settings;
+ GSettings *interface_settings;
+
+ GnomeDesktopThumbnailFactory *thumb_factory;
+ GDBusProxy *proxy;
+
+ CcBackgroundItem *current_background;
+
+ CcBackgroundChooser *background_chooser;
+ CcBackgroundPreview *default_preview;
+ CcBackgroundPreview *dark_preview;
+ GtkToggleButton *default_toggle;
+ GtkToggleButton *dark_toggle;
+};
+
+CC_PANEL_REGISTER (CcBackgroundPanel, cc_background_panel)
+
+static void
+load_custom_css (CcBackgroundPanel *self)
+{
+ g_autoptr(GtkCssProvider) provider = NULL;
+
+ provider = gtk_css_provider_new ();
+ gtk_css_provider_load_from_resource (provider, "/org/gnome/control-center/background/preview.css");
+ gtk_style_context_add_provider_for_display (gdk_display_get_default (),
+ GTK_STYLE_PROVIDER (provider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+}
+
+static void
+reload_color_scheme_toggles (CcBackgroundPanel *self)
+{
+ GDesktopColorScheme scheme;
+
+ scheme = g_settings_get_enum (self->interface_settings, INTERFACE_COLOR_SCHEME_KEY);
+
+ if (scheme == G_DESKTOP_COLOR_SCHEME_DEFAULT)
+ {
+ gtk_toggle_button_set_active (self->default_toggle, TRUE);
+ }
+ else if (scheme == G_DESKTOP_COLOR_SCHEME_PREFER_DARK)
+ {
+ gtk_toggle_button_set_active (self->dark_toggle, TRUE);
+ }
+ else
+ {
+ gtk_toggle_button_set_active (self->default_toggle, FALSE);
+ gtk_toggle_button_set_active (self->dark_toggle, FALSE);
+ }
+}
+
+static void
+transition_screen (CcBackgroundPanel *self)
+{
+ g_autoptr (GError) error = NULL;
+
+ if (!self->proxy)
+ return;
+
+ g_dbus_proxy_call_sync (self->proxy,
+ "ScreenTransition",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if (error)
+ g_warning ("Couldn't transition screen: %s", error->message);
+}
+
+static void
+set_color_scheme (CcBackgroundPanel *self,
+ GDesktopColorScheme color_scheme)
+{
+ GDesktopColorScheme scheme;
+
+ scheme = g_settings_get_enum (self->interface_settings,
+ INTERFACE_COLOR_SCHEME_KEY);
+
+ /* We have to check the equality manually to avoid starting an unnecessary
+ * screen transition */
+ if (color_scheme == scheme)
+ return;
+
+ transition_screen (self);
+
+ g_settings_set_enum (self->interface_settings,
+ INTERFACE_COLOR_SCHEME_KEY,
+ color_scheme);
+}
+
+/* Color schemes */
+
+static void
+on_color_scheme_toggle_active_cb (CcBackgroundPanel *self)
+{
+ if (gtk_toggle_button_get_active (self->default_toggle))
+ set_color_scheme (self, G_DESKTOP_COLOR_SCHEME_DEFAULT);
+ else if (gtk_toggle_button_get_active (self->dark_toggle))
+ set_color_scheme (self, G_DESKTOP_COLOR_SCHEME_PREFER_DARK);
+}
+
+static void
+got_transition_proxy_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer data)
+{
+ g_autoptr(GError) error = NULL;
+ CcBackgroundPanel *self = data;
+
+ self->proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+
+ if (self->proxy == NULL)
+ {
+ g_warning ("Error creating proxy: %s", error->message);
+ return;
+ }
+}
+
+/* Background */
+
+static void
+update_preview (CcBackgroundPanel *panel)
+{
+ CcBackgroundItem *current_background;
+
+ current_background = panel->current_background;
+ cc_background_preview_set_item (panel->default_preview, current_background);
+ cc_background_preview_set_item (panel->dark_preview, current_background);
+}
+
+static gchar *
+get_save_path (void)
+{
+ return g_build_filename (g_get_user_config_dir (),
+ "gnome-control-center",
+ "backgrounds",
+ "last-edited.xml",
+ NULL);
+}
+
+static void
+reload_current_bg (CcBackgroundPanel *panel)
+{
+ g_autoptr(CcBackgroundItem) saved = NULL;
+ CcBackgroundItem *configured;
+ GSettings *settings = NULL;
+ g_autofree gchar *uri = NULL;
+ g_autofree gchar *dark_uri = NULL;
+ g_autofree gchar *pcolor = NULL;
+ g_autofree gchar *scolor = NULL;
+
+ /* Load the saved configuration */
+ uri = get_save_path ();
+ saved = cc_background_xml_get_item (uri);
+
+ /* initalise the current background information from settings */
+ settings = panel->settings;
+ uri = g_settings_get_string (settings, WP_URI_KEY);
+ if (uri && *uri == '\0')
+ g_clear_pointer (&uri, g_free);
+
+
+ configured = cc_background_item_new (uri);
+
+ dark_uri = g_settings_get_string (settings, WP_URI_DARK_KEY);
+ pcolor = g_settings_get_string (settings, WP_PCOLOR_KEY);
+ scolor = g_settings_get_string (settings, WP_SCOLOR_KEY);
+ g_object_set (G_OBJECT (configured),
+ "name", _("Current background"),
+ "uri-dark", dark_uri,
+ "placement", g_settings_get_enum (settings, WP_OPTIONS_KEY),
+ "shading", g_settings_get_enum (settings, WP_SHADING_KEY),
+ "primary-color", pcolor,
+ "secondary-color", scolor,
+ NULL);
+
+ if (saved != NULL && cc_background_item_compare (saved, configured))
+ {
+ CcBackgroundItemFlags flags;
+ flags = cc_background_item_get_flags (saved);
+ /* Special case for colours */
+ if (cc_background_item_get_placement (saved) == G_DESKTOP_BACKGROUND_STYLE_NONE)
+ flags &=~ (CC_BACKGROUND_ITEM_HAS_PCOLOR | CC_BACKGROUND_ITEM_HAS_SCOLOR);
+ g_object_set (G_OBJECT (configured),
+ "name", cc_background_item_get_name (saved),
+ "flags", flags,
+ "source-url", cc_background_item_get_source_url (saved),
+ "source-xml", cc_background_item_get_source_xml (saved),
+ NULL);
+ }
+
+ g_clear_object (&panel->current_background);
+ panel->current_background = configured;
+ cc_background_item_load (configured, NULL);
+}
+
+static gboolean
+create_save_dir (void)
+{
+ g_autofree char *path = NULL;
+
+ path = g_build_filename (g_get_user_config_dir (),
+ "gnome-control-center",
+ "backgrounds",
+ NULL);
+ if (g_mkdir_with_parents (path, USER_DIR_MODE) < 0)
+ {
+ g_warning ("Failed to create directory '%s'", path);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+set_background (CcBackgroundPanel *panel,
+ GSettings *settings,
+ CcBackgroundItem *item,
+ gboolean set_dark)
+{
+ GDesktopBackgroundStyle style;
+ CcBackgroundItemFlags flags;
+ g_autofree gchar *filename = NULL;
+ const char *uri;
+
+ if (item == NULL)
+ return;
+
+ uri = cc_background_item_get_uri (item);
+ flags = cc_background_item_get_flags (item);
+
+ g_settings_set_string (settings, WP_URI_KEY, uri);
+
+ if (set_dark)
+ {
+ const char *uri_dark;
+
+ uri_dark = cc_background_item_get_uri_dark (item);
+
+ if (uri_dark && uri_dark[0])
+ g_settings_set_string (settings, WP_URI_DARK_KEY, uri_dark);
+ else
+ g_settings_set_string (settings, WP_URI_DARK_KEY, uri);
+ }
+
+ /* Also set the placement if we have a URI and the previous value was none */
+ if (flags & CC_BACKGROUND_ITEM_HAS_PLACEMENT)
+ {
+ g_settings_set_enum (settings, WP_OPTIONS_KEY, cc_background_item_get_placement (item));
+ }
+ else if (uri != NULL)
+ {
+ style = g_settings_get_enum (settings, WP_OPTIONS_KEY);
+ if (style == G_DESKTOP_BACKGROUND_STYLE_NONE)
+ g_settings_set_enum (settings, WP_OPTIONS_KEY, cc_background_item_get_placement (item));
+ }
+
+ if (flags & CC_BACKGROUND_ITEM_HAS_SHADING)
+ g_settings_set_enum (settings, WP_SHADING_KEY, cc_background_item_get_shading (item));
+
+ g_settings_set_string (settings, WP_PCOLOR_KEY, cc_background_item_get_pcolor (item));
+ g_settings_set_string (settings, WP_SCOLOR_KEY, cc_background_item_get_scolor (item));
+
+ /* Apply all changes */
+ g_settings_apply (settings);
+
+ /* Save the source XML if there is one */
+ filename = get_save_path ();
+ if (create_save_dir ())
+ cc_background_xml_save (panel->current_background, filename);
+}
+
+static void
+on_chooser_background_chosen_cb (CcBackgroundPanel *self,
+ CcBackgroundItem *item)
+{
+ set_background (self, self->settings, item, TRUE);
+ set_background (self, self->lock_settings, item, FALSE);
+}
+
+static void
+on_add_picture_button_clicked_cb (CcBackgroundPanel *self)
+{
+ cc_background_chooser_select_file (self->background_chooser);
+}
+
+static const char *
+cc_background_panel_get_help_uri (CcPanel *panel)
+{
+ return "help:gnome-help/look-background";
+}
+
+static void
+cc_background_panel_dispose (GObject *object)
+{
+ CcBackgroundPanel *panel = CC_BACKGROUND_PANEL (object);
+
+ g_clear_object (&panel->settings);
+ g_clear_object (&panel->lock_settings);
+ g_clear_object (&panel->interface_settings);
+ g_clear_object (&panel->thumb_factory);
+ g_clear_object (&panel->proxy);
+
+ G_OBJECT_CLASS (cc_background_panel_parent_class)->dispose (object);
+}
+
+static void
+cc_background_panel_finalize (GObject *object)
+{
+ CcBackgroundPanel *panel = CC_BACKGROUND_PANEL (object);
+
+ g_clear_object (&panel->current_background);
+
+ G_OBJECT_CLASS (cc_background_panel_parent_class)->finalize (object);
+}
+
+static void
+cc_background_panel_class_init (CcBackgroundPanelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ g_type_ensure (CC_TYPE_BACKGROUND_CHOOSER);
+ g_type_ensure (CC_TYPE_BACKGROUND_PREVIEW);
+
+ panel_class->get_help_uri = cc_background_panel_get_help_uri;
+
+ object_class->dispose = cc_background_panel_dispose;
+ object_class->finalize = cc_background_panel_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/background/cc-background-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, background_chooser);
+ gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, default_preview);
+ gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, dark_preview);
+ gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, default_toggle);
+ gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, dark_toggle);
+
+ gtk_widget_class_bind_template_callback (widget_class, on_color_scheme_toggle_active_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_chooser_background_chosen_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_add_picture_button_clicked_cb);
+}
+
+static void
+on_settings_changed (CcBackgroundPanel *panel)
+{
+ reload_current_bg (panel);
+ update_preview (panel);
+}
+
+static void
+cc_background_panel_init (CcBackgroundPanel *panel)
+{
+ g_resources_register (cc_background_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (panel));
+
+ panel->connection = g_application_get_dbus_connection (g_application_get_default ());
+
+ panel->thumb_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
+
+ panel->settings = g_settings_new (WP_PATH_ID);
+ g_settings_delay (panel->settings);
+
+ panel->lock_settings = g_settings_new (WP_LOCK_PATH_ID);
+ g_settings_delay (panel->lock_settings);
+
+ panel->interface_settings = g_settings_new (INTERFACE_PATH_ID);
+
+ /* Load the background */
+ reload_current_bg (panel);
+ update_preview (panel);
+
+ /* Background settings */
+ g_signal_connect_object (panel->settings, "changed", G_CALLBACK (on_settings_changed), panel, G_CONNECT_SWAPPED);
+
+ /* Interface settings */
+ reload_color_scheme_toggles (panel);
+
+ g_signal_connect_object (panel->interface_settings,
+ "changed::" INTERFACE_COLOR_SCHEME_KEY,
+ G_CALLBACK (reload_color_scheme_toggles),
+ panel,
+ G_CONNECT_SWAPPED);
+
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.gnome.Shell",
+ "/org/gnome/Shell",
+ "org.gnome.Shell",
+ NULL,
+ got_transition_proxy_cb,
+ panel);
+
+ load_custom_css (panel);
+}
diff --git a/panels/background/cc-background-panel.h b/panels/background/cc-background-panel.h
new file mode 100644
index 0000000..abc894a
--- /dev/null
+++ b/panels/background/cc-background-panel.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2010 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ *
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_BACKGROUND_PANEL (cc_background_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcBackgroundPanel, cc_background_panel, CC, BACKGROUND_PANEL, CcPanel)
+
+G_END_DECLS
diff --git a/panels/background/cc-background-panel.ui b/panels/background/cc-background-panel.ui
new file mode 100644
index 0000000..33a8638
--- /dev/null
+++ b/panels/background/cc-background-panel.ui
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcBackgroundPanel" parent="CcPanel">
+ <child type="content">
+ <object class="AdwPreferencesPage">
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Style</property>
+
+ <child>
+ <object class="AdwPreferencesRow">
+ <property name="activatable">False</property>
+ <property name="focusable">False</property>
+ <child>
+ <object class="AdwClamp">
+ <property name="maximum_size">400</property>
+ <property name="tightening_threshold">300</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="column-homogeneous">True</property>
+ <property name="column-spacing">24</property>
+ <property name="row-spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="margin-top">18</property>
+ <property name="margin-bottom">12</property>
+ <property name="hexpand">True</property>
+ <child>
+ <object class="GtkToggleButton" id="default_toggle">
+ <accessibility>
+ <relation name="labelled-by">default_label</relation>
+ </accessibility>
+ <signal name="notify::active" handler="on_color_scheme_toggle_active_cb" swapped="true"/>
+ <child>
+ <object class="CcBackgroundPreview" id="default_preview"/>
+ </child>
+ <style>
+ <class name="background-preview-button"/>
+ </style>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="default_label">
+ <property name="label" translatable="yes">Default</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="dark_toggle">
+ <property name="group">default_toggle</property>
+ <accessibility>
+ <relation name="labelled-by">dark_label</relation>
+ </accessibility>
+ <signal name="notify::active" handler="on_color_scheme_toggle_active_cb" swapped="true"/>
+ <child>
+ <object class="CcBackgroundPreview" id="dark_preview">
+ <property name="is-dark">True</property>
+ </object>
+ </child>
+ <style>
+ <class name="background-preview-button"/>
+ </style>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="dark_label">
+ <property name="label" translatable="yes">Dark</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Background</property>
+ <property name="header-suffix">
+ <object class="GtkButton">
+ <child>
+ <object class="AdwButtonContent">
+ <property name="icon-name">list-add-symbolic</property>
+ <property name="label" translatable="yes">Add Picture…</property>
+ </object>
+ </child>
+ <signal name="clicked" handler="on_add_picture_button_clicked_cb" object="CcBackgroundPanel" swapped="yes" />
+ <style>
+ <class name="flat"/>
+ </style>
+ </object>
+ </property>
+
+ <child>
+ <object class="AdwBin">
+ <style>
+ <class name="card"/>
+ </style>
+ <child>
+ <object class="CcBackgroundChooser" id="background_chooser">
+ <property name="hexpand">True</property>
+ <signal name="background-chosen" handler="on_chooser_background_chosen_cb" object="CcBackgroundPanel" swapped="yes" />
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/background/cc-background-preview.c b/panels/background/cc-background-preview.c
new file mode 100644
index 0000000..428c44f
--- /dev/null
+++ b/panels/background/cc-background-preview.c
@@ -0,0 +1,351 @@
+/* cc-background-preview.c
+ *
+ * Copyright 2019 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <libgnome-desktop/gnome-desktop-thumbnail.h>
+
+#include "cc-background-preview.h"
+
+struct _CcBackgroundPreview
+{
+ GtkWidget parent;
+
+ GtkWidget *drawing_area;
+ GtkWidget *light_dark_window;
+ GtkWidget *dark_window;
+
+ GnomeDesktopThumbnailFactory *thumbnail_factory;
+
+ gboolean is_dark;
+ CcBackgroundItem *item;
+};
+
+G_DEFINE_TYPE (CcBackgroundPreview, cc_background_preview, GTK_TYPE_WIDGET)
+
+enum
+{
+ PROP_0,
+ PROP_IS_DARK,
+ PROP_ITEM,
+ N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+/* Callbacks */
+
+static void
+draw_preview_func (GtkDrawingArea *drawing_area,
+ cairo_t *cr,
+ gint width,
+ gint height,
+ gpointer user_data)
+{
+ CcBackgroundPreview *self = CC_BACKGROUND_PREVIEW (user_data);
+ g_autoptr(GdkPixbuf) pixbuf = NULL;
+ gint scale_factor;
+
+ if (!self->item)
+ return;
+
+ scale_factor = gtk_widget_get_scale_factor (GTK_WIDGET (drawing_area));
+ pixbuf = cc_background_item_get_frame_thumbnail (self->item,
+ self->thumbnail_factory,
+ width,
+ height,
+ scale_factor,
+ 0,
+ TRUE,
+ self->is_dark &&
+ cc_background_item_has_dark_version (self->item));
+
+
+ gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
+ cairo_paint (cr);
+}
+
+/* GObject overrides */
+
+static void
+cc_background_preview_dispose (GObject *object)
+{
+ CcBackgroundPreview *self = (CcBackgroundPreview *)object;
+
+ g_clear_pointer (&self->drawing_area, gtk_widget_unparent);
+ g_clear_pointer (&self->light_dark_window, gtk_widget_unparent);
+ g_clear_pointer (&self->dark_window, gtk_widget_unparent);
+
+ G_OBJECT_CLASS (cc_background_preview_parent_class)->dispose (object);
+}
+
+static void
+cc_background_preview_finalize (GObject *object)
+{
+ CcBackgroundPreview *self = (CcBackgroundPreview *)object;
+
+ g_clear_object (&self->item);
+ g_clear_object (&self->thumbnail_factory);
+
+ G_OBJECT_CLASS (cc_background_preview_parent_class)->finalize (object);
+}
+
+static void
+set_is_dark (CcBackgroundPreview *self,
+ gboolean is_dark)
+{
+ self->is_dark = is_dark;
+
+ if (self->is_dark)
+ {
+ gtk_widget_add_css_class (self->light_dark_window, "dark");
+ gtk_widget_remove_css_class (self->light_dark_window, "light");
+ }
+ else
+ {
+ gtk_widget_add_css_class (self->light_dark_window, "light");
+ gtk_widget_remove_css_class (self->light_dark_window, "dark");
+ }
+}
+
+static void
+cc_background_preview_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcBackgroundPreview *self = CC_BACKGROUND_PREVIEW (object);
+
+ switch (prop_id)
+ {
+ case PROP_IS_DARK:
+ g_value_set_boolean (value, self->is_dark);
+ break;
+
+ case PROP_ITEM:
+ g_value_set_object (value, self->item);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_background_preview_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcBackgroundPreview *self = CC_BACKGROUND_PREVIEW (object);
+
+ switch (prop_id)
+ {
+ case PROP_IS_DARK:
+ set_is_dark (self, g_value_get_boolean (value));
+ break;
+
+ case PROP_ITEM:
+ cc_background_preview_set_item (self, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static GtkSizeRequestMode
+cc_background_preview_get_request_mode (GtkWidget *widget)
+{
+ return GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
+}
+
+static void
+get_primary_monitor_geometry (int *width, int *height)
+{
+ GdkDisplay *display;
+ GListModel *monitors;
+
+ display = gdk_display_get_default ();
+
+ monitors = gdk_display_get_monitors (display);
+ if (monitors)
+ {
+ g_autoptr(GdkMonitor) primary_monitor = NULL;
+ GdkRectangle monitor_layout;
+
+ primary_monitor = g_list_model_get_item (monitors, 0);
+ gdk_monitor_get_geometry (primary_monitor, &monitor_layout);
+ if (width)
+ *width = monitor_layout.width;
+ if (height)
+ *height = monitor_layout.height;
+
+ return;
+ }
+
+ if (width)
+ *width = 1920;
+ if (height)
+ *height = 1080;
+}
+
+static void
+cc_background_preview_measure (GtkWidget *widget,
+ GtkOrientation orientation,
+ gint for_size,
+ gint *minimum,
+ gint *natural,
+ gint *minimum_baseline,
+ gint *natural_baseline)
+{
+ GtkWidget *child;
+ int width;
+
+ get_primary_monitor_geometry (&width, NULL);
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ *natural = width;
+ else if (for_size < 0)
+ *natural = 0;
+ else
+ *natural = floor ((double) for_size * 0.75); /* 4:3 aspect ratio */
+
+ if (orientation == GTK_ORIENTATION_VERTICAL)
+ *minimum = *natural;
+ else
+ *minimum = 0;
+
+ for (child = gtk_widget_get_first_child (widget);
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ {
+ int child_min, child_nat;
+
+ gtk_widget_measure (child, orientation, for_size,
+ &child_min, &child_nat, NULL, NULL);
+
+ *minimum = MAX (*minimum, child_min);
+ *natural = MAX (*natural, child_nat);
+ }
+}
+
+static void
+cc_background_preview_size_allocate (GtkWidget *widget,
+ gint width,
+ gint height,
+ gint baseline)
+{
+ CcBackgroundPreview *self = CC_BACKGROUND_PREVIEW (widget);
+ int window_width, window_height, margin_x, margin_y;
+ int opposite_margin_x, opposite_margin_y;
+ GskTransform *front_transform, *back_transform;
+ gboolean is_rtl;
+
+ window_width = ceil (width * 0.5);
+ window_height = ceil (height * 0.5);
+ margin_x = floor (width * 0.15);
+ margin_y = floor (height * 0.15);
+ opposite_margin_x = width - window_width - margin_x;
+ opposite_margin_y = height - window_height - margin_y;
+ is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
+
+ front_transform =
+ gsk_transform_translate (NULL, &GRAPHENE_POINT_INIT (is_rtl ? opposite_margin_x : margin_x,
+ opposite_margin_y));
+ back_transform =
+ gsk_transform_translate (NULL, &GRAPHENE_POINT_INIT (is_rtl ? margin_x : opposite_margin_x,
+ margin_y));
+
+ gtk_widget_allocate (self->drawing_area, width, height, baseline, NULL);
+ gtk_widget_allocate (self->dark_window, window_width, window_height,
+ baseline, back_transform);
+ gtk_widget_allocate (self->light_dark_window, window_width, window_height,
+ baseline, front_transform);
+}
+
+static void
+cc_background_preview_class_init (CcBackgroundPreviewClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_background_preview_dispose;
+ object_class->finalize = cc_background_preview_finalize;
+ object_class->get_property = cc_background_preview_get_property;
+ object_class->set_property = cc_background_preview_set_property;
+
+ widget_class->get_request_mode = cc_background_preview_get_request_mode;
+ widget_class->measure = cc_background_preview_measure;
+ widget_class->size_allocate = cc_background_preview_size_allocate;
+
+ properties[PROP_IS_DARK] = g_param_spec_boolean ("is-dark",
+ "Is dark",
+ "Whether the preview is dark",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_ITEM] = g_param_spec_object ("item",
+ "Item",
+ "Background item",
+ CC_TYPE_BACKGROUND_ITEM,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/background/cc-background-preview.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcBackgroundPreview, drawing_area);
+ gtk_widget_class_bind_template_child (widget_class, CcBackgroundPreview, light_dark_window);
+ gtk_widget_class_bind_template_child (widget_class, CcBackgroundPreview, dark_window);
+
+ gtk_widget_class_set_css_name (widget_class, "background-preview");
+}
+
+static void
+cc_background_preview_init (CcBackgroundPreview *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->thumbnail_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
+}
+
+CcBackgroundItem*
+cc_background_preview_get_item (CcBackgroundPreview *self)
+{
+ g_return_val_if_fail (CC_IS_BACKGROUND_PREVIEW (self), NULL);
+
+ return self->item;
+}
+
+void
+cc_background_preview_set_item (CcBackgroundPreview *self,
+ CcBackgroundItem *item)
+{
+ g_return_if_fail (CC_IS_BACKGROUND_PREVIEW (self));
+ g_return_if_fail (CC_IS_BACKGROUND_ITEM (item));
+
+ if (!g_set_object (&self->item, item))
+ return;
+
+ gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (self->drawing_area),
+ draw_preview_func, self, NULL);
+ gtk_widget_queue_draw (self->drawing_area);
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ITEM]);
+}
diff --git a/panels/background/cc-background-preview.h b/panels/background/cc-background-preview.h
new file mode 100644
index 0000000..40393c0
--- /dev/null
+++ b/panels/background/cc-background-preview.h
@@ -0,0 +1,36 @@
+/* cc-background-preview.h
+ *
+ * Copyright 2019 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "cc-background-item.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_BACKGROUND_PREVIEW (cc_background_preview_get_type())
+G_DECLARE_FINAL_TYPE (CcBackgroundPreview, cc_background_preview, CC, BACKGROUND_PREVIEW, GtkWidget)
+
+CcBackgroundItem* cc_background_preview_get_item (CcBackgroundPreview *self);
+void cc_background_preview_set_item (CcBackgroundPreview *self,
+ CcBackgroundItem *item);
+
+G_END_DECLS
diff --git a/panels/background/cc-background-preview.ui b/panels/background/cc-background-preview.ui
new file mode 100644
index 0000000..4c4f573
--- /dev/null
+++ b/panels/background/cc-background-preview.ui
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcBackgroundPreview" parent="GtkWidget">
+ <property name="overflow">hidden</property>
+ <property name="width-request">2</property>
+ <property name="height-request">2</property>
+
+ <!-- Wallpaper -->
+ <child>
+ <object class="GtkDrawingArea" id="drawing_area"/>
+ </child>
+
+ <!-- Always dark window -->
+ <child>
+ <object class="AdwBin" id="dark_window">
+ <property name="overflow">hidden</property>
+ <style>
+ <class name="window"/>
+ <class name="back"/>
+ <class name="dark"/>
+ </style>
+ <child>
+ <object class="AdwBin">
+ <style>
+ <class name="header-bar"/>
+ </style>
+ <property name="valign">start</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- Light/dark window -->
+ <child>
+ <object class="AdwBin" id="light_dark_window">
+ <property name="overflow">hidden</property>
+ <style>
+ <class name="window"/>
+ <class name="front"/>
+ <class name="light"/>
+ </style>
+ <child>
+ <object class="AdwBin">
+ <style>
+ <class name="header-bar"/>
+ </style>
+ <property name="valign">start</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </template>
+</interface>
diff --git a/panels/background/cc-background-xml.c b/panels/background/cc-background-xml.c
new file mode 100644
index 0000000..84f0a04
--- /dev/null
+++ b/panels/background/cc-background-xml.c
@@ -0,0 +1,669 @@
+/*
+ * Authors: Rodney Dawes <dobey@ximian.com>
+ * Bastien Nocera <hadess@hadess.net>
+ *
+ * Copyright 2003-2006 Novell, Inc. (www.novell.com)
+ * Copyright 2011 Red Hat Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <gio/gio.h>
+#include <string.h>
+#include <libxml/parser.h>
+#include <gdesktop-enums.h>
+
+#include "gdesktop-enums-types.h"
+#include "cc-background-item.h"
+#include "cc-background-xml.h"
+
+/* The number of items we signal as "added" before
+ * returning to the main loop */
+#define NUM_ITEMS_PER_BATCH 1
+
+struct _CcBackgroundXml
+{
+ GObject parent_instance;
+
+ GHashTable *wp_hash;
+ GAsyncQueue *item_added_queue;
+ guint item_added_id;
+ GSList *monitors; /* GSList of GFileMonitor */
+};
+
+enum {
+ ADDED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (CcBackgroundXml, cc_background_xml, G_TYPE_OBJECT)
+
+static gboolean
+cc_background_xml_get_bool (const xmlNode *parent,
+ const gchar *prop_name)
+{
+ xmlChar *prop;
+ gboolean ret_val = FALSE;
+
+ g_return_val_if_fail (parent != NULL, FALSE);
+ g_return_val_if_fail (prop_name != NULL, FALSE);
+
+ prop = xmlGetProp ((xmlNode *) parent, (xmlChar*)prop_name);
+ if (prop != NULL) {
+ if (!g_ascii_strcasecmp ((gchar *)prop, "true") || !g_ascii_strcasecmp ((gchar *)prop, "1")) {
+ ret_val = TRUE;
+ } else {
+ ret_val = FALSE;
+ }
+ xmlFree (prop);
+ }
+
+ return ret_val;
+}
+
+static struct {
+ int value;
+ const char *string;
+} lookups[] = {
+ { G_DESKTOP_BACKGROUND_SHADING_HORIZONTAL, "horizontal-gradient" },
+ { G_DESKTOP_BACKGROUND_SHADING_VERTICAL, "vertical-gradient" },
+};
+
+static int
+enum_string_to_value (GType type,
+ const char *string)
+{
+ GEnumClass *eclass;
+ GEnumValue *value;
+
+ eclass = G_ENUM_CLASS (g_type_class_peek (type));
+ value = g_enum_get_value_by_nick (eclass, string);
+
+ /* Here's a bit of hand-made parsing, bad bad */
+ if (value == NULL) {
+ guint i;
+ for (i = 0; i < G_N_ELEMENTS (lookups); i++) {
+ if (g_str_equal (lookups[i].string, string))
+ return lookups[i].value;
+ }
+ g_warning ("Unhandled value '%s' for enum '%s'",
+ string, G_FLAGS_CLASS_TYPE_NAME (eclass));
+ return 0;
+ }
+
+ return value->value;
+}
+
+static gboolean
+idle_emit (CcBackgroundXml *xml)
+{
+ gint i;
+
+ g_async_queue_lock (xml->item_added_queue);
+
+ for (i = 0; i < NUM_ITEMS_PER_BATCH; i++) {
+ g_autoptr(GObject) item = NULL;
+
+ item = g_async_queue_try_pop_unlocked (xml->item_added_queue);
+ if (item == NULL)
+ break;
+ g_signal_emit (G_OBJECT (xml), signals[ADDED], 0, item);
+ }
+
+ g_async_queue_unlock (xml->item_added_queue);
+
+ if (g_async_queue_length (xml->item_added_queue) > 0) {
+ return TRUE;
+ } else {
+ xml->item_added_id = 0;
+ return FALSE;
+ }
+}
+
+static void
+emit_added_in_idle (CcBackgroundXml *xml,
+ GObject *object)
+{
+ g_async_queue_lock (xml->item_added_queue);
+ g_async_queue_push_unlocked (xml->item_added_queue, object);
+ if (xml->item_added_id == 0)
+ xml->item_added_id = g_idle_add ((GSourceFunc) idle_emit, xml);
+ g_async_queue_unlock (xml->item_added_queue);
+}
+
+#define NONE "(none)"
+#define UNSET_FLAG(flag) G_STMT_START{ (flags&=~(flag)); }G_STMT_END
+#define SET_FLAG(flag) G_STMT_START{ (flags|=flag); }G_STMT_END
+
+static gboolean
+cc_background_xml_load_xml_internal (CcBackgroundXml *xml,
+ const gchar *filename,
+ gboolean in_thread)
+{
+ xmlDoc * wplist;
+ xmlNode * root, * list, * wpa;
+ xmlChar * nodelang;
+ const gchar * const * syslangs;
+ gint i;
+ gboolean retval;
+
+ wplist = xmlParseFile (filename);
+ retval = FALSE;
+
+ if (!wplist)
+ return retval;
+
+ syslangs = g_get_language_names ();
+
+ root = xmlDocGetRootElement (wplist);
+
+ for (list = root->children; list != NULL; list = list->next) {
+ if (!strcmp ((gchar *)list->name, "wallpaper")) {
+ g_autoptr(CcBackgroundItem) item = NULL;
+ CcBackgroundItemFlags flags;
+ g_autofree gchar *uri = NULL;
+ g_autofree gchar *cname = NULL;
+ g_autofree gchar *id = NULL;
+
+ flags = 0;
+ item = cc_background_item_new (NULL);
+
+ g_object_set (G_OBJECT (item),
+ "is-deleted", cc_background_xml_get_bool (list, "deleted"),
+ "source-xml", filename,
+ NULL);
+
+ for (wpa = list->children; wpa != NULL; wpa = wpa->next) {
+ if (wpa->type == XML_COMMENT_NODE) {
+ continue;
+ } else if (!strcmp ((gchar *)wpa->name, "filename")) {
+ if (wpa->last != NULL && wpa->last->content != NULL) {
+ gchar *content = g_strstrip ((gchar *)wpa->last->content);
+ g_autofree gchar *bg_uri = NULL;
+
+ /* FIXME same rubbish as in other parts of the code */
+ if (strcmp (content, NONE) == 0) {
+ bg_uri = NULL;
+ } else {
+ g_autoptr(GFile) file = NULL;
+ g_autofree gchar *dirname = NULL;
+
+ dirname = g_path_get_dirname (filename);
+ file = g_file_new_for_commandline_arg_and_cwd (content, dirname);
+ bg_uri = g_file_get_uri (file);
+ }
+ SET_FLAG(CC_BACKGROUND_ITEM_HAS_URI);
+ g_object_set (G_OBJECT (item), "uri", bg_uri, NULL);
+ } else {
+ break;
+ }
+ } else if (!strcmp ((gchar *)wpa->name, "filename-dark")) {
+ if (wpa->last != NULL && wpa->last->content != NULL) {
+ gchar *content = g_strstrip ((gchar *)wpa->last->content);
+ g_autofree gchar *bg_uri = NULL;
+
+ /* FIXME same rubbish as in other parts of the code */
+ if (strcmp (content, NONE) == 0) {
+ bg_uri = NULL;
+ } else {
+ g_autoptr(GFile) file = NULL;
+ g_autofree gchar *dirname = NULL;
+
+ dirname = g_path_get_dirname (filename);
+ file = g_file_new_for_commandline_arg_and_cwd (content, dirname);
+ bg_uri = g_file_get_uri (file);
+ }
+ SET_FLAG(CC_BACKGROUND_ITEM_HAS_URI_DARK);
+ g_object_set (G_OBJECT (item), "uri-dark", bg_uri, NULL);
+ } else {
+ break;
+ }
+ } else if (!strcmp ((gchar *)wpa->name, "name")) {
+ if (wpa->last != NULL && wpa->last->content != NULL) {
+ g_autofree gchar *name = NULL;
+ nodelang = xmlNodeGetLang (wpa->last);
+
+ g_object_get (G_OBJECT (item), "name", &name, NULL);
+
+ if (name == NULL && nodelang == NULL) {
+ g_free (cname);
+ cname = g_strdup (g_strstrip ((gchar *)wpa->last->content));
+ g_object_set (G_OBJECT (item), "name", cname, NULL);
+ } else {
+ for (i = 0; syslangs[i] != NULL; i++) {
+ if (!strcmp (syslangs[i], (gchar *)nodelang)) {
+ g_object_set (G_OBJECT (item), "name",
+ g_strstrip ((gchar *)wpa->last->content), NULL);
+ break;
+ }
+ }
+ }
+
+ xmlFree (nodelang);
+ } else {
+ break;
+ }
+ } else if (!strcmp ((gchar *)wpa->name, "options")) {
+ if (wpa->last != NULL) {
+ g_object_set (G_OBJECT (item), "placement",
+ enum_string_to_value (G_DESKTOP_TYPE_DESKTOP_BACKGROUND_STYLE,
+ g_strstrip ((gchar *)wpa->last->content)), NULL);
+ SET_FLAG(CC_BACKGROUND_ITEM_HAS_PLACEMENT);
+ }
+ } else if (!strcmp ((gchar *)wpa->name, "shade_type")) {
+ if (wpa->last != NULL) {
+ g_object_set (G_OBJECT (item), "shading",
+ enum_string_to_value (G_DESKTOP_TYPE_DESKTOP_BACKGROUND_SHADING,
+ g_strstrip ((gchar *)wpa->last->content)), NULL);
+ SET_FLAG(CC_BACKGROUND_ITEM_HAS_SHADING);
+ }
+ } else if (!strcmp ((gchar *)wpa->name, "pcolor")) {
+ if (wpa->last != NULL) {
+ g_object_set (G_OBJECT (item), "primary-color",
+ g_strstrip ((gchar *)wpa->last->content), NULL);
+ SET_FLAG(CC_BACKGROUND_ITEM_HAS_PCOLOR);
+ }
+ } else if (!strcmp ((gchar *)wpa->name, "scolor")) {
+ if (wpa->last != NULL) {
+ g_object_set (G_OBJECT (item), "secondary-color",
+ g_strstrip ((gchar *)wpa->last->content), NULL);
+ SET_FLAG(CC_BACKGROUND_ITEM_HAS_SCOLOR);
+ }
+ } else if (!strcmp ((gchar *)wpa->name, "source_url")) {
+ if (wpa->last != NULL) {
+ g_object_set (G_OBJECT (item),
+ "source-url", g_strstrip ((gchar *)wpa->last->content),
+ "needs-download", FALSE,
+ NULL);
+ }
+ } else if (!strcmp ((gchar *)wpa->name, "text")) {
+ /* Do nothing here, libxml2 is being weird */
+ } else {
+ g_debug ("Unknown Tag in %s: %s", filename, wpa->name);
+ }
+ }
+
+ /* Check whether the target file exists */
+ {
+ const char *uri;
+
+ uri = cc_background_item_get_uri (item);
+ if (uri != NULL)
+ {
+ g_autoptr(GFile) file = NULL;
+
+ file = g_file_new_for_uri (uri);
+ if (g_file_query_exists (file, NULL) == FALSE)
+ {
+ g_clear_pointer (&cname, g_free);
+ g_clear_object (&item);
+ continue;
+ }
+ }
+ }
+
+ /* FIXME, this is a broken way of doing,
+ * need to use proper code here */
+ uri = g_filename_to_uri (filename, NULL, NULL);
+ id = g_strdup_printf ("%s#%s", uri, cname);
+
+ /* Make sure we don't already have this one and that filename exists */
+ if (g_hash_table_lookup (xml->wp_hash, id) != NULL) {
+ continue;
+ }
+
+ g_object_set (G_OBJECT (item), "flags", flags, NULL);
+ g_hash_table_insert (xml->wp_hash,
+ g_strdup (id),
+ g_object_ref (item));
+ if (in_thread)
+ emit_added_in_idle (xml, g_object_ref (G_OBJECT (item)));
+ else
+ g_signal_emit (G_OBJECT (xml), signals[ADDED], 0, item);
+ retval = TRUE;
+ }
+ }
+ xmlFreeDoc (wplist);
+
+ return retval;
+}
+
+static void
+gnome_wp_file_changed (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ CcBackgroundXml *data)
+{
+ g_autofree gchar *filename = NULL;
+
+ switch (event_type) {
+ case G_FILE_MONITOR_EVENT_CHANGED:
+ case G_FILE_MONITOR_EVENT_CREATED:
+ filename = g_file_get_path (file);
+ cc_background_xml_load_xml_internal (data, filename, FALSE);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+cc_background_xml_add_monitor (GFile *directory,
+ CcBackgroundXml *data)
+{
+ GFileMonitor *monitor;
+ g_autoptr(GError) error = NULL;
+
+ monitor = g_file_monitor_directory (directory,
+ G_FILE_MONITOR_NONE,
+ NULL,
+ &error);
+ if (error != NULL) {
+ g_autofree gchar *path = NULL;
+
+ path = g_file_get_parse_name (directory);
+ g_warning ("Unable to monitor directory %s: %s",
+ path, error->message);
+ return;
+ }
+
+ g_signal_connect (monitor, "changed",
+ G_CALLBACK (gnome_wp_file_changed),
+ data);
+
+ data->monitors = g_slist_prepend (data->monitors, monitor);
+}
+
+static void
+cc_background_xml_load_from_dir (const gchar *path,
+ CcBackgroundXml *data,
+ gboolean in_thread)
+{
+ g_autoptr(GFile) directory = NULL;
+ g_autoptr(GFileEnumerator) enumerator = NULL;
+ g_autoptr(GError) error = NULL;
+
+ if (!g_file_test (path, G_FILE_TEST_IS_DIR)) {
+ return;
+ }
+
+ directory = g_file_new_for_path (path);
+ enumerator = g_file_enumerate_children (directory,
+ G_FILE_ATTRIBUTE_STANDARD_NAME,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ &error);
+ if (error != NULL) {
+ g_warning ("Unable to check directory %s: %s", path, error->message);
+ return;
+ }
+
+ while (TRUE) {
+ g_autoptr(GFileInfo) info = NULL;
+ const gchar *filename;
+ g_autofree gchar *fullpath = NULL;
+
+ info = g_file_enumerator_next_file (enumerator, NULL, NULL);
+ if (info == NULL) {
+ g_file_enumerator_close (enumerator, NULL, NULL);
+ cc_background_xml_add_monitor (directory, data);
+ return;
+ }
+
+ filename = g_file_info_get_name (info);
+ fullpath = g_build_filename (path, filename, NULL);
+
+ cc_background_xml_load_xml_internal (data, fullpath, in_thread);
+ }
+}
+
+static void
+cc_background_xml_load_list (CcBackgroundXml *data,
+ gboolean in_thread)
+{
+ const char * const *system_data_dirs;
+ g_autofree gchar *datadir = NULL;
+ gint i;
+
+ datadir = g_build_filename (g_get_user_data_dir (),
+ "gnome-background-properties",
+ NULL);
+ cc_background_xml_load_from_dir (datadir, data, in_thread);
+
+ system_data_dirs = g_get_system_data_dirs ();
+ for (i = 0; system_data_dirs[i]; i++) {
+ g_autofree gchar *sdatadir = NULL;
+ sdatadir = g_build_filename (system_data_dirs[i],
+ "gnome-background-properties",
+ NULL);
+ cc_background_xml_load_from_dir (sdatadir, data, in_thread);
+ }
+}
+
+gboolean
+cc_background_xml_load_list_finish (CcBackgroundXml *xml,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (result, xml), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+static void
+load_list_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ CcBackgroundXml *xml = CC_BACKGROUND_XML (source_object);
+ cc_background_xml_load_list (xml, TRUE);
+ g_task_return_boolean (task, TRUE);
+}
+
+void
+cc_background_xml_load_list_async (CcBackgroundXml *xml,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (CC_IS_BACKGROUND_XML (xml));
+
+ task = g_task_new (xml, cancellable, callback, user_data);
+ g_task_run_in_thread (task, load_list_thread);
+}
+
+gboolean
+cc_background_xml_load_xml (CcBackgroundXml *xml,
+ const gchar *filename)
+{
+ g_return_val_if_fail (CC_IS_BACKGROUND_XML (xml), FALSE);
+
+ if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) == FALSE)
+ return FALSE;
+
+ return cc_background_xml_load_xml_internal (xml, filename, FALSE);
+}
+
+static void
+single_xml_added (CcBackgroundXml *xml,
+ CcBackgroundItem *item,
+ CcBackgroundItem **ret)
+{
+ g_assert (*ret == NULL);
+ *ret = g_object_ref (item);
+}
+
+CcBackgroundItem *
+cc_background_xml_get_item (const char *filename)
+{
+ g_autoptr(CcBackgroundXml) xml = NULL;
+ CcBackgroundItem *item = NULL;
+
+ if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) == FALSE)
+ return NULL;
+
+ xml = cc_background_xml_new ();
+ g_signal_connect (G_OBJECT (xml), "added",
+ G_CALLBACK (single_xml_added), &item);
+ if (cc_background_xml_load_xml (xml, filename) == FALSE)
+ return NULL;
+
+ return item;
+}
+
+static const char *
+enum_to_str (GType type,
+ int v)
+{
+ GEnumClass *eclass;
+ GEnumValue *value;
+
+ eclass = G_ENUM_CLASS (g_type_class_peek (type));
+ value = g_enum_get_value (eclass, v);
+
+ g_assert (value);
+
+ return value->value_nick;
+}
+
+void
+cc_background_xml_save (CcBackgroundItem *item,
+ const char *filename)
+{
+ xmlDoc *wp;
+ xmlNode *root, *wallpaper;
+ xmlNode *xml_item G_GNUC_UNUSED;
+ const char * none = "(none)";
+ const char *placement_str, *shading_str;
+ g_autofree gchar *name = NULL;
+ g_autofree gchar *pcolor = NULL;
+ g_autofree gchar *scolor = NULL;
+ g_autofree gchar *uri = NULL;
+ g_autofree gchar *source_url = NULL;
+ CcBackgroundItemFlags flags;
+ GDesktopBackgroundStyle placement;
+ GDesktopBackgroundShading shading;
+
+ xmlKeepBlanksDefault (0);
+
+ wp = xmlNewDoc ((xmlChar *)"1.0");
+ xmlCreateIntSubset (wp, (xmlChar *)"wallpapers", NULL, (xmlChar *)"gnome-wp-list.dtd");
+ root = xmlNewNode (NULL, (xmlChar *)"wallpapers");
+ xmlDocSetRootElement (wp, root);
+
+ g_object_get (G_OBJECT (item),
+ "name", &name,
+ "uri", &uri,
+ "shading", &shading,
+ "placement", &placement,
+ "primary-color", &pcolor,
+ "secondary-color", &scolor,
+ "source-url", &source_url,
+ "flags", &flags,
+ NULL);
+
+ placement_str = enum_to_str (G_DESKTOP_TYPE_DESKTOP_BACKGROUND_STYLE, placement);
+ shading_str = enum_to_str (G_DESKTOP_TYPE_DESKTOP_BACKGROUND_SHADING, shading);
+
+ wallpaper = xmlNewChild (root, NULL, (xmlChar *)"wallpaper", NULL);
+ xml_item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"name", (xmlChar *)name);
+ if (flags & CC_BACKGROUND_ITEM_HAS_URI &&
+ uri != NULL)
+ {
+ g_autoptr(GFile) file = NULL;
+ g_autofree gchar *fname = NULL;
+
+ file = g_file_new_for_commandline_arg (uri);
+ fname = g_file_get_path (file);
+ xml_item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"filename", (xmlChar *)fname);
+ }
+ else if (flags & CC_BACKGROUND_ITEM_HAS_URI)
+ {
+ xml_item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"filename", (xmlChar *)none);
+ }
+
+ if (flags & CC_BACKGROUND_ITEM_HAS_PLACEMENT)
+ xml_item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"options", (xmlChar *)placement_str);
+ if (flags & CC_BACKGROUND_ITEM_HAS_SHADING)
+ xml_item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"shade_type", (xmlChar *)shading_str);
+ if (flags & CC_BACKGROUND_ITEM_HAS_PCOLOR)
+ xml_item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"pcolor", (xmlChar *)pcolor);
+ if (flags & CC_BACKGROUND_ITEM_HAS_SCOLOR)
+ xml_item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"scolor", (xmlChar *)scolor);
+ if (source_url != NULL)
+ xml_item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"source_url", (xmlChar *)source_url);
+
+ xmlSaveFormatFile (filename, wp, 1);
+ xmlFreeDoc (wp);
+}
+
+static void
+cc_background_xml_finalize (GObject *object)
+{
+ CcBackgroundXml *xml;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (CC_IS_BACKGROUND_XML (object));
+
+ xml = CC_BACKGROUND_XML (object);
+
+ g_slist_free_full (xml->monitors, g_object_unref);
+
+ g_clear_pointer (&xml->wp_hash, g_hash_table_destroy);
+ if (xml->item_added_id != 0) {
+ g_source_remove (xml->item_added_id);
+ xml->item_added_id = 0;
+ }
+ g_clear_pointer (&xml->item_added_queue, g_async_queue_unref);
+
+ G_OBJECT_CLASS (cc_background_xml_parent_class)->finalize (object);
+}
+
+static void
+cc_background_xml_class_init (CcBackgroundXmlClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = cc_background_xml_finalize;
+
+ signals[ADDED] = g_signal_new ("added",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, CC_TYPE_BACKGROUND_ITEM);
+}
+
+static void
+cc_background_xml_init (CcBackgroundXml *xml)
+{
+ xml->wp_hash = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_object_unref);
+ xml->item_added_queue = g_async_queue_new_full ((GDestroyNotify) g_object_unref);
+}
+
+CcBackgroundXml *
+cc_background_xml_new (void)
+{
+ return CC_BACKGROUND_XML (g_object_new (CC_TYPE_BACKGROUND_XML, NULL));
+}
diff --git a/panels/background/cc-background-xml.h b/panels/background/cc-background-xml.h
new file mode 100644
index 0000000..3d2038c
--- /dev/null
+++ b/panels/background/cc-background-xml.h
@@ -0,0 +1,46 @@
+/*
+ * Authors: Rodney Dawes <dobey@ximian.com>
+ *
+ * Copyright 2003-2012 Novell, Inc. (www.novell.com)
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_BACKGROUND_XML (cc_background_xml_get_type ())
+G_DECLARE_FINAL_TYPE (CcBackgroundXml, cc_background_xml, CC, BACKGROUND_XML, GObject)
+
+CcBackgroundXml *cc_background_xml_new (void);
+
+void cc_background_xml_save (CcBackgroundItem *item,
+ const char *filename);
+
+CcBackgroundItem *cc_background_xml_get_item (const char *filename);
+gboolean cc_background_xml_load_xml (CcBackgroundXml *data,
+ const char *filename);
+void cc_background_xml_load_list_async (CcBackgroundXml *xml,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean cc_background_xml_load_list_finish (CcBackgroundXml *xml,
+ GAsyncResult *result,
+ GError **error);
+
+G_END_DECLS
diff --git a/panels/background/gnome-background-panel.desktop.in.in b/panels/background/gnome-background-panel.desktop.in.in
new file mode 100644
index 0000000..a6a044c
--- /dev/null
+++ b/panels/background/gnome-background-panel.desktop.in.in
@@ -0,0 +1,14 @@
+[Desktop Entry]
+Name=Appearance
+Comment=Change your background image or the UI colors
+Exec=gnome-control-center background
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-appearance-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-PersonalizationSettings;
+OnlyShowIn=GNOME;
+# Translators: Search terms to find the Appearance panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=Background;Wallpaper;Screen;Desktop;Style;Light;Dark;Appearance;
diff --git a/panels/background/icons/meson.build b/panels/background/icons/meson.build
new file mode 100644
index 0000000..53082c1
--- /dev/null
+++ b/panels/background/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-appearance-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/background/icons/scalable/org.gnome.Settings-appearance-symbolic.svg b/panels/background/icons/scalable/org.gnome.Settings-appearance-symbolic.svg
new file mode 100644
index 0000000..7190bbd
--- /dev/null
+++ b/panels/background/icons/scalable/org.gnome.Settings-appearance-symbolic.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <g fill="#2e3436">
+ <path d="m 3.011719 1 c -1.644531 0 -3.0000002 1.355469 -3.0000002 3 v 6 c 0 1.644531 1.3554692 3 3.0000002 3 h 10 c 1.644531 0 3 -1.355469 3 -3 v -6 c 0 -0.570312 -0.167969 -1.101562 -0.449219 -1.558594 l -1.550781 1.554688 v 6.003906 c 0 0.570312 -0.429688 1 -1 1 h -10 c -0.570313 0 -1 -0.429688 -1 -1 v -6 c 0 -0.570312 0.429687 -1 1 -1 h 5.96875 l 2.007812 -2 z m 0 0"/>
+ <path d="m 11.011719 7 c 0 1.65625 -1.339844 3.007812 -3 3 h -3 v -3 c 0 -1.660156 1.34375 -3 3 -3 c 1.660156 0 3 1.339844 3 3 z m 0 0"/>
+ <path d="m 13.410156 0 l -3.46875 3.457031 c 0.683594 0.355469 1.234375 0.910157 1.589844 1.589844 l 0.171875 -0.171875 l 0.007813 0.007812 l 4.300781 -4.300781 v -0.582031 z m 0 0"/>
+ <path d="m 5.011719 14 c -1.105469 0 -2 0.894531 -2 2 h 10 c 0 -1.105469 -0.894531 -2 -2 -2 z m 0 0"/>
+ </g>
+</svg>
diff --git a/panels/background/meson.build b/panels/background/meson.build
new file mode 100644
index 0000000..3634c47
--- /dev/null
+++ b/panels/background/meson.build
@@ -0,0 +1,99 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+install_data(
+ 'noise-texture-light.png',
+ install_dir: join_paths(control_center_pkgdatadir, 'pixmaps')
+)
+
+common_sources = []
+
+enums = 'gdesktop-enums-types'
+enums_header = files(
+ gsettings_desktop_dep.get_pkgconfig_variable('prefix') + '/include/gsettings-desktop-schemas/gdesktop-enums.h',
+ 'cc-background-item.h'
+)
+
+common_sources += gnome.mkenums(
+ enums + '.h',
+ sources: enums_header,
+ fhead: '#pragma once\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n',
+ fprod: '/* enumerations from "@filename@" */\n',
+ vhead: 'GType @enum_name@_get_type (void) G_GNUC_CONST;\n#define G_DESKTOP_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n',
+ ftail: 'G_END_DECLS\n'
+)
+
+common_sources += gnome.mkenums(
+ enums + '.c',
+ sources: enums_header,
+ fhead: '#include <gdesktop-enums.h>\n#include "gdesktop-enums-types.h"\n#include "cc-background-item.h"',
+ fprod: '\n/* enumerations from "@filename@" */',
+ vhead: 'GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {',
+ vprod: ' { @VALUENAME@, "@VALUENAME@", "@valuenick@" },',
+ vtail: ' { 0, NULL, NULL }\n };\n etype = g_@type@_register_static ("@EnumName@", values);\n }\n return etype;\n}\n'
+)
+
+resource_data = files(
+ 'cc-background-chooser.ui',
+ 'cc-background-panel.ui',
+ 'cc-background-preview.ui',
+ 'preview.css',
+)
+
+common_sources += gnome.compile_resources(
+ 'cc-@0@-resources'.format(cappletname),
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname,
+ dependencies: resource_data,
+ export: true
+)
+
+sources = common_sources + files(
+ 'bg-colors-source.c',
+ 'bg-recent-source.c',
+ 'bg-source.c',
+ 'bg-wallpapers-source.c',
+ 'cc-background-chooser.c',
+ 'cc-background-item.c',
+ 'cc-background-paintable.c',
+ 'cc-background-panel.c',
+ 'cc-background-preview.c',
+ 'cc-background-xml.c',
+)
+
+deps = common_deps + [
+ gdk_pixbuf_dep,
+ gnome_bg_dep,
+ libxml_dep,
+ dependency('cairo-gobject'),
+]
+
+cflags += [
+ '-DDATADIR="@0@"'.format(control_center_datadir),
+ '-DGNOME_DESKTOP_USE_UNSTABLE_API'
+]
+
+panels_libs += static_library(
+ cappletname,
+ sources: sources,
+ include_directories: top_inc,
+ dependencies: deps,
+ c_args: cflags,
+)
+
+subdir('icons')
diff --git a/panels/background/noise-texture-light.png b/panels/background/noise-texture-light.png
new file mode 100644
index 0000000..f73293e
--- /dev/null
+++ b/panels/background/noise-texture-light.png
Binary files differ
diff --git a/panels/background/preview.css b/panels/background/preview.css
new file mode 100644
index 0000000..e949734
--- /dev/null
+++ b/panels/background/preview.css
@@ -0,0 +1,96 @@
+background-preview {
+ border-radius: 6px;
+}
+
+background-preview .window {
+ border-radius: 6px;
+ box-shadow: 0 1px 4px 1px alpha(black, 0.13),
+ 0 1px 10px 5px alpha(black, 0.09),
+ 0 3px 16px 8px alpha(black, 0.04),
+ 0 0 0 1px alpha(black, .05);
+}
+
+background-preview .window .header-bar {
+ min-height: 15px;
+}
+
+background-preview .window.light {
+ background-color: #fafafa;
+ color: alpha(black, .8);
+}
+
+background-preview .window.light .header-bar {
+ box-shadow: inset 0 -1px alpha(black, .07);
+}
+
+background-preview .window.front.light .header-bar {
+ background-color: #ebebeb;
+}
+
+background-preview .window.dark {
+ background-color: #242424;
+ color: white;
+}
+
+background-preview .window.dark .header-bar {
+ box-shadow: inset 0 -1px alpha(black, .36);
+}
+
+background-preview .window.front.dark .header-bar {
+ background-color: #303030;
+}
+
+.background-preview-button {
+ background: none;
+ border-radius: 9px;
+ padding: 3px;
+ box-shadow: none;
+ outline: none;
+}
+
+.background-preview-button:checked {
+ box-shadow: 0 0 0 3px @accent_color;
+}
+
+.background-preview-button:focus:focus-visible {
+ box-shadow: 0 0 0 3px alpha(@accent_color, .3);
+}
+
+.background-preview-button:checked:focus:focus-visible {
+ box-shadow: 0 0 0 3px @accent_color, 0 0 0 6px alpha(@accent_color, .3);
+}
+
+.background-flowbox > flowboxchild {
+ background: none;
+ border-radius: 9px;
+}
+
+.background-thumbnail {
+ border-radius: 6px;
+}
+
+.slideshow-icon {
+ color: white;
+ -gtk-icon-shadow: 0 1px 2px rgba(0, 0, 0, 0.33);
+ margin: 8px;
+}
+
+.selected-check {
+ color: @accent_fg_color;
+ background: @accent_bg_color;
+ border-radius: 100px;
+ padding: 2px;
+ opacity: 0;
+ margin: 6px;
+}
+
+flowboxchild:selected .selected-check {
+ opacity: 1;
+}
+
+.remove-button {
+ padding: 2px;
+ min-width: 0;
+ min-height: 0;
+ margin: 6px;
+}
diff --git a/panels/background/slideshow-symbolic.svg b/panels/background/slideshow-symbolic.svg
new file mode 100644
index 0000000..77350c3
--- /dev/null
+++ b/panels/background/slideshow-symbolic.svg
@@ -0,0 +1 @@
+<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><path d="M7.486.02A7.492 7.492 0 0 0 0 7.508a7.492 7.492 0 0 0 7.486 7.484 7.492 7.492 0 0 0 7.487-7.484A7.492 7.492 0 0 0 7.486.02zm0 1.972A5.508 5.508 0 0 1 13 7.508a5.508 5.508 0 0 1-5.514 5.512 5.508 5.508 0 0 1-5.513-5.512 5.508 5.508 0 0 1 5.513-5.516zm3.01 2.01a.5.5 0 0 0-.103.006.5.5 0 0 0-.25.154L7.486 6.818 5.83 5.162a.5.5 0 1 0-.687.688l2 2a.5.5 0 0 0 .687 0l3-3a.5.5 0 0 0-.334-.848z" style="fill:#000"/></svg> \ No newline at end of file
diff --git a/panels/bluetooth/bluetooth-panel-scenario-tester.py b/panels/bluetooth/bluetooth-panel-scenario-tester.py
new file mode 100755
index 0000000..45b021c
--- /dev/null
+++ b/panels/bluetooth/bluetooth-panel-scenario-tester.py
@@ -0,0 +1,226 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2021 Red Hat Inc.
+#
+# Author: Bastien Nocera <hadess@hadess.net>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import dbus
+import sys
+import os
+import fcntl
+import gi
+import subprocess
+import time
+from collections import OrderedDict
+from dbusmock import DBusTestCase, mockobject
+from dbus.mainloop.glib import DBusGMainLoop
+from consolemenu import *
+from consolemenu.items import *
+
+from gi.repository import Gio
+from gi.repository import GLib
+
+DBusGMainLoop(set_as_default=True)
+
+
+def set_nonblock(fd):
+ '''Set a file object to non-blocking'''
+ flags = fcntl.fcntl(fd, fcntl.F_GETFL)
+ fcntl.fcntl(fd, fcntl.F_SETFL, flags | os.O_NONBLOCK)
+
+def get_templates_dir():
+ return os.path.join(os.path.dirname(__file__), 'dbusmock-templates')
+
+def get_template_path(template_name):
+ return os.path.join(get_templates_dir(), template_name + '.py')
+
+class GccDBusTestCase(DBusTestCase):
+ @classmethod
+ def setUpClass(klass):
+ klass.mocks = OrderedDict()
+
+ # Start system bus
+ DBusTestCase.setUpClass()
+ klass.test_bus = Gio.TestDBus.new(Gio.TestDBusFlags.NONE)
+ klass.test_bus.up()
+ os.environ['DBUS_SYSTEM_BUS_ADDRESS'] = klass.test_bus.get_bus_address()
+
+ # Start session bus
+ klass.session_test_bus = Gio.TestDBus.new(Gio.TestDBusFlags.NONE)
+ klass.session_test_bus.up()
+ os.environ['DBUS_SESSION_BUS_ADDRESS'] = klass.session_test_bus.get_bus_address()
+
+ # process = subprocess.Popen(['gdbus', 'monitor', '--session', '--dest', 'org.gnome.SettingsDaemon.Rfkill'])
+ # process = subprocess.Popen(['gdbus', 'monitor', '--system', '--dest', 'org.bluez'])
+
+ # Start bluez and gsd-rfkill
+ klass.start_from_template('bluez5')
+ klass.start_from_local_template(
+ 'gsd_rfkill', {'templates-dir': get_templates_dir()})
+
+ klass.system_bus = Gio.bus_get_sync(Gio.BusType.SYSTEM, None)
+
+ @classmethod
+ def tearDownClass(klass):
+ for (mock_server, mock_obj) in reversed(klass.mocks.values()):
+ mock_server.terminate()
+ mock_server.wait()
+
+ DBusTestCase.tearDownClass()
+
+ @classmethod
+ def start_from_template(klass, template, params={}):
+ mock_server, mock_obj = \
+ klass.spawn_server_template(template,
+ params,
+ stdout=subprocess.PIPE)
+ set_nonblock(mock_server.stdout)
+
+ mocks = (mock_server, mock_obj)
+ assert klass.mocks.setdefault(template, mocks) == mocks
+ return mocks
+
+ @classmethod
+ def start_from_local_template(klass, template_file_name, params={}):
+ template = get_template_path(template_file_name)
+ ret = klass.start_from_template(template, params)
+ klass.mocks.setdefault(template_file_name, ret)
+ return ret
+
+ def __init__(self):
+ self.devices = {}
+ self.rfkill = self.mocks['gsd_rfkill'][1]
+
+ self.bluez_mock = self.mocks['bluez5'][1]
+ self.hci0_powered = True
+ self.hci0_plugged_in = True
+ self.add_adapter()
+ bus = dbus.SystemBus()
+ self.hci0_props = dbus.Interface(bus.get_object('org.bluez', '/org/bluez/hci0'), 'org.freedesktop.DBus.Properties')
+
+ def adapter_exists(self):
+ try:
+ self.get_dbus(True).get_object('org.bluez', '/org/bluez/hci0').Get('org.bluez.Adapter1', 'Name')
+ except:
+ return False
+ return True
+
+ def add_adapter(self):
+ if self.adapter_exists():
+ return
+ self.bluez_mock.AddAdapter('hci0', 'hci0')
+ adapter = self.get_dbus(True).get_object('org.bluez', '/org/bluez/hci0')
+ adapter.AddProperties('org.bluez.Adapter1',
+ {'Blocked': dbus.Boolean(not self.hci0_powered, variant_level=1)})
+ adapter.UpdateProperties('org.bluez.Adapter1',
+ {'Powered': dbus.Boolean(self.hci0_powered, variant_level=1)})
+ self.devices = []
+ self.add_device('hci0', '22:33:44:55:66:77', "Bastienʼs mouse", True, 0x580, 'input-mouse')
+ self.add_device('hci0', '22:33:44:55:66:78', 'Bloutouf keyboard & keys', True, 0x540, 'input-keyboard')
+ self.add_device('hci0', '60:8B:0E:55:66:79', 'iPhoone 19S', True, 0x20C, 'phone')
+ # Uncategorised audio device
+ self.add_device('hci0', '22:33:44:55:66:79', 'MEGA Speakers', True, 0x200400, 'audio-card')
+ self.add_device('hci0', '22:33:44:55:66:80', 'Ski-bi dibby dib yo da dub dub Yo da dub dub Ski-bi dibby dib yo da dub dub Yo da dub dub (I\'m the Scatman) Ski-bi dibby dib yo da dub dub Yo da dub dub Ski-bi dibby dib yo da dub dub Yo da dub dub Ba-da-ba-da-ba-be bop bop bodda bope Bop ba bodda bope Be bop ba bodda bope Bop ba bodda Ba-da-ba-da-ba-be bop ba bodda bope Bop ba bodda bope Be bop ba bodda bope Bop ba bodda bope', True, 0x80C, '')
+ self.rfkill.Set('org.gnome.SettingsDaemon.Rfkill', 'BluetoothHasAirplaneMode', dbus.Boolean(True))
+
+ def remove_adapter(self):
+ if not self.adapter_exists():
+ return
+ for dev in self.devices:
+ adapter = self.get_dbus(True).get_object('org.bluez', '/org/bluez/hci0')
+ adapter.RemoveDevice(dev)
+ self.devices = []
+ self.bluez_mock.RemoveAdapter('hci0')
+ if self.rfkill.Get('org.gnome.SettingsDaemon.Rfkill', 'BluetoothHardwareAirplaneMode') == 0:
+ self.rfkill.Set('org.gnome.SettingsDaemon.Rfkill', 'BluetoothHasAirplaneMode', dbus.Boolean(False))
+
+ def add_device(self, adapter, address, name, paired, klass, icon):
+ dev_path = self.bluez_mock.AddDevice(adapter, address, name)
+ dev = self.get_dbus(True).get_object('org.bluez', str(dev_path))
+ dev.UpdateProperties('org.bluez.Device1',
+ {'Paired': dbus.Boolean(paired, variant_level=1),
+ 'Class': dbus.UInt32(klass, variant_level=1),
+ 'Icon': dbus.String(icon, variant_level=1)})
+ self.devices.append(dev)
+
+ def get_rfkill_prop(self, prop_name):
+ return self.rfkill.Get('org.gnome.SettingsDaemon.Rfkill', prop_name)
+
+ def toggle_hw_rfkill(self):
+ if self.rfkill.Get('org.gnome.SettingsDaemon.Rfkill', 'BluetoothHardwareAirplaneMode') == 0:
+ self.rfkill.Set('org.gnome.SettingsDaemon.Rfkill', 'BluetoothHardwareAirplaneMode', dbus.Boolean(True))
+ if self.adapter_exists():
+ self.remove_adapter()
+ else:
+ self.rfkill.Set('org.gnome.SettingsDaemon.Rfkill', 'BluetoothHardwareAirplaneMode', dbus.Boolean(False))
+ if not self.adapter_exists():
+ self.add_adapter()
+
+ def set_unpowered(self):
+ if self.hci0_powered:
+ print('hci0 will now default to unpowered')
+ self.hci0_powered = False
+ else:
+ print('hci0 will now default to powered')
+ self.hci0_powered = True
+
+ def unplug_default_adapter(self):
+ if self.hci0_plugged_in:
+ print('default adapter is unplugged')
+ self.hci0_plugged_in = False
+ self.remove_adapter()
+ else:
+ print('default adapter is plugged in')
+ self.hci0_plugged_in = True
+ self.add_adapter()
+
+ def toggle_airplane_mode(self):
+ if self.rfkill.Get('org.gnome.SettingsDaemon.Rfkill', 'AirplaneMode') == 0:
+ self.rfkill.Set('org.gnome.SettingsDaemon.Rfkill', 'AirplaneMode', dbus.Boolean(True))
+ self.rfkill.Set('org.gnome.SettingsDaemon.Rfkill', 'BluetoothAirplaneMode', dbus.Boolean(True))
+ else:
+ self.rfkill.Set('org.gnome.SettingsDaemon.Rfkill', 'AirplaneMode', dbus.Boolean(False))
+ self.rfkill.Set('org.gnome.SettingsDaemon.Rfkill', 'BluetoothAirplaneMode', dbus.Boolean(False))
+
+ def start_menu(self):
+ menu = ConsoleMenu("Bluetooth Panel", "Scenario Tester", clear_screen = False)
+ function_item = FunctionItem("Toggle Bluetooth hardware rfkill", self.toggle_hw_rfkill)
+ menu.append_item(function_item)
+
+ function_item = FunctionItem("Toggle default adapter unpowered", self.set_unpowered)
+ menu.append_item(function_item)
+
+ function_item = FunctionItem("Unplug/plug default adapter", self.unplug_default_adapter)
+ menu.append_item(function_item)
+
+ function_item = FunctionItem("Toggle airplane mode", self.toggle_airplane_mode)
+ menu.append_item(function_item)
+
+ menu.start(show_exit_option=False)
+
+ def wrap_call(self):
+ os.environ['GSETTINGS_BACKEND'] = 'memory'
+
+ wrapper = os.environ.get('META_DBUS_RUNNER_WRAPPER')
+ args = ['gnome-control-center', '-v', 'bluetooth']
+ if wrapper == 'gdb':
+ args = ['gdb', '-ex', 'r', '-ex', 'bt full', '--args'] + args
+ elif wrapper:
+ args = wrapper.split(' ') + args
+
+ p = subprocess.Popen(args, env=os.environ)
+ p.wait()
+
+if __name__ == '__main__':
+ #if 'umockdev' not in os.environ.get('LD_PRELOAD', ''):
+ # os.execvp('umockdev-wrapper', ['umockdev-wrapper'] + sys.argv)
+
+ GccDBusTestCase.setUpClass()
+ test_case = GccDBusTestCase()
+ test_case.start_menu()
+ try:
+ test_case.wrap_call()
+ finally:
+ GccDBusTestCase.tearDownClass()
diff --git a/panels/bluetooth/bluetooth.gresource.xml b/panels/bluetooth/bluetooth.gresource.xml
new file mode 100644
index 0000000..75b960a
--- /dev/null
+++ b/panels/bluetooth/bluetooth.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/bluetooth">
+ <file preprocess="xml-stripblanks">cc-bluetooth-panel.ui</file>
+ </gresource>
+</gresources>
diff --git a/panels/bluetooth/cc-bluetooth-panel.c b/panels/bluetooth/cc-bluetooth-panel.c
new file mode 100644
index 0000000..175e365
--- /dev/null
+++ b/panels/bluetooth/cc-bluetooth-panel.c
@@ -0,0 +1,269 @@
+/*
+ *
+ * Copyright (C) 2013 Bastien Nocera <hadess@hadess.net>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <adwaita.h>
+
+#include <shell/cc-shell.h>
+#include <shell/cc-object-storage.h>
+#include <bluetooth-settings-widget.h>
+
+#include "cc-bluetooth-panel.h"
+#include "cc-bluetooth-resources.h"
+
+struct _CcBluetoothPanel {
+ CcPanel parent_instance;
+
+ AdwStatusPage *airplane_page;
+ AdwStatusPage *disabled_page;
+ GtkSwitch *enable_switch;
+ GtkBox *header_box;
+ AdwStatusPage *hw_airplane_page;
+ AdwStatusPage *no_devices_page;
+ BluetoothSettingsWidget *settings_widget;
+ GtkStack *stack;
+
+ /* Killswitch */
+ GDBusProxy *rfkill;
+ GDBusProxy *properties;
+ gboolean airplane_mode;
+ gboolean bt_airplane_mode;
+ gboolean hardware_airplane_mode;
+ gboolean has_airplane_mode;
+};
+
+CC_PANEL_REGISTER (CcBluetoothPanel, cc_bluetooth_panel)
+
+static const char *
+cc_bluetooth_panel_get_help_uri (CcPanel *panel)
+{
+ return "help:gnome-help/bluetooth";
+}
+
+static void
+cc_bluetooth_panel_finalize (GObject *object)
+{
+ CcBluetoothPanel *self;
+
+ self = CC_BLUETOOTH_PANEL (object);
+
+ g_clear_object (&self->properties);
+ g_clear_object (&self->rfkill);
+
+ G_OBJECT_CLASS (cc_bluetooth_panel_parent_class)->finalize (object);
+}
+
+static void
+airplane_mode_changed_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GVariant) ret = NULL;
+ g_autoptr(GError) error = NULL;
+ gboolean state = GPOINTER_TO_UINT (user_data);
+
+ if (!g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
+ res, &error)) {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to change Bluetooth killswitch state to %s: %s",
+ state ? "on" : "off", error->message);
+ } else {
+ CcBluetoothPanel *self = user_data;
+
+ g_debug ("Changed Bluetooth killswitch state to %s",
+ state ? "on" : "off");
+
+ if (!bluetooth_settings_widget_get_default_adapter_powered (self->settings_widget))
+ bluetooth_settings_widget_set_default_adapter_powered(self->settings_widget, TRUE);
+ }
+}
+
+static void
+enable_switch_state_set_cb (CcBluetoothPanel *self, gboolean state)
+{
+ g_debug ("Power switched to %s", state ? "on" : "off");
+ g_dbus_proxy_call (self->properties,
+ "Set",
+ g_variant_new_parsed ("('org.gnome.SettingsDaemon.Rfkill', 'BluetoothAirplaneMode', %v)",
+ g_variant_new_boolean (!state)),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ airplane_mode_changed_cb, self);
+}
+
+static void
+adapter_status_changed_cb (CcBluetoothPanel *self)
+{
+ GtkAlign valign;
+ gboolean sensitive, powered;
+ GtkWidget *page;
+
+ g_debug ("Updating airplane mode: BluetoothHasAirplaneMode %d, BluetoothHardwareAirplaneMode %d, BluetoothAirplaneMode %d, AirplaneMode %d",
+ self->has_airplane_mode, self->hardware_airplane_mode, self->bt_airplane_mode, self->airplane_mode);
+
+ valign = GTK_ALIGN_CENTER;
+
+ if (self->has_airplane_mode == FALSE) {
+ g_debug ("No Bluetooth available");
+ sensitive = FALSE;
+ powered = FALSE;
+ page = GTK_WIDGET (self->no_devices_page);
+ } else if (self->hardware_airplane_mode) {
+ g_debug ("Bluetooth is Hard blocked");
+ sensitive = FALSE;
+ powered = FALSE;
+ page = GTK_WIDGET (self->hw_airplane_page);
+ } else if (self->airplane_mode) {
+ g_debug ("Airplane mode is on, Wi-Fi and Bluetooth are disabled");
+ sensitive = FALSE;
+ powered = FALSE;
+ page = GTK_WIDGET (self->airplane_page);
+ } else if (self->bt_airplane_mode ||
+ !bluetooth_settings_widget_get_default_adapter_powered (self->settings_widget)) {
+ g_debug ("Default adapter is unpowered");
+ sensitive = TRUE;
+ powered = FALSE;
+ page = GTK_WIDGET (self->disabled_page);
+ } else {
+ g_debug ("Bluetooth is available and powered");
+ sensitive = TRUE;
+ powered = TRUE;
+ page = GTK_WIDGET (self->settings_widget);
+ valign = GTK_ALIGN_FILL;
+ }
+
+ gtk_widget_set_valign (GTK_WIDGET (self->stack), valign);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->header_box), sensitive);
+ g_signal_handlers_block_by_func (self->enable_switch, enable_switch_state_set_cb, self);
+ gtk_switch_set_state (self->enable_switch, powered);
+ g_signal_handlers_unblock_by_func (self->enable_switch, enable_switch_state_set_cb, self);
+
+ gtk_stack_set_visible_child (self->stack, page);
+}
+
+static void
+airplane_mode_changed (CcBluetoothPanel *self)
+{
+ g_autoptr(GVariant) airplane_mode = NULL;
+ g_autoptr(GVariant) bluetooth_airplane_mode = NULL;
+ g_autoptr(GVariant) bluetooth_hardware_airplane_mode = NULL;
+ g_autoptr(GVariant) bluetooth_has_airplane_mode = NULL;
+
+ airplane_mode = g_dbus_proxy_get_cached_property (self->rfkill, "AirplaneMode");
+ self->airplane_mode = g_variant_get_boolean (airplane_mode);
+
+ bluetooth_airplane_mode = g_dbus_proxy_get_cached_property (self->rfkill, "BluetoothAirplaneMode");
+ self->bt_airplane_mode = g_variant_get_boolean (bluetooth_airplane_mode);
+
+ bluetooth_hardware_airplane_mode = g_dbus_proxy_get_cached_property (self->rfkill, "BluetoothHardwareAirplaneMode");
+ g_message ("BluetoothHardwareAirplaneMode: %d", self->hardware_airplane_mode);
+ self->hardware_airplane_mode = g_variant_get_boolean (bluetooth_hardware_airplane_mode);
+
+ bluetooth_has_airplane_mode = g_dbus_proxy_get_cached_property (self->rfkill, "BluetoothHasAirplaneMode");
+ self->has_airplane_mode = g_variant_get_boolean (bluetooth_has_airplane_mode);
+
+ adapter_status_changed_cb (self);
+}
+
+static void
+airplane_mode_off_button_clicked_cb (CcBluetoothPanel *self)
+{
+ g_debug ("Airplane Mode Off clicked, disabling airplane mode");
+ g_dbus_proxy_call (self->rfkill,
+ "org.freedesktop.DBus.Properties.Set",
+ g_variant_new_parsed ("('org.gnome.SettingsDaemon.Rfkill',"
+ "'AirplaneMode', %v)",
+ g_variant_new_boolean (FALSE)),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ NULL, NULL);
+}
+
+static void
+panel_changed_cb (CcBluetoothPanel *self,
+ const char *panel)
+{
+ CcShell *shell;
+ g_autoptr(GError) error = NULL;
+
+ shell = cc_panel_get_shell (CC_PANEL (self));
+ if (cc_shell_set_active_panel_from_id (shell, panel, NULL, &error) == FALSE)
+ g_warning ("Failed to activate '%s' panel: %s", panel, error->message);
+}
+
+static void
+cc_bluetooth_panel_class_init (CcBluetoothPanelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+
+ object_class->finalize = cc_bluetooth_panel_finalize;
+
+ panel_class->get_help_uri = cc_bluetooth_panel_get_help_uri;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/bluetooth/cc-bluetooth-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcBluetoothPanel, airplane_page);
+ gtk_widget_class_bind_template_child (widget_class, CcBluetoothPanel, disabled_page);
+ gtk_widget_class_bind_template_child (widget_class, CcBluetoothPanel, enable_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcBluetoothPanel, header_box);
+ gtk_widget_class_bind_template_child (widget_class, CcBluetoothPanel, no_devices_page);
+ gtk_widget_class_bind_template_child (widget_class, CcBluetoothPanel, hw_airplane_page);
+ gtk_widget_class_bind_template_child (widget_class, CcBluetoothPanel, settings_widget);
+ gtk_widget_class_bind_template_child (widget_class, CcBluetoothPanel, stack);
+
+ gtk_widget_class_bind_template_callback (widget_class, adapter_status_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, airplane_mode_off_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, enable_switch_state_set_cb);
+ gtk_widget_class_bind_template_callback (widget_class, panel_changed_cb);
+}
+
+static void
+cc_bluetooth_panel_init (CcBluetoothPanel *self)
+{
+ bluetooth_settings_widget_get_type ();
+ g_resources_register (cc_bluetooth_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ /* RFKill */
+ self->rfkill = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "org.gnome.SettingsDaemon.Rfkill",
+ "/org/gnome/SettingsDaemon/Rfkill",
+ "org.gnome.SettingsDaemon.Rfkill",
+ NULL, NULL);
+ self->properties = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "org.gnome.SettingsDaemon.Rfkill",
+ "/org/gnome/SettingsDaemon/Rfkill",
+ "org.freedesktop.DBus.Properties",
+ NULL, NULL);
+
+ airplane_mode_changed (self);
+ g_signal_connect_object (self->rfkill, "g-properties-changed",
+ G_CALLBACK (airplane_mode_changed), self, G_CONNECT_SWAPPED);
+}
diff --git a/panels/bluetooth/cc-bluetooth-panel.h b/panels/bluetooth/cc-bluetooth-panel.h
new file mode 100644
index 0000000..2252cd2
--- /dev/null
+++ b/panels/bluetooth/cc-bluetooth-panel.h
@@ -0,0 +1,34 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2005-2008 Marcel Holtmann <marcel@holtmann.org>
+ * Copyright (C) 2006-2010 Bastien Nocera <hadess@hadess.net>
+ *
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#pragma once
+
+#include <shell/cc-shell.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_BLUETOOTH_PANEL (cc_bluetooth_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcBluetoothPanel, cc_bluetooth_panel, CC, BLUETOOTH_PANEL, CcPanel)
+
+G_END_DECLS
diff --git a/panels/bluetooth/cc-bluetooth-panel.ui b/panels/bluetooth/cc-bluetooth-panel.ui
new file mode 100644
index 0000000..94ad137
--- /dev/null
+++ b/panels/bluetooth/cc-bluetooth-panel.ui
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcBluetoothPanel" parent="CcPanel">
+
+ <child type="titlebar-end">
+ <object class="GtkBox" id="header_box">
+ <child>
+ <object class="GtkSwitch" id="enable_switch">
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Enable</property>
+ </accessibility>
+ <signal name="state-set" handler="enable_switch_state_set_cb" object="CcBluetoothPanel" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child type="content">
+ <object class="GtkStack" id="stack">
+ <child>
+ <object class="AdwStatusPage" id="no_devices_page">
+ <property name="icon-name">bluetooth-active-symbolic</property>
+ <property name="title" translatable="yes">No Bluetooth Found</property>
+ <property name="description" translatable="yes">Plug in a dongle to use Bluetooth.</property>
+ </object>
+ </child>
+ <child>
+ <object class="AdwStatusPage" id="disabled_page">
+ <property name="icon-name">bluetooth-active-symbolic</property>
+ <property name="title" translatable="yes">Bluetooth Turned Off</property>
+ <property name="description" translatable="yes">Turn on to connect devices and receive file transfers.</property>
+ </object>
+ </child>
+ <child>
+ <object class="AdwStatusPage" id="airplane_page">
+ <property name="icon-name">airplane-mode-symbolic</property>
+ <property name="title" translatable="yes">Airplane Mode is On</property>
+ <property name="description" translatable="yes">Bluetooth is disabled when airplane mode is on.</property>
+ <property name="child">
+ <object class="GtkButton">
+ <property name="label" translatable="yes">Turn Off Airplane Mode</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <signal name="clicked" handler="airplane_mode_off_button_clicked_cb" object="CcBluetoothPanel" swapped="yes"/>
+ <style>
+ <class name="pill"/>
+ </style>
+ </object>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="AdwStatusPage" id="hw_airplane_page">
+ <property name="icon-name">airplane-mode-symbolic</property>
+ <property name="title" translatable="yes">Hardware Airplane Mode is On</property>
+ <property name="description" translatable="yes">Turn off the Airplane mode switch to enable Bluetooth.</property>
+ </object>
+ </child>
+ <child>
+ <object class="BluetoothSettingsWidget" id="settings_widget">
+ <signal name="panel-changed" handler="panel_changed_cb" object="CcBluetoothPanel" swapped="yes"/>
+ <signal name="adapter-status-changed" handler="adapter_status_changed_cb" object="CcBluetoothPanel" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/bluetooth/dbusmock-templates/gsd_rfkill.py b/panels/bluetooth/dbusmock-templates/gsd_rfkill.py
new file mode 100644
index 0000000..1a57b4c
--- /dev/null
+++ b/panels/bluetooth/dbusmock-templates/gsd_rfkill.py
@@ -0,0 +1,75 @@
+'''gsd-rfkill mock template
+
+This creates the expected methods and properties of the main
+org.gnome.SettingsDaemon.Rfkill object.
+'''
+
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation; either version 3 of the License, or (at your option) any
+# later version. See http://www.gnu.org/copyleft/lgpl.html for the full text
+# of the license.
+
+__author__ = 'Bastien Nocera'
+__copyright__ = '(c) 2022, Red Hat Inc.'
+
+import dbus
+import os
+from dbusmock import mockobject
+
+BUS_NAME = 'org.gnome.SettingsDaemon.Rfkill'
+MAIN_OBJ = '/org/gnome/SettingsDaemon/Rfkill'
+MAIN_IFACE = 'org.gnome.SettingsDaemon.Rfkill'
+SYSTEM_BUS = False
+
+ADAPTER_IFACE = 'org.bluez.Adapter1'
+
+def rfkill_changed(*args, **kwargs):
+ [iface, changed, _invalidated] = args
+
+ rfkill = mockobject.objects[MAIN_OBJ]
+ adapter = dbus.bus.BusConnection(os.environ['DBUS_SYSTEM_BUS_ADDRESS']).get_object('org.bluez', '/org/bluez/hci0')
+ try:
+ adapter.Get(ADAPTER_IFACE, 'Name')
+ except:
+ adapter = None
+
+ if 'BluetoothAirplaneMode' in changed:
+ if adapter and rfkill.props[MAIN_IFACE]['BluetoothAirplaneMode'] == 1:
+ adapter.UpdateProperties(ADAPTER_IFACE,
+ {'Powered': dbus.Boolean(False),
+ 'Blocked': dbus.Boolean(True)})
+ elif adapter:
+ adapter.UpdateProperties(ADAPTER_IFACE,
+ {'Blocked': dbus.Boolean(False)})
+ if 'BluetoothHardwareAirplaneMode' in changed:
+ if rfkill.props[MAIN_IFACE]['BluetoothAirplaneMode'] == 0:
+ rfkill.Set(MAIN_IFACE, 'BluetoothAirplaneMode', dbus.Boolean(False))
+
+def load(mock, parameters):
+ # Loaded!
+ mock.loaded = True
+
+ props = {
+ 'AirplaneMode': parameters.get('AirplaneMode', dbus.Boolean(False)),
+ 'HardwareAirplaneMode': parameters.get('HardwareAirplaneMode', dbus.Boolean(False)),
+ 'HasAirplaneMode': parameters.get('HasAirplaneMode', dbus.Boolean(True)),
+ # True if not desktop, server, vm or container
+ 'ShouldShowAirplaneMode': parameters.get('ShouldShowAirplaneMode', dbus.Boolean(True)),
+ 'BluetoothAirplaneMode': parameters.get('BluetoothAirplaneMode', dbus.Boolean(False)),
+ 'BluetoothHardwareAirplaneMode': parameters.get('BluetoothAirplaneMode', dbus.Boolean(False)),
+ 'BluetoothHasAirplaneMode': parameters.get('BluetoothHasAirplaneMode', dbus.Boolean(True)),
+ 'WwanAirplaneMode': parameters.get('WwanAirplaneMode', dbus.Boolean(False)),
+ 'WwanHardwareAirplaneMode': parameters.get('WwanHardwareAirplaneMode', dbus.Boolean(False)),
+ 'WwanHasAirplaneMode': parameters.get('WwanHasAirplaneMode', dbus.Boolean(False)),
+ }
+ mock.AddProperties(MAIN_IFACE, dbus.Dictionary(props, signature='sv'))
+
+ rfkill = mockobject.objects[MAIN_OBJ]
+ rfkill.hci0_power = True
+
+ session_bus = dbus.SessionBus()
+ session_bus.add_signal_receiver(rfkill_changed,
+ signal_name='PropertiesChanged',
+ path=MAIN_OBJ,
+ dbus_interface='org.freedesktop.DBus.Properties')
diff --git a/panels/bluetooth/gnome-bluetooth-panel.desktop.in.in b/panels/bluetooth/gnome-bluetooth-panel.desktop.in.in
new file mode 100644
index 0000000..4d81f07
--- /dev/null
+++ b/panels/bluetooth/gnome-bluetooth-panel.desktop.in.in
@@ -0,0 +1,18 @@
+[Desktop Entry]
+Name=Bluetooth
+Comment=Turn Bluetooth on and off and connect your devices
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-bluetooth-symbolic
+Exec=gnome-control-center bluetooth
+Terminal=false
+Type=Application
+NoDisplay=true
+Categories=GTK;GNOME;Settings;X-GNOME-NetworkSettings;HardwareSettings;X-GNOME-Settings-Panel;X-GNOME-ConnectivitySettings;
+OnlyShowIn=GNOME;Unity;
+StartupNotify=true
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-bluetooth
+X-GNOME-Bugzilla-Component=properties
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: Search terms to find the Bluetooth panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=share;sharing;bluetooth;obex;
diff --git a/panels/bluetooth/icons/meson.build b/panels/bluetooth/icons/meson.build
new file mode 100644
index 0000000..ffaee3f
--- /dev/null
+++ b/panels/bluetooth/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-bluetooth-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/bluetooth/icons/scalable/org.gnome.Settings-bluetooth-symbolic.svg b/panels/bluetooth/icons/scalable/org.gnome.Settings-bluetooth-symbolic.svg
new file mode 100644
index 0000000..f086eb3
--- /dev/null
+++ b/panels/bluetooth/icons/scalable/org.gnome.Settings-bluetooth-symbolic.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <path d="m 7.585938 0.0898438 c -0.355469 0.1640622 -0.585938 0.5195312 -0.585938 0.9101562 v 5.296875 l -2.34375 -2.046875 c -0.414062 -0.363281 -1.042969 -0.324219 -1.40625 0.089844 c -0.363281 0.417968 -0.324219 1.046875 0.09375 1.410156 l 2.566406 2.25 l -2.566406 2.25 c -0.417969 0.363281 -0.457031 0.992188 -0.09375 1.40625 c 0.363281 0.417969 0.992188 0.457031 1.40625 0.09375 l 2.34375 -2.046875 v 5.296875 c 0 0.390625 0.230469 0.746094 0.585938 0.910156 c 0.359374 0.160156 0.777343 0.101563 1.070312 -0.160156 l 4 -3.5 c 0.21875 -0.1875 0.34375 -0.460938 0.34375 -0.75 s -0.125 -0.5625 -0.34375 -0.75 l -3.140625 -2.75 l 3.140625 -2.75 c 0.21875 -0.1875 0.34375 -0.460938 0.34375 -0.75 s -0.125 -0.5625 -0.34375 -0.75 l -4 -3.5 c -0.292969 -0.2617188 -0.710938 -0.3242188 -1.070312 -0.1601562 z m 1.414062 3.1132812 l 1.484375 1.296875 l -1.484375 1.296875 z m 0 7 l 1.484375 1.296875 l -1.484375 1.296875 z m 0 0" fill="#2e3436"/>
+</svg>
diff --git a/panels/bluetooth/meson.build b/panels/bluetooth/meson.build
new file mode 100644
index 0000000..e5be2b4
--- /dev/null
+++ b/panels/bluetooth/meson.build
@@ -0,0 +1,41 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+sources = files('cc-bluetooth-panel.c')
+
+resource_data = files('cc-bluetooth-panel.ui')
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname,
+ dependencies: resource_data,
+ export: true
+)
+
+deps = common_deps + [gnome_bluetooth_dep]
+
+panels_libs += static_library(
+ cappletname,
+ sources: sources,
+ include_directories: top_inc,
+ dependencies: deps,
+ c_args: cflags
+)
+
+subdir('icons')
diff --git a/panels/camera/camera.gresource.xml b/panels/camera/camera.gresource.xml
new file mode 100644
index 0000000..1d077c3
--- /dev/null
+++ b/panels/camera/camera.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/camera">
+ <file preprocess="xml-stripblanks">cc-camera-panel.ui</file>
+ </gresource>
+</gresources>
diff --git a/panels/camera/cc-camera-panel.c b/panels/camera/cc-camera-panel.c
new file mode 100644
index 0000000..3965b67
--- /dev/null
+++ b/panels/camera/cc-camera-panel.c
@@ -0,0 +1,416 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2018 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#include "cc-camera-panel.h"
+#include "cc-camera-resources.h"
+#include "cc-util.h"
+
+#include <adwaita.h>
+#include <gio/gdesktopappinfo.h>
+#include <glib/gi18n.h>
+
+#define APP_PERMISSIONS_TABLE "devices"
+#define APP_PERMISSIONS_ID "camera"
+
+struct _CcCameraPanel
+{
+ CcPanel parent_instance;
+
+ GtkStack *stack;
+ GtkListBox *camera_apps_list_box;
+ GtkSwitch *main_switch;
+
+ GSettings *privacy_settings;
+
+ GDBusProxy *perm_store;
+ GVariant *camera_apps_perms;
+ GVariant *camera_apps_data;
+ GHashTable *camera_app_switches;
+
+ GtkSizeGroup *camera_icon_size_group;
+};
+
+CC_PANEL_REGISTER (CcCameraPanel, cc_camera_panel)
+
+typedef struct
+{
+ CcCameraPanel *self;
+ GtkWidget *widget;
+ gchar *app_id;
+ gboolean changing_state;
+ gboolean pending_state;
+} CameraAppStateData;
+
+static void
+camera_app_state_data_free (CameraAppStateData *data)
+{
+ g_free (data->app_id);
+ g_slice_free (CameraAppStateData, data);
+}
+
+static void
+on_perm_store_set_done (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GVariant) results = NULL;
+ g_autoptr(GError) error = NULL;
+ CameraAppStateData *data;
+
+ results = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
+ res,
+ &error);
+ if (results == NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to store permissions: %s", error->message);
+ return;
+ }
+
+ data = (CameraAppStateData *) user_data;
+ data->changing_state = FALSE;
+ gtk_switch_set_state (GTK_SWITCH (data->widget), data->pending_state);
+}
+
+static gboolean
+on_camera_app_state_set (GtkSwitch *widget,
+ gboolean state,
+ gpointer user_data)
+{
+ CameraAppStateData *data = (CameraAppStateData *) user_data;
+ GVariantBuilder builder;
+ CcCameraPanel *self;
+ GVariantIter iter;
+ GVariant *params;
+ const gchar *key;
+ gchar **value;
+
+ self = data->self;
+
+ if (data->changing_state)
+ return TRUE;
+
+ data->changing_state = TRUE;
+ data->pending_state = state;
+
+ g_variant_iter_init (&iter, self->camera_apps_perms);
+ g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
+ while (g_variant_iter_loop (&iter, "{&s^a&s}", &key, &value))
+ {
+ gchar *tmp = NULL;
+
+ /* It's OK to drop the entry if it's not in expected format */
+ if (g_strv_length (value) != 1)
+ continue;
+
+ if (g_strcmp0 (data->app_id, key) == 0)
+ {
+ tmp = value[0];
+ value[0] = state ? "yes" : "no";
+ }
+
+ g_variant_builder_add (&builder, "{s^as}", key, value);
+
+ if (tmp != NULL)
+ value[0] = tmp;
+ }
+
+ params = g_variant_new ("(sbsa{sas}v)",
+ APP_PERMISSIONS_TABLE,
+ TRUE,
+ APP_PERMISSIONS_ID,
+ &builder,
+ self->camera_apps_data);
+
+ g_dbus_proxy_call (self->perm_store,
+ "Set",
+ params,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ on_perm_store_set_done,
+ data);
+
+ return TRUE;
+}
+
+static void
+add_camera_app (CcCameraPanel *self,
+ const gchar *app_id,
+ gboolean enabled)
+{
+ g_autofree gchar *desktop_id = NULL;
+ CameraAppStateData *data;
+ GDesktopAppInfo *app_info;
+ GtkWidget *row, *w;
+ GIcon *icon;
+
+ w = g_hash_table_lookup (self->camera_app_switches, app_id);
+ if (w != NULL)
+ {
+ gtk_switch_set_active (GTK_SWITCH (w), enabled);
+ return;
+ }
+
+ desktop_id = g_strdup_printf ("%s.desktop", app_id);
+ app_info = g_desktop_app_info_new (desktop_id);
+ if (!app_info)
+ return;
+
+ row = adw_action_row_new ();
+ gtk_list_box_append (self->camera_apps_list_box, row);
+
+ icon = g_app_info_get_icon (G_APP_INFO (app_info));
+ w = gtk_image_new_from_gicon (icon);
+ gtk_widget_set_valign (w, GTK_ALIGN_CENTER);
+ gtk_size_group_add_widget (self->camera_icon_size_group, w);
+ adw_action_row_add_prefix (ADW_ACTION_ROW (row), w);
+
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row),
+ g_app_info_get_name (G_APP_INFO (app_info)));
+
+ w = gtk_switch_new ();
+ gtk_switch_set_active (GTK_SWITCH (w), enabled);
+ gtk_widget_set_valign (w, GTK_ALIGN_CENTER);
+ adw_action_row_add_suffix (ADW_ACTION_ROW (row), w);
+ g_settings_bind (self->privacy_settings,
+ "disable-camera",
+ w,
+ "sensitive",
+ G_SETTINGS_BIND_INVERT_BOOLEAN);
+ g_hash_table_insert (self->camera_app_switches,
+ g_strdup (app_id),
+ g_object_ref (w));
+
+ data = g_slice_new (CameraAppStateData);
+ data->self = self;
+ data->app_id = g_strdup (app_id);
+ data->widget = w;
+ data->changing_state = FALSE;
+ g_signal_connect_data (G_OBJECT (w),
+ "state-set",
+ G_CALLBACK (on_camera_app_state_set),
+ data,
+ (GClosureNotify) camera_app_state_data_free,
+ 0);
+}
+
+/* Steals permissions and permissions_data references */
+
+static gboolean
+to_child_name (GBinding *binding,
+ const GValue *from,
+ GValue *to,
+ gpointer user_data)
+{
+ if (g_value_get_boolean (from))
+ g_value_set_string (to, "content");
+ else
+ g_value_set_string (to, "empty");
+ return TRUE;
+}
+
+static void
+update_perm_store (CcCameraPanel *self,
+ GVariant *permissions,
+ GVariant *permissions_data)
+{
+ GVariantIter iter;
+ const gchar *key;
+ gchar **value;
+
+ g_clear_pointer (&self->camera_apps_perms, g_variant_unref);
+ self->camera_apps_perms = permissions;
+ g_clear_pointer (&self->camera_apps_data, g_variant_unref);
+ self->camera_apps_data = permissions_data;
+
+ g_variant_iter_init (&iter, permissions);
+ while (g_variant_iter_loop (&iter, "{&s^a&s}", &key, &value))
+ {
+ gboolean enabled;
+
+ if (g_strv_length (value) != 1)
+ {
+ g_debug ("Permissions for %s in incorrect format, ignoring..", key);
+ continue;
+ }
+
+ enabled = (g_strcmp0 (value[0], "no") != 0);
+
+ add_camera_app (self, key, enabled);
+ }
+}
+
+static void
+on_perm_store_signal (GDBusProxy *proxy,
+ gchar *sender_name,
+ gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ GVariant *permissions, *permissions_data;
+
+ if (g_strcmp0 (signal_name, "Changed") != 0)
+ return;
+
+ permissions = g_variant_get_child_value (parameters, 4);
+ permissions_data = g_variant_get_child_value (parameters, 3);
+ update_perm_store (user_data, permissions, permissions_data);
+}
+
+static void
+on_perm_store_lookup_done (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcCameraPanel *self = user_data;
+ GVariant *ret, *permissions, *permissions_data;
+ g_autoptr(GError) error = NULL;
+
+ ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
+ res,
+ &error);
+ if (ret == NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed fetch permissions from flatpak permission store: %s", error->message);
+ return;
+ }
+
+ permissions = g_variant_get_child_value (ret, 0);
+ permissions_data = g_variant_get_child_value (ret, 1);
+ update_perm_store (user_data, permissions, permissions_data);
+
+ g_signal_connect_object (source_object,
+ "g-signal",
+ G_CALLBACK (on_perm_store_signal),
+ self,
+ 0);
+}
+
+static void
+on_perm_store_ready (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcCameraPanel *self;
+ g_autoptr(GVariant) params = NULL;
+ g_autoptr(GError) error = NULL;
+ GDBusProxy *proxy;
+
+ proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+ if (proxy == NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to connect to flatpak permission store: %s", error->message);
+ return;
+ }
+ self = user_data;
+ self->perm_store = proxy;
+
+ params = g_variant_new ("(ss)",
+ APP_PERMISSIONS_TABLE,
+ APP_PERMISSIONS_ID);
+ g_dbus_proxy_call (self->perm_store,
+ "Lookup",
+ params,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ on_perm_store_lookup_done,
+ self);
+}
+
+static void
+cc_camera_panel_finalize (GObject *object)
+{
+ CcCameraPanel *self = CC_CAMERA_PANEL (object);
+
+ g_clear_object (&self->privacy_settings);
+ g_clear_object (&self->perm_store);
+ g_clear_object (&self->camera_icon_size_group);
+ g_clear_pointer (&self->camera_apps_perms, g_variant_unref);
+ g_clear_pointer (&self->camera_apps_data, g_variant_unref);
+ g_clear_pointer (&self->camera_app_switches, g_hash_table_unref);
+
+ G_OBJECT_CLASS (cc_camera_panel_parent_class)->finalize (object);
+}
+
+static const char *
+cc_camera_panel_get_help_uri (CcPanel *panel)
+{
+ return "help:gnome-help/camera";
+}
+
+static void
+cc_camera_panel_class_init (CcCameraPanelClass *klass)
+{
+ CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ panel_class->get_help_uri = cc_camera_panel_get_help_uri;
+
+ object_class->finalize = cc_camera_panel_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/camera/cc-camera-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcCameraPanel, stack);
+ gtk_widget_class_bind_template_child (widget_class, CcCameraPanel, camera_apps_list_box);
+ gtk_widget_class_bind_template_child (widget_class, CcCameraPanel, main_switch);
+}
+
+static void
+cc_camera_panel_init (CcCameraPanel *self)
+{
+ g_resources_register (cc_camera_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->camera_icon_size_group = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);
+
+ self->privacy_settings = g_settings_new ("org.gnome.desktop.privacy");
+
+ g_settings_bind (self->privacy_settings, "disable-camera",
+ self->main_switch, "active",
+ G_SETTINGS_BIND_INVERT_BOOLEAN);
+
+ g_object_bind_property_full (self->main_switch, "active",
+ self->stack, "visible-child-name",
+ G_BINDING_SYNC_CREATE,
+ to_child_name,
+ NULL,
+ NULL, NULL);
+
+ self->camera_app_switches = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ g_object_unref);
+
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.freedesktop.impl.portal.PermissionStore",
+ "/org/freedesktop/impl/portal/PermissionStore",
+ "org.freedesktop.impl.portal.PermissionStore",
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ on_perm_store_ready,
+ self);
+}
diff --git a/panels/camera/cc-camera-panel.h b/panels/camera/cc-camera-panel.h
new file mode 100644
index 0000000..dfc45ab
--- /dev/null
+++ b/panels/camera/cc-camera-panel.h
@@ -0,0 +1,30 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2018 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_CAMERA_PANEL (cc_camera_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcCameraPanel, cc_camera_panel, CC, CAMERA_PANEL, CcPanel)
+
+G_END_DECLS
diff --git a/panels/camera/cc-camera-panel.ui b/panels/camera/cc-camera-panel.ui
new file mode 100644
index 0000000..b357cec
--- /dev/null
+++ b/panels/camera/cc-camera-panel.ui
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcCameraPanel" parent="CcPanel">
+
+ <child type="titlebar-end">
+ <object class="GtkSwitch" id="main_switch">
+ <accessibility>
+ <property name="label" translatable="yes">Enable</property>
+ </accessibility>
+ <property name="valign">center</property>
+ </object>
+ </child>
+
+ <child type="content">
+ <object class="GtkStack" id="stack">
+
+ <!-- Empty page -->
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">empty</property>
+ <property name="child">
+ <object class="AdwStatusPage">
+ <property name="icon-name">camera-disabled-symbolic</property>
+ <property name="title" translatable="yes">Camera is Turned Off</property>
+ <property name="description" translatable="yes">No applications can capture photos or video.</property>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <!-- Cameras -->
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">content</property>
+ <property name="child">
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="description" translatable="yes">Use of the camera allows applications to capture photos and video. Disabling the camera may cause some applications to not function properly.
+
+Allow the applications below to use your camera.</property>
+ <child>
+ <object class="GtkListBox" id="camera_apps_list_box">
+ <property name="selection-mode">none</property>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+
+ <child type="placeholder">
+ <object class="GtkLabel">
+ <property name="margin-start">18</property>
+ <property name="margin-end">18</property>
+ <property name="margin-top">18</property>
+ <property name="margin-bottom">18</property>
+ <property name="label" translatable="yes">No Applications Have Asked for Camera Access</property>
+ <property name="wrap">true</property>
+ <property name="max-width-chars">50</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/camera/gnome-camera-panel.desktop.in.in b/panels/camera/gnome-camera-panel.desktop.in.in
new file mode 100644
index 0000000..e05d5a2
--- /dev/null
+++ b/panels/camera/gnome-camera-panel.desktop.in.in
@@ -0,0 +1,19 @@
+[Desktop Entry]
+Name=Camera
+Comment=Protect your pictures
+Exec=gnome-control-center camera
+# FIXME
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-camera-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-PrivacySettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=privacy
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: Search terms to find the Camera panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=camera;photos;video;webcam;lock;private;privacy;
diff --git a/panels/camera/icons/meson.build b/panels/camera/icons/meson.build
new file mode 100644
index 0000000..c0372b2
--- /dev/null
+++ b/panels/camera/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-camera-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/camera/icons/scalable/org.gnome.Settings-camera-symbolic.svg b/panels/camera/icons/scalable/org.gnome.Settings-camera-symbolic.svg
new file mode 100644
index 0000000..1219b9c
--- /dev/null
+++ b/panels/camera/icons/scalable/org.gnome.Settings-camera-symbolic.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <path d="m 6.414062 0 c -0.265624 0 -0.519531 0.105469 -0.707031 0.292969 l -1.707031 1.707031 h -1.085938 c -1.644531 0 -2.9999995 1.355469 -2.9999995 3 v 7 c 0 1.644531 1.3554685 3 2.9999995 3 h 10 c 1.644532 0 3 -1.355469 3 -3 v -7 c 0 -1.644531 -1.355468 -3 -3 -3 h -1.085937 l -1.707031 -1.707031 c -0.1875 -0.1875 -0.441406 -0.292969 -0.707032 -0.292969 z m 0.414063 2 h 2.171875 l 1.707031 1.707031 c 0.1875 0.1875 0.441407 0.292969 0.707031 0.292969 h 1.5 c 0.570313 0 1 0.429688 1 1 v 7 c 0 0.570312 -0.429687 1 -1 1 h -10 c -0.570312 0 -1 -0.429688 -1 -1 v -7 c 0 -0.570312 0.429688 -1 1 -1 h 1.5 c 0.265626 0 0.519532 -0.105469 0.707032 -0.292969 z m 1.085937 3 c -1.644531 0 -3 1.355469 -3 3 s 1.585938 3 3 3 c 1.414063 0 3 -1.355469 3 -3 s -1.355468 -3 -3 -3 z m 0 2 c 0.5625 0 1 0.4375 1 1 s -0.4375 1 -1 1 s -1 -0.4375 -1 -1 s 0.4375 -1 1 -1 z m 0 0" fill="#2e3434"/>
+</svg>
diff --git a/panels/camera/meson.build b/panels/camera/meson.build
new file mode 100644
index 0000000..a69227b
--- /dev/null
+++ b/panels/camera/meson.build
@@ -0,0 +1,41 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+sources = files('cc-camera-panel.c')
+
+resource_data = files('cc-camera-panel.ui')
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname,
+ dependencies: resource_data,
+ export: true
+)
+
+cflags += '-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir)
+
+panels_libs += static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [top_inc, common_inc],
+ dependencies: common_deps,
+ c_args: cflags
+)
+
+subdir('icons')
diff --git a/panels/color/cc-color-calibrate.c b/panels/color/cc-color-calibrate.c
new file mode 100644
index 0000000..dc9d0f0
--- /dev/null
+++ b/panels/color/cc-color-calibrate.c
@@ -0,0 +1,993 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <colord-gtk.h>
+#include <gio/gunixfdlist.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <math.h>
+#include <colord-session/cd-session.h>
+
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <gnome-rr/gnome-rr.h>
+
+#include "cc-color-calibrate.h"
+
+#define CALIBRATE_WINDOW_OPACITY 0.9
+
+struct _CcColorCalibrate
+{
+ GObject parent_instance;
+
+ CdDevice *device;
+ CdSensorCap device_kind;
+ CdSensor *sensor;
+ CdProfile *profile;
+ gchar *title;
+ GDBusProxy *proxy_helper;
+ GDBusProxy *proxy_inhibit;
+ GMainLoop *loop;
+ GnomeRROutput *output;
+ GnomeRRScreen *x11_screen;
+ GtkBuilder *builder;
+ GtkWindow *window;
+ GtkWidget *sample_widget;
+ guint gamma_size;
+ CdProfileQuality quality;
+ guint target_whitepoint; /* in Kelvin */
+ gdouble target_gamma;
+ gint inhibit_fd;
+ gint inhibit_cookie;
+ CdSessionError session_error_code;
+};
+
+#define CD_SESSION_ERROR cc_color_calibrate_error_quark()
+
+#define COLORD_SETTINGS_SCHEMA "org.freedesktop.ColorHelper"
+
+G_DEFINE_TYPE (CcColorCalibrate, cc_color_calibrate, G_TYPE_OBJECT)
+
+static GQuark
+cc_color_calibrate_error_quark (void)
+{
+ static GQuark quark = 0;
+ if (!quark)
+ quark = g_quark_from_static_string ("CcColorCalibrateError");
+ return quark;
+}
+
+void
+cc_color_calibrate_set_kind (CcColorCalibrate *calibrate,
+ CdSensorCap kind)
+{
+ g_return_if_fail (CC_IS_COLOR_CALIBRATE (calibrate));
+ calibrate->device_kind = kind;
+}
+
+void
+cc_color_calibrate_set_temperature (CcColorCalibrate *calibrate,
+ guint temperature)
+{
+ g_return_if_fail (CC_IS_COLOR_CALIBRATE (calibrate));
+ g_return_if_fail (temperature < 10000);
+ calibrate->target_whitepoint = temperature;
+}
+
+void
+cc_color_calibrate_set_quality (CcColorCalibrate *calibrate,
+ CdProfileQuality quality)
+{
+ g_return_if_fail (CC_IS_COLOR_CALIBRATE (calibrate));
+ calibrate->quality = quality;
+}
+
+CdProfileQuality
+cc_color_calibrate_get_quality (CcColorCalibrate *calibrate)
+{
+ g_return_val_if_fail (CC_IS_COLOR_CALIBRATE (calibrate), 0);
+ return calibrate->quality;
+}
+
+void
+cc_color_calibrate_set_device (CcColorCalibrate *calibrate,
+ CdDevice *device)
+{
+ g_return_if_fail (CC_IS_COLOR_CALIBRATE (calibrate));
+ g_return_if_fail (CD_IS_DEVICE (device));
+ if (calibrate->device != NULL)
+ g_object_unref (calibrate->device);
+ calibrate->device = g_object_ref (device);
+}
+
+void
+cc_color_calibrate_set_sensor (CcColorCalibrate *calibrate,
+ CdSensor *sensor)
+{
+ g_return_if_fail (CC_IS_COLOR_CALIBRATE (calibrate));
+ g_return_if_fail (CD_IS_SENSOR (sensor));
+ if (calibrate->sensor != NULL)
+ g_object_unref (calibrate->sensor);
+ calibrate->sensor = g_object_ref (sensor);
+}
+
+void
+cc_color_calibrate_set_title (CcColorCalibrate *calibrate,
+ const gchar *title)
+{
+ g_return_if_fail (CC_IS_COLOR_CALIBRATE (calibrate));
+ g_return_if_fail (title != NULL);
+ g_free (calibrate->title);
+ calibrate->title = g_strdup (title);
+}
+
+CdProfile *
+cc_color_calibrate_get_profile (CcColorCalibrate *calibrate)
+{
+ g_return_val_if_fail (CC_IS_COLOR_CALIBRATE (calibrate), NULL);
+ return calibrate->profile;
+}
+
+static guint
+_gnome_rr_output_get_gamma_size (GnomeRROutput *output)
+{
+ GnomeRRCrtc *crtc;
+ gint len = 0;
+
+ crtc = gnome_rr_output_get_crtc (output);
+ if (crtc == NULL)
+ return 0;
+ gnome_rr_crtc_get_gamma (crtc,
+ &len,
+ NULL, NULL, NULL);
+ return (guint) len;
+}
+
+static gboolean
+cc_color_calibrate_calib_setup_screen (CcColorCalibrate *calibrate,
+ const gchar *name,
+ GError **error)
+{
+ gboolean ret = TRUE;
+
+ /* get screen */
+ calibrate->x11_screen = gnome_rr_screen_new (gdk_display_get_default (), error);
+ if (calibrate->x11_screen == NULL)
+ {
+ ret = FALSE;
+ goto out;
+ }
+
+ /* get the output */
+ calibrate->output = gnome_rr_screen_get_output_by_name (calibrate->x11_screen,
+ name);
+ if (calibrate->output == NULL)
+ {
+ ret = FALSE;
+ g_set_error_literal (error,
+ CD_SESSION_ERROR,
+ CD_SESSION_ERROR_INTERNAL,
+ "failed to get output");
+ goto out;
+ }
+
+ /* create a lookup table */
+ calibrate->gamma_size = _gnome_rr_output_get_gamma_size (calibrate->output);
+ if (calibrate->gamma_size == 0)
+ {
+ ret = FALSE;
+ g_set_error_literal (error,
+ CD_SESSION_ERROR,
+ CD_SESSION_ERROR_INTERNAL,
+ "gamma size is zero");
+ }
+out:
+ return ret;
+}
+
+/**
+ * cc_color_calibrate_calib_set_output_gamma:
+ *
+ * Handle this here rather than in gnome-settings-daemon for two reasons:
+ *
+ * - We don't want to create a profile each time the video card gamma
+ * table is created, as that would mean ~15 DBus requests each time
+ * we get UpdateGamma from the session helper.
+ *
+ * - We only have 100ms to process the request before the next update
+ * could be scheduled.
+ **/
+static gboolean
+cc_color_calibrate_calib_set_output_gamma (CcColorCalibrate *calibrate,
+ GPtrArray *array,
+ GError **error)
+{
+ CdColorRGB *p1;
+ CdColorRGB *p2;
+ CdColorRGB result;
+ gdouble mix;
+ GnomeRRCrtc *crtc;
+ g_autofree guint16 *blue = NULL;
+ g_autofree guint16 *green = NULL;
+ g_autofree guint16 *red = NULL;
+ guint i;
+
+ /* no length? */
+ if (array->len == 0)
+ {
+ g_set_error_literal (error,
+ CD_SESSION_ERROR,
+ CD_SESSION_ERROR_INTERNAL,
+ "no data in the CLUT array");
+ return FALSE;
+ }
+
+ /* convert to a type X understands of the right size */
+ red = g_new (guint16, calibrate->gamma_size);
+ green = g_new (guint16, calibrate->gamma_size);
+ blue = g_new (guint16, calibrate->gamma_size);
+ cd_color_rgb_set (&result, 1.0, 1.0, 1.0);
+ for (i = 0; i < calibrate->gamma_size; i++)
+ {
+ mix = (gdouble) (array->len - 1) /
+ (gdouble) (calibrate->gamma_size - 1) *
+ (gdouble) i;
+ p1 = g_ptr_array_index (array, (guint) floor (mix));
+ p2 = g_ptr_array_index (array, (guint) ceil (mix));
+ cd_color_rgb_interpolate (p1,
+ p2,
+ mix - (gint) mix,
+ &result);
+ red[i] = result.R * 0xffff;
+ green[i] = result.G * 0xffff;
+ blue[i] = result.B * 0xffff;
+ }
+
+ /* send to LUT */
+ crtc = gnome_rr_output_get_crtc (calibrate->output);
+ if (crtc == NULL)
+ {
+ g_set_error (error,
+ CD_SESSION_ERROR,
+ CD_SESSION_ERROR_INTERNAL,
+ "failed to get ctrc for %s",
+ gnome_rr_output_get_name (calibrate->output));
+ return FALSE;
+ }
+ gnome_rr_crtc_set_gamma (crtc, calibrate->gamma_size,
+ red, green, blue);
+ return TRUE;
+}
+
+static void
+cc_color_calibrate_property_changed_cb (CcColorCalibrate *calibrate,
+ GVariant *changed_properties,
+ GStrv invalidated_properties)
+{
+ gboolean ret;
+ GtkWidget *widget;
+ guint value;
+
+ ret = g_variant_lookup (changed_properties,
+ "Progress",
+ "u", &value);
+ if (ret)
+ {
+ widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder,
+ "progressbar_status"));
+ gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (widget),
+ value / 100.0f);
+ }
+}
+
+static void
+cc_color_calibrate_interaction_required (CcColorCalibrate *calibrate,
+ CdSessionInteraction code,
+ const gchar *message,
+ const gchar *image_path)
+{
+ const gchar *message_transl;
+ gboolean show_button_start = FALSE;
+ GtkImage *img;
+ GtkLabel *label;
+ GtkWidget *widget;
+
+ /* the client helper does not ship an icon for this */
+ if (code == CD_SESSION_INTERACTION_SHUT_LAPTOP_LID)
+ image_path = "preferences-color-symbolic";
+
+ /* set image */
+ img = GTK_IMAGE (gtk_builder_get_object (calibrate->builder,
+ "image_status"));
+ if (image_path != NULL && image_path[0] != '\0')
+ {
+ g_autoptr(GdkPixbuf) pixbuf = NULL;
+
+ g_debug ("showing image %s", image_path);
+ pixbuf = gdk_pixbuf_new_from_file_at_size (image_path,
+ 400, 400,
+ NULL);
+ if (pixbuf != NULL)
+ gtk_image_set_from_pixbuf (img, pixbuf);
+ gtk_widget_set_visible (GTK_WIDGET (img), TRUE);
+ gtk_widget_set_visible (GTK_WIDGET (calibrate->sample_widget), FALSE);
+ }
+ else
+ {
+ g_debug ("hiding image");
+ gtk_widget_set_visible (GTK_WIDGET (img), FALSE);
+ gtk_widget_set_visible (GTK_WIDGET (calibrate->sample_widget), TRUE);
+ }
+
+ /* set new status */
+ switch (code)
+ {
+ case CD_SESSION_INTERACTION_ATTACH_TO_SCREEN:
+ show_button_start = TRUE;
+ /* TRANSLATORS: The user has to attach the sensor to the screen */
+ message_transl = _("Place your calibration device over the square and press “Start”");
+ break;
+ case CD_SESSION_INTERACTION_MOVE_TO_CALIBRATION:
+ /* TRANSLATORS: Some calibration devices need the user to move a
+ * dial or switch manually. We also show a picture showing them
+ * what to do... */
+ message_transl = _("Move your calibration device to the calibrate position and press “Continue”");
+ break;
+ case CD_SESSION_INTERACTION_MOVE_TO_SURFACE:
+ /* TRANSLATORS: Some calibration devices need the user to move a
+ * dial or switch manually. We also show a picture showing them
+ * what to do... */
+ message_transl = _("Move your calibration device to the surface position and press “Continue”");
+ break;
+ case CD_SESSION_INTERACTION_SHUT_LAPTOP_LID:
+ /* TRANSLATORS: on some hardware e.g. Lenovo W700 the sensor
+ * is built into the palmrest and we need to fullscreen the
+ * sample widget and shut the lid. */
+ message_transl = _("Shut the laptop lid");
+ break;
+ default:
+ message_transl = message;
+ break;
+ }
+ label = GTK_LABEL (gtk_builder_get_object (calibrate->builder,
+ "label_status"));
+ gtk_label_set_label (label, message_transl);
+
+ /* show the correct button */
+ widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder,
+ "button_start"));
+ gtk_widget_set_visible (widget, show_button_start);
+ widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder,
+ "button_resume"));
+ gtk_widget_set_visible (widget, !show_button_start);
+}
+
+static const gchar *
+cc_color_calibrate_get_error_translation (CdSessionError code)
+{
+ const gchar *str = NULL;
+ switch (code)
+ {
+ case CD_SESSION_ERROR_FAILED_TO_FIND_DEVICE:
+ case CD_SESSION_ERROR_FAILED_TO_FIND_SENSOR:
+ case CD_SESSION_ERROR_INTERNAL:
+ case CD_SESSION_ERROR_INVALID_VALUE:
+ /* TRANSLATORS: We suck, the calibration failed and we have no
+ * good idea why or any suggestions */
+ str = _("An internal error occurred that could not be recovered.");
+ break;
+ case CD_SESSION_ERROR_FAILED_TO_FIND_TOOL:
+ /* TRANSLATORS: Some required-at-runtime tools were not
+ * installed, which should only affect insane distros */
+ str = _("Tools required for calibration are not installed.");
+ break;
+ case CD_SESSION_ERROR_FAILED_TO_GENERATE_PROFILE:
+ case CD_SESSION_ERROR_FAILED_TO_OPEN_PROFILE:
+ case CD_SESSION_ERROR_FAILED_TO_SAVE_PROFILE:
+ /* TRANSLATORS: The profile failed for some reason */
+ str = _("The profile could not be generated.");
+ break;
+ case CD_SESSION_ERROR_FAILED_TO_GET_WHITEPOINT:
+ /* TRANSLATORS: The user specified a whitepoint that was
+ * unobtainable with the hardware they've got -- see
+ * https://en.wikipedia.org/wiki/White_point for details */
+ str = _("The target whitepoint was not obtainable.");
+ break;
+ default:
+ break;
+ }
+ return str;
+}
+
+static void
+cc_color_calibrate_finished (CcColorCalibrate *calibrate,
+ CdSessionError code,
+ const gchar *error_fallback)
+{
+ GtkWidget *widget;
+ g_autoptr(GString) str = NULL;
+ const gchar *tmp;
+
+ /* save failure so we can get this after we've quit the loop */
+ calibrate->session_error_code = code;
+
+ /* show correct buttons */
+ widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder,
+ "button_cancel"));
+ gtk_widget_set_visible (widget, FALSE);
+ widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder,
+ "button_start"));
+ gtk_widget_set_visible (widget, FALSE);
+ widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder,
+ "button_resume"));
+ gtk_widget_set_visible (widget, FALSE);
+ widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder,
+ "button_done"));
+ gtk_widget_set_visible (widget, TRUE);
+
+ str = g_string_new ("");
+ if (code == CD_SESSION_ERROR_NONE)
+ {
+ g_debug ("calibration succeeded");
+ /* TRANSLATORS: the display calibration process is finished */
+ g_string_append (str, _("Complete!"));
+ }
+ else
+ {
+ g_warning ("calibration failed with code %i: %s",
+ code, error_fallback);
+ /* TRANSLATORS: the display calibration failed, and we also show
+ * the translated (or untranslated) error string after this */
+ g_string_append (str, _("Calibration failed!"));
+ g_string_append (str, "\n\n");
+ tmp = cc_color_calibrate_get_error_translation (code);
+ g_string_append (str, tmp != NULL ? tmp : error_fallback);
+ }
+ g_string_append (str, "\n");
+ /* TRANSLATORS: The user can now remove the sensor from the screen */
+ g_string_append (str, _("You can remove the calibration device."));
+
+ widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder,
+ "label_status"));
+ gtk_label_set_label (GTK_LABEL (widget), str->str);
+}
+
+static void
+cc_color_calibrate_signal_cb (CcColorCalibrate *calibrate,
+ const gchar *sender_name,
+ const gchar *signal_name,
+ GVariant *parameters)
+{
+ CdColorRGB color;
+ CdColorRGB *color_tmp;
+ const gchar *image = NULL;
+ const gchar *message;
+ const gchar *profile_path = NULL;
+ const gchar *str = NULL;
+ gboolean ret;
+ g_autoptr(GError) error = NULL;
+ GPtrArray *array = NULL;
+ GtkImage *img;
+ GtkLabel *label;
+ g_autoptr(GVariant) dict = NULL;
+
+ if (g_strcmp0 (signal_name, "Finished") == 0)
+ {
+ CdSessionError error_code;
+
+ g_variant_get (parameters, "(u@a{sv})",
+ &error_code,
+ &dict);
+ g_variant_lookup (dict, "ErrorDetails", "&s", &str);
+ ret = g_variant_lookup (dict, "ProfilePath", "&s", &profile_path);
+ if (ret)
+ calibrate->profile = cd_profile_new_with_object_path (profile_path);
+ cc_color_calibrate_finished (calibrate, error_code, str);
+ return;
+ }
+ if (g_strcmp0 (signal_name, "UpdateSample") == 0)
+ {
+ g_variant_get (parameters, "(ddd)",
+ &color.R,
+ &color.G,
+ &color.B);
+ img = GTK_IMAGE (gtk_builder_get_object (calibrate->builder,
+ "image_status"));
+ gtk_widget_set_visible (GTK_WIDGET (img), FALSE);
+ gtk_widget_set_visible (GTK_WIDGET (calibrate->sample_widget), TRUE);
+ cd_sample_widget_set_color (CD_SAMPLE_WIDGET (calibrate->sample_widget),
+ &color);
+
+ /* for Lenovo W700 and W520 laptops we almost fullscreen the
+ * sample widget as the device is actually embedded in the
+ * palmrest! */
+ if (cd_sensor_get_embedded (calibrate->sensor))
+ {
+ g_debug ("Making sample window larger for embedded sensor");
+ gtk_widget_set_size_request (calibrate->sample_widget, 1000, 600);
+ }
+
+ /* set the generic label too */
+ label = GTK_LABEL (gtk_builder_get_object (calibrate->builder,
+ "label_status"));
+ /* TRANSLATORS: The user has to be careful not to knock the
+ * display off the screen (although we do cope if this is
+ * detected early enough) */
+ gtk_label_set_label (label, _("Do not disturb the calibration device while in progress"));
+ return;
+ }
+ if (g_strcmp0 (signal_name, "InteractionRequired") == 0)
+ {
+ CdSessionInteraction code;
+
+ g_variant_get (parameters, "(u&s&s)",
+ &code,
+ &message,
+ &image);
+ g_debug ("Interaction required type %i: %s",
+ code, message);
+ cc_color_calibrate_interaction_required (calibrate,
+ code,
+ message,
+ image);
+ return;
+ }
+ if (g_strcmp0 (signal_name, "UpdateGamma") == 0)
+ {
+ g_autoptr(GVariantIter) iter = NULL;
+
+ g_variant_get (parameters,
+ "(a(ddd))",
+ &iter);
+ array = g_ptr_array_new_with_free_func (g_free);
+ while (g_variant_iter_loop (iter, "(ddd)",
+ &color.R,
+ &color.G,
+ &color.B))
+ {
+ color_tmp = cd_color_rgb_new ();
+ cd_color_rgb_copy (&color, color_tmp);
+ g_ptr_array_add (array, color_tmp);
+ }
+ ret = cc_color_calibrate_calib_set_output_gamma (calibrate,
+ array,
+ &error);
+ if (!ret)
+ {
+ g_warning ("failed to update gamma: %s",
+ error->message);
+ return;
+ }
+ return;
+ }
+ g_warning ("got unknown signal %s", signal_name);
+}
+
+static void
+cc_color_calibrate_cancel (CcColorCalibrate *calibrate)
+{
+ g_autoptr(GVariant) retval = NULL;
+ g_autoptr(GError) error = NULL;
+
+ /* cancel the calibration to ensure the helper quits */
+ retval = g_dbus_proxy_call_sync (calibrate->proxy_helper,
+ "Cancel",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+ if (retval == NULL)
+ g_warning ("Failed to send Cancel: %s", error->message);
+
+ /* return */
+ g_main_loop_quit (calibrate->loop);
+}
+
+static void
+cc_color_calibrate_button_done_cb (CcColorCalibrate *calibrate)
+{
+ g_main_loop_quit (calibrate->loop);
+}
+
+static void
+cc_color_calibrate_button_start_cb (CcColorCalibrate *calibrate)
+{
+ GtkWidget *widget;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) retval = NULL;
+
+ /* set correct buttons */
+ widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder,
+ "button_start"));
+ gtk_widget_set_visible (widget, FALSE);
+ widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder,
+ "button_resume"));
+ gtk_widget_set_visible (widget, FALSE);
+
+ /* continue */
+ retval = g_dbus_proxy_call_sync (calibrate->proxy_helper,
+ "Resume",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+ if (retval == NULL)
+ g_warning ("Failed to send Resume: %s", error->message);
+}
+
+static void
+cc_color_calibrate_button_cancel_cb (CcColorCalibrate *calibrate)
+{
+ cc_color_calibrate_cancel (calibrate);
+}
+
+#if 0
+static gboolean
+cc_color_calibrate_alpha_window_draw (CcColorCalibrate *calibrate, cairo_t *cr)
+{
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder,
+ "dialog_calibrate"));
+
+ if (gdk_screen_get_rgba_visual (gtk_widget_get_screen (widget)) &&
+ gdk_screen_is_composited (gtk_widget_get_screen (widget)))
+ {
+ /* transparent */
+ cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, CALIBRATE_WINDOW_OPACITY);
+ }
+ else
+ {
+ /* opaque black */
+ cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
+ }
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ cairo_paint (cr);
+ return FALSE;
+}
+
+static void
+cc_color_calibrate_alpha_screen_changed_cb (CcColorCalibrate *calibrate)
+{
+ GtkWidget *window;
+ GdkScreen *screen;
+ GdkVisual *visual;
+
+ window = GTK_WIDGET (gtk_builder_get_object (calibrate->builder,
+ "dialog_calibrate"));
+ screen = gtk_widget_get_screen (GTK_WIDGET (window));
+ visual = gdk_screen_get_rgba_visual (screen);
+ if (visual == NULL)
+ visual = gdk_screen_get_system_visual (screen);
+ gtk_widget_set_visual (GTK_WIDGET (window), visual);
+}
+#endif
+
+static void
+cc_color_calibrate_uninhibit (CcColorCalibrate *calibrate)
+{
+ GtkApplication *application;
+
+ if (calibrate->inhibit_fd != -1)
+ {
+ close (calibrate->inhibit_fd);
+ calibrate->inhibit_fd = -1;
+ }
+
+ if (calibrate->inhibit_cookie != 0)
+ {
+ application = GTK_APPLICATION (g_application_get_default ());
+ gtk_application_uninhibit (application, calibrate->inhibit_cookie);
+ calibrate->inhibit_cookie = 0;
+ }
+}
+
+static void
+cc_color_calibrate_inhibit (CcColorCalibrate *calibrate, GtkWindow *window)
+{
+ g_autoptr(GError) error = NULL;
+ gint idx;
+ g_autoptr(GUnixFDList) fd_list = NULL;
+ g_autoptr(GVariant) retval = NULL;
+ GtkApplication *application;
+
+ /* inhibit basically everything we can */
+ application = GTK_APPLICATION (g_application_get_default ());
+ calibrate->inhibit_cookie = gtk_application_inhibit (application,
+ window,
+ GTK_APPLICATION_INHIBIT_LOGOUT |
+ GTK_APPLICATION_INHIBIT_SWITCH |
+ GTK_APPLICATION_INHIBIT_SUSPEND |
+ GTK_APPLICATION_INHIBIT_IDLE,
+ "Display calibration in progress");
+
+ /* tell logind to disallow the lid switch */
+ retval = g_dbus_proxy_call_with_unix_fd_list_sync (calibrate->proxy_inhibit,
+ "Inhibit",
+ g_variant_new ("(ssss)",
+ "shutdown:"
+ "sleep:"
+ "idle:"
+ "handle-lid-switch",
+ "Display Calibrator",
+ "Display calibration in progress",
+ "block"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &fd_list,
+ NULL,
+ &error);
+ if (retval == NULL)
+ {
+ g_warning ("Failed to send Inhibit: %s", error->message);
+ return;
+ }
+ g_variant_get (retval, "(h)", &idx);
+ calibrate->inhibit_fd = g_unix_fd_list_get (fd_list, idx, &error);
+ if (calibrate->inhibit_fd == -1)
+ {
+ g_warning ("Failed to receive system inhibitor fd: %s", error->message);
+ return;
+ }
+ g_debug ("System inhibitor fd is %d", calibrate->inhibit_fd);
+}
+
+gboolean
+cc_color_calibrate_setup (CcColorCalibrate *calibrate,
+ GError **error)
+{
+ gboolean ret = TRUE;
+
+ g_return_val_if_fail (CC_IS_COLOR_CALIBRATE (calibrate), FALSE);
+ g_return_val_if_fail (calibrate->device_kind != CD_SENSOR_CAP_UNKNOWN, FALSE);
+
+ /* use logind to disable system state idle */
+ calibrate->proxy_inhibit = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.freedesktop.login1",
+ "/org/freedesktop/login1",
+ "org.freedesktop.login1.Manager",
+ NULL,
+ error);
+ if (calibrate->proxy_inhibit == NULL)
+ {
+ ret = FALSE;
+ goto out;
+ }
+
+ /* start the calibration session daemon */
+ calibrate->proxy_helper = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ CD_SESSION_DBUS_SERVICE,
+ CD_SESSION_DBUS_PATH,
+ CD_SESSION_DBUS_INTERFACE_DISPLAY,
+ NULL,
+ error);
+ if (calibrate->proxy_helper == NULL)
+ {
+ ret = FALSE;
+ goto out;
+ }
+ g_signal_connect_object (calibrate->proxy_helper,
+ "g-properties-changed",
+ G_CALLBACK (cc_color_calibrate_property_changed_cb),
+ calibrate, G_CONNECT_SWAPPED);
+ g_signal_connect_object (calibrate->proxy_helper,
+ "g-signal",
+ G_CALLBACK (cc_color_calibrate_signal_cb),
+ calibrate, G_CONNECT_SWAPPED);
+out:
+ return ret;
+}
+
+gboolean
+cc_color_calibrate_start (CcColorCalibrate *calibrate,
+ GtkWindow *parent,
+ GError **error)
+{
+ const gchar *name;
+ GtkWidget *widget;
+ GtkWindow *window;
+ GVariantBuilder builder;
+ g_autoptr(GVariant) retval = NULL;
+
+ g_return_val_if_fail (CC_IS_COLOR_CALIBRATE (calibrate), FALSE);
+
+ /* get screen */
+ name = cd_device_get_metadata_item (calibrate->device,
+ CD_DEVICE_METADATA_XRANDR_NAME);
+ if (!cc_color_calibrate_calib_setup_screen (calibrate, name, error))
+ return FALSE;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
+ g_variant_builder_add (&builder,
+ "{sv}",
+ "Quality",
+ g_variant_new_uint32 (calibrate->quality));
+ g_variant_builder_add (&builder,
+ "{sv}",
+ "Whitepoint",
+ g_variant_new_uint32 (calibrate->target_whitepoint));
+ g_variant_builder_add (&builder,
+ "{sv}",
+ "Gamma",
+ g_variant_new_double (calibrate->target_gamma));
+ g_variant_builder_add (&builder,
+ "{sv}",
+ "Title",
+ g_variant_new_string (calibrate->title));
+ g_variant_builder_add (&builder,
+ "{sv}",
+ "DeviceKind",
+ g_variant_new_uint32 (calibrate->device_kind));
+ retval = g_dbus_proxy_call_sync (calibrate->proxy_helper,
+ "Start",
+ g_variant_new ("(ssa{sv})",
+ cd_device_get_id (calibrate->device),
+ cd_sensor_get_id (calibrate->sensor),
+ &builder),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ error);
+ if (retval == NULL)
+ return FALSE;
+
+ /* set this above our parent */
+ window = GTK_WINDOW (gtk_builder_get_object (calibrate->builder,
+ "dialog_calibrate"));
+ gtk_window_set_modal (window, TRUE);
+ gtk_widget_show (GTK_WIDGET (window));
+
+ /* show correct buttons */
+ widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder,
+ "button_cancel"));
+ gtk_widget_set_visible (widget, TRUE);
+ widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder,
+ "button_start"));
+ gtk_widget_set_visible (widget, TRUE);
+ widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder,
+ "button_resume"));
+ gtk_widget_set_visible (widget, FALSE);
+ widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder,
+ "button_done"));
+ gtk_widget_set_visible (widget, FALSE);
+
+ /* stop the computer from auto-suspending or turning off the screen */
+ cc_color_calibrate_inhibit (calibrate, parent);
+
+ g_main_loop_run (calibrate->loop);
+ gtk_widget_hide (GTK_WIDGET (window));
+
+ /* we can go idle now */
+ cc_color_calibrate_uninhibit (calibrate);
+
+ /* see if we failed */
+ if (calibrate->session_error_code != CD_SESSION_ERROR_NONE)
+ {
+ g_set_error_literal (error,
+ CD_SESSION_ERROR,
+ CD_SESSION_ERROR_INTERNAL,
+ "failed to calibrate");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+cc_color_calibrate_finalize (GObject *object)
+{
+ CcColorCalibrate *calibrate = CC_COLOR_CALIBRATE (object);
+
+ g_clear_pointer (&calibrate->window, gtk_window_destroy);
+ g_clear_object (&calibrate->builder);
+ g_clear_object (&calibrate->device);
+ g_clear_object (&calibrate->proxy_helper);
+ g_clear_object (&calibrate->proxy_inhibit);
+ g_clear_object (&calibrate->sensor);
+ g_clear_object (&calibrate->x11_screen);
+ g_free (calibrate->title);
+ g_main_loop_unref (calibrate->loop);
+
+ G_OBJECT_CLASS (cc_color_calibrate_parent_class)->finalize (object);
+}
+
+static void
+cc_color_calibrate_class_init (CcColorCalibrateClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = cc_color_calibrate_finalize;
+}
+
+static void
+cc_color_calibrate_init (CcColorCalibrate *calibrate)
+{
+ g_autoptr(GError) error = NULL;
+ gint retval;
+ g_autoptr(GSettings) settings = NULL;
+ GtkBox *box;
+ GtkWidget *widget;
+ GtkWindow *window;
+
+ calibrate->loop = g_main_loop_new (NULL, FALSE);
+ calibrate->inhibit_fd = -1;
+
+ /* load UI */
+ calibrate->builder = gtk_builder_new ();
+ retval = gtk_builder_add_from_resource (calibrate->builder,
+ "/org/gnome/control-center/color/cc-color-calibrate.ui",
+ &error);
+ if (retval == 0)
+ g_warning ("Could not load interface: %s", error->message);
+
+ /* add sample widget */
+ box = GTK_BOX (gtk_builder_get_object (calibrate->builder,
+ "vbox_status"));
+ calibrate->sample_widget = cd_sample_widget_new ();
+ gtk_widget_set_size_request (calibrate->sample_widget, 400, 400);
+ gtk_box_prepend (box, calibrate->sample_widget);
+ gtk_widget_set_vexpand (calibrate->sample_widget, FALSE);
+ gtk_widget_set_hexpand (calibrate->sample_widget, FALSE);
+
+ /* get defaults */
+ settings = g_settings_new (COLORD_SETTINGS_SCHEMA);
+ calibrate->target_whitepoint = g_settings_get_int (settings, "display-whitepoint");
+ calibrate->target_gamma = g_settings_get_double (settings, "display-gamma");
+
+ /* connect to buttons */
+ widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder,
+ "button_start"));
+ g_signal_connect_object (widget, "clicked",
+ G_CALLBACK (cc_color_calibrate_button_start_cb), calibrate, G_CONNECT_SWAPPED);
+ widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder,
+ "button_resume"));
+ g_signal_connect_object (widget, "clicked",
+ G_CALLBACK (cc_color_calibrate_button_start_cb), calibrate, G_CONNECT_SWAPPED);
+ widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder,
+ "button_done"));
+ g_signal_connect_object (widget, "clicked",
+ G_CALLBACK (cc_color_calibrate_button_done_cb), calibrate, G_CONNECT_SWAPPED);
+ widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder,
+ "button_cancel"));
+ g_signal_connect_object (widget, "clicked",
+ G_CALLBACK (cc_color_calibrate_button_cancel_cb), calibrate, G_CONNECT_SWAPPED);
+ gtk_widget_show (widget);
+
+ /* setup the specialist calibration window */
+ window = GTK_WINDOW (gtk_builder_get_object (calibrate->builder,
+ "dialog_calibrate"));
+ calibrate->window = window;
+}
+
+CcColorCalibrate *
+cc_color_calibrate_new (void)
+{
+ CcColorCalibrate *calibrate;
+ calibrate = g_object_new (CC_TYPE_COLOR_CALIBRATE, NULL);
+ return CC_COLOR_CALIBRATE (calibrate);
+}
diff --git a/panels/color/cc-color-calibrate.h b/panels/color/cc-color-calibrate.h
new file mode 100644
index 0000000..15ea06d
--- /dev/null
+++ b/panels/color/cc-color-calibrate.h
@@ -0,0 +1,54 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <colord.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_COLOR_CALIBRATE (cc_color_calibrate_get_type ())
+G_DECLARE_FINAL_TYPE (CcColorCalibrate, cc_color_calibrate, CC, COLOR_CALIBRATE, GObject)
+
+CcColorCalibrate *cc_color_calibrate_new (void);
+void cc_color_calibrate_set_kind (CcColorCalibrate *calibrate,
+ CdSensorCap kind);
+void cc_color_calibrate_set_temperature (CcColorCalibrate *calibrate,
+ guint temperature);
+void cc_color_calibrate_set_quality (CcColorCalibrate *calibrate,
+ CdProfileQuality quality);
+CdProfileQuality cc_color_calibrate_get_quality (CcColorCalibrate *calibrate);
+void cc_color_calibrate_set_device (CcColorCalibrate *calibrate,
+ CdDevice *device);
+void cc_color_calibrate_set_sensor (CcColorCalibrate *calibrate,
+ CdSensor *sensor);
+void cc_color_calibrate_set_title (CcColorCalibrate *calibrate,
+ const gchar *title);
+gboolean cc_color_calibrate_start (CcColorCalibrate *calibrate,
+ GtkWindow *parent,
+ GError **error);
+gboolean cc_color_calibrate_setup (CcColorCalibrate *calibrate,
+ GError **error);
+CdProfile *cc_color_calibrate_get_profile (CcColorCalibrate *calibrate);
+
+G_END_DECLS
diff --git a/panels/color/cc-color-calibrate.ui b/panels/color/cc-color-calibrate.ui
new file mode 100644
index 0000000..44f67e7
--- /dev/null
+++ b/panels/color/cc-color-calibrate.ui
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkDialog" id="dialog_calibrate">
+ <property name="margin_top">32</property>
+ <property name="margin_bottom">32</property>
+ <property name="margin_start">12</property>
+ <property name="margin_end">12</property>
+ <property name="title" translatable="yes">Display Calibration</property>
+ <property name="deletable">False</property>
+ <style>
+ <class name="osd"/>
+ </style>
+ <child>
+ <object class="GtkBox" id="dialog-vbox4">
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkBox" id="dialog-action_area1">
+ <child>
+ <object class="GtkButton" id="button_cancel">
+ <property name="label" translatable="yes">_Cancel</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="button_start">
+ <property name="label" translatable="yes" comments="This starts the calibration process">_Start</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="button_resume">
+ <property name="label" translatable="yes" comments="This resumes the calibration process">_Resume</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="button_done">
+ <property name="label" translatable="yes" comments="This button returns the user back to the color control panel">_Done</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="vbox_status">
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">15</property>
+ <child>
+ <object class="GtkImage" id="image_status">
+ <property name="valign">end</property>
+ <property name="pixel_size">192</property>
+ <property name="icon_name">address-book-new</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_status">
+ <property name="valign">start</property>
+ <property name="label">Do not disturb the calibration device while in progress</property>
+ <property name="justify">center</property>
+ <property name="wrap">True</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ <attribute name="foreground" value="#ffffffffffff"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkProgressBar" id="progressbar_status">
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="0">button_cancel</action-widget>
+ <action-widget response="0">button_start</action-widget>
+ <action-widget response="0">button_resume</action-widget>
+ <action-widget response="0">button_done</action-widget>
+ </action-widgets>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup_sample"/>
+</interface>
diff --git a/panels/color/cc-color-cell-renderer-text.c b/panels/color/cc-color-cell-renderer-text.c
new file mode 100644
index 0000000..5803ac5
--- /dev/null
+++ b/panels/color/cc-color-cell-renderer-text.c
@@ -0,0 +1,132 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+
+#include "cc-color-cell-renderer-text.h"
+
+enum {
+ PROP_0,
+ PROP_IS_DIM_LABEL,
+ PROP_LAST
+};
+
+struct _CcColorCellRendererText
+{
+ GtkCellRendererText parent_instance;
+
+ gboolean is_dim_label;
+};
+
+G_DEFINE_TYPE (CcColorCellRendererText, cc_color_cell_renderer_text, GTK_TYPE_CELL_RENDERER_TEXT)
+
+static gpointer parent_class = NULL;
+
+static void
+cc_color_cell_renderer_text_get_property (GObject *object, guint param_id,
+ GValue *value, GParamSpec *pspec)
+{
+ CcColorCellRendererText *renderer = CC_COLOR_CELL_RENDERER_TEXT (object);
+
+ switch (param_id)
+ {
+ case PROP_IS_DIM_LABEL:
+ g_value_set_boolean (value, renderer->is_dim_label);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_color_cell_renderer_text_set_property (GObject *object, guint param_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ CcColorCellRendererText *renderer = CC_COLOR_CELL_RENDERER_TEXT (object);
+
+ switch (param_id)
+ {
+ case PROP_IS_DIM_LABEL:
+ renderer->is_dim_label = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_color_cell_renderer_snapshot (GtkCellRenderer *cell,
+ GtkSnapshot *snapshot,
+ GtkWidget *widget,
+ const GdkRectangle *background_area,
+ const GdkRectangle *cell_area,
+ GtkCellRendererState flags)
+{
+ CcColorCellRendererText *renderer;
+ GtkStyleContext *context;
+
+ renderer = CC_COLOR_CELL_RENDERER_TEXT (cell);
+ context = gtk_widget_get_style_context (widget);
+ gtk_style_context_save (context);
+ if (renderer->is_dim_label)
+ gtk_style_context_add_class (context, "dim-label");
+ else
+ gtk_style_context_remove_class (context, "dim-label");
+ GTK_CELL_RENDERER_CLASS (parent_class)->snapshot (cell, snapshot, widget,
+ background_area,
+ cell_area, flags);
+ gtk_style_context_restore (context);
+}
+
+static void
+cc_color_cell_renderer_text_class_init (CcColorCellRendererTextClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ GtkCellRendererClass *object_class_gcr = GTK_CELL_RENDERER_CLASS (class);
+ object_class_gcr->snapshot = cc_color_cell_renderer_snapshot;
+
+ parent_class = g_type_class_peek_parent (class);
+
+ object_class->get_property = cc_color_cell_renderer_text_get_property;
+ object_class->set_property = cc_color_cell_renderer_text_set_property;
+
+ g_object_class_install_property (object_class, PROP_IS_DIM_LABEL,
+ g_param_spec_boolean ("is-dim-label",
+ NULL, NULL,
+ FALSE,
+ G_PARAM_READWRITE));
+}
+
+static void
+cc_color_cell_renderer_text_init (CcColorCellRendererText *renderer)
+{
+ renderer->is_dim_label = FALSE;
+}
+
+GtkCellRenderer *
+cc_color_cell_renderer_text_new (void)
+{
+ return g_object_new (CC_COLOR_TYPE_CELL_RENDERER_TEXT, NULL);
+}
diff --git a/panels/color/cc-color-cell-renderer-text.h b/panels/color/cc-color-cell-renderer-text.h
new file mode 100644
index 0000000..241663a
--- /dev/null
+++ b/panels/color/cc-color-cell-renderer-text.h
@@ -0,0 +1,32 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#define CC_COLOR_TYPE_CELL_RENDERER_TEXT (cc_color_cell_renderer_text_get_type ())
+G_DECLARE_FINAL_TYPE (CcColorCellRendererText, cc_color_cell_renderer_text, CC_COLOR, CELL_RENDERER_TEXT, GtkCellRendererText)
+
+GtkCellRenderer *cc_color_cell_renderer_text_new (void);
+
+G_END_DECLS
+
diff --git a/panels/color/cc-color-common.c b/panels/color/cc-color-common.c
new file mode 100644
index 0000000..cf269c2
--- /dev/null
+++ b/panels/color/cc-color-common.c
@@ -0,0 +1,116 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include "cc-color-common.h"
+
+gchar *
+cc_color_device_get_title (CdDevice *device)
+{
+ const gchar *tmp;
+ GString *string;
+
+ string = g_string_new ("");
+
+ /* is laptop panel */
+ if (cd_device_get_kind (device) == CD_DEVICE_KIND_DISPLAY &&
+ cd_device_get_embedded (device))
+ {
+ /* TRANSLATORS: This refers to the TFT display on a laptop */
+ g_string_append (string, _("Laptop Screen"));
+ goto out;
+ }
+
+ /* is internal webcam */
+ if (cd_device_get_kind (device) == CD_DEVICE_KIND_WEBCAM &&
+ cd_device_get_embedded (device))
+ {
+ /* TRANSLATORS: This refers to the embedded webcam on a laptop */
+ g_string_append (string, _("Built-in Webcam"));
+ goto out;
+ }
+
+ /* get the display model, falling back to something sane */
+ tmp = cd_device_get_model (device);
+ if (tmp == NULL)
+ tmp = cd_device_get_vendor (device);
+ if (tmp == NULL)
+ tmp = cd_device_get_id (device);
+
+ switch (cd_device_get_kind (device)) {
+ case CD_DEVICE_KIND_DISPLAY:
+ /* TRANSLATORS: an externally connected display, where %s is either the
+ * model, vendor or ID, e.g. 'LP2480zx Monitor' */
+ g_string_append_printf (string, _("%s Monitor"), tmp);
+ break;
+ case CD_DEVICE_KIND_SCANNER:
+ /* TRANSLATORS: a flatbed scanner device, e.g. 'Epson Scanner' */
+ g_string_append_printf (string, _("%s Scanner"), tmp);
+ break;
+ case CD_DEVICE_KIND_CAMERA:
+ /* TRANSLATORS: a camera device, e.g. 'Nikon D60 Camera' */
+ g_string_append_printf (string, _("%s Camera"), tmp);
+ break;
+ case CD_DEVICE_KIND_PRINTER:
+ /* TRANSLATORS: a printer device, e.g. 'Epson Photosmart Printer' */
+ g_string_append_printf (string, _("%s Printer"), tmp);
+ break;
+ case CD_DEVICE_KIND_WEBCAM:
+ /* TRANSLATORS: a webcam device, e.g. 'Philips HiDef Camera' */
+ g_string_append_printf (string, _("%s Webcam"), tmp);
+ break;
+ default:
+ g_string_append (string, tmp);
+ break;
+ }
+out:
+ return g_string_free (string, FALSE);
+}
+
+static const gchar *
+cc_color_device_kind_to_sort (CdDevice *device)
+{
+ CdDeviceKind kind = cd_device_get_kind (device);
+ if (kind == CD_DEVICE_KIND_DISPLAY)
+ return "4";
+ if (kind == CD_DEVICE_KIND_SCANNER)
+ return "3";
+ if (kind == CD_DEVICE_KIND_CAMERA)
+ return "2";
+ if (kind == CD_DEVICE_KIND_WEBCAM)
+ return "1";
+ if (kind == CD_DEVICE_KIND_PRINTER)
+ return "0";
+ return "9";
+}
+
+gchar *
+cc_color_device_get_sortable_base (CdDevice *device)
+{
+ g_autofree gchar *title = cc_color_device_get_title (device);
+ return g_strdup_printf ("%s-%s-%s",
+ cc_color_device_kind_to_sort (device),
+ cd_device_get_id (device),
+ title);
+}
diff --git a/panels/color/cc-color-common.h b/panels/color/cc-color-common.h
new file mode 100644
index 0000000..c90193e
--- /dev/null
+++ b/panels/color/cc-color-common.h
@@ -0,0 +1,32 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <colord.h>
+
+#define GCM_SETTINGS_SCHEMA "org.gnome.settings-daemon.plugins.color"
+
+gchar *cc_color_device_get_sortable_base (CdDevice *device);
+gchar *cc_color_device_get_title (CdDevice *device);
+
+G_END_DECLS
+
diff --git a/panels/color/cc-color-device.c b/panels/color/cc-color-device.c
new file mode 100644
index 0000000..fbb74d8
--- /dev/null
+++ b/panels/color/cc-color-device.c
@@ -0,0 +1,309 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "cc-color-common.h"
+#include "cc-color-device.h"
+
+struct _CcColorDevice
+{
+ GtkListBoxRow parent_instance;
+
+ CdDevice *device;
+ gboolean expanded;
+ gchar *sortable;
+ GtkWidget *widget_description;
+ GtkWidget *widget_button;
+ GtkWidget *widget_switch;
+ GtkWidget *widget_arrow;
+ GtkWidget *widget_nocalib;
+};
+
+G_DEFINE_TYPE (CcColorDevice, cc_color_device, GTK_TYPE_LIST_BOX_ROW)
+
+enum
+{
+ SIGNAL_EXPANDED_CHANGED,
+ SIGNAL_LAST
+};
+
+enum
+{
+ PROP_0,
+ PROP_DEVICE,
+ PROP_LAST
+};
+
+static guint signals [SIGNAL_LAST] = { 0 };
+
+static void
+cc_color_device_refresh (CcColorDevice *color_device)
+{
+ g_autofree gchar *title = NULL;
+ g_autoptr(GPtrArray) profiles = NULL;
+ g_autofree gchar *name1 = NULL;
+ g_autofree gchar *name2 = NULL;
+
+ /* add switch and expander if there are profiles, otherwise use a label */
+ profiles = cd_device_get_profiles (color_device->device);
+ if (profiles == NULL)
+ return;
+
+ title = cc_color_device_get_title (color_device->device);
+ gtk_label_set_label (GTK_LABEL (color_device->widget_description), title);
+ gtk_widget_set_visible (color_device->widget_description, TRUE);
+
+ gtk_widget_set_visible (color_device->widget_switch, profiles->len > 0);
+ gtk_widget_set_visible (color_device->widget_button, profiles->len > 0);
+ gtk_image_set_from_icon_name (GTK_IMAGE (color_device->widget_arrow),
+ color_device->expanded ? "pan-down-symbolic" : "pan-end-symbolic");
+ gtk_widget_set_visible (color_device->widget_nocalib, profiles->len == 0);
+ gtk_widget_set_sensitive (color_device->widget_button, cd_device_get_enabled (color_device->device));
+ gtk_switch_set_active (GTK_SWITCH (color_device->widget_switch),
+ cd_device_get_enabled (color_device->device));
+
+ name1 = g_strdup_printf (_("Enable color management for %s"), title);
+ gtk_accessible_update_property (GTK_ACCESSIBLE (color_device->widget_switch),
+ GTK_ACCESSIBLE_PROPERTY_LABEL, name1,
+ -1);
+
+ name2 = g_strdup_printf (_("Show color profiles for %s"), title);
+ gtk_accessible_update_property (GTK_ACCESSIBLE (color_device->widget_button),
+ GTK_ACCESSIBLE_PROPERTY_LABEL, name2,
+ -1);
+}
+
+CdDevice *
+cc_color_device_get_device (CcColorDevice *color_device)
+{
+ g_return_val_if_fail (CC_IS_COLOR_DEVICE (color_device), NULL);
+ return color_device->device;
+}
+
+const gchar *
+cc_color_device_get_sortable (CcColorDevice *color_device)
+{
+ g_return_val_if_fail (CC_IS_COLOR_DEVICE (color_device), NULL);
+ return color_device->sortable;
+}
+
+static void
+cc_color_device_get_property (GObject *object, guint param_id,
+ GValue *value, GParamSpec *pspec)
+{
+ CcColorDevice *color_device = CC_COLOR_DEVICE (object);
+ switch (param_id)
+ {
+ case PROP_DEVICE:
+ g_value_set_object (value, color_device->device);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_color_device_set_property (GObject *object, guint param_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ CcColorDevice *color_device = CC_COLOR_DEVICE (object);
+
+ switch (param_id)
+ {
+ case PROP_DEVICE:
+ color_device->device = g_value_dup_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_color_device_finalize (GObject *object)
+{
+ CcColorDevice *color_device = CC_COLOR_DEVICE (object);
+
+ g_free (color_device->sortable);
+ g_object_unref (color_device->device);
+
+ G_OBJECT_CLASS (cc_color_device_parent_class)->finalize (object);
+}
+
+void
+cc_color_device_set_expanded (CcColorDevice *color_device,
+ gboolean expanded)
+{
+ /* same as before */
+ if (color_device->expanded == expanded)
+ return;
+
+ /* refresh */
+ color_device->expanded = expanded;
+ g_signal_emit (color_device,
+ signals[SIGNAL_EXPANDED_CHANGED], 0,
+ color_device->expanded);
+ cc_color_device_refresh (color_device);
+}
+
+static void
+cc_color_device_notify_enable_device_cb (CcColorDevice *color_device)
+{
+ gboolean enable;
+ gboolean ret;
+ g_autoptr(GError) error = NULL;
+
+ enable = gtk_switch_get_active (GTK_SWITCH (color_device->widget_switch));
+ g_debug ("Set %s to %i", cd_device_get_id (color_device->device), enable);
+ ret = cd_device_set_enabled_sync (color_device->device,
+ enable, NULL, &error);
+ if (!ret)
+ g_warning ("failed to %s to the device: %s",
+ enable ? "enable" : "disable", error->message);
+
+ /* if expanded, close */
+ cc_color_device_set_expanded (color_device, FALSE);
+}
+
+static void
+cc_color_device_changed_cb (CcColorDevice *color_device)
+{
+ cc_color_device_refresh (color_device);
+}
+
+static void
+cc_color_device_constructed (GObject *object)
+{
+ CcColorDevice *color_device = CC_COLOR_DEVICE (object);
+ g_autofree gchar *sortable_tmp = NULL;
+
+ /* watch the device for changes */
+ g_signal_connect_object (color_device->device, "changed",
+ G_CALLBACK (cc_color_device_changed_cb), color_device, G_CONNECT_SWAPPED);
+
+ /* calculate sortable -- FIXME: we have to hack this as EggListBox
+ * does not let us specify a GtkSortType:
+ * https://bugzilla.gnome.org/show_bug.cgi?id=691341 */
+ sortable_tmp = cc_color_device_get_sortable_base (color_device->device);
+ color_device->sortable = g_strdup_printf ("%sXX", sortable_tmp);
+
+ cc_color_device_refresh (color_device);
+
+ /* watch to see if the user flicked the switch */
+ g_signal_connect_object (color_device->widget_switch, "notify::active",
+ G_CALLBACK (cc_color_device_notify_enable_device_cb),
+ color_device, G_CONNECT_SWAPPED);
+}
+
+static void
+cc_color_device_class_init (CcColorDeviceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->get_property = cc_color_device_get_property;
+ object_class->set_property = cc_color_device_set_property;
+ object_class->constructed = cc_color_device_constructed;
+ object_class->finalize = cc_color_device_finalize;
+
+ g_object_class_install_property (object_class, PROP_DEVICE,
+ g_param_spec_object ("device", NULL,
+ NULL,
+ CD_TYPE_DEVICE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ signals [SIGNAL_EXPANDED_CHANGED] =
+ g_signal_new ("expanded-changed",
+ G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+}
+
+static void
+cc_color_device_clicked_expander_cb (CcColorDevice *color_device)
+{
+ color_device->expanded = !color_device->expanded;
+ cc_color_device_refresh (color_device);
+ g_signal_emit (color_device, signals[SIGNAL_EXPANDED_CHANGED], 0,
+ color_device->expanded);
+}
+
+static void
+cc_color_device_init (CcColorDevice *color_device)
+{
+ GtkStyleContext *context;
+ GtkWidget *box;
+
+ /* description */
+ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 9);
+ color_device->widget_description = gtk_label_new ("");
+ gtk_widget_set_margin_start (color_device->widget_description, 20);
+ gtk_widget_set_margin_top (color_device->widget_description, 12);
+ gtk_widget_set_margin_bottom (color_device->widget_description, 12);
+ gtk_widget_set_halign (color_device->widget_description, GTK_ALIGN_START);
+ gtk_widget_set_hexpand (color_device->widget_description, TRUE);
+ gtk_label_set_ellipsize (GTK_LABEL (color_device->widget_description), PANGO_ELLIPSIZE_END);
+ gtk_label_set_xalign (GTK_LABEL (color_device->widget_description), 0);
+ gtk_box_append (GTK_BOX (box), color_device->widget_description);
+
+ /* switch */
+ color_device->widget_switch = gtk_switch_new ();
+ gtk_widget_set_valign (color_device->widget_switch, GTK_ALIGN_CENTER);
+ gtk_box_append (GTK_BOX (box), color_device->widget_switch);
+
+ /* arrow button */
+ color_device->widget_arrow = gtk_image_new_from_icon_name ("pan-end-symbolic");
+ color_device->widget_button = gtk_button_new ();
+ g_signal_connect_object (color_device->widget_button, "clicked",
+ G_CALLBACK (cc_color_device_clicked_expander_cb),
+ color_device, G_CONNECT_SWAPPED);
+ gtk_widget_set_valign (color_device->widget_button, GTK_ALIGN_CENTER);
+ gtk_widget_add_css_class (color_device->widget_button, "flat");
+ gtk_button_set_child (GTK_BUTTON (color_device->widget_button), color_device->widget_arrow);
+ gtk_widget_set_visible (color_device->widget_arrow, TRUE);
+ gtk_widget_set_margin_top (color_device->widget_button, 9);
+ gtk_widget_set_margin_bottom (color_device->widget_button, 9);
+ gtk_widget_set_margin_end (color_device->widget_button, 12);
+ gtk_box_append (GTK_BOX (box), color_device->widget_button);
+
+ /* not calibrated */
+ color_device->widget_nocalib = gtk_label_new (_("Not calibrated"));
+ context = gtk_widget_get_style_context (color_device->widget_nocalib);
+ gtk_style_context_add_class (context, "dim-label");
+ gtk_widget_set_margin_end (color_device->widget_nocalib, 18);
+ gtk_box_append (GTK_BOX (box), color_device->widget_nocalib);
+
+ /* refresh */
+ gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (color_device), box);
+}
+
+GtkWidget *
+cc_color_device_new (CdDevice *device)
+{
+ return g_object_new (CC_TYPE_COLOR_DEVICE,
+ "device", device,
+ NULL);
+}
+
diff --git a/panels/color/cc-color-device.h b/panels/color/cc-color-device.h
new file mode 100644
index 0000000..41e0d63
--- /dev/null
+++ b/panels/color/cc-color-device.h
@@ -0,0 +1,38 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <colord.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_COLOR_DEVICE (cc_color_device_get_type ())
+G_DECLARE_FINAL_TYPE (CcColorDevice, cc_color_device, CC, COLOR_DEVICE, GtkListBoxRow)
+
+GtkWidget *cc_color_device_new (CdDevice *device);
+CdDevice *cc_color_device_get_device (CcColorDevice *color_device);
+const gchar *cc_color_device_get_sortable (CcColorDevice *color_device);
+void cc_color_device_set_expanded (CcColorDevice *color_device,
+ gboolean expanded);
+
+G_END_DECLS
diff --git a/panels/color/cc-color-panel.c b/panels/color/cc-color-panel.c
new file mode 100644
index 0000000..42820c7
--- /dev/null
+++ b/panels/color/cc-color-panel.c
@@ -0,0 +1,2208 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2010 Red Hat, Inc
+ * Copyright (C) 2011 Richard Hughes <richard@hughsie.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+
+#include <glib/gi18n.h>
+#include <colord.h>
+#include <gtk/gtk.h>
+#include <gdk/x11/gdkx.h>
+
+#include "cc-color-calibrate.h"
+#include "cc-color-cell-renderer-text.h"
+#include "cc-color-panel.h"
+#include "cc-color-resources.h"
+#include "cc-color-common.h"
+#include "cc-color-device.h"
+#include "cc-color-profile.h"
+
+struct _CcColorPanel
+{
+ CcPanel parent_instance;
+
+ CdClient *client;
+ CdDevice *current_device;
+ GPtrArray *devices;
+ GPtrArray *sensors;
+ GDBusProxy *proxy;
+ GSettings *settings;
+ GSettings *settings_colord;
+ GtkWidget *assistant_calib;
+ GtkWidget *box_calib_brightness;
+ GtkWidget *box_calib_kind;
+ GtkWidget *box_calib_quality;
+ GtkWidget *box_calib_sensor;
+ GtkWidget *box_calib_summary;
+ GtkWidget *box_calib_temp;
+ GtkWidget *box_calib_title;
+ GtkWidget *box_devices;
+ GtkWidget *button_assign_import;
+ GtkWidget *button_assign_ok;
+ GtkWidget *button_calib_export;
+ GtkWidget *dialog_assign;
+ GtkWidget *entry_calib_title;
+ GtkWidget *label_assign_warning;
+ GtkWidget *label_calib_summary_message;
+ GtkWidget *label_no_devices;
+ GtkTreeModel *liststore_assign;
+ GtkTreeModel *liststore_calib_kind;
+ GtkTreeModel *liststore_calib_sensor;
+ GtkWidget *toolbar_devices;
+ GtkWidget *toolbutton_device_calibrate;
+ GtkWidget *toolbutton_device_default;
+ GtkWidget *toolbutton_device_enable;
+ GtkWidget *toolbutton_profile_add;
+ GtkWidget *toolbutton_profile_remove;
+ GtkWidget *toolbutton_profile_view;
+ GtkWidget *treeview_assign;
+ GtkWidget *treeview_calib_kind;
+ GtkWidget *treeview_calib_quality;
+ GtkWidget *treeview_calib_sensor;
+ GtkWidget *treeview_calib_temp;
+ CcColorCalibrate *calibrate;
+ GtkListBox *list_box;
+ gchar *list_box_filter;
+ GtkSizeGroup *list_box_size;
+ gboolean is_live_cd;
+ gboolean model_is_changing;
+};
+
+CC_PANEL_REGISTER (CcColorPanel, cc_color_panel)
+
+enum {
+ GCM_PREFS_COMBO_COLUMN_TEXT,
+ GCM_PREFS_COMBO_COLUMN_PROFILE,
+ GCM_PREFS_COMBO_COLUMN_TYPE,
+ GCM_PREFS_COMBO_COLUMN_WARNING_FILENAME,
+ GCM_PREFS_COMBO_COLUMN_NUM_COLUMNS
+};
+
+/* for the GtkListStores */
+enum {
+ COLUMN_CALIB_KIND_DESCRIPTION,
+ COLUMN_CALIB_KIND_CAP_VALUE,
+ COLUMN_CALIB_KIND_VISIBLE,
+ COLUMN_CALIB_KIND_LAST
+};
+enum {
+ COLUMN_CALIB_QUALITY_DESCRIPTION,
+ COLUMN_CALIB_QUALITY_APPROX_TIME,
+ COLUMN_CALIB_QUALITY_VALUE,
+ COLUMN_CALIB_QUALITY_LAST
+};
+enum {
+ COLUMN_CALIB_SENSOR_OBJECT,
+ COLUMN_CALIB_SENSOR_DESCRIPTION,
+ COLUMN_CALIB_SENSOR_LAST
+};
+enum {
+ COLUMN_CALIB_TEMP_DESCRIPTION,
+ COLUMN_CALIB_TEMP_VALUE_K,
+ COLUMN_CALIB_TEMP_LAST
+};
+
+#define COLORD_SETTINGS_SCHEMA "org.freedesktop.ColorHelper"
+#define GCM_SETTINGS_SCHEMA "org.gnome.settings-daemon.plugins.color"
+#define GCM_SETTINGS_RECALIBRATE_PRINTER_THRESHOLD "recalibrate-printer-threshold"
+#define GCM_SETTINGS_RECALIBRATE_DISPLAY_THRESHOLD "recalibrate-display-threshold"
+
+/* max number of devices and profiles to cause auto-expand at startup */
+#define GCM_PREFS_MAX_DEVICES_PROFILES_EXPANDED 5
+
+static void gcm_prefs_refresh_toolbar_buttons (CcColorPanel *panel);
+
+static void
+gcm_prefs_combobox_add_profile (CcColorPanel *prefs,
+ CdProfile *profile,
+ GtkTreeIter *iter)
+{
+ const gchar *id;
+ GtkTreeIter iter_tmp;
+ g_autoptr(GString) string = NULL;
+ gchar *escaped = NULL;
+ guint kind = 0;
+ const gchar *warning = NULL;
+#if CD_CHECK_VERSION(0,1,25)
+ gchar **warnings;
+#endif
+
+ /* iter is optional */
+ if (iter == NULL)
+ iter = &iter_tmp;
+
+ /* use description */
+ string = g_string_new (cd_profile_get_title (profile));
+
+ /* any source prefix? */
+ id = cd_profile_get_metadata_item (profile,
+ CD_PROFILE_METADATA_DATA_SOURCE);
+ if (g_strcmp0 (id, CD_PROFILE_METADATA_DATA_SOURCE_EDID) == 0)
+ {
+ /* TRANSLATORS: this is a profile prefix to signify the
+ * profile has been auto-generated for this hardware */
+ g_string_prepend (string, _("Default: "));
+ kind = 1;
+ }
+#if CD_CHECK_VERSION(0,1,14)
+ if (g_strcmp0 (id, CD_PROFILE_METADATA_DATA_SOURCE_STANDARD) == 0)
+ {
+ /* TRANSLATORS: this is a profile prefix to signify the
+ * profile his a standard space like AdobeRGB */
+ g_string_prepend (string, _("Colorspace: "));
+ kind = 2;
+ }
+ if (g_strcmp0 (id, CD_PROFILE_METADATA_DATA_SOURCE_TEST) == 0)
+ {
+ /* TRANSLATORS: this is a profile prefix to signify the
+ * profile is a test profile */
+ g_string_prepend (string, _("Test profile: "));
+ kind = 3;
+ }
+#endif
+
+ /* is the profile faulty */
+#if CD_CHECK_VERSION(0,1,25)
+ warnings = cd_profile_get_warnings (profile);
+ if (warnings != NULL && warnings[0] != NULL)
+ warning = "dialog-warning-symbolic";
+#endif
+
+ escaped = g_markup_escape_text (string->str, -1);
+ gtk_list_store_append (GTK_LIST_STORE (prefs->liststore_assign), iter);
+ gtk_list_store_set (GTK_LIST_STORE (prefs->liststore_assign), iter,
+ GCM_PREFS_COMBO_COLUMN_TEXT, escaped,
+ GCM_PREFS_COMBO_COLUMN_PROFILE, profile,
+ GCM_PREFS_COMBO_COLUMN_TYPE, kind,
+ GCM_PREFS_COMBO_COLUMN_WARNING_FILENAME, warning,
+ -1);
+}
+
+static void
+gcm_prefs_default_cb (CcColorPanel *prefs)
+{
+ g_autoptr(CdProfile) profile = NULL;
+ gboolean ret;
+ g_autoptr(GError) error = NULL;
+
+ /* TODO: check if the profile is already systemwide */
+ profile = cd_device_get_default_profile (prefs->current_device);
+ if (profile == NULL)
+ return;
+
+ /* install somewhere out of $HOME */
+ ret = cd_profile_install_system_wide_sync (profile,
+ cc_panel_get_cancellable (CC_PANEL (prefs)),
+ &error);
+ if (!ret)
+ g_warning ("failed to set profile system-wide: %s",
+ error->message);
+}
+
+typedef struct
+{
+ GtkResponseType response;
+ GMainLoop *mainloop;
+} DialogRunData;
+
+static void
+dialog_response_cb (GtkDialog *dialog,
+ GtkResponseType response,
+ DialogRunData *run_data)
+{
+ run_data->response = response;
+ g_main_loop_quit (run_data->mainloop);
+}
+
+static gboolean
+dialog_close_cb (GtkDialog *dialog,
+ GtkResponseType response,
+ DialogRunData *run_data)
+{
+ g_main_loop_quit (run_data->mainloop);
+ return GDK_EVENT_PROPAGATE;
+}
+
+static GtkResponseType
+run_dialog (GtkDialog *dialog)
+{
+ g_autoptr(GMainLoop) mainloop = NULL;
+ DialogRunData run_data;
+ guint response_id;
+ guint close_id;
+
+ mainloop = g_main_loop_new (NULL, FALSE);
+
+ run_data = (DialogRunData) {
+ .response = GTK_RESPONSE_DELETE_EVENT,
+ .mainloop = mainloop,
+ };
+
+ response_id = g_signal_connect (dialog, "response", G_CALLBACK (dialog_response_cb), &run_data);
+ close_id = g_signal_connect (dialog, "close-request", G_CALLBACK (dialog_close_cb), &run_data);
+
+ gtk_window_present (GTK_WINDOW (dialog));
+
+ g_main_loop_run (mainloop);
+
+ g_signal_handler_disconnect (dialog, response_id);
+ g_signal_handler_disconnect (dialog, close_id);
+
+ return run_data.response;
+}
+
+static GFile *
+gcm_prefs_file_chooser_get_icc_profile (CcColorPanel *prefs)
+{
+ g_autoptr(GFile) current_folder = NULL;
+ GtkWindow *window;
+ GtkWidget *dialog;
+ GFile *file = NULL;
+ GtkFileFilter *filter;
+
+ /* create new dialog */
+ window = GTK_WINDOW (prefs->dialog_assign);
+ /* TRANSLATORS: an ICC profile is a file containing colorspace data */
+ dialog = gtk_file_chooser_dialog_new (_("Select ICC Profile File"), window,
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Import"), GTK_RESPONSE_ACCEPT,
+ NULL);
+ current_folder = g_file_new_for_path (g_get_home_dir ());
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER(dialog), current_folder, NULL);
+ gtk_file_chooser_set_create_folders (GTK_FILE_CHOOSER(dialog), FALSE);
+
+ /* setup the filter */
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_add_mime_type (filter, "application/vnd.iccprofile");
+
+ /* TRANSLATORS: filter name on the file->open dialog */
+ gtk_file_filter_set_name (filter, _("Supported ICC profiles"));
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog), filter);
+
+ /* setup the all files filter */
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_add_pattern (filter, "*");
+ /* TRANSLATORS: filter name on the file->open dialog */
+ gtk_file_filter_set_name (filter, _("All files"));
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog), filter);
+
+ /* did user choose file */
+ if (run_dialog (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER(dialog));
+
+ /* we're done */
+ gtk_window_destroy (GTK_WINDOW (dialog));
+
+ /* or NULL for missing */
+ return file;
+}
+
+static void
+gcm_prefs_calib_cancel_cb (CcColorPanel *prefs)
+{
+ gtk_widget_hide (prefs->assistant_calib);
+}
+
+static gboolean
+gcm_prefs_calib_delayed_complete_cb (gpointer user_data)
+{
+ CcColorPanel *panel = CC_COLOR_PANEL (user_data);
+ GtkAssistant *assistant;
+
+ assistant = GTK_ASSISTANT (panel->assistant_calib);
+ gtk_assistant_set_page_complete (assistant, panel->box_calib_brightness, TRUE);
+ return FALSE;
+}
+
+static void
+gcm_prefs_calib_prepare_cb (CcColorPanel *panel,
+ GtkWidget *page)
+{
+ /* give the user the indication they should actually manually set the
+ * desired brightness rather than clicking blindly by delaying the
+ * "Next" button deliberately for a second or so */
+ if (page == panel->box_calib_brightness)
+ {
+ g_timeout_add_seconds (1, gcm_prefs_calib_delayed_complete_cb, panel);
+ return;
+ }
+
+ /* disable the brightness page as we don't want to show a 'Finished'
+ * button if the user goes back at any point */
+ gtk_assistant_set_page_complete (GTK_ASSISTANT (panel->assistant_calib), panel->box_calib_brightness, FALSE);
+}
+
+static void
+gcm_prefs_calib_apply_cb (CcColorPanel *prefs)
+{
+ gboolean ret;
+ g_autoptr(GError) error = NULL;
+ GtkWindow *window = NULL;
+
+ /* setup the calibration object with items that can fail */
+ ret = cc_color_calibrate_setup (prefs->calibrate,
+ &error);
+ if (!ret)
+ {
+ g_warning ("failed to setup calibrate: %s", error->message);
+ return;
+ }
+
+ /* actually start the calibration */
+ window = GTK_WINDOW (prefs->assistant_calib);
+ ret = cc_color_calibrate_start (prefs->calibrate,
+ window,
+ &error);
+ if (!ret)
+ {
+ g_warning ("failed to start calibrate: %s", error->message);
+ gtk_widget_hide (GTK_WIDGET (window));
+ return;
+ }
+
+ /* if we are a LiveCD then don't close the window as there is another
+ * summary pane with the export button */
+ if (!prefs->is_live_cd)
+ gtk_widget_hide (GTK_WIDGET (window));
+}
+
+static void
+gcm_prefs_calib_temp_treeview_clicked_cb (CcColorPanel *prefs,
+ GtkTreeSelection *selection)
+{
+ gboolean ret;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ guint target_whitepoint;
+ GtkAssistant *assistant;
+
+ /* check to see if anything is selected */
+ ret = gtk_tree_selection_get_selected (selection, &model, &iter);
+ assistant = GTK_ASSISTANT (prefs->assistant_calib);
+ gtk_assistant_set_page_complete (assistant, prefs->box_calib_temp, ret);
+ if (!ret)
+ return;
+
+ gtk_tree_model_get (model, &iter,
+ COLUMN_CALIB_TEMP_VALUE_K, &target_whitepoint,
+ -1);
+ cc_color_calibrate_set_temperature (prefs->calibrate, target_whitepoint);
+}
+
+static void
+gcm_prefs_calib_kind_treeview_clicked_cb (CcColorPanel *prefs,
+ GtkTreeSelection *selection)
+{
+ CdSensorCap device_kind;
+ gboolean ret;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ GtkAssistant *assistant;
+
+ /* check to see if anything is selected */
+ ret = gtk_tree_selection_get_selected (selection, &model, &iter);
+ assistant = GTK_ASSISTANT (prefs->assistant_calib);
+ gtk_assistant_set_page_complete (assistant, prefs->box_calib_kind, ret);
+ if (!ret)
+ return;
+
+ /* save the values if we have a selection */
+ gtk_tree_model_get (model, &iter,
+ COLUMN_CALIB_KIND_CAP_VALUE, &device_kind,
+ -1);
+ cc_color_calibrate_set_kind (prefs->calibrate, device_kind);
+}
+
+static void
+gcm_prefs_calib_quality_treeview_clicked_cb (CcColorPanel *prefs,
+ GtkTreeSelection *selection)
+{
+ CdProfileQuality quality;
+ gboolean ret;
+ GtkAssistant *assistant;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+
+ /* check to see if anything is selected */
+ ret = gtk_tree_selection_get_selected (selection, &model, &iter);
+ assistant = GTK_ASSISTANT (prefs->assistant_calib);
+ gtk_assistant_set_page_complete (assistant, prefs->box_calib_quality, ret);
+ if (!ret)
+ return;
+
+ /* save the values if we have a selection */
+ gtk_tree_model_get (model, &iter,
+ COLUMN_CALIB_QUALITY_VALUE, &quality,
+ -1);
+ cc_color_calibrate_set_quality (prefs->calibrate, quality);
+}
+
+static gboolean
+gcm_prefs_calib_set_sensor_cap_supported_cb (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ CdSensorCap cap;
+ CdSensor *sensor = CD_SENSOR (data);
+ gboolean supported;
+
+ gtk_tree_model_get (model, iter,
+ COLUMN_CALIB_KIND_CAP_VALUE, &cap,
+ -1);
+ supported = cd_sensor_has_cap (sensor, cap);
+ g_debug ("%s(%s) is %s",
+ cd_sensor_get_model (sensor),
+ cd_sensor_cap_to_string (cap),
+ supported ? "supported" : "not-supported");
+ gtk_list_store_set (GTK_LIST_STORE (model), iter,
+ COLUMN_CALIB_KIND_VISIBLE, supported,
+ -1);
+ return FALSE;
+}
+
+static guint8
+_cd_bitfield_popcount (guint64 bitfield)
+{
+ guint8 i;
+ guint8 tmp = 0;
+ for (i = 0; i < 64; i++)
+ tmp += cd_bitfield_contain (bitfield, i);
+ return tmp;
+}
+
+static void
+gcm_prefs_calib_set_sensor (CcColorPanel *prefs,
+ CdSensor *sensor)
+{
+ guint64 caps;
+ guint8 i;
+
+ /* use this sensor for calibration */
+ cc_color_calibrate_set_sensor (prefs->calibrate, sensor);
+
+ /* hide display types the sensor does not support */
+ gtk_tree_model_foreach (prefs->liststore_calib_kind,
+ gcm_prefs_calib_set_sensor_cap_supported_cb,
+ sensor);
+
+ /* if the sensor only supports one kind then do not show the panel at all */
+ caps = cd_sensor_get_caps (sensor);
+ if (_cd_bitfield_popcount (caps) == 1)
+ {
+ gtk_widget_set_visible (prefs->box_calib_kind, FALSE);
+ for (i = 0; i < CD_SENSOR_CAP_LAST; i++)
+ {
+ if (cd_bitfield_contain (caps, i))
+ cc_color_calibrate_set_kind (prefs->calibrate, i);
+ }
+ }
+ else
+ {
+ cc_color_calibrate_set_kind (prefs->calibrate, CD_SENSOR_CAP_UNKNOWN);
+ gtk_widget_set_visible (prefs->box_calib_kind, TRUE);
+ }
+}
+
+static void
+gcm_prefs_calib_sensor_treeview_clicked_cb (CcColorPanel *prefs,
+ GtkTreeSelection *selection)
+{
+ gboolean ret;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ g_autoptr(CdSensor) sensor = NULL;
+ GtkAssistant *assistant;
+
+ /* check to see if anything is selected */
+ ret = gtk_tree_selection_get_selected (selection, &model, &iter);
+ assistant = GTK_ASSISTANT (prefs->assistant_calib);
+ gtk_assistant_set_page_complete (assistant, prefs->box_calib_sensor, ret);
+ if (!ret)
+ return;
+
+ /* save the values if we have a selection */
+ gtk_tree_model_get (model, &iter,
+ COLUMN_CALIB_SENSOR_OBJECT, &sensor,
+ -1);
+ gcm_prefs_calib_set_sensor (prefs, sensor);
+}
+
+static void
+gcm_prefs_calibrate_display (CcColorPanel *prefs)
+{
+ CdSensor *sensor_tmp;
+ const gchar *tmp;
+ GtkTreeIter iter;
+ guint i;
+
+ /* set target device */
+ cc_color_calibrate_set_device (prefs->calibrate, prefs->current_device);
+
+ /* add sensors to list */
+ gtk_list_store_clear (GTK_LIST_STORE (prefs->liststore_calib_sensor));
+ if (prefs->sensors->len > 1)
+ {
+ for (i = 0; i < prefs->sensors->len; i++)
+ {
+ sensor_tmp = g_ptr_array_index (prefs->sensors, i);
+ gtk_list_store_append (GTK_LIST_STORE (prefs->liststore_calib_sensor), &iter);
+ gtk_list_store_set (GTK_LIST_STORE (prefs->liststore_calib_sensor), &iter,
+ COLUMN_CALIB_SENSOR_OBJECT, sensor_tmp,
+ COLUMN_CALIB_SENSOR_DESCRIPTION, cd_sensor_get_model (sensor_tmp),
+ -1);
+ }
+ gtk_widget_set_visible (prefs->box_calib_sensor, TRUE);
+ }
+ else
+ {
+ sensor_tmp = g_ptr_array_index (prefs->sensors, 0);
+ gcm_prefs_calib_set_sensor (prefs, sensor_tmp);
+ gtk_widget_set_visible (prefs->box_calib_sensor, FALSE);
+ }
+
+ /* set default profile title */
+ tmp = cd_device_get_model (prefs->current_device);
+ if (tmp == NULL)
+ tmp = cd_device_get_vendor (prefs->current_device);
+ if (tmp == NULL)
+ tmp = _("Screen");
+ gtk_editable_set_text (GTK_EDITABLE (prefs->entry_calib_title), tmp);
+ cc_color_calibrate_set_title (prefs->calibrate, tmp);
+
+ /* set the display whitepoint to D65 by default */
+ //FIXME?
+
+ /* show ui */
+ gtk_window_set_transient_for (GTK_WINDOW (prefs->assistant_calib),
+ GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (prefs))));
+ gtk_widget_show (prefs->assistant_calib);
+}
+
+static void
+gcm_prefs_title_entry_changed_cb (CcColorPanel *prefs)
+{
+ GtkAssistant *assistant;
+ const gchar *value;
+
+ assistant = GTK_ASSISTANT (prefs->assistant_calib);
+ value = gtk_editable_get_text (GTK_EDITABLE (prefs->entry_calib_title));
+ cc_color_calibrate_set_title (prefs->calibrate, value);
+ gtk_assistant_set_page_complete (assistant, prefs->box_calib_title, value[0] != '\0');
+}
+
+static void
+gcm_prefs_calibrate_cb (CcColorPanel *prefs)
+{
+ GtkNative *native;
+ GdkSurface *surface;
+ gboolean ret;
+ g_autoptr(GError) error = NULL;
+ guint xid = 0;
+ g_autoptr(GPtrArray) argv = NULL;
+
+ /* use the new-style calibration helper */
+ if (cd_device_get_kind (prefs->current_device) == CD_DEVICE_KIND_DISPLAY)
+ {
+ gcm_prefs_calibrate_display (prefs);
+ return;
+ }
+
+ /* get xid */
+ native = gtk_widget_get_native (GTK_WIDGET (prefs));
+ surface = gtk_native_get_surface (native);
+
+ if (GDK_IS_X11_SURFACE (surface))
+ xid = gdk_x11_surface_get_xid (GDK_X11_SURFACE (surface));
+
+ /* run with modal set */
+ argv = g_ptr_array_new_with_free_func (g_free);
+ g_ptr_array_add (argv, g_strdup ("gcm-calibrate"));
+ g_ptr_array_add (argv, g_strdup ("--device"));
+ g_ptr_array_add (argv, g_strdup (cd_device_get_id (prefs->current_device)));
+ g_ptr_array_add (argv, g_strdup ("--parent-window"));
+ g_ptr_array_add (argv, g_strdup_printf ("%i", xid));
+ g_ptr_array_add (argv, NULL);
+ ret = g_spawn_async (NULL, (gchar**) argv->pdata, NULL, G_SPAWN_SEARCH_PATH,
+ NULL, NULL, NULL, &error);
+ if (!ret)
+ g_warning ("failed to run calibrate: %s", error->message);
+}
+
+static gboolean
+gcm_prefs_is_profile_suitable_for_device (CdProfile *profile,
+ CdDevice *device)
+{
+ const gchar *data_source;
+ CdProfileKind profile_kind_tmp;
+ CdProfileKind profile_kind;
+ CdColorspace profile_colorspace;
+ CdColorspace device_colorspace = 0;
+ gboolean ret = FALSE;
+ CdDeviceKind device_kind;
+ CdStandardSpace standard_space;
+
+ /* not the right colorspace */
+ device_colorspace = cd_device_get_colorspace (device);
+ profile_colorspace = cd_profile_get_colorspace (profile);
+ if (device_colorspace != profile_colorspace)
+ goto out;
+
+ /* if this is a display matching with one of the standard spaces that displays
+ * could emulate, also mark it as suitable */
+ if (cd_device_get_kind (device) == CD_DEVICE_KIND_DISPLAY &&
+ cd_profile_get_kind (profile) == CD_PROFILE_KIND_DISPLAY_DEVICE)
+ {
+ data_source = cd_profile_get_metadata_item (profile,
+ CD_PROFILE_METADATA_STANDARD_SPACE);
+ standard_space = cd_standard_space_from_string (data_source);
+ if (standard_space == CD_STANDARD_SPACE_SRGB ||
+ standard_space == CD_STANDARD_SPACE_ADOBE_RGB)
+ {
+ ret = TRUE;
+ goto out;
+ }
+ }
+
+ /* not the correct kind */
+ device_kind = cd_device_get_kind (device);
+ profile_kind_tmp = cd_profile_get_kind (profile);
+ profile_kind = cd_device_kind_to_profile_kind (device_kind);
+ if (profile_kind_tmp != profile_kind)
+ goto out;
+
+ /* ignore the colorspace profiles */
+ data_source = cd_profile_get_metadata_item (profile,
+ CD_PROFILE_METADATA_DATA_SOURCE);
+ if (g_strcmp0 (data_source, CD_PROFILE_METADATA_DATA_SOURCE_STANDARD) == 0)
+ goto out;
+
+ /* success */
+ ret = TRUE;
+out:
+ return ret;
+}
+
+static gint
+gcm_prefs_combo_sort_func_cb (GtkTreeModel *model,
+ GtkTreeIter *a,
+ GtkTreeIter *b,
+ gpointer user_data)
+{
+ gint type_a, type_b;
+ g_autofree gchar *text_a = NULL;
+ g_autofree gchar *text_b = NULL;
+
+ /* get data from model */
+ gtk_tree_model_get (model, a,
+ GCM_PREFS_COMBO_COLUMN_TYPE, &type_a,
+ GCM_PREFS_COMBO_COLUMN_TEXT, &text_a,
+ -1);
+ gtk_tree_model_get (model, b,
+ GCM_PREFS_COMBO_COLUMN_TYPE, &type_b,
+ GCM_PREFS_COMBO_COLUMN_TEXT, &text_b,
+ -1);
+
+ /* prefer normal type profiles over the 'Other Profile...' entry */
+ if (type_a < type_b)
+ return -1;
+ else if (type_a > type_b)
+ return 1;
+ else
+ return g_strcmp0 (text_a, text_b);
+}
+
+static gboolean
+gcm_prefs_profile_exists_in_array (GPtrArray *array, CdProfile *profile)
+{
+ CdProfile *profile_tmp;
+ guint i;
+
+ for (i = 0; i < array->len; i++)
+ {
+ profile_tmp = g_ptr_array_index (array, i);
+ if (cd_profile_equal (profile, profile_tmp))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+gcm_prefs_add_profiles_suitable_for_devices (CcColorPanel *prefs,
+ GPtrArray *profiles)
+{
+ CdProfile *profile_tmp;
+ gboolean ret;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) profile_array = NULL;
+ GtkTreeIter iter;
+ guint i;
+
+ gtk_list_store_clear (GTK_LIST_STORE (prefs->liststore_assign));
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (prefs->liststore_assign),
+ GCM_PREFS_COMBO_COLUMN_TEXT,
+ GTK_SORT_ASCENDING);
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (prefs->liststore_assign),
+ GCM_PREFS_COMBO_COLUMN_TEXT,
+ gcm_prefs_combo_sort_func_cb,
+ prefs->liststore_assign, NULL);
+
+ gtk_widget_hide (prefs->label_assign_warning);
+
+ /* get profiles */
+ profile_array = cd_client_get_profiles_sync (prefs->client,
+ cc_panel_get_cancellable (CC_PANEL (prefs)),
+ &error);
+ if (profile_array == NULL)
+ {
+ g_warning ("failed to get profiles: %s",
+ error->message);
+ return;
+ }
+
+ /* add profiles of the right kind */
+ for (i = 0; i < profile_array->len; i++)
+ {
+ profile_tmp = g_ptr_array_index (profile_array, i);
+
+ /* get properties */
+ ret = cd_profile_connect_sync (profile_tmp,
+ cc_panel_get_cancellable (CC_PANEL (prefs)),
+ &error);
+ if (!ret)
+ {
+ g_warning ("failed to get profile: %s", error->message);
+ return;
+ }
+
+ /* don't add any of the already added profiles */
+ if (profiles != NULL)
+ {
+ if (gcm_prefs_profile_exists_in_array (profiles, profile_tmp))
+ continue;
+ }
+
+ /* only add correct types */
+ ret = gcm_prefs_is_profile_suitable_for_device (profile_tmp,
+ prefs->current_device);
+ if (!ret)
+ continue;
+
+#if CD_CHECK_VERSION(0,1,13)
+ /* ignore profiles from other user accounts */
+ if (!cd_profile_has_access (profile_tmp))
+ continue;
+#endif
+
+ /* add */
+ gcm_prefs_combobox_add_profile (prefs,
+ profile_tmp,
+ &iter);
+ }
+}
+
+static void
+gcm_prefs_calib_export_cb (CcColorPanel *prefs)
+{
+ CdProfile *profile;
+ gboolean ret;
+ g_autofree gchar *default_name = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GFile) destination = NULL;
+ g_autoptr(GFile) source = NULL;
+ GtkWidget *dialog;
+
+ profile = cc_color_calibrate_get_profile (prefs->calibrate);
+ ret = cd_profile_connect_sync (profile, NULL, &error);
+ if (!ret)
+ {
+ g_warning ("Failed to get imported profile: %s", error->message);
+ return;
+ }
+
+ /* TRANSLATORS: this is the dialog to save the ICC profile */
+ dialog = gtk_file_chooser_dialog_new (_("Save Profile"),
+ GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (prefs))),
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Save"), GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ default_name = g_strdup_printf ("%s.icc", cd_profile_get_title (profile));
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), default_name);
+
+ if (run_dialog (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+ {
+ source = g_file_new_for_path (cd_profile_get_filename (profile));
+ destination = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+ ret = g_file_copy (source,
+ destination,
+ G_FILE_COPY_OVERWRITE,
+ NULL,
+ NULL,
+ NULL,
+ &error);
+ if (!ret)
+ g_warning ("Failed to copy profile: %s", error->message);
+ }
+
+ gtk_window_destroy (GTK_WINDOW (dialog));
+}
+
+static void
+gcm_prefs_calib_export_link_cb (CcColorPanel *prefs,
+ const gchar *url)
+{
+ gtk_show_uri (GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (prefs))),
+ "help:gnome-help/color-howtoimport",
+ GDK_CURRENT_TIME);
+}
+
+static void
+gcm_prefs_profile_add_cb (CcColorPanel *prefs)
+{
+ g_autoptr(GPtrArray) profiles = NULL;
+
+ /* add profiles of the right kind */
+ profiles = cd_device_get_profiles (prefs->current_device);
+ gcm_prefs_add_profiles_suitable_for_devices (prefs, profiles);
+
+ /* make insensitive until we have a selection */
+ gtk_widget_set_sensitive (prefs->button_assign_ok, FALSE);
+
+ /* show the dialog */
+ gtk_window_set_transient_for (GTK_WINDOW (prefs->dialog_assign),
+ GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (prefs))));
+
+ gtk_widget_show (prefs->dialog_assign);
+}
+
+static void
+gcm_prefs_profile_remove_cb (CcColorPanel *prefs)
+{
+ CdProfile *profile;
+ gboolean ret = FALSE;
+ g_autoptr(GError) error = NULL;
+ GtkListBoxRow *row;
+
+ /* get the selected profile */
+ row = gtk_list_box_get_selected_row (prefs->list_box);
+ if (row == NULL)
+ return;
+ profile = cc_color_profile_get_profile (CC_COLOR_PROFILE (row));
+ if (profile == NULL)
+ {
+ g_warning ("failed to get the active profile");
+ return;
+ }
+
+ /* just remove it, the list store will get ::changed */
+ ret = cd_device_remove_profile_sync (prefs->current_device,
+ profile,
+ cc_panel_get_cancellable (CC_PANEL (prefs)),
+ &error);
+ if (!ret)
+ g_warning ("failed to remove profile: %s", error->message);
+}
+
+static void
+gcm_prefs_make_profile_default_cb (GObject *object,
+ GAsyncResult *res,
+ CcColorPanel *prefs)
+{
+ CdDevice *device = CD_DEVICE (object);
+ gboolean ret = FALSE;
+ g_autoptr(GError) error = NULL;
+
+ ret = cd_device_make_profile_default_finish (device,
+ res,
+ &error);
+ if (!ret)
+ {
+ g_warning ("failed to set default profile on %s: %s",
+ cd_device_get_id (device),
+ error->message);
+ }
+ else
+ {
+ gcm_prefs_refresh_toolbar_buttons (prefs);
+ }
+}
+
+static void
+gcm_prefs_device_profile_enable_cb (CcColorPanel *prefs)
+{
+ CdProfile *profile;
+ GtkListBoxRow *row;
+
+ /* get the selected profile */
+ row = gtk_list_box_get_selected_row (prefs->list_box);
+ if (row == NULL)
+ return;
+ profile = cc_color_profile_get_profile (CC_COLOR_PROFILE (row));
+ if (profile == NULL)
+ {
+ g_warning ("failed to get the active profile");
+ return;
+ }
+
+ /* just set it default */
+ g_debug ("setting %s default on %s",
+ cd_profile_get_id (profile),
+ cd_device_get_id (prefs->current_device));
+ cd_device_make_profile_default (prefs->current_device,
+ profile,
+ cc_panel_get_cancellable (CC_PANEL (prefs)),
+ (GAsyncReadyCallback) gcm_prefs_make_profile_default_cb,
+ prefs);
+}
+
+static void
+gcm_prefs_profile_view (CcColorPanel *prefs, CdProfile *profile)
+{
+ GtkNative *native;
+ GdkSurface *surface;
+ g_autoptr(GPtrArray) argv = NULL;
+ guint xid = 0;
+ gboolean ret;
+ g_autoptr(GError) error = NULL;
+
+ /* get xid */
+ native = gtk_widget_get_native (GTK_WIDGET (prefs));
+ surface = gtk_native_get_surface (native);
+
+ if (GDK_IS_X11_SURFACE (surface))
+ xid = gdk_x11_surface_get_xid (GDK_X11_SURFACE (surface));
+
+ /* open up gcm-viewer as a info pane */
+ argv = g_ptr_array_new_with_free_func (g_free);
+ g_ptr_array_add (argv, g_strdup ("gcm-viewer"));
+ g_ptr_array_add (argv, g_strdup ("--profile"));
+ g_ptr_array_add (argv, g_strdup (cd_profile_get_id (profile)));
+ g_ptr_array_add (argv, g_strdup ("--parent-window"));
+ g_ptr_array_add (argv, g_strdup_printf ("%i", xid));
+ g_ptr_array_add (argv, NULL);
+ ret = g_spawn_async (NULL, (gchar**) argv->pdata, NULL, G_SPAWN_SEARCH_PATH,
+ NULL, NULL, NULL, &error);
+ if (!ret)
+ g_warning ("failed to run calibrate: %s", error->message);
+}
+
+static void
+gcm_prefs_profile_assign_link_activate_cb (CcColorPanel *prefs,
+ const gchar *uri)
+{
+ CdProfile *profile;
+ GtkListBoxRow *row;
+
+ /* get the selected profile */
+ row = gtk_list_box_get_selected_row (prefs->list_box);
+ if (row == NULL)
+ return;
+ profile = cc_color_profile_get_profile (CC_COLOR_PROFILE (row));
+ if (profile == NULL)
+ {
+ g_warning ("failed to get the active profile");
+ return;
+ }
+
+ /* show it in the viewer */
+ gcm_prefs_profile_view (prefs, profile);
+}
+
+static void
+gcm_prefs_profile_view_cb (CcColorPanel *prefs)
+{
+ CdProfile *profile;
+ GtkListBoxRow *row;
+
+ /* get the selected profile */
+ row = gtk_list_box_get_selected_row (prefs->list_box);
+ if (row == NULL)
+ return;
+ profile = cc_color_profile_get_profile (CC_COLOR_PROFILE (row));
+ if (profile == NULL)
+ {
+ g_warning ("failed to get the active profile");
+ return;
+ }
+
+ /* open up gcm-viewer as a info pane */
+ gcm_prefs_profile_view (prefs, profile);
+}
+
+static void
+gcm_prefs_button_assign_ok_cb (CcColorPanel *prefs)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ g_autoptr(CdProfile) profile = NULL;
+ gboolean ret = FALSE;
+ g_autoptr(GError) error = NULL;
+ GtkTreeSelection *selection;
+
+ /* hide window */
+ gtk_widget_hide (GTK_WIDGET (prefs->dialog_assign));
+
+ /* get the selected profile */
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prefs->treeview_assign));
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+ return;
+ gtk_tree_model_get (model, &iter,
+ GCM_PREFS_COMBO_COLUMN_PROFILE, &profile,
+ -1);
+ if (profile == NULL)
+ {
+ g_warning ("failed to get the active profile");
+ return;
+ }
+
+ /* if the device is disabled, enable the device so that we can
+ * add color profiles to it */
+ if (!cd_device_get_enabled (prefs->current_device))
+ {
+ ret = cd_device_set_enabled_sync (prefs->current_device,
+ TRUE,
+ cc_panel_get_cancellable (CC_PANEL (prefs)),
+ &error);
+ if (!ret)
+ {
+ g_warning ("failed to enabled device: %s", error->message);
+ return;
+ }
+ }
+
+ /* just add it, the list store will get ::changed */
+ ret = cd_device_add_profile_sync (prefs->current_device,
+ CD_DEVICE_RELATION_HARD,
+ profile,
+ cc_panel_get_cancellable (CC_PANEL (prefs)),
+ &error);
+ if (!ret)
+ {
+ g_warning ("failed to add: %s", error->message);
+ return;
+ }
+
+ /* make it default */
+ cd_device_make_profile_default (prefs->current_device,
+ profile,
+ cc_panel_get_cancellable (CC_PANEL (prefs)),
+ (GAsyncReadyCallback) gcm_prefs_make_profile_default_cb,
+ prefs);
+}
+
+static void
+gcm_prefs_add_profiles_columns (CcColorPanel *prefs,
+ GtkTreeView *treeview)
+{
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+
+ /* text */
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "markup", GCM_PREFS_COMBO_COLUMN_TEXT);
+ gtk_tree_view_column_set_expand (column, TRUE);
+ gtk_tree_view_append_column (treeview, column);
+
+ /* image */
+ column = gtk_tree_view_column_new ();
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "icon-name", GCM_PREFS_COMBO_COLUMN_WARNING_FILENAME);
+ gtk_tree_view_append_column (treeview, column);
+}
+
+static void
+gcm_prefs_set_calibrate_button_sensitivity (CcColorPanel *prefs)
+{
+ gboolean ret = FALSE;
+ const gchar *tooltip;
+ CdDeviceKind kind;
+ CdSensor *sensor_tmp;
+
+ /* TRANSLATORS: this is when the button is sensitive */
+ tooltip = _("Create a color profile for the selected device");
+
+ /* no device selected */
+ if (prefs->current_device == NULL)
+ goto out;
+
+ /* are we a display */
+ kind = cd_device_get_kind (prefs->current_device);
+ if (kind == CD_DEVICE_KIND_DISPLAY)
+ {
+
+ /* find whether we have hardware installed */
+ if (prefs->sensors == NULL || prefs->sensors->len == 0)
+ {
+ /* TRANSLATORS: this is when the button is insensitive */
+ tooltip = _("The measuring instrument is not detected. Please check it is turned on and correctly connected.");
+ goto out;
+ }
+
+ /* success */
+ ret = TRUE;
+
+ }
+ else if (kind == CD_DEVICE_KIND_SCANNER ||
+ kind == CD_DEVICE_KIND_CAMERA ||
+ kind == CD_DEVICE_KIND_WEBCAM)
+ {
+
+ /* TODO: find out if we can scan using gnome-scan */
+ ret = TRUE;
+
+ }
+ else if (kind == CD_DEVICE_KIND_PRINTER)
+ {
+
+ /* find whether we have hardware installed */
+ if (prefs->sensors == NULL || prefs->sensors->len == 0)
+ {
+ /* TRANSLATORS: this is when the button is insensitive */
+ tooltip = _("The measuring instrument is not detected. Please check it is turned on and correctly connected.");
+ goto out;
+ }
+
+ /* find whether we have hardware installed */
+ sensor_tmp = g_ptr_array_index (prefs->sensors, 0);
+ ret = cd_sensor_has_cap (sensor_tmp, CD_SENSOR_CAP_PRINTER);
+ if (!ret)
+ {
+ /* TRANSLATORS: this is when the button is insensitive */
+ tooltip = _("The measuring instrument does not support printer profiling.");
+ goto out;
+ }
+
+ /* success */
+ ret = TRUE;
+
+ }
+ else
+ {
+ /* TRANSLATORS: this is when the button is insensitive */
+ tooltip = _("The device type is not currently supported.");
+ }
+out:
+ /* control the tooltip and sensitivity of the button */
+ gtk_widget_set_tooltip_text (prefs->toolbutton_device_calibrate, tooltip);
+ gtk_widget_set_sensitive (prefs->toolbutton_device_calibrate, ret);
+}
+
+static void
+gcm_prefs_device_clicked (CcColorPanel *prefs, CdDevice *device)
+{
+ /* we have a new device */
+ g_debug ("selected device is: %s",
+ cd_device_get_id (device));
+
+ /* can this device calibrate */
+ gcm_prefs_set_calibrate_button_sensitivity (prefs);
+}
+
+static void
+gcm_prefs_profile_clicked (CcColorPanel *prefs, CdProfile *profile, CdDevice *device)
+{
+ g_autofree gchar *s = NULL;
+
+ /* get profile */
+ g_debug ("selected profile = %s",
+ cd_profile_get_filename (profile));
+
+ /* allow getting profile info */
+ if (cd_profile_get_filename (profile) != NULL &&
+ (s = g_find_program_in_path ("gcm-viewer")) != NULL)
+ gtk_widget_set_sensitive (prefs->toolbutton_profile_view, TRUE);
+ else
+ gtk_widget_set_sensitive (prefs->toolbutton_profile_view, FALSE);
+}
+
+static void
+gcm_prefs_profiles_treeview_clicked_cb (CcColorPanel *prefs,
+ GtkTreeSelection *selection)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ g_autoptr(CdProfile) profile = NULL;
+#if CD_CHECK_VERSION(0,1,25)
+ gchar **warnings;
+#endif
+
+ /* get selection */
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+ return;
+ gtk_tree_model_get (model, &iter,
+ GCM_PREFS_COMBO_COLUMN_PROFILE, &profile,
+ -1);
+
+ /* as soon as anything is selected, make the Add button sensitive */
+ gtk_widget_set_sensitive (prefs->button_assign_ok, TRUE);
+
+ /* is the profile faulty */
+#if CD_CHECK_VERSION(0,1,25)
+ warnings = cd_profile_get_warnings (profile);
+ gtk_widget_set_visible (prefs->label_assign_warning, warnings != NULL && warnings[0] != NULL);
+#else
+ gtk_widget_set_visible (prefs->label_assign_warning, FALSE);
+#endif
+}
+
+static void
+gcm_prefs_profiles_row_activated_cb (CcColorPanel *prefs,
+ GtkTreePath *path)
+{
+ GtkTreeIter iter;
+ gboolean ret;
+
+ ret = gtk_tree_model_get_iter (gtk_tree_view_get_model (GTK_TREE_VIEW (prefs->treeview_assign)), &iter, path);
+ if (!ret)
+ return;
+ gcm_prefs_button_assign_ok_cb (prefs);
+}
+
+
+static void
+gcm_prefs_button_assign_import_cb (CcColorPanel *prefs)
+{
+ g_autoptr(GFile) file = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(CdProfile) profile = NULL;
+
+ file = gcm_prefs_file_chooser_get_icc_profile (prefs);
+ if (file == NULL)
+ {
+ g_warning ("failed to get ICC file");
+ gtk_widget_hide (GTK_WIDGET (prefs->dialog_assign));
+ return;
+ }
+
+#if CD_CHECK_VERSION(0,1,12)
+ profile = cd_client_import_profile_sync (prefs->client,
+ file,
+ cc_panel_get_cancellable (CC_PANEL (prefs)),
+ &error);
+ if (profile == NULL)
+ {
+ g_warning ("failed to get imported profile: %s", error->message);
+ return;
+ }
+#endif
+
+ /* add to list view */
+ gcm_prefs_profile_add_cb (prefs);
+}
+
+static void
+gcm_prefs_sensor_coldplug (CcColorPanel *prefs)
+{
+ CdSensor *sensor_tmp;
+ gboolean ret;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) sensors = NULL;
+ guint i;
+
+ /* unref old */
+ g_clear_pointer (&prefs->sensors, g_ptr_array_unref);
+
+ /* no present */
+ sensors = cd_client_get_sensors_sync (prefs->client, NULL, &error);
+ if (sensors == NULL)
+ {
+ g_warning ("%s", error->message);
+ return;
+ }
+ if (sensors->len == 0)
+ return;
+
+ /* save a copy of the sensor list */
+ prefs->sensors = g_ptr_array_ref (sensors);
+
+ /* connect to each sensor */
+ for (i = 0; i < sensors->len; i++)
+ {
+ sensor_tmp = g_ptr_array_index (sensors, i);
+ ret = cd_sensor_connect_sync (sensor_tmp, NULL, &error);
+ if (!ret)
+ {
+ g_warning ("%s", error->message);
+ return;
+ }
+ }
+}
+
+static void
+gcm_prefs_client_sensor_changed_cb (CdClient *client,
+ CdSensor *sensor,
+ CcColorPanel *prefs)
+{
+ gcm_prefs_sensor_coldplug (prefs);
+ gcm_prefs_set_calibrate_button_sensitivity (prefs);
+}
+
+static void
+gcm_prefs_add_device_profile (CcColorPanel *prefs,
+ CdDevice *device,
+ CdProfile *profile,
+ gboolean is_default)
+{
+ gboolean ret;
+ g_autoptr(GError) error = NULL;
+ GtkWidget *widget;
+
+ /* get properties */
+ ret = cd_profile_connect_sync (profile,
+ cc_panel_get_cancellable (CC_PANEL (prefs)),
+ &error);
+ if (!ret)
+ {
+ g_warning ("failed to get profile: %s", error->message);
+ return;
+ }
+
+ /* ignore profiles from other user accounts */
+ if (!cd_profile_has_access (profile))
+ {
+ /* only print the filename if it exists */
+ if (cd_profile_get_filename (profile) != NULL)
+ {
+ g_warning ("%s is not usable by this user",
+ cd_profile_get_filename (profile));
+ }
+ else
+ {
+ g_warning ("%s is not usable by this user",
+ cd_profile_get_id (profile));
+ }
+ return;
+ }
+
+ /* add to listbox */
+ widget = cc_color_profile_new (device, profile, is_default);
+ gtk_list_box_append (prefs->list_box, widget);
+ gtk_size_group_add_widget (prefs->list_box_size, widget);
+}
+
+static void
+gcm_prefs_add_device_profiles (CcColorPanel *prefs, CdDevice *device)
+{
+ CdProfile *profile_tmp;
+ g_autoptr(GPtrArray) profiles = NULL;
+ guint i;
+
+ /* add profiles */
+ profiles = cd_device_get_profiles (device);
+ if (profiles == NULL)
+ return;
+ for (i = 0; i < profiles->len; i++)
+ {
+ profile_tmp = g_ptr_array_index (profiles, i);
+ gcm_prefs_add_device_profile (prefs, device, profile_tmp, i == 0);
+ }
+}
+
+/* find the profile in the array -- for flicker-free changes */
+static gboolean
+gcm_prefs_find_profile_by_object_path (GPtrArray *profiles,
+ const gchar *object_path)
+{
+ CdProfile *profile_tmp;
+ guint i;
+
+ for (i = 0; i < profiles->len; i++)
+ {
+ profile_tmp = g_ptr_array_index (profiles, i);
+ if (g_strcmp0 (cd_profile_get_object_path (profile_tmp), object_path) == 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* find the profile in the list view -- for flicker-free changes */
+static gboolean
+gcm_prefs_find_widget_by_object_path (GList *list,
+ const gchar *object_path_device,
+ const gchar *object_path_profile)
+{
+ GList *l;
+ CdDevice *device_tmp;
+ CdProfile *profile_tmp;
+
+ for (l = list; l != NULL; l = l->next)
+ {
+ if (!CC_IS_COLOR_PROFILE (l->data))
+ continue;
+
+ /* correct device ? */
+ device_tmp = cc_color_profile_get_device (CC_COLOR_PROFILE (l->data));
+ if (g_strcmp0 (object_path_device,
+ cd_device_get_object_path (device_tmp)) != 0)
+ {
+ continue;
+ }
+
+ /* this profile */
+ profile_tmp = cc_color_profile_get_profile (CC_COLOR_PROFILE (l->data));
+ if (g_strcmp0 (object_path_profile,
+ cd_profile_get_object_path (profile_tmp)) == 0)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static void
+gcm_prefs_device_changed_cb (CcColorPanel *prefs, CdDevice *device)
+{
+ GtkWidget *child;
+ CdDevice *device_tmp;
+ CdProfile *profile_tmp;
+ gboolean ret;
+ g_autoptr(GList) list = NULL;
+ GPtrArray *profiles;
+ guint i;
+
+ /* remove anything in the list view that's not in Device.Profiles */
+ profiles = cd_device_get_profiles (device);
+ child = gtk_widget_get_first_child (GTK_WIDGET (prefs->list_box));
+ while (child)
+ {
+ GtkWidget *next = gtk_widget_get_next_sibling (child);
+
+ if (!CC_IS_COLOR_PROFILE (child))
+ {
+ list = g_list_prepend (list, child);
+ goto next;
+ }
+
+ /* correct device ? */
+ device_tmp = cc_color_profile_get_device (CC_COLOR_PROFILE (child));
+ if (g_strcmp0 (cd_device_get_id (device),
+ cd_device_get_id (device_tmp)) != 0)
+ {
+ list = g_list_prepend (list, child);
+ goto next;
+ }
+
+ /* if profile is not in Device.Profiles then remove */
+ profile_tmp = cc_color_profile_get_profile (CC_COLOR_PROFILE (child));
+ ret = gcm_prefs_find_profile_by_object_path (profiles,
+ cd_profile_get_object_path (profile_tmp));
+ if (!ret)
+ gtk_list_box_remove (prefs->list_box, child);
+ else
+ list = g_list_prepend (list, child);
+
+next:
+ child = next;
+ }
+
+ /* add anything in Device.Profiles that's not in the list view */
+ for (i = 0; i < profiles->len; i++)
+ {
+ profile_tmp = g_ptr_array_index (profiles, i);
+ ret = gcm_prefs_find_widget_by_object_path (list,
+ cd_device_get_object_path (device),
+ cd_profile_get_object_path (profile_tmp));
+ if (!ret)
+ gcm_prefs_add_device_profile (prefs, device, profile_tmp, i == 0);
+ }
+
+ /* resort */
+ gtk_list_box_invalidate_sort (prefs->list_box);
+}
+
+static void
+gcm_prefs_device_expanded_changed_cb (CcColorPanel *prefs,
+ gboolean is_expanded,
+ CcColorDevice *widget)
+{
+ /* ignore internal changes */
+ if (prefs->model_is_changing)
+ return;
+
+ g_free (prefs->list_box_filter);
+ if (is_expanded)
+ {
+ GtkWidget *child;
+
+ prefs->list_box_filter = g_strdup (cd_device_get_id (cc_color_device_get_device (widget)));
+
+ /* unexpand other device widgets */
+ prefs->model_is_changing = TRUE;
+ for (child = gtk_widget_get_first_child (GTK_WIDGET (prefs->list_box));
+ child != NULL;
+ child = gtk_widget_get_next_sibling (child))
+ {
+ if (!CC_IS_COLOR_DEVICE (child))
+ continue;
+ if (CC_COLOR_DEVICE (child) != widget)
+ cc_color_device_set_expanded (CC_COLOR_DEVICE (child), FALSE);
+ }
+ prefs->model_is_changing = FALSE;
+ }
+ else
+ {
+ prefs->list_box_filter = NULL;
+ }
+ gtk_list_box_invalidate_filter (prefs->list_box);
+}
+
+static void
+gcm_prefs_add_device (CcColorPanel *prefs, CdDevice *device)
+{
+ gboolean ret;
+ g_autoptr(GError) error = NULL;
+ GtkWidget *widget;
+
+ /* get device properties */
+ ret = cd_device_connect_sync (device, cc_panel_get_cancellable (CC_PANEL (prefs)), &error);
+ if (!ret)
+ {
+ g_warning ("failed to connect to the device: %s", error->message);
+ return;
+ }
+
+ /* add device */
+ widget = cc_color_device_new (device);
+ g_signal_connect_object (widget, "expanded-changed",
+ G_CALLBACK (gcm_prefs_device_expanded_changed_cb), prefs, G_CONNECT_SWAPPED);
+ gtk_list_box_append (prefs->list_box, widget);
+ gtk_size_group_add_widget (prefs->list_box_size, widget);
+
+ /* add profiles */
+ gcm_prefs_add_device_profiles (prefs, device);
+
+ /* watch for changes */
+ g_ptr_array_add (prefs->devices, g_object_ref (device));
+ g_signal_connect_object (device, "changed",
+ G_CALLBACK (gcm_prefs_device_changed_cb), prefs, G_CONNECT_SWAPPED);
+ gtk_list_box_invalidate_sort (prefs->list_box);
+}
+
+static void
+gcm_prefs_remove_device (CcColorPanel *prefs, CdDevice *device)
+{
+ GtkWidget *child;
+ CdDevice *device_tmp;
+
+ child = gtk_widget_get_first_child (GTK_WIDGET (prefs->list_box));
+ while (child)
+ {
+ GtkWidget *next = gtk_widget_get_next_sibling (child);
+
+ if (CC_IS_COLOR_DEVICE (child))
+ device_tmp = cc_color_device_get_device (CC_COLOR_DEVICE (child));
+ else
+ device_tmp = cc_color_profile_get_device (CC_COLOR_PROFILE (child));
+ if (g_strcmp0 (cd_device_get_object_path (device),
+ cd_device_get_object_path (device_tmp)) == 0)
+ {
+ gtk_list_box_remove (prefs->list_box, child);
+ }
+
+ child = next;
+ }
+ g_signal_handlers_disconnect_by_func (device,
+ G_CALLBACK (gcm_prefs_device_changed_cb),
+ prefs);
+ g_ptr_array_remove (prefs->devices, device);
+}
+
+static void
+gcm_prefs_update_device_list_extra_entry (CcColorPanel *prefs)
+{
+ GtkListBoxRow *first_row;
+
+ /* any devices to show? */
+ first_row = gtk_list_box_get_row_at_index (prefs->list_box, 0);
+ gtk_widget_set_visible (prefs->label_no_devices, first_row == NULL);
+ gtk_widget_set_visible (prefs->box_devices, first_row != NULL);
+
+ /* if we have only one device expand it by default */
+ if (first_row != NULL &&
+ gtk_list_box_get_row_at_index (prefs->list_box, 1) == NULL)
+ cc_color_device_set_expanded (CC_COLOR_DEVICE (first_row), TRUE);
+}
+
+static void
+gcm_prefs_device_added_cb (CdClient *client,
+ CdDevice *device,
+ CcColorPanel *prefs)
+{
+ /* add the device */
+ gcm_prefs_add_device (prefs, device);
+
+ /* ensure we're not showing the 'No devices detected' entry */
+ gcm_prefs_update_device_list_extra_entry (prefs);
+}
+
+static void
+gcm_prefs_device_removed_cb (CdClient *client,
+ CdDevice *device,
+ CcColorPanel *prefs)
+{
+ /* remove from the UI */
+ gcm_prefs_remove_device (prefs, device);
+
+ /* ensure we showing the 'No devices detected' entry if required */
+ gcm_prefs_update_device_list_extra_entry (prefs);
+}
+
+static void
+gcm_prefs_get_devices_cb (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcColorPanel *prefs = (CcColorPanel *) user_data;
+ CdClient *client = CD_CLIENT (object);
+ CdDevice *device;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) devices = NULL;
+ guint i;
+
+ /* get devices and add them */
+ devices = cd_client_get_devices_finish (client, res, &error);
+ if (devices == NULL)
+ {
+ g_warning ("failed to add connected devices: %s",
+ error->message);
+ return;
+ }
+ for (i = 0; i < devices->len; i++)
+ {
+ device = g_ptr_array_index (devices, i);
+ gcm_prefs_add_device (prefs, device);
+ }
+
+ /* ensure we show the 'No devices detected' entry if empty */
+ gcm_prefs_update_device_list_extra_entry (prefs);
+}
+
+static void
+gcm_prefs_list_box_row_selected_cb (CcColorPanel *panel,
+ GtkListBoxRow *row)
+{
+ if (gtk_widget_in_destruction (panel->toolbar_devices))
+ return;
+
+ gcm_prefs_refresh_toolbar_buttons (panel);
+}
+
+static void
+gcm_prefs_refresh_toolbar_buttons (CcColorPanel *panel)
+{
+ CdProfile *profile = NULL;
+ GtkListBoxRow *row;
+ gboolean is_device;
+
+ /* get the selected profile */
+ row = gtk_list_box_get_selected_row (panel->list_box);
+
+ is_device = CC_IS_COLOR_DEVICE (row);
+
+ /* nothing selected */
+ gtk_widget_set_visible (panel->toolbar_devices, row != NULL);
+ if (row == NULL)
+ return;
+
+ /* save current device */
+ g_clear_object (&panel->current_device);
+ g_object_get (row, "device", &panel->current_device, NULL);
+
+ /* device actions */
+ g_debug ("%s selected", is_device ? "device" : "profile");
+ if (CC_IS_COLOR_DEVICE (row))
+ {
+ gcm_prefs_device_clicked (panel, panel->current_device);
+ cc_color_device_set_expanded (CC_COLOR_DEVICE (row), TRUE);
+ }
+ else if (CC_IS_COLOR_PROFILE (row))
+ {
+ profile = cc_color_profile_get_profile (CC_COLOR_PROFILE (row));
+ gcm_prefs_profile_clicked (panel, profile, panel->current_device);
+ }
+ else
+ g_assert_not_reached ();
+
+ gtk_widget_set_visible (panel->toolbutton_device_default, !is_device && cc_color_profile_get_is_default (CC_COLOR_PROFILE (row)));
+ if (profile)
+ gtk_widget_set_sensitive (panel->toolbutton_device_default, !cd_profile_get_is_system_wide (profile));
+ gtk_widget_set_visible (panel->toolbutton_device_enable, !is_device && !cc_color_profile_get_is_default (CC_COLOR_PROFILE (row)));
+ gtk_widget_set_visible (panel->toolbutton_device_calibrate, is_device);
+ gtk_widget_set_visible (panel->toolbutton_profile_add, is_device);
+ gtk_widget_set_visible (panel->toolbutton_profile_view, !is_device);
+ gtk_widget_set_visible (panel->toolbutton_profile_remove, !is_device);
+}
+
+static void
+gcm_prefs_list_box_row_activated_cb (CcColorPanel *prefs,
+ GtkListBoxRow *row)
+{
+ if (CC_IS_COLOR_PROFILE (row))
+ {
+ gcm_prefs_device_profile_enable_cb (prefs);
+ }
+}
+
+static void
+gcm_prefs_connect_cb (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcColorPanel *prefs;
+ gboolean ret;
+ g_autoptr(GError) error = NULL;
+
+ ret = cd_client_connect_finish (CD_CLIENT (object),
+ res,
+ &error);
+ if (!ret)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("failed to connect to colord: %s", error->message);
+ return;
+ }
+
+ /* Only cast the parameters after making sure it didn't fail. At this point,
+ * the user can potentially already have changed to another panel, effectively
+ * making user_data invalid. */
+ prefs = CC_COLOR_PANEL (user_data);
+
+ /* set calibrate button sensitivity */
+ gcm_prefs_sensor_coldplug (prefs);
+
+ /* get devices */
+ cd_client_get_devices (prefs->client,
+ cc_panel_get_cancellable (CC_PANEL (prefs)),
+ gcm_prefs_get_devices_cb,
+ prefs);
+}
+
+static gboolean
+gcm_prefs_is_livecd (void)
+{
+#ifdef __linux__
+ gboolean ret = TRUE;
+ g_autofree gchar *data = NULL;
+ g_autoptr(GError) error = NULL;
+
+ /* allow testing */
+ if (g_getenv ("CC_COLOR_PANEL_IS_LIVECD") != NULL)
+ return TRUE;
+
+ /* get the kernel commandline */
+ ret = g_file_get_contents ("/proc/cmdline", &data, NULL, &error);
+ if (!ret)
+ {
+ g_warning ("failed to get kernel command line: %s",
+ error->message);
+ return TRUE;
+ }
+ return (g_strstr_len (data, -1, "liveimg") != NULL ||
+ g_strstr_len (data, -1, "casper") != NULL);
+#else
+ return FALSE;
+#endif
+}
+
+static const char *
+cc_color_panel_get_help_uri (CcPanel *panel)
+{
+ return "help:gnome-help/color";
+}
+
+static void
+cc_color_panel_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+cc_color_panel_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+cc_color_panel_dispose (GObject *object)
+{
+ CcColorPanel *prefs = CC_COLOR_PANEL (object);
+
+ g_clear_object (&prefs->settings);
+ g_clear_object (&prefs->settings_colord);
+ g_clear_object (&prefs->client);
+ g_clear_object (&prefs->current_device);
+ g_clear_pointer (&prefs->devices, g_ptr_array_unref);
+ g_clear_object (&prefs->calibrate);
+ g_clear_object (&prefs->list_box_size);
+ g_clear_pointer (&prefs->sensors, g_ptr_array_unref);
+ g_clear_pointer (&prefs->list_box_filter, g_free);
+ g_clear_pointer ((GtkWindow **)&prefs->dialog_assign, gtk_window_destroy);
+
+ G_OBJECT_CLASS (cc_color_panel_parent_class)->dispose (object);
+}
+
+static void
+cc_color_panel_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (cc_color_panel_parent_class)->finalize (object);
+}
+
+static void
+cc_color_panel_class_init (CcColorPanelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+
+ panel_class->get_help_uri = cc_color_panel_get_help_uri;
+
+ object_class->get_property = cc_color_panel_get_property;
+ object_class->set_property = cc_color_panel_set_property;
+ object_class->dispose = cc_color_panel_dispose;
+ object_class->finalize = cc_color_panel_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/color/cc-color-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, assistant_calib);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, box_calib_brightness);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, box_calib_kind);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, box_calib_quality);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, box_calib_sensor);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, box_calib_summary);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, box_calib_temp);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, box_calib_title);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, box_devices);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, button_assign_import);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, button_assign_ok);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, button_calib_export);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, dialog_assign);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, entry_calib_title);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, label_assign_warning);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, label_calib_summary_message);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, label_no_devices);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, list_box);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, liststore_assign);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, liststore_calib_kind);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, liststore_calib_sensor);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, toolbar_devices);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, toolbutton_device_calibrate);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, toolbutton_device_default);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, toolbutton_device_enable);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, toolbutton_profile_add);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, toolbutton_profile_remove);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, toolbutton_profile_view);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, treeview_assign);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, treeview_calib_kind);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, treeview_calib_quality);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, treeview_calib_sensor);
+ gtk_widget_class_bind_template_child (widget_class, CcColorPanel, treeview_calib_temp);
+}
+
+static gint
+cc_color_panel_sort_func (GtkListBoxRow *a,
+ GtkListBoxRow *b,
+ gpointer user_data)
+{
+ const gchar *sort_a = NULL;
+ const gchar *sort_b = NULL;
+ if (CC_IS_COLOR_DEVICE (a))
+ sort_a = cc_color_device_get_sortable (CC_COLOR_DEVICE (a));
+ else if (CC_IS_COLOR_PROFILE (a))
+ sort_a = cc_color_profile_get_sortable (CC_COLOR_PROFILE (a));
+ else
+ g_assert_not_reached ();
+ if (CC_IS_COLOR_DEVICE (b))
+ sort_b = cc_color_device_get_sortable (CC_COLOR_DEVICE (b));
+ else if (CC_IS_COLOR_PROFILE (b))
+ sort_b = cc_color_profile_get_sortable (CC_COLOR_PROFILE (b));
+ else
+ g_assert_not_reached ();
+ return g_strcmp0 (sort_b, sort_a);
+}
+
+static gboolean
+cc_color_panel_filter_func (GtkListBoxRow *row, void *user_data)
+{
+ CcColorPanel *prefs = CC_COLOR_PANEL (user_data);
+ g_autoptr(CdDevice) device = NULL;
+
+ /* always show all devices */
+ if (CC_IS_COLOR_DEVICE (row))
+ return TRUE;
+
+ g_object_get (row, "device", &device, NULL);
+ return g_strcmp0 (cd_device_get_id (device), prefs->list_box_filter) == 0;
+}
+
+static gboolean
+cc_color_panel_treeview_quality_default_cb (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ CdProfileQuality quality;
+ GtkTreeSelection *selection = GTK_TREE_SELECTION (data);
+
+ gtk_tree_model_get (model, iter,
+ COLUMN_CALIB_QUALITY_VALUE, &quality,
+ -1);
+ if (quality == CD_PROFILE_QUALITY_MEDIUM)
+ gtk_tree_selection_select_iter (selection, iter);
+ return FALSE;
+}
+
+static void
+cc_color_panel_init (CcColorPanel *prefs)
+{
+ GtkCellRenderer *renderer;
+ GtkTreeModel *model;
+ GtkTreeModel *model_filter;
+ GtkTreeSelection *selection;
+ GtkTreeViewColumn *column;
+
+ g_resources_register (cc_color_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (prefs));
+
+ prefs->devices = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+
+ /* can do native display calibration using colord-session */
+ prefs->calibrate = cc_color_calibrate_new ();
+ cc_color_calibrate_set_quality (prefs->calibrate, CD_PROFILE_QUALITY_MEDIUM);
+
+ /* setup defaults */
+ prefs->settings = g_settings_new (GCM_SETTINGS_SCHEMA);
+ prefs->settings_colord = g_settings_new (COLORD_SETTINGS_SCHEMA);
+
+ /* assign buttons */
+ g_signal_connect_object (prefs->toolbutton_profile_add, "clicked",
+ G_CALLBACK (gcm_prefs_profile_add_cb), prefs, G_CONNECT_SWAPPED);
+ g_signal_connect_object (prefs->toolbutton_profile_remove, "clicked",
+ G_CALLBACK (gcm_prefs_profile_remove_cb), prefs, G_CONNECT_SWAPPED);
+ g_signal_connect_object (prefs->toolbutton_profile_view, "clicked",
+ G_CALLBACK (gcm_prefs_profile_view_cb), prefs, G_CONNECT_SWAPPED);
+
+ /* href */
+ g_signal_connect_object (prefs->label_assign_warning, "activate-link",
+ G_CALLBACK (gcm_prefs_profile_assign_link_activate_cb), prefs, G_CONNECT_SWAPPED);
+
+ /* add columns to profile tree view */
+ gcm_prefs_add_profiles_columns (prefs, GTK_TREE_VIEW (prefs->treeview_assign));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prefs->treeview_assign));
+ g_signal_connect_object (selection, "changed",
+ G_CALLBACK (gcm_prefs_profiles_treeview_clicked_cb),
+ prefs, G_CONNECT_SWAPPED);
+ g_signal_connect_object (prefs->treeview_assign, "row-activated",
+ G_CALLBACK (gcm_prefs_profiles_row_activated_cb),
+ prefs, G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (prefs->toolbutton_device_default, "clicked",
+ G_CALLBACK (gcm_prefs_default_cb), prefs, G_CONNECT_SWAPPED);
+ g_signal_connect_object (prefs->toolbutton_device_enable, "clicked",
+ G_CALLBACK (gcm_prefs_device_profile_enable_cb), prefs, G_CONNECT_SWAPPED);
+ g_signal_connect_object (prefs->toolbutton_device_calibrate, "clicked",
+ G_CALLBACK (gcm_prefs_calibrate_cb), prefs, G_CONNECT_SWAPPED);
+
+ /* set up assign dialog */
+ g_signal_connect_object (prefs->button_assign_ok, "clicked",
+ G_CALLBACK (gcm_prefs_button_assign_ok_cb), prefs, G_CONNECT_SWAPPED);
+
+ /* setup icc profiles list */
+ g_signal_connect_object (prefs->button_assign_import, "clicked",
+ G_CALLBACK (gcm_prefs_button_assign_import_cb), prefs, G_CONNECT_SWAPPED);
+
+ /* setup the calibration helper */
+ g_signal_connect_object (prefs->assistant_calib, "apply",
+ G_CALLBACK (gcm_prefs_calib_apply_cb),
+ prefs, G_CONNECT_SWAPPED);
+ g_signal_connect_object (prefs->assistant_calib, "cancel",
+ G_CALLBACK (gcm_prefs_calib_cancel_cb),
+ prefs, G_CONNECT_SWAPPED);
+ g_signal_connect_object (prefs->assistant_calib, "close",
+ G_CALLBACK (gcm_prefs_calib_cancel_cb),
+ prefs, G_CONNECT_SWAPPED);
+ g_signal_connect_object (prefs->assistant_calib, "prepare",
+ G_CALLBACK (gcm_prefs_calib_prepare_cb),
+ prefs, G_CONNECT_SWAPPED);
+
+ /* setup the calibration helper ::TreeView */
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prefs->treeview_calib_quality));
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (prefs->treeview_calib_quality));
+ gtk_tree_model_foreach (model,
+ cc_color_panel_treeview_quality_default_cb,
+ selection);
+ g_signal_connect_object (selection, "changed",
+ G_CALLBACK (gcm_prefs_calib_quality_treeview_clicked_cb),
+ prefs, G_CONNECT_SWAPPED);
+ column = gtk_tree_view_column_new ();
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (renderer,
+ "xpad", 9,
+ "ypad", 9,
+ NULL);
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "markup", COLUMN_CALIB_QUALITY_DESCRIPTION);
+ gtk_tree_view_column_set_expand (column, TRUE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (prefs->treeview_calib_quality),
+ GTK_TREE_VIEW_COLUMN (column));
+ column = gtk_tree_view_column_new ();
+ renderer = cc_color_cell_renderer_text_new ();
+ g_object_set (renderer,
+ "xpad", 9,
+ "ypad", 9,
+ "is-dim-label", TRUE,
+ NULL);
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "markup", COLUMN_CALIB_QUALITY_APPROX_TIME);
+ gtk_tree_view_column_set_expand (column, FALSE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (prefs->treeview_calib_quality),
+ GTK_TREE_VIEW_COLUMN (column));
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prefs->treeview_calib_sensor));
+ g_signal_connect_object (selection, "changed",
+ G_CALLBACK (gcm_prefs_calib_sensor_treeview_clicked_cb),
+ prefs, G_CONNECT_SWAPPED);
+ column = gtk_tree_view_column_new ();
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (renderer,
+ "xpad", 9,
+ "ypad", 9,
+ NULL);
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "markup", COLUMN_CALIB_SENSOR_DESCRIPTION);
+ gtk_tree_view_column_set_expand (column, TRUE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (prefs->treeview_calib_sensor),
+ GTK_TREE_VIEW_COLUMN (column));
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prefs->treeview_calib_kind));
+ g_signal_connect_object (selection, "changed",
+ G_CALLBACK (gcm_prefs_calib_kind_treeview_clicked_cb),
+ prefs, G_CONNECT_SWAPPED);
+ column = gtk_tree_view_column_new ();
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (renderer,
+ "xpad", 9,
+ "ypad", 9,
+ NULL);
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "markup", COLUMN_CALIB_KIND_DESCRIPTION);
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (prefs->treeview_calib_kind));
+ model_filter = gtk_tree_model_filter_new (model, NULL);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (prefs->treeview_calib_kind), model_filter);
+ gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (model_filter),
+ COLUMN_CALIB_KIND_VISIBLE);
+
+ gtk_tree_view_column_set_expand (column, TRUE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (prefs->treeview_calib_kind),
+ GTK_TREE_VIEW_COLUMN (column));
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prefs->treeview_calib_temp));
+ g_signal_connect_object (selection, "changed",
+ G_CALLBACK (gcm_prefs_calib_temp_treeview_clicked_cb),
+ prefs, G_CONNECT_SWAPPED);
+ column = gtk_tree_view_column_new ();
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (renderer,
+ "xpad", 9,
+ "ypad", 9,
+ NULL);
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "markup", COLUMN_CALIB_TEMP_DESCRIPTION);
+ gtk_tree_view_column_set_expand (column, TRUE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (prefs->treeview_calib_temp),
+ GTK_TREE_VIEW_COLUMN (column));
+ g_signal_connect_object (prefs->entry_calib_title, "notify::text",
+ G_CALLBACK (gcm_prefs_title_entry_changed_cb), prefs, G_CONNECT_SWAPPED);
+
+ /* use a device client array */
+ prefs->client = cd_client_new ();
+ g_signal_connect_object (prefs->client, "device-added",
+ G_CALLBACK (gcm_prefs_device_added_cb), prefs, 0);
+ g_signal_connect_object (prefs->client, "device-removed",
+ G_CALLBACK (gcm_prefs_device_removed_cb), prefs, 0);
+
+ /* use a listbox for the main UI */
+ gtk_list_box_set_filter_func (prefs->list_box,
+ cc_color_panel_filter_func,
+ prefs,
+ NULL);
+ gtk_list_box_set_sort_func (prefs->list_box,
+ cc_color_panel_sort_func,
+ prefs,
+ NULL);
+ g_signal_connect_object (prefs->list_box, "row-selected",
+ G_CALLBACK (gcm_prefs_list_box_row_selected_cb),
+ prefs, G_CONNECT_SWAPPED);
+ g_signal_connect_object (prefs->list_box, "row-activated",
+ G_CALLBACK (gcm_prefs_list_box_row_activated_cb),
+ prefs, G_CONNECT_SWAPPED);
+ prefs->list_box_size = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
+
+ /* connect to colord */
+ cd_client_connect (prefs->client,
+ cc_panel_get_cancellable (CC_PANEL (prefs)),
+ gcm_prefs_connect_cb,
+ prefs);
+
+ /* use the color sensor */
+ g_signal_connect_object (prefs->client, "sensor-added",
+ G_CALLBACK (gcm_prefs_client_sensor_changed_cb),
+ prefs, 0);
+ g_signal_connect_object (prefs->client, "sensor-removed",
+ G_CALLBACK (gcm_prefs_client_sensor_changed_cb),
+ prefs, 0);
+
+ /* set calibrate button sensitivity */
+ gcm_prefs_set_calibrate_button_sensitivity (prefs);
+
+ /* show the confirmation export page if we are running from a LiveCD */
+ prefs->is_live_cd = gcm_prefs_is_livecd ();
+ gtk_widget_set_visible (prefs->box_calib_summary, prefs->is_live_cd);
+ g_signal_connect_object (prefs->button_calib_export, "clicked",
+ G_CALLBACK (gcm_prefs_calib_export_cb), prefs, G_CONNECT_SWAPPED);
+ g_signal_connect_object (prefs->label_calib_summary_message, "activate-link",
+ G_CALLBACK (gcm_prefs_calib_export_link_cb), prefs, G_CONNECT_SWAPPED);
+}
diff --git a/panels/color/cc-color-panel.h b/panels/color/cc-color-panel.h
new file mode 100644
index 0000000..27861d1
--- /dev/null
+++ b/panels/color/cc-color-panel.h
@@ -0,0 +1,30 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2010 Red Hat, Inc
+ * Copyright (C) 2011 Richard Hughes <richard@hughsie.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_COLOR_PANEL (cc_color_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcColorPanel, cc_color_panel, CC, COLOR_PANEL, CcPanel)
+
+G_END_DECLS
diff --git a/panels/color/cc-color-panel.ui b/panels/color/cc-color-panel.ui
new file mode 100644
index 0000000..5f7c3fb
--- /dev/null
+++ b/panels/color/cc-color-panel.ui
@@ -0,0 +1,707 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <object class="GtkAssistant" id="assistant_calib">
+ <property name="title" translatable="yes">Screen Calibration</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="hide-on-close">True</property>
+
+ <child>
+ <object class="GtkAssistantPage">
+ <property name="title" translatable="yes">Calibration Quality</property>
+ <property name="complete">True</property>
+ <property name="child">
+ <object class="GtkBox" id="box_calib_quality">
+ <property name="orientation">vertical</property>
+ <property name="spacing">9</property>
+ <child>
+ <object class="GtkLabel" id="label_calib_quality_message">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Calibration will produce a profile that you can use to color manage your screen. The longer you spend on calibration, the better the quality of the color profile.</property>
+ <property name="wrap">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_calib_quality_message2">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">You will not be able to use your computer while calibration takes place.</property>
+ <property name="wrap">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="box_label_calib_quality_header">
+ <property name="margin_top">12</property>
+ <child>
+ <object class="GtkLabel" id="label_calib_quality_header">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes" comments="This is the approximate time it takes to calibrate the display.">Quality</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_calib_quality_approx_time">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes" comments="This is the approximate time it takes to calibrate the display.">Approximate Time</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow_calib_quality">
+ <property name="hscrollbar_policy">never</property>
+ <property name="vscrollbar_policy">never</property>
+ <child>
+ <object class="GtkTreeView" id="treeview_calib_quality">
+ <property name="model">liststore_calib_quality</property>
+ <property name="headers_visible">False</property>
+ <property name="search_column">0</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview-selection3"/>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkAssistantPage">
+ <property name="title" translatable="yes">Calibration Device</property>
+ <property name="child">
+ <object class="GtkBox" id="box_calib_sensor">
+ <property name="orientation">vertical</property>
+ <property name="spacing">9</property>
+ <child>
+ <object class="GtkLabel" id="label_calib_sensor_message">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Select the sensor device you want to use for calibration.</property>
+ <property name="wrap">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow_calib_sensor">
+ <property name="hscrollbar_policy">never</property>
+ <property name="vscrollbar_policy">never</property>
+ <child>
+ <object class="GtkTreeView" id="treeview_calib_sensor">
+ <property name="model">liststore_calib_sensor</property>
+ <property name="headers_visible">False</property>
+ <property name="search_column">1</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview-selection4"/>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkAssistantPage">
+ <property name="title" translatable="yes">Display Type</property>
+ <property name="child">
+ <object class="GtkBox" id="box_calib_kind">
+ <property name="orientation">vertical</property>
+ <property name="spacing">9</property>
+ <child>
+ <object class="GtkLabel" id="label_calib_kind_message">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Select the type of display that is connected.</property>
+ <property name="wrap">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow_calib_kind">
+ <property name="hscrollbar_policy">never</property>
+ <property name="vscrollbar_policy">never</property>
+ <child>
+ <object class="GtkTreeView" id="treeview_calib_kind">
+ <property name="model">liststore_calib_kind</property>
+ <property name="headers_visible">False</property>
+ <property name="search_column">0</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview-selection5"/>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkAssistantPage">
+ <property name="title" translatable="yes">Profile Whitepoint</property>
+ <property name="child">
+ <object class="GtkBox" id="box_calib_temp">
+ <property name="orientation">vertical</property>
+ <property name="spacing">9</property>
+ <child>
+ <object class="GtkLabel" id="label_calib_temp_message">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Select a display target white point. Most displays should be calibrated to a D65 illuminant.</property>
+ <property name="wrap">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow_calib_temp">
+ <property name="hscrollbar_policy">never</property>
+ <property name="vscrollbar_policy">never</property>
+ <child>
+ <object class="GtkTreeView" id="treeview_calib_temp">
+ <property name="model">liststore_calib_temp</property>
+ <property name="headers_visible">False</property>
+ <property name="search_column">0</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview-selection6"/>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkAssistantPage">
+ <property name="title" translatable="yes">Display Brightness</property>
+ <property name="child">
+ <object class="GtkBox" id="box_calib_brightness">
+ <property name="orientation">vertical</property>
+ <property name="spacing">9</property>
+ <child>
+ <object class="GtkLabel" id="label_calib_brightness_message1">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Please set the display to a brightness that is typical for you. Color management will be most accurate at this brightness level.</property>
+ <property name="wrap">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_calib_brightness_message2">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Alternatively, you can use the brightness level used with one of the other profiles for this device.</property>
+ <property name="wrap">True</property>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkAssistantPage">
+ <property name="page_type">confirm</property>
+ <property name="title" translatable="yes">Profile Name</property>
+ <property name="child">
+ <object class="GtkBox" id="box_calib_title">
+ <property name="orientation">vertical</property>
+ <property name="spacing">9</property>
+ <child>
+ <object class="GtkLabel" id="label_calib_title_message">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">You can use a color profile on different computers, or even create profiles for different lighting conditions.</property>
+ <property name="wrap">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_calib_title_header">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Profile Name:</property>
+ <property name="wrap">True</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry_calib_title">
+ <property name="invisible_char">●</property>
+ <property name="truncate_multiline">True</property>
+ <property name="invisible_char_set">True</property>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkAssistantPage">
+ <property name="page_type">summary</property>
+ <property name="title" translatable="yes">Summary</property>
+ <property name="child">
+ <object class="GtkBox" id="box_calib_summary">
+ <property name="orientation">vertical</property>
+ <property name="spacing">9</property>
+ <child>
+ <object class="GtkLabel" id="label_calib_summary_title">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Profile successfully created!</property>
+ <property name="wrap">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="halign">center</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkButton" id="button_calib_export">
+ <property name="halign">start</property>
+ <child>
+ <object class="GtkBox" id="box3">
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">6</property>
+ <property name="margin_start">6</property>
+ <property name="margin_end">6</property>
+ <property name="spacing">9</property>
+ <child>
+ <object class="GtkImage" id="image2">
+ <property name="pixel_size">48</property>
+ <property name="icon_name">folder-symbolic</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="box6">
+ <property name="orientation">vertical</property>
+ <property name="spacing">3</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Copy profile</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Requires writable media</property>
+ <attributes>
+ <attribute name="style" value="italic"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_calib_summary_message">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">You may find these instructions on how to use the profile on &lt;a href="linux"&gt;GNU/Linux&lt;/a&gt;, &lt;a href="osx"&gt;Apple OS X&lt;/a&gt; and &lt;a href="windows"&gt;Microsoft Windows&lt;/a&gt; systems useful.</property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child internal-child="action_area">
+ <object class="GtkBox" id="assistant-action_area1">
+ <property name="halign">end</property>
+ <property name="spacing">6</property>
+ </object>
+ </child>
+ </object>
+
+ <object class="GtkDialog" id="dialog_assign">
+ <property name="title" translatable="yes">Add Profile</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="icon_name">gnome-color-manager</property>
+ <property name="use-header-bar">1</property>
+ <property name="hide-on-close">True</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow_assign">
+ <property name="hscrollbar_policy">never</property>
+ <property name="hscrollbar-policy">GTK_POLICY_NEVER</property>
+ <property name="min-content-height">300</property>
+ <child>
+ <object class="GtkTreeView" id="treeview_assign">
+ <property name="model">liststore_assign</property>
+ <property name="headers_visible">False</property>
+ <property name="enable_search">False</property>
+ <property name="search_column">0</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview-selection2"/>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_assign_warning">
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">6</property>
+ <property name="margin_start">6</property>
+ <property name="margin_end">6</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Problems detected. The profile may not work correctly. &lt;a href=""&gt;Show details.&lt;/a&gt;</property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="titlebar">
+ <object class="GtkHeaderBar">
+ <child type="start">
+ <object class="GtkButton" id="button_assign_import">
+ <property name="label" translatable="yes">_Import File…</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ <child type="end">
+ <object class="GtkButton" id="button_assign_ok">
+ <property name="label" translatable="yes">_Add</property>
+ <property name="use_underline">True</property>
+ <style>
+ <class name="suggested-action" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="0">button_assign_import</action-widget>
+ <action-widget response="ok">button_assign_ok</action-widget>
+ </action-widgets>
+ </object>
+ <template class="CcColorPanel" parent="CcPanel">
+ <child type="content">
+ <object class="GtkScrolledWindow" id="dialog_scroll">
+ <child>
+ <object class="AdwClamp">
+ <property name="margin_top">32</property>
+ <property name="margin_bottom">32</property>
+ <property name="margin_start">12</property>
+ <property name="margin_end">12</property>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <property name="hexpand">True</property>
+ <child>
+ <object class="GtkBox" id="hbox3">
+ <property name="spacing">9</property>
+ <child>
+ <object class="GtkLabel" id="label_intro">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Each device needs an up to date color profile to be color managed.</property>
+ <property name="wrap">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_padding">
+ </object>
+ </child>
+ <child>
+ <object class="GtkLinkButton" id="linkbutton_help">
+ <property name="label" translatable="yes">Learn more</property>
+ <property name="has_tooltip">True</property>
+ <property name="tooltip_text" translatable="yes">Learn more about color management</property>
+ <property name="uri">help:gnome-help/color-whyimportant</property>
+ <accessibility>
+ <relation name="labelled-by">label_intro</relation>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="box_devices">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkListBox" id="list_box">
+ <property name="activate-on-single-click">False</property>
+ <property name="selection-mode">single</property>
+ <style>
+ <class name="boxed-list" />
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="toolbar_devices">
+ <property name="visible">False</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">6</property>
+ <property name="margin_start">6</property>
+ <property name="margin_end">6</property>
+ <child>
+ <object class="GtkBox" id="left_button_group_box">
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <style>
+ <class name="linked" />
+ </style>
+ <child>
+ <object class="GtkButton" id="toolbutton_device_default">
+ <property name="label" translatable="yes">_Set for all users</property>
+ <property name="has_tooltip">True</property>
+ <property name="tooltip_text" translatable="yes">Set this profile for all users on this computer</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="toolbutton_device_enable">
+ <property name="label" translatable="yes">_Enable</property>
+ <property name="has_tooltip">True</property>
+ <property name="tooltip_markup" translatable="yes">Set this profile for all users on this computer</property>
+ <property name="tooltip_text" translatable="yes">Set this profile for all users on this computer</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="right_button_group_box">
+ <style>
+ <class name="linked" />
+ </style>
+ <child>
+ <object class="GtkButton" id="toolbutton_profile_add">
+ <property name="label" translatable="yes">_Add profile</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="toolbutton_device_calibrate">
+ <property name="label" translatable="yes">_Calibrate…</property>
+ <property name="has_tooltip">True</property>
+ <property name="tooltip_text" translatable="yes">Calibrate the device</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="toolbutton_profile_remove">
+ <property name="label" translatable="yes">_Remove profile</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="toolbutton_profile_view">
+ <property name="label" translatable="yes">_View details</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_no_devices">
+ <property name="label" translatable="yes">Unable to detect any devices that can be color managed</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GtkListStore" id="liststore_assign">
+ <columns>
+ <!-- column-name title -->
+ <column type="gchararray"/>
+ <!-- column-name profile -->
+ <column type="GObject"/>
+ <!-- column-name kind -->
+ <column type="guint"/>
+ <!-- column-name warningfn -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkListStore" id="liststore_calib_kind">
+ <columns>
+ <!-- column-name display_kind -->
+ <column type="gchararray"/>
+ <!-- column-name kind -->
+ <column type="guint"/>
+ <!-- column-name visible -->
+ <column type="gboolean"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">LCD</col>
+ <col id="1">1</col>
+ <col id="2">False</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">LED</col>
+ <col id="1">8</col>
+ <col id="2">False</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">CRT</col>
+ <col id="1">2</col>
+ <col id="2">False</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Projector</col>
+ <col id="1">5</col>
+ <col id="2">False</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Plasma</col>
+ <col id="1">9</col>
+ <col id="2">False</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">LCD (CCFL backlight)</col>
+ <col id="1">10</col>
+ <col id="2">False</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">LCD (RGB LED backlight)</col>
+ <col id="1">11</col>
+ <col id="2">False</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">LCD (white LED backlight)</col>
+ <col id="1">12</col>
+ <col id="2">False</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Wide gamut LCD (CCFL backlight)</col>
+ <col id="1">13</col>
+ <col id="2">False</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Wide gamut LCD (RGB LED backlight)</col>
+ <col id="1">14</col>
+ <col id="2">False</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="liststore_calib_quality">
+ <columns>
+ <!-- column-name quality -->
+ <column type="gchararray"/>
+ <!-- column-name approx_time -->
+ <column type="gchararray"/>
+ <!-- column-name value -->
+ <column type="guint"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes" context="Calibration quality">High</col>
+ <col id="1" translatable="yes">40 minutes</col>
+ <col id="2" translatable="no">2</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" context="Calibration quality">Medium</col>
+ <col id="1" translatable="yes">30 minutes</col>
+ <col id="2" translatable="no">1</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" context="Calibration quality">Low</col>
+ <col id="1" translatable="yes">15 minutes</col>
+ <col id="2" translatable="no">0</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="liststore_calib_sensor">
+ <columns>
+ <!-- column-name sensor -->
+ <column type="GObject"/>
+ <!-- column-name sensor_desc -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkListStore" id="liststore_calib_temp">
+ <columns>
+ <!-- column-name temp_desc -->
+ <column type="gchararray"/>
+ <!-- column-name temp_value -->
+ <column type="guint"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Native to display</col>
+ <col id="1">0</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">D50 (Printing and publishing)</col>
+ <col id="1">5000</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">D55</col>
+ <col id="1">5500</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">D65 (Photography and graphics)</col>
+ <col id="1">6500</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">D75</col>
+ <col id="1">7500</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup_assign">
+ <widgets>
+ <widget name="label_assign_warning"/>
+ <widget name="scrolledwindow_assign"/>
+ </widgets>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup_buttons">
+ <widgets>
+ <widget name="toolbutton_profile_add"/>
+ <widget name="toolbutton_device_calibrate"/>
+ <widget name="toolbutton_profile_remove"/>
+ <widget name="toolbutton_profile_view"/>
+ </widgets>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup_buttons_enable">
+ <widgets>
+ <widget name="toolbutton_device_default"/>
+ <widget name="toolbutton_device_enable"/>
+ </widgets>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup_combos"/>
+ <object class="GtkSizeGroup" id="sizegroup_defaults"/>
+ <object class="GtkSizeGroup" id="sizegroup_devices"/>
+</interface>
diff --git a/panels/color/cc-color-profile.c b/panels/color/cc-color-profile.c
new file mode 100644
index 0000000..65cb99f
--- /dev/null
+++ b/panels/color/cc-color-profile.c
@@ -0,0 +1,475 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "cc-color-common.h"
+#include "cc-color-profile.h"
+
+struct _CcColorProfile
+{
+ GtkListBoxRow parent_instance;
+
+ GtkWidget *box;
+ CdDevice *device;
+ CdProfile *profile;
+ gboolean is_default;
+ gchar *sortable;
+ GtkWidget *widget_description;
+ GtkWidget *widget_image;
+ GtkWidget *widget_info;
+ GSettings *settings;
+};
+
+#define GCM_SETTINGS_RECALIBRATE_PRINTER_THRESHOLD "recalibrate-printer-threshold"
+#define GCM_SETTINGS_RECALIBRATE_DISPLAY_THRESHOLD "recalibrate-display-threshold"
+
+
+#define IMAGE_WIDGET_PADDING 12
+
+G_DEFINE_TYPE (CcColorProfile, cc_color_profile, GTK_TYPE_LIST_BOX_ROW)
+
+enum
+{
+ PROP_0,
+ PROP_DEVICE,
+ PROP_PROFILE,
+ PROP_IS_DEFAULT,
+ PROP_LAST
+};
+
+static gchar *
+cc_color_profile_get_profile_date (CdProfile *profile)
+{
+ gint64 created;
+ g_autoptr(GDateTime) dt = NULL;
+
+ /* get profile age */
+ created = cd_profile_get_created (profile);
+ if (created == 0)
+ return NULL;
+ dt = g_date_time_new_from_unix_utc (created);
+ return g_date_time_format (dt, "%x");
+}
+
+static gchar *
+gcm_prefs_get_profile_title (CdProfile *profile)
+{
+ CdColorspace colorspace;
+ const gchar *tmp;
+ GString *str;
+
+ str = g_string_new ("");
+
+ /* add date only if it's a calibration profile or the profile has
+ * not been tagged with this data */
+ tmp = cd_profile_get_metadata_item (profile, CD_PROFILE_METADATA_DATA_SOURCE);
+ if (tmp == NULL || g_strcmp0 (tmp, CD_PROFILE_METADATA_DATA_SOURCE_CALIB) == 0)
+ {
+ tmp = cc_color_profile_get_profile_date (profile);
+ if (tmp != NULL)
+ g_string_append_printf (str, "%s - ", tmp);
+ }
+ else if (g_strcmp0 (tmp, CD_PROFILE_METADATA_DATA_SOURCE_STANDARD) == 0)
+ {
+ /* TRANSLATORS: standard spaces are well known colorspaces like
+ * sRGB, AdobeRGB and ProPhotoRGB */
+ g_string_append_printf (str, "%s - ", _("Standard Space"));
+ }
+ else if (g_strcmp0 (tmp, CD_PROFILE_METADATA_DATA_SOURCE_TEST) == 0)
+ {
+ /* TRANSLATORS: test profiles do things like changing the screen
+ * a different color, or swap the red and green channels */
+ g_string_append_printf (str, "%s - ", _("Test Profile"));
+ }
+ else if (g_strcmp0 (tmp, CD_PROFILE_METADATA_DATA_SOURCE_EDID) == 0)
+ {
+ /* TRANSLATORS: automatic profiles are generated automatically
+ * by the color management system based on manufacturing data,
+ * for instance the default monitor profile is created from the
+ * primaries specified in the monitor EDID */
+ g_string_append_printf (str, "%s - ", C_("Automatically generated profile", "Automatic"));
+ }
+
+ /* add quality if it exists */
+ tmp = cd_profile_get_metadata_item (profile, CD_PROFILE_METADATA_QUALITY);
+ if (g_strcmp0 (tmp, CD_PROFILE_METADATA_QUALITY_LOW) == 0)
+ {
+ /* TRANSLATORS: the profile quality - low quality profiles take
+ * much less time to generate but may be a poor reflection of the
+ * device capability */
+ g_string_append_printf (str, "%s - ", C_("Profile quality", "Low Quality"));
+ }
+ else if (g_strcmp0 (tmp, CD_PROFILE_METADATA_QUALITY_MEDIUM) == 0)
+ {
+ /* TRANSLATORS: the profile quality */
+ g_string_append_printf (str, "%s - ", C_("Profile quality", "Medium Quality"));
+ }
+ else if (g_strcmp0 (tmp, CD_PROFILE_METADATA_QUALITY_HIGH) == 0)
+ {
+ /* TRANSLATORS: the profile quality - high quality profiles take
+ * a *long* time, and have the best calibration and
+ * characterisation data. */
+ g_string_append_printf (str, "%s - ", C_("Profile quality", "High Quality"));
+ }
+
+ /* add profile description */
+ tmp = cd_profile_get_title (profile);
+ if (tmp != NULL)
+ {
+ g_string_append (str, tmp);
+ goto out;
+ }
+
+ /* some meta profiles do not have ICC profiles */
+ colorspace = cd_profile_get_colorspace (profile);
+ if (colorspace == CD_COLORSPACE_RGB)
+ {
+ /* TRANSLATORS: this default RGB space is used for printers that
+ * do not have additional printer profiles specified in the PPD */
+ g_string_append (str, C_("Colorspace fallback", "Default RGB"));
+ goto out;
+ }
+ if (colorspace == CD_COLORSPACE_CMYK)
+ {
+ /* TRANSLATORS: this default CMYK space is used for printers that
+ * do not have additional printer profiles specified in the PPD */
+ g_string_append (str, C_("Colorspace fallback", "Default CMYK"));
+ goto out;
+ }
+ if (colorspace == CD_COLORSPACE_GRAY)
+ {
+ /* TRANSLATORS: this default gray space is used for printers that
+ * do not have additional printer profiles specified in the PPD */
+ g_string_append (str, C_("Colorspace fallback", "Default Gray"));
+ goto out;
+ }
+
+ /* fall back to ID, ick */
+ tmp = g_strdup (cd_profile_get_id (profile));
+ g_string_append (str, tmp);
+out:
+ return g_string_free (str, FALSE);
+}
+
+static const gchar *
+cc_color_profile_get_warnings (CcColorProfile *color_profile)
+{
+ const gchar *tooltip = NULL;
+ const guint seconds_in_one_day = 60 * 60 * 24;
+ gint num_days;
+ guint threshold_days = 0;
+
+ /* autogenerated printer defaults */
+ if (cd_device_get_kind (color_profile->device) == CD_DEVICE_KIND_PRINTER &&
+ cd_profile_get_filename (color_profile->profile) == NULL)
+ {
+ tooltip = _("Vendor supplied factory calibration data");
+ goto out;
+ }
+
+ /* autogenerated profiles are crap */
+ if (cd_device_get_kind (color_profile->device) == CD_DEVICE_KIND_DISPLAY &&
+ cd_profile_get_kind (color_profile->profile) == CD_PROFILE_KIND_DISPLAY_DEVICE &&
+ !cd_profile_get_has_vcgt (color_profile->profile))
+ {
+ tooltip = _("Full-screen display correction not possible with this profile");
+ goto out;
+ }
+
+ /* greater than the calibration threshold for the device type */
+ num_days = cd_profile_get_age (color_profile->profile) / seconds_in_one_day;
+ if (cd_device_get_kind (color_profile->device) == CD_DEVICE_KIND_DISPLAY)
+ {
+ g_settings_get (color_profile->settings,
+ GCM_SETTINGS_RECALIBRATE_DISPLAY_THRESHOLD,
+ "u",
+ &threshold_days);
+ }
+ else if (cd_device_get_kind (color_profile->device) == CD_DEVICE_KIND_DISPLAY)
+ {
+ g_settings_get (color_profile->settings,
+ GCM_SETTINGS_RECALIBRATE_PRINTER_THRESHOLD,
+ "u",
+ &threshold_days);
+ }
+ if (threshold_days > 0 && num_days > threshold_days)
+ {
+ tooltip = _("This profile may no longer be accurate");
+ goto out;
+ }
+out:
+ return tooltip;
+}
+
+static void
+cc_color_profile_refresh (CcColorProfile *color_profile)
+{
+ const gchar *warnings;
+ g_autofree gchar *title = NULL;
+
+ /* show the image if the profile is default */
+ gtk_widget_set_visible (color_profile->widget_image, color_profile->is_default);
+ gtk_widget_set_margin_start (color_profile->widget_description,
+ color_profile->is_default ? 0 : IMAGE_WIDGET_PADDING * 4);
+
+ /* set the title */
+ title = gcm_prefs_get_profile_title (color_profile->profile);
+ gtk_label_set_markup (GTK_LABEL (color_profile->widget_description), title);
+
+ /* show any information */
+ warnings = cc_color_profile_get_warnings (color_profile);
+ gtk_widget_set_visible (color_profile->widget_info, warnings != NULL);
+ gtk_widget_set_tooltip_text (color_profile->widget_info, warnings);
+}
+
+CdDevice *
+cc_color_profile_get_device (CcColorProfile *color_profile)
+{
+ g_return_val_if_fail (CC_IS_COLOR_PROFILE (color_profile), NULL);
+ return color_profile->device;
+}
+
+CdProfile *
+cc_color_profile_get_profile (CcColorProfile *color_profile)
+{
+ g_return_val_if_fail (CC_IS_COLOR_PROFILE (color_profile), NULL);
+ return color_profile->profile;
+}
+
+const gchar *
+cc_color_profile_get_sortable (CcColorProfile *color_profile)
+{
+ g_return_val_if_fail (CC_IS_COLOR_PROFILE (color_profile), NULL);
+ return color_profile->sortable;
+}
+
+gboolean
+cc_color_profile_get_is_default (CcColorProfile *color_profile)
+{
+ g_return_val_if_fail (CC_IS_COLOR_PROFILE (color_profile), 0);
+ return color_profile->is_default;
+}
+
+void
+cc_color_profile_set_is_default (CcColorProfile *color_profile, gboolean is_default)
+{
+ g_return_if_fail (CC_IS_COLOR_PROFILE (color_profile));
+ color_profile->is_default = is_default;
+ cc_color_profile_refresh (color_profile);
+}
+
+static void
+cc_color_profile_get_property (GObject *object, guint param_id,
+ GValue *value, GParamSpec *pspec)
+{
+ CcColorProfile *color_profile = CC_COLOR_PROFILE (object);
+ switch (param_id)
+ {
+ case PROP_DEVICE:
+ g_value_set_object (value, color_profile->device);
+ break;
+ case PROP_PROFILE:
+ g_value_set_object (value, color_profile->profile);
+ break;
+ case PROP_IS_DEFAULT:
+ g_value_set_boolean (value, color_profile->is_default);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_color_profile_set_property (GObject *object, guint param_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ CcColorProfile *color_profile = CC_COLOR_PROFILE (object);
+
+ switch (param_id)
+ {
+ case PROP_DEVICE:
+ color_profile->device = g_value_dup_object (value);
+ break;
+ case PROP_PROFILE:
+ color_profile->profile = g_value_dup_object (value);
+ break;
+ case PROP_IS_DEFAULT:
+ color_profile->is_default = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_color_profile_finalize (GObject *object)
+{
+ CcColorProfile *color_profile = CC_COLOR_PROFILE (object);
+
+ g_free (color_profile->sortable);
+ g_object_unref (color_profile->device);
+ g_object_unref (color_profile->profile);
+ g_object_unref (color_profile->settings);
+
+ G_OBJECT_CLASS (cc_color_profile_parent_class)->finalize (object);
+}
+
+static void
+cc_color_profile_changed_cb (CcColorProfile *color_profile)
+{
+ g_autoptr(CdProfile) profile = NULL;
+
+ /* check to see if the default has changed */
+ profile = cd_device_get_default_profile (color_profile->device);
+ if (profile != NULL)
+ color_profile->is_default = g_strcmp0 (cd_profile_get_object_path (profile),
+ cd_profile_get_object_path (color_profile->profile)) == 0;
+ cc_color_profile_refresh (color_profile);
+}
+
+static const gchar *
+cc_color_profile_get_profile_sort_data_source (CdProfile *profile)
+{
+ const gchar *tmp;
+ tmp = cd_profile_get_metadata_item (profile, CD_PROFILE_METADATA_DATA_SOURCE);
+ if (tmp == NULL)
+ return "9";
+ if (g_strcmp0 (tmp, CD_PROFILE_METADATA_DATA_SOURCE_CALIB) == 0)
+ return "3";
+ if (g_strcmp0 (tmp, CD_PROFILE_METADATA_DATA_SOURCE_STANDARD) == 0)
+ return "2";
+ if (g_strcmp0 (tmp, CD_PROFILE_METADATA_DATA_SOURCE_TEST) == 0)
+ return "1";
+ return "0";
+}
+
+static void
+cc_color_profile_constructed (GObject *object)
+{
+ CcColorProfile *color_profile = CC_COLOR_PROFILE (object);
+ const gchar *sortable_data_source;
+ g_autofree gchar *sortable_device = NULL;
+ g_autofree gchar *title = NULL;
+
+ /* watch to see if the default changes */
+ g_signal_connect_object (color_profile->device, "changed",
+ G_CALLBACK (cc_color_profile_changed_cb), color_profile, G_CONNECT_SWAPPED);
+ g_signal_connect_object (color_profile->profile, "changed",
+ G_CALLBACK (cc_color_profile_changed_cb), color_profile, G_CONNECT_SWAPPED);
+
+ /* sort the profiles in the list by:
+ * 1. their device (required)
+ * 2. the data source (so calibration profiles are listed before autogenerated ones)
+ * 3. the date the profiles were created (newest first)
+ * 4. the alpha sorting of the filename
+ */
+ title = gcm_prefs_get_profile_title (color_profile->profile);
+ sortable_device = cc_color_device_get_sortable_base (color_profile->device);
+ sortable_data_source = cc_color_profile_get_profile_sort_data_source (color_profile->profile);
+ color_profile->sortable = g_strdup_printf ("%s-%s-%012" G_GINT64_FORMAT "-%s",
+ sortable_device,
+ sortable_data_source,
+ cd_profile_get_created (color_profile->profile),
+ title);
+
+ cc_color_profile_refresh (color_profile);
+}
+
+static void
+cc_color_profile_class_init (CcColorProfileClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->get_property = cc_color_profile_get_property;
+ object_class->set_property = cc_color_profile_set_property;
+ object_class->constructed = cc_color_profile_constructed;
+ object_class->finalize = cc_color_profile_finalize;
+
+ g_object_class_install_property (object_class, PROP_DEVICE,
+ g_param_spec_object ("device", NULL,
+ NULL,
+ CD_TYPE_DEVICE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class, PROP_PROFILE,
+ g_param_spec_object ("profile", NULL,
+ NULL,
+ CD_TYPE_PROFILE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class, PROP_IS_DEFAULT,
+ g_param_spec_boolean ("is-default", NULL,
+ NULL,
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+cc_color_profile_init (CcColorProfile *color_profile)
+{
+ GtkWidget *box;
+
+ color_profile->settings = g_settings_new (GCM_SETTINGS_SCHEMA);
+
+ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 9);
+
+ /* default tick */
+ color_profile->widget_image = gtk_image_new_from_icon_name ("object-select-symbolic");
+ gtk_widget_set_margin_start (color_profile->widget_image, IMAGE_WIDGET_PADDING);
+ gtk_widget_set_margin_end (color_profile->widget_image, IMAGE_WIDGET_PADDING);
+ gtk_box_append (GTK_BOX (box), color_profile->widget_image);
+
+ /* description */
+ color_profile->widget_description = gtk_label_new ("");
+ gtk_widget_set_margin_top (color_profile->widget_description, 9);
+ gtk_widget_set_margin_bottom (color_profile->widget_description, 9);
+ gtk_widget_set_halign (color_profile->widget_description, GTK_ALIGN_START);
+ gtk_label_set_ellipsize (GTK_LABEL (color_profile->widget_description), PANGO_ELLIPSIZE_END);
+ gtk_label_set_xalign (GTK_LABEL (color_profile->widget_description), 0);
+ gtk_widget_set_hexpand (color_profile->widget_description, TRUE);
+ gtk_widget_set_vexpand (color_profile->widget_description, TRUE);
+ gtk_box_append (GTK_BOX (box), color_profile->widget_description);
+
+ /* profile warnings/info */
+ color_profile->widget_info = gtk_image_new_from_icon_name ("dialog-information-symbolic");
+ gtk_widget_set_margin_start (color_profile->widget_info, IMAGE_WIDGET_PADDING);
+ gtk_widget_set_margin_end (color_profile->widget_info, IMAGE_WIDGET_PADDING);
+ gtk_box_append (GTK_BOX (box), color_profile->widget_info);
+
+ /* refresh */
+ gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (color_profile), box);
+}
+
+GtkWidget *
+cc_color_profile_new (CdDevice *device,
+ CdProfile *profile,
+ gboolean is_default)
+{
+ return g_object_new (CC_TYPE_COLOR_PROFILE,
+ "device", device,
+ "profile", profile,
+ "is-default", is_default,
+ NULL);
+}
+
diff --git a/panels/color/cc-color-profile.h b/panels/color/cc-color-profile.h
new file mode 100644
index 0000000..c749add
--- /dev/null
+++ b/panels/color/cc-color-profile.h
@@ -0,0 +1,43 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <colord.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_COLOR_PROFILE (cc_color_profile_get_type ())
+G_DECLARE_FINAL_TYPE (CcColorProfile, cc_color_profile, CC, COLOR_PROFILE, GtkListBoxRow)
+
+GtkWidget *cc_color_profile_new (CdDevice *device,
+ CdProfile *profile,
+ gboolean is_default);
+gboolean cc_color_profile_get_is_default (CcColorProfile *color_profile);
+void cc_color_profile_set_is_default (CcColorProfile *color_profile,
+ gboolean profile_is_default);
+CdDevice *cc_color_profile_get_device (CcColorProfile *color_profile);
+CdProfile *cc_color_profile_get_profile (CcColorProfile *color_profile);
+const gchar *cc_color_profile_get_sortable (CcColorProfile *color_profile);
+
+G_END_DECLS
+
diff --git a/panels/color/color.gresource.xml b/panels/color/color.gresource.xml
new file mode 100644
index 0000000..04cf9b3
--- /dev/null
+++ b/panels/color/color.gresource.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/color">
+ <file preprocess="xml-stripblanks">cc-color-calibrate.ui</file>
+ <file preprocess="xml-stripblanks">cc-color-panel.ui</file>
+ </gresource>
+</gresources>
diff --git a/panels/color/gnome-color-panel.desktop.in.in b/panels/color/gnome-color-panel.desktop.in.in
new file mode 100644
index 0000000..75e3f2c
--- /dev/null
+++ b/panels/color/gnome-color-panel.desktop.in.in
@@ -0,0 +1,20 @@
+[Desktop Entry]
+Name=Color
+Comment=Calibrate the color of your devices, such as displays, cameras or printers
+Exec=gnome-control-center color
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-color-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;X-GNOME-Settings-Panel;HardwareSettings;X-GNOME-DevicesSettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=color
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: Search terms to find the Color panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=Color;ICC;Profile;Calibrate;Printer;Display;
+# Notifications are emitted by gnome-settings-daemon
+X-GNOME-UsesNotifications=true
diff --git a/panels/color/icons/meson.build b/panels/color/icons/meson.build
new file mode 100644
index 0000000..5dfae21
--- /dev/null
+++ b/panels/color/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-color-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/color/icons/scalable/org.gnome.Settings-color-symbolic.svg b/panels/color/icons/scalable/org.gnome.Settings-color-symbolic.svg
new file mode 100644
index 0000000..9c1ec0c
--- /dev/null
+++ b/panels/color/icons/scalable/org.gnome.Settings-color-symbolic.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <g fill="#2e3434">
+ <path d="m 8.085938 0.015625 c -2.203126 0 -4 1.796875 -4 4 s 1.796874 4 4 4 c 2.203124 0 4 -1.796875 4 -4 s -1.796876 -4 -4 -4 z m 0 1.972656 c 1.121093 -0.003906 2.03125 0.90625 2.027343 2.027344 c 0.003907 1.121094 -0.90625 2.03125 -2.027343 2.027344 c -1.121094 0.003906 -2.027344 -0.90625 -2.027344 -2.027344 s 0.90625 -2.03125 2.027344 -2.027344 z m 0 0"/>
+ <path d="m 4.070312 7.015625 c -2.21875 0 -4.0312495 1.8125 -4.0312495 4.03125 s 1.8124995 4.03125 4.0312495 4.03125 c 2.222657 0 4.03125 -1.8125 4.03125 -4.03125 s -1.808593 -4.03125 -4.03125 -4.03125 z m 0 1.988281 c 1.132813 -0.003906 2.046876 0.914063 2.042969 2.042969 c 0.003907 1.128906 -0.910156 2.046875 -2.042969 2.042969 c -1.128906 0.003906 -2.042968 -0.914063 -2.042968 -2.042969 s 0.914062 -2.046875 2.042968 -2.042969 z m 0 0"/>
+ <path d="m 15.992188 11 c 0 2.207031 -1.789063 4 -4 4 c -2.207032 0 -4 -1.789062 -4 -4 s 1.792968 -4 4 -4 c 2.210937 0 4 1.792969 4 4 z m 0 0"/>
+ <path d="m 6.898438 11 c 0 1.554688 -1.257813 2.8125 -2.8125 2.8125 c -1.550782 0 -2.8125 -1.257812 -2.8125 -2.8125 s 1.261718 -2.8125 2.8125 -2.8125 c 1.554687 0 2.8125 1.257812 2.8125 2.8125 z m 0 0" fill-opacity="0.5"/>
+ </g>
+</svg>
diff --git a/panels/color/meson.build b/panels/color/meson.build
new file mode 100644
index 0000000..9368ae9
--- /dev/null
+++ b/panels/color/meson.build
@@ -0,0 +1,56 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+sources = files(
+ 'cc-color-panel.c',
+ 'cc-color-calibrate.c',
+ 'cc-color-cell-renderer-text.c',
+ 'cc-color-common.c',
+ 'cc-color-device.c',
+ 'cc-color-profile.c'
+)
+
+resource_data = files(
+ 'cc-color-calibrate.ui',
+ 'cc-color-panel.ui',
+)
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname,
+ dependencies: resource_data,
+ export: true
+)
+
+deps = common_deps + [
+ colord_dep,
+ gnome_rr_dep,
+ m_dep,
+ dependency('colord-gtk4', version: '>= 0.1.24'),
+]
+
+panels_libs += static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [ top_inc, common_inc ],
+ dependencies: deps,
+ c_args: cflags
+)
+
+subdir('icons')
diff --git a/panels/common/cc-common-language.c b/panels/common/cc-common-language.c
new file mode 100644
index 0000000..9357c3e
--- /dev/null
+++ b/panels/common/cc-common-language.c
@@ -0,0 +1,304 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2009-2010 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <locale.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <fontconfig/fontconfig.h>
+
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnome-desktop/gnome-languages.h>
+
+#include "cc-common-language.h"
+#include "shell/cc-object-storage.h"
+
+static char *get_lang_for_user_object_path (const char *path);
+
+static gboolean
+iter_for_language (GtkTreeModel *model,
+ const gchar *lang,
+ GtkTreeIter *iter,
+ gboolean region)
+{
+ g_autofree gchar *name = NULL;
+
+ g_assert (gtk_tree_model_get_iter_first (model, iter));
+ do {
+ g_autofree gchar *l = NULL;
+ gtk_tree_model_get (model, iter, LOCALE_COL, &l, -1);
+ if (g_strcmp0 (l, lang) == 0)
+ return TRUE;
+ } while (gtk_tree_model_iter_next (model, iter));
+
+ name = gnome_normalize_locale (lang);
+ if (name != NULL) {
+ g_autofree gchar *language = NULL;
+
+ if (region) {
+ language = gnome_get_country_from_locale (name, NULL);
+ }
+ else {
+ language = gnome_get_language_from_locale (name, NULL);
+ }
+
+ gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
+ iter,
+ -1,
+ LOCALE_COL, name,
+ DISPLAY_LOCALE_COL, language,
+ -1);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gboolean
+cc_common_language_get_iter_for_language (GtkTreeModel *model,
+ const gchar *lang,
+ GtkTreeIter *iter)
+{
+ return iter_for_language (model, lang, iter, FALSE);
+}
+
+gboolean
+cc_common_language_has_font (const gchar *locale)
+{
+ const FcCharSet *charset;
+ FcPattern *pattern;
+ FcObjectSet *object_set;
+ FcFontSet *font_set;
+ g_autofree gchar *language_code = NULL;
+ gboolean is_displayable;
+
+ is_displayable = FALSE;
+ pattern = NULL;
+ object_set = NULL;
+ font_set = NULL;
+
+ if (!gnome_parse_locale (locale, &language_code, NULL, NULL, NULL))
+ return FALSE;
+
+ charset = FcLangGetCharSet ((FcChar8 *) language_code);
+ if (!charset) {
+ /* fontconfig does not know about this language */
+ is_displayable = TRUE;
+ }
+ else {
+ /* see if any fonts support rendering it */
+ pattern = FcPatternBuild (NULL, FC_LANG, FcTypeString, language_code, NULL);
+
+ if (pattern == NULL)
+ goto done;
+
+ object_set = FcObjectSetCreate ();
+
+ if (object_set == NULL)
+ goto done;
+
+ font_set = FcFontList (NULL, pattern, object_set);
+
+ if (font_set == NULL)
+ goto done;
+
+ is_displayable = (font_set->nfont > 0);
+ }
+
+ done:
+ if (font_set != NULL)
+ FcFontSetDestroy (font_set);
+
+ if (object_set != NULL)
+ FcObjectSetDestroy (object_set);
+
+ if (pattern != NULL)
+ FcPatternDestroy (pattern);
+
+ return is_displayable;
+}
+
+gchar *
+cc_common_language_get_current_language (void)
+{
+ gchar *language;
+ g_autofree gchar *path = NULL;
+ const gchar *locale;
+
+ path = g_strdup_printf ("/org/freedesktop/Accounts/User%d", getuid ());
+ language = get_lang_for_user_object_path (path);
+ if (language != NULL && *language != '\0')
+ return language;
+
+ locale = (const gchar *) setlocale (LC_MESSAGES, NULL);
+ if (locale)
+ language = gnome_normalize_locale (locale);
+ else
+ language = NULL;
+
+ return language;
+}
+
+static char *
+get_lang_for_user_object_path (const char *path)
+{
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GDBusProxy) user = NULL;
+ g_autoptr(GVariant) props = NULL;
+ char *lang;
+
+ user = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "org.freedesktop.Accounts",
+ path,
+ "org.freedesktop.Accounts.User",
+ NULL,
+ &error);
+ if (user == NULL) {
+ g_warning ("Failed to get proxy for user '%s': %s",
+ path, error->message);
+ return NULL;
+ }
+
+ props = g_dbus_proxy_get_cached_property (user, "Language");
+ if (props == NULL)
+ return NULL;
+ lang = g_variant_dup_string (props, NULL);
+
+ return lang;
+}
+
+/*
+ * Note that @lang needs to be formatted like the locale strings
+ * returned by gnome_get_all_locales().
+ */
+static void
+insert_language (GHashTable *ht,
+ const char *lang)
+{
+ g_autofree gchar *label_own_lang = NULL;
+ g_autofree gchar *label_current_lang = NULL;
+ g_autofree gchar *label_untranslated = NULL;
+
+ label_own_lang = gnome_get_language_from_locale (lang, lang);
+ label_current_lang = gnome_get_language_from_locale (lang, NULL);
+ label_untranslated = gnome_get_language_from_locale (lang, "C");
+
+ /* We don't have a translation for the label in
+ * its own language? */
+ if (g_strcmp0 (label_own_lang, label_untranslated) == 0) {
+ if (g_strcmp0 (label_current_lang, label_untranslated) == 0)
+ g_hash_table_insert (ht, g_strdup (lang), g_strdup (label_untranslated));
+ else
+ g_hash_table_insert (ht, g_strdup (lang), g_strdup (label_current_lang));
+ } else {
+ g_hash_table_insert (ht, g_strdup (lang), g_strdup (label_own_lang));
+ }
+}
+
+GHashTable *
+cc_common_language_get_initial_languages (void)
+{
+ GHashTable *ht;
+
+ ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ insert_language (ht, "en_US.UTF-8");
+ insert_language (ht, "en_GB.UTF-8");
+ insert_language (ht, "de_DE.UTF-8");
+ insert_language (ht, "fr_FR.UTF-8");
+ insert_language (ht, "es_ES.UTF-8");
+ insert_language (ht, "zh_CN.UTF-8");
+ insert_language (ht, "ja_JP.UTF-8");
+ insert_language (ht, "ru_RU.UTF-8");
+ insert_language (ht, "ar_EG.UTF-8");
+
+ return ht;
+}
+
+static void
+foreach_user_lang_cb (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ GtkListStore *store = (GtkListStore *) user_data;
+ const char *locale = (const char *) key;
+ const char *display_locale = (const char *) value;
+ GtkTreeIter iter;
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ LOCALE_COL, locale,
+ DISPLAY_LOCALE_COL, display_locale,
+ -1);
+}
+
+void
+cc_common_language_add_user_languages (GtkTreeModel *model)
+{
+ g_autofree gchar *name = NULL;
+ GtkTreeIter iter;
+ GtkListStore *store = GTK_LIST_STORE (model);
+ GHashTable *user_langs;
+ const char *display;
+
+ gtk_list_store_clear (store);
+
+ user_langs = cc_common_language_get_initial_languages ();
+
+ /* Add the current locale first */
+ name = cc_common_language_get_current_language ();
+ display = g_hash_table_lookup (user_langs, name);
+ if (!display) {
+ g_autofree gchar *language = NULL;
+ g_autofree gchar *country = NULL;
+ g_autofree gchar *codeset = NULL;
+
+ gnome_parse_locale (name, &language, &country, &codeset, NULL);
+
+ if (!codeset || !g_str_equal (codeset, "UTF-8"))
+ g_warning ("Current user locale codeset isn't UTF-8");
+
+ g_free (name);
+ name = g_strdup_printf ("%s_%s.UTF-8", language, country);
+
+ insert_language (user_langs, name);
+ display = g_hash_table_lookup (user_langs, name);
+ }
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, LOCALE_COL, name, DISPLAY_LOCALE_COL, display, -1);
+ g_hash_table_remove (user_langs, name);
+
+ /* The rest of the languages */
+ g_hash_table_foreach (user_langs, (GHFunc) foreach_user_lang_cb, store);
+
+ /* And now the "Other…" selection */
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, LOCALE_COL, NULL, DISPLAY_LOCALE_COL, _("Other…"), -1);
+
+ g_hash_table_destroy (user_langs);
+}
+
diff --git a/panels/common/cc-common-language.h b/panels/common/cc-common-language.h
new file mode 100644
index 0000000..1f578b7
--- /dev/null
+++ b/panels/common/cc-common-language.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2009-2010 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+enum {
+ LOCALE_COL,
+ DISPLAY_LOCALE_COL,
+ SEPARATOR_COL,
+ USER_LANGUAGE,
+ NUM_COLS
+};
+
+gboolean cc_common_language_get_iter_for_language (GtkTreeModel *model,
+ const gchar *lang,
+ GtkTreeIter *iter);
+gboolean cc_common_language_get_iter_for_region (GtkTreeModel *model,
+ const gchar *lang,
+ GtkTreeIter *iter);
+guint cc_common_language_add_available_languages (GtkListStore *store,
+ gboolean regions,
+ GHashTable *user_langs);
+gboolean cc_common_language_has_font (const gchar *locale);
+gchar *cc_common_language_get_current_language (void);
+
+GHashTable *cc_common_language_get_initial_languages (void);
+GHashTable *cc_common_language_get_user_languages (void);
+GHashTable *cc_common_language_get_initial_regions (const gchar *lang);
+
+void cc_common_language_setup_list (GtkWidget *treeview,
+ GHashTable *users,
+ GHashTable *initial);
+void cc_common_language_select_current_language (GtkTreeView *treeview);
+
+void cc_common_language_add_user_languages (GtkTreeModel *model);
+
+G_END_DECLS
diff --git a/panels/common/cc-hostname-entry.c b/panels/common/cc-hostname-entry.c
new file mode 100644
index 0000000..8a79b03
--- /dev/null
+++ b/panels/common/cc-hostname-entry.c
@@ -0,0 +1,265 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2013 Intel, Inc
+ * Copyright (C) 2011,2012 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "cc-common-resources.h"
+#include "cc-hostname-entry.h"
+#include "hostname-helper.h"
+
+#include <polkit/polkit.h>
+
+struct _CcHostnameEntry
+{
+ GtkEntry parent;
+
+ GDBusProxy *hostnamed_proxy;
+ guint set_hostname_timeout_source_id;
+};
+
+G_DEFINE_TYPE (CcHostnameEntry, cc_hostname_entry, GTK_TYPE_ENTRY)
+
+#define SET_HOSTNAME_TIMEOUT 1
+
+static void
+cc_hostname_entry_set_hostname (CcHostnameEntry *self)
+{
+ g_autofree gchar *hostname = NULL;
+ g_autoptr(GVariant) pretty_result = NULL;
+ g_autoptr(GVariant) static_result = NULL;
+ g_autoptr(GError) pretty_error = NULL;
+ g_autoptr(GError) static_error = NULL;
+ const gchar *text;
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self));
+
+ g_debug ("Setting PrettyHostname to '%s'", text);
+ pretty_result = g_dbus_proxy_call_sync (self->hostnamed_proxy,
+ "SetPrettyHostname",
+ g_variant_new ("(sb)", text, FALSE),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &pretty_error);
+ if (pretty_result == NULL)
+ g_warning ("Could not set PrettyHostname: %s", pretty_error->message);
+
+ /* Set the static hostname */
+ hostname = pretty_hostname_to_static (text, FALSE);
+ g_assert (hostname);
+
+ g_debug ("Setting StaticHostname to '%s'", hostname);
+ static_result = g_dbus_proxy_call_sync (self->hostnamed_proxy,
+ "SetStaticHostname",
+ g_variant_new ("(sb)", hostname, FALSE),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &static_error);
+ if (static_result == NULL)
+ g_warning ("Could not set StaticHostname: %s", static_error->message);
+}
+
+static char *
+get_hostname_property (CcHostnameEntry *self,
+ const char *property)
+{
+ g_autoptr(GVariant) variant = NULL;
+
+ if (!self->hostnamed_proxy)
+ return g_strdup ("");
+
+ variant = g_dbus_proxy_get_cached_property (self->hostnamed_proxy,
+ property);
+ if (!variant)
+ {
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) inner = NULL;
+
+ /* Work around systemd-hostname not sending us back
+ * the property value when changing values */
+ variant = g_dbus_proxy_call_sync (self->hostnamed_proxy,
+ "org.freedesktop.DBus.Properties.Get",
+ g_variant_new ("(ss)", "org.freedesktop.hostname1", property),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+ if (variant == NULL)
+ {
+ g_warning ("Failed to get property '%s': %s", property, error->message);
+ return NULL;
+ }
+
+ g_variant_get (variant, "(v)", &inner);
+ return g_variant_dup_string (inner, NULL);
+ }
+ else
+ {
+ return g_variant_dup_string (variant, NULL);
+ }
+}
+
+static char *
+cc_hostname_entry_get_display_hostname (CcHostnameEntry *self)
+{
+ g_autofree gchar *str = NULL;
+
+ str = get_hostname_property (self, "PrettyHostname");
+
+ /* Empty strings means that we need to fallback */
+ if (str != NULL &&
+ *str == '\0')
+ return get_hostname_property (self, "Hostname");
+
+ return g_steal_pointer (&str);
+}
+
+static gboolean
+set_hostname_timeout (CcHostnameEntry *self)
+{
+ self->set_hostname_timeout_source_id = 0;
+
+ cc_hostname_entry_set_hostname (self);
+
+ return FALSE;
+}
+
+static void
+remove_hostname_timeout (CcHostnameEntry *self)
+{
+ if (self->set_hostname_timeout_source_id)
+ g_source_remove (self->set_hostname_timeout_source_id);
+
+ self->set_hostname_timeout_source_id = 0;
+}
+
+static void
+reset_hostname_timeout (CcHostnameEntry *self)
+{
+ remove_hostname_timeout (self);
+
+ self->set_hostname_timeout_source_id = g_timeout_add_seconds (SET_HOSTNAME_TIMEOUT,
+ (GSourceFunc) set_hostname_timeout,
+ self);
+}
+
+static void
+text_changed_cb (CcHostnameEntry *entry)
+{
+ reset_hostname_timeout (entry);
+}
+
+static void
+cc_hostname_entry_dispose (GObject *object)
+{
+ CcHostnameEntry *self = CC_HOSTNAME_ENTRY (object);
+
+ if (self->set_hostname_timeout_source_id)
+ {
+ remove_hostname_timeout (self);
+ set_hostname_timeout (self);
+ }
+
+ g_clear_object (&self->hostnamed_proxy);
+
+ G_OBJECT_CLASS (cc_hostname_entry_parent_class)->dispose (object);
+}
+
+static void
+cc_hostname_entry_constructed (GObject *object)
+{
+ CcHostnameEntry *self = CC_HOSTNAME_ENTRY (object);
+ GPermission *permission;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *str = NULL;
+
+ permission = polkit_permission_new_sync ("org.freedesktop.hostname1.set-static-hostname",
+ NULL, NULL, NULL);
+
+ /* Is hostnamed installed? */
+ if (permission == NULL)
+ {
+ g_debug ("Will not show hostname, hostnamed not installed");
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
+
+ return;
+ }
+
+ if (g_permission_get_allowed (permission))
+ gtk_widget_set_sensitive (GTK_WIDGET (self), TRUE);
+ else
+ {
+ g_debug ("Not allowed to change the hostname");
+ gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
+ }
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self),
+ g_permission_get_allowed (permission));
+
+ self->hostnamed_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.freedesktop.hostname1",
+ "/org/freedesktop/hostname1",
+ "org.freedesktop.hostname1",
+ NULL,
+ &error);
+
+ /* This could only happen if the policy file was installed
+ * but not hostnamed, which points to a system bug */
+ if (self->hostnamed_proxy == NULL)
+ {
+ g_debug ("Couldn't get hostnamed to start, bailing: %s", error->message);
+ return;
+ }
+
+ str = cc_hostname_entry_get_display_hostname (CC_HOSTNAME_ENTRY (self));
+
+ if (str != NULL)
+ gtk_editable_set_text (GTK_EDITABLE (self), str);
+ else
+ gtk_editable_set_text (GTK_EDITABLE (self), "");
+
+ g_signal_connect (self, "changed", G_CALLBACK (text_changed_cb), NULL);
+}
+
+static void
+cc_hostname_entry_class_init (CcHostnameEntryClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructed = cc_hostname_entry_constructed;
+ object_class->dispose = cc_hostname_entry_dispose;
+}
+
+static void
+cc_hostname_entry_init (CcHostnameEntry *self)
+{
+ g_resources_register (cc_common_get_resource ());
+}
+
+CcHostnameEntry *
+cc_hostname_entry_new (void)
+{
+ return g_object_new (CC_TYPE_HOSTNAME_ENTRY, NULL);
+}
+
+gchar*
+cc_hostname_entry_get_hostname (CcHostnameEntry *entry)
+{
+ return get_hostname_property (entry, "Hostname");
+}
diff --git a/panels/common/cc-hostname-entry.h b/panels/common/cc-hostname-entry.h
new file mode 100644
index 0000000..a481779
--- /dev/null
+++ b/panels/common/cc-hostname-entry.h
@@ -0,0 +1,33 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2013 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_HOSTNAME_ENTRY (cc_hostname_entry_get_type())
+
+G_DECLARE_FINAL_TYPE (CcHostnameEntry, cc_hostname_entry, CC, HOSTNAME_ENTRY, GtkEntry)
+
+CcHostnameEntry *cc_hostname_entry_new (void);
+gchar* cc_hostname_entry_get_hostname (CcHostnameEntry *entry);
+
+G_END_DECLS
diff --git a/panels/common/cc-language-chooser.c b/panels/common/cc-language-chooser.c
new file mode 100644
index 0000000..1aa2ec4
--- /dev/null
+++ b/panels/common/cc-language-chooser.c
@@ -0,0 +1,343 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2013 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#define _GNU_SOURCE
+#include <config.h>
+#include "cc-language-chooser.h"
+#include "cc-language-row.h"
+#include "cc-common-resources.h"
+
+#include <locale.h>
+#include <string.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+
+#include "cc-common-language.h"
+#include "cc-util.h"
+
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnome-desktop/gnome-languages.h>
+
+struct _CcLanguageChooser {
+ GtkDialog parent_instance;
+
+ GtkSearchEntry *language_filter_entry;
+ GtkListBox *language_listbox;
+ GtkListBoxRow *more_row;
+ GtkSearchBar *search_bar;
+ GtkButton *select_button;
+
+ gboolean showing_extra;
+ gchar *language;
+ gchar **filter_words;
+};
+
+G_DEFINE_TYPE (CcLanguageChooser, cc_language_chooser, GTK_TYPE_DIALOG)
+
+static void
+add_all_languages (CcLanguageChooser *self)
+{
+ g_auto(GStrv) locale_ids = NULL;
+ g_autoptr(GHashTable) initial = NULL;
+
+ locale_ids = gnome_get_all_locales ();
+ initial = cc_common_language_get_initial_languages ();
+ for (int i = 0; locale_ids[i] != NULL; i++) {
+ CcLanguageRow *row;
+ gboolean is_initial;
+
+ if (!cc_common_language_has_font (locale_ids[i]))
+ continue;
+
+ row = cc_language_row_new (locale_ids[i]);
+ gtk_widget_show (GTK_WIDGET (row));
+ is_initial = (g_hash_table_lookup (initial, locale_ids[i]) != NULL);
+ cc_language_row_set_is_extra (row, !is_initial);
+ gtk_list_box_prepend (self->language_listbox, GTK_WIDGET (row));
+ }
+}
+
+static gboolean
+match_all (gchar **words,
+ const gchar *str)
+{
+ gchar **w;
+
+ if (str == NULL)
+ return FALSE;
+
+ for (w = words; *w; ++w)
+ if (!strstr (str, *w))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+language_visible (GtkListBoxRow *row,
+ gpointer user_data)
+{
+ CcLanguageChooser *self = user_data;
+ g_autofree gchar *language = NULL;
+ g_autofree gchar *country = NULL;
+ g_autofree gchar *language_local = NULL;
+ g_autofree gchar *country_local = NULL;
+ gboolean visible;
+
+ if (row == self->more_row)
+ return !self->showing_extra;
+
+ if (!CC_IS_LANGUAGE_ROW (row))
+ return TRUE;
+
+ if (!self->showing_extra && cc_language_row_get_is_extra (CC_LANGUAGE_ROW (row)))
+ return FALSE;
+
+ if (!self->filter_words)
+ return TRUE;
+
+ language =
+ cc_util_normalize_casefold_and_unaccent (cc_language_row_get_language (CC_LANGUAGE_ROW (row)));
+ visible = match_all (self->filter_words, language);
+ if (visible)
+ return TRUE;
+
+ country =
+ cc_util_normalize_casefold_and_unaccent (cc_language_row_get_country (CC_LANGUAGE_ROW (row)));
+ visible = match_all (self->filter_words, country);
+ if (visible)
+ return TRUE;
+
+ language_local =
+ cc_util_normalize_casefold_and_unaccent (cc_language_row_get_language_local (CC_LANGUAGE_ROW (row)));
+ visible = match_all (self->filter_words, language_local);
+ if (visible)
+ return TRUE;
+
+ country_local =
+ cc_util_normalize_casefold_and_unaccent (cc_language_row_get_country_local (CC_LANGUAGE_ROW (row)));
+ return match_all (self->filter_words, country_local);
+}
+
+static gint
+sort_languages (GtkListBoxRow *a,
+ GtkListBoxRow *b,
+ gpointer data)
+{
+ int d;
+
+ if (!CC_IS_LANGUAGE_ROW (a))
+ return 1;
+ if (!CC_IS_LANGUAGE_ROW (b))
+ return -1;
+
+ d = g_strcmp0 (cc_language_row_get_language (CC_LANGUAGE_ROW (a)), cc_language_row_get_language (CC_LANGUAGE_ROW (b)));
+ if (d != 0)
+ return d;
+
+ return g_strcmp0 (cc_language_row_get_country (CC_LANGUAGE_ROW (a)), cc_language_row_get_country (CC_LANGUAGE_ROW (b)));
+}
+
+static void
+language_filter_entry_search_changed_cb (CcLanguageChooser *self)
+{
+ g_autofree gchar *filter_contents = NULL;
+
+ g_clear_pointer (&self->filter_words, g_strfreev);
+
+ filter_contents =
+ cc_util_normalize_casefold_and_unaccent (gtk_editable_get_text (GTK_EDITABLE (self->language_filter_entry)));
+ if (!filter_contents) {
+ gtk_list_box_invalidate_filter (self->language_listbox);
+ return;
+ }
+ self->filter_words = g_strsplit_set (g_strstrip (filter_contents), " ", 0);
+ gtk_list_box_invalidate_filter (self->language_listbox);
+}
+
+static void
+show_more (CcLanguageChooser *self, gboolean visible)
+{
+ gint width, height;
+
+ gtk_window_get_default_size (GTK_WINDOW (self), &width, &height);
+ gtk_widget_set_size_request (GTK_WIDGET (self), width, height);
+
+ gtk_search_bar_set_search_mode (self->search_bar, visible);
+ gtk_widget_grab_focus (visible ? GTK_WIDGET (self->language_filter_entry) : GTK_WIDGET (self->language_listbox));
+
+ self->showing_extra = visible;
+
+ gtk_list_box_invalidate_filter (self->language_listbox);
+}
+
+static void
+set_locale_id (CcLanguageChooser *self,
+ const gchar *locale_id)
+{
+ GtkWidget *child;
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->select_button), FALSE);
+
+ for (child = gtk_widget_get_first_child (GTK_WIDGET (self->language_listbox));
+ child;
+ child = gtk_widget_get_next_sibling (child)) {
+ CcLanguageRow *row;
+
+ if (!CC_IS_LANGUAGE_ROW (child))
+ continue;
+
+ row = CC_LANGUAGE_ROW (child);
+ if (g_strcmp0 (locale_id, cc_language_row_get_locale_id (row)) == 0) {
+ cc_language_row_set_checked (row, TRUE);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->select_button), TRUE);
+
+ /* make sure the selected language is shown */
+ if (!self->showing_extra && cc_language_row_get_is_extra (row)) {
+ cc_language_row_set_is_extra (row, FALSE);
+ gtk_list_box_invalidate_filter (self->language_listbox);
+ }
+ } else {
+ cc_language_row_set_checked (row, FALSE);
+ }
+ }
+
+ g_free (self->language);
+ self->language = g_strdup (locale_id);
+}
+
+static void
+language_listbox_row_activated_cb (CcLanguageChooser *self, GtkListBoxRow *row)
+{
+ const gchar *new_locale_id;
+
+ if (row == self->more_row) {
+ show_more (self, TRUE);
+ return;
+ }
+
+ if (!CC_IS_LANGUAGE_ROW (row))
+ return;
+
+ new_locale_id = cc_language_row_get_locale_id (CC_LANGUAGE_ROW (row));
+ if (g_strcmp0 (new_locale_id, self->language) == 0) {
+ gtk_dialog_response (GTK_DIALOG (self),
+ gtk_dialog_get_response_for_widget (GTK_DIALOG (self),
+ GTK_WIDGET (self->select_button)));
+ } else {
+ set_locale_id (self, new_locale_id);
+ }
+}
+
+static void
+activate_default_cb (CcLanguageChooser *self)
+{
+ GtkWidget *focus;
+
+ focus = gtk_window_get_focus (GTK_WINDOW (self));
+ if (!focus || !CC_IS_LANGUAGE_ROW (focus))
+ return;
+
+ if (g_strcmp0 (cc_language_row_get_locale_id (CC_LANGUAGE_ROW (focus)), self->language) == 0)
+ return;
+
+ g_signal_stop_emission_by_name (GTK_WINDOW (self), "activate-default");
+ gtk_widget_activate (focus);
+}
+
+void
+cc_language_chooser_init (CcLanguageChooser *self)
+{
+ g_resources_register (cc_common_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ gtk_list_box_set_sort_func (self->language_listbox,
+ sort_languages, self, NULL);
+ gtk_list_box_set_filter_func (self->language_listbox,
+ language_visible, self, NULL);
+ add_all_languages (self);
+
+ gtk_list_box_invalidate_filter (self->language_listbox);
+}
+
+static void
+cc_language_chooser_dispose (GObject *object)
+{
+ CcLanguageChooser *self = CC_LANGUAGE_CHOOSER (object);
+
+ g_clear_pointer (&self->filter_words, g_strfreev);
+ g_clear_pointer (&self->language, g_free);
+
+ G_OBJECT_CLASS (cc_language_chooser_parent_class)->dispose (object);
+}
+
+void
+cc_language_chooser_class_init (CcLanguageChooserClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_language_chooser_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/common/cc-language-chooser.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcLanguageChooser, language_filter_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcLanguageChooser, language_listbox);
+ gtk_widget_class_bind_template_child (widget_class, CcLanguageChooser, more_row);
+ gtk_widget_class_bind_template_child (widget_class, CcLanguageChooser, search_bar);
+ gtk_widget_class_bind_template_child (widget_class, CcLanguageChooser, select_button);
+
+ gtk_widget_class_bind_template_callback (widget_class, activate_default_cb);
+ gtk_widget_class_bind_template_callback (widget_class, language_filter_entry_search_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, language_listbox_row_activated_cb);
+}
+
+CcLanguageChooser *
+cc_language_chooser_new (void)
+{
+ return CC_LANGUAGE_CHOOSER (g_object_new (CC_TYPE_LANGUAGE_CHOOSER,
+ "use-header-bar", 1,
+ NULL));
+}
+
+void
+cc_language_chooser_clear_filter (CcLanguageChooser *self)
+{
+ g_return_if_fail (CC_IS_LANGUAGE_CHOOSER (self));
+ gtk_editable_set_text (GTK_EDITABLE (self->language_filter_entry), "");
+ show_more (self, FALSE);
+}
+
+const gchar *
+cc_language_chooser_get_language (CcLanguageChooser *self)
+{
+ g_return_val_if_fail (CC_IS_LANGUAGE_CHOOSER (self), NULL);
+ return self->language;
+}
+
+void
+cc_language_chooser_set_language (CcLanguageChooser *self,
+ const gchar *language)
+{
+ g_return_if_fail (CC_IS_LANGUAGE_CHOOSER (self));
+ set_locale_id (self, language);
+}
diff --git a/panels/common/cc-language-chooser.h b/panels/common/cc-language-chooser.h
new file mode 100644
index 0000000..8e050ee
--- /dev/null
+++ b/panels/common/cc-language-chooser.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2013 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_LANGUAGE_CHOOSER (cc_language_chooser_get_type ())
+G_DECLARE_FINAL_TYPE (CcLanguageChooser, cc_language_chooser, CC, LANGUAGE_CHOOSER, GtkDialog)
+
+CcLanguageChooser *cc_language_chooser_new (void);
+void cc_language_chooser_clear_filter (CcLanguageChooser *chooser);
+const gchar *cc_language_chooser_get_language (CcLanguageChooser *chooser);
+void cc_language_chooser_set_language (CcLanguageChooser *chooser,
+ const gchar *language);
+
+G_END_DECLS
diff --git a/panels/common/cc-language-chooser.ui b/panels/common/cc-language-chooser.ui
new file mode 100644
index 0000000..4efc9a8
--- /dev/null
+++ b/panels/common/cc-language-chooser.ui
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcLanguageChooser" parent="GtkDialog">
+ <property name="title" translatable="yes">Select Language</property>
+ <property name="modal">True</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="default_width">400</property>
+ <property name="default_height">475</property>
+ <signal name="activate-default" handler="activate_default_cb"/>
+ <child type="action">
+ <object class="GtkButton" id="select_button">
+ <property name="label" translatable="yes">_Select</property>
+ <property name="sensitive">False</property>
+ <property name="use_underline">True</property>
+ <property name="valign">center</property>
+ </object>
+ </child>
+ <child type="action">
+ <object class="GtkButton" id="cancel_button">
+ <property name="label" translatable="yes">_Cancel</property>
+ <property name="use_underline">True</property>
+ <property name="valign">center</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">0</property>
+ <child>
+ <object class="GtkSearchBar" id="search_bar">
+ <property name="hexpand">True</property>
+ <child>
+ <object class="GtkSearchEntry" id="language_filter_entry">
+ <property name="width_chars">30</property>
+ <signal name="search-changed" handler="language_filter_entry_search_changed_cb" object="CcLanguageChooser" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="hscrollbar-policy">never</property>
+ <property name="vscrollbar-policy">automatic</property>
+ <property name="propagate-natural-height">True</property>
+ <property name="min-content-height">200</property>
+ <child>
+ <object class="GtkListBox" id="language_listbox">
+ <property name="can-focus">True</property>
+ <property name="vexpand">True</property>
+ <property name="halign">fill</property>
+ <property name="valign">fill</property>
+ <property name="selection-mode">none</property>
+ <property name="show-separators">True</property>
+ <signal name="row-activated" handler="language_listbox_row_activated_cb" object="CcLanguageChooser" swapped="yes"/>
+ <child type="placeholder">
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">No languages found</property>
+ <property name="sensitive">False</property>
+ </object>
+ </child>
+
+ <!-- "More" row -->
+ <child>
+ <object class="GtkListBoxRow" id="more_row">
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">10</property>
+ <property name="tooltip_markup" translatable="yes">More…</property>
+ <child>
+ <object class="GtkImage">
+ <property name="hexpand">True</property>
+ <property name="halign">center</property>
+ <property name="icon-name">view-more-symbolic</property>
+ <property name="icon-size">1</property>
+ <property name="margin-top">10</property>
+ <property name="margin-bottom">10</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5" default="true">select_button</action-widget>
+ <action-widget response="-6">cancel_button</action-widget>
+ </action-widgets>
+ </template>
+</interface>
diff --git a/panels/common/cc-language-row.c b/panels/common/cc-language-row.c
new file mode 100644
index 0000000..a2832df
--- /dev/null
+++ b/panels/common/cc-language-row.c
@@ -0,0 +1,184 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2020 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cc-language-row.h"
+#include "cc-common-resources.h"
+
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnome-desktop/gnome-languages.h>
+
+struct _CcLanguageRow {
+ GtkListBoxRow parent_instance;
+
+ GtkImage *check_image;
+ GtkLabel *country_label;
+ GtkLabel *language_label;
+
+ gchar *locale_id;
+ gchar *language;
+ gchar *language_local;
+ gchar *country;
+ gchar *country_local;
+
+ gboolean is_extra;
+};
+
+G_DEFINE_TYPE (CcLanguageRow, cc_language_row, GTK_TYPE_LIST_BOX_ROW)
+
+static gchar *
+get_language_label (const gchar *language_code,
+ const gchar *modifier,
+ const gchar *locale_id)
+{
+ g_autofree gchar *language = NULL;
+
+ language = gnome_get_language_from_code (language_code, locale_id);
+
+ if (modifier == NULL)
+ return g_steal_pointer (&language);
+ else
+ {
+ g_autofree gchar *t_mod = gnome_get_translated_modifier (modifier, locale_id);
+ return g_strdup_printf ("%s — %s", language, t_mod);
+ }
+}
+
+static void
+cc_language_row_dispose (GObject *object)
+{
+ CcLanguageRow *self = CC_LANGUAGE_ROW (object);
+
+ g_clear_pointer (&self->locale_id, g_free);
+ g_clear_pointer (&self->country, g_free);
+ g_clear_pointer (&self->country_local, g_free);
+ g_clear_pointer (&self->language, g_free);
+ g_clear_pointer (&self->language_local, g_free);
+
+ G_OBJECT_CLASS (cc_language_row_parent_class)->dispose (object);
+}
+
+void
+cc_language_row_class_init (CcLanguageRowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_language_row_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/common/cc-language-row.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcLanguageRow, check_image);
+ gtk_widget_class_bind_template_child (widget_class, CcLanguageRow, country_label);
+ gtk_widget_class_bind_template_child (widget_class, CcLanguageRow, language_label);
+}
+
+void
+cc_language_row_init (CcLanguageRow *self)
+{
+ g_resources_register (cc_common_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+CcLanguageRow *
+cc_language_row_new (const gchar *locale_id)
+{
+ CcLanguageRow *self;
+ g_autofree gchar *language_code = NULL;
+ g_autofree gchar *country_code = NULL;
+ g_autofree gchar *modifier = NULL;
+
+ self = CC_LANGUAGE_ROW (g_object_new (CC_TYPE_LANGUAGE_ROW, NULL));
+ self->locale_id = g_strdup (locale_id);
+
+ gnome_parse_locale (locale_id, &language_code, &country_code, NULL, &modifier);
+
+ self->language = get_language_label (language_code, modifier, locale_id);
+ self->language_local = get_language_label (language_code, modifier, NULL);
+ gtk_label_set_label (self->language_label, self->language);
+
+ if (country_code == NULL)
+ {
+ self->country = NULL;
+ self->country_local = NULL;
+ }
+ else
+ {
+ self->country = gnome_get_country_from_code (country_code, locale_id);
+ self->country_local = gnome_get_country_from_code (country_code, NULL);
+ gtk_label_set_label (self->country_label, self->country);
+ }
+
+ return self;
+}
+
+const gchar *
+cc_language_row_get_locale_id (CcLanguageRow *self)
+{
+ g_return_val_if_fail (CC_IS_LANGUAGE_ROW (self), NULL);
+ return self->locale_id;
+}
+
+const gchar *
+cc_language_row_get_language (CcLanguageRow *self)
+{
+ g_return_val_if_fail (CC_IS_LANGUAGE_ROW (self), NULL);
+ return self->language;
+}
+
+const gchar *
+cc_language_row_get_language_local (CcLanguageRow *self)
+{
+ g_return_val_if_fail (CC_IS_LANGUAGE_ROW (self), NULL);
+ return self->language_local;
+}
+
+const gchar *
+cc_language_row_get_country (CcLanguageRow *self)
+{
+ g_return_val_if_fail (CC_IS_LANGUAGE_ROW (self), NULL);
+ return self->country;
+}
+
+const gchar *
+cc_language_row_get_country_local (CcLanguageRow *self)
+{
+ g_return_val_if_fail (CC_IS_LANGUAGE_ROW (self), NULL);
+ return self->country_local;
+}
+
+void
+cc_language_row_set_checked (CcLanguageRow *self, gboolean checked)
+{
+ g_return_if_fail (CC_IS_LANGUAGE_ROW (self));
+ gtk_widget_set_visible (GTK_WIDGET (self->check_image), checked);
+}
+
+void
+cc_language_row_set_is_extra (CcLanguageRow *self, gboolean is_extra)
+{
+ g_return_if_fail (CC_IS_LANGUAGE_ROW (self));
+ self->is_extra = is_extra;
+}
+
+gboolean
+cc_language_row_get_is_extra (CcLanguageRow *self)
+{
+ g_return_val_if_fail (CC_IS_LANGUAGE_ROW (self), FALSE);
+ return self->is_extra;
+}
diff --git a/panels/common/cc-language-row.h b/panels/common/cc-language-row.h
new file mode 100644
index 0000000..2e3e8cd
--- /dev/null
+++ b/panels/common/cc-language-row.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2020 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_LANGUAGE_ROW (cc_language_row_get_type ())
+G_DECLARE_FINAL_TYPE (CcLanguageRow, cc_language_row, CC, LANGUAGE_ROW, GtkListBoxRow)
+
+CcLanguageRow *cc_language_row_new (const gchar *locale_id);
+
+const gchar *cc_language_row_get_locale_id (CcLanguageRow *row);
+
+const gchar *cc_language_row_get_language (CcLanguageRow *row);
+
+const gchar *cc_language_row_get_language_local (CcLanguageRow *row);
+
+const gchar *cc_language_row_get_country (CcLanguageRow *row);
+
+const gchar *cc_language_row_get_country_local (CcLanguageRow *row);
+
+void cc_language_row_set_checked (CcLanguageRow *row, gboolean checked);
+
+void cc_language_row_set_is_extra (CcLanguageRow *row, gboolean is_extra);
+
+gboolean cc_language_row_get_is_extra (CcLanguageRow *row);
+
+G_END_DECLS
diff --git a/panels/common/cc-language-row.ui b/panels/common/cc-language-row.ui
new file mode 100644
index 0000000..957df54
--- /dev/null
+++ b/panels/common/cc-language-row.ui
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcLanguageRow" parent="GtkListBoxRow">
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">18</property>
+ <property name="margin-end">18</property>
+ <child>
+ <object class="GtkLabel" id="language_label">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="ellipsize">end</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage" id="check_image">
+ <property name="visible">False</property>
+ <property name="icon-name">object-select-symbolic</property>
+ <property name="icon-size">1</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="country_label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="ellipsize">end</property>
+ <property name="hexpand">True</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/common/cc-list-row.c b/panels/common/cc-list-row.c
new file mode 100644
index 0000000..6dc4388
--- /dev/null
+++ b/panels/common/cc-list-row.c
@@ -0,0 +1,283 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-list-row.c
+ *
+ * Copyright 2019 Purism SPC
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "cc-list-row"
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "cc-common-resources.h"
+#include "cc-list-row.h"
+
+struct _CcListRow
+{
+ AdwActionRow parent_instance;
+
+ GtkLabel *secondary_label;
+
+ GtkImage *arrow;
+ gboolean show_arrow;
+
+ GtkSwitch *enable_switch;
+ gboolean show_switch;
+
+ gboolean switch_active;
+};
+
+G_DEFINE_TYPE (CcListRow, cc_list_row, ADW_TYPE_ACTION_ROW)
+
+
+enum {
+ PROP_0,
+ PROP_SECONDARY_LABEL,
+ PROP_SHOW_ARROW,
+ PROP_SHOW_SWITCH,
+ PROP_ACTIVE,
+ N_PROPS
+};
+
+static GParamSpec *properties[N_PROPS];
+
+static void
+cc_list_row_switch_active_cb (CcListRow *self)
+{
+ gboolean switch_active;
+
+ g_assert (CC_IS_LIST_ROW (self));
+ g_assert (self->show_switch);
+
+ switch_active = gtk_switch_get_active (self->enable_switch);
+
+ if (switch_active == self->switch_active)
+ return;
+
+ self->switch_active = switch_active;
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ACTIVE]);
+}
+
+static void
+cc_list_row_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcListRow *self = (CcListRow *)object;
+
+ switch (prop_id)
+ {
+ case PROP_SECONDARY_LABEL:
+ g_value_set_string (value, gtk_label_get_label (self->secondary_label));
+ break;
+
+ case PROP_SHOW_ARROW:
+ g_value_set_boolean (value, self->show_arrow);
+ break;
+
+ case PROP_ACTIVE:
+ g_value_set_boolean (value, self->switch_active);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_list_row_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcListRow *self = (CcListRow *)object;
+
+ switch (prop_id)
+ {
+ case PROP_SECONDARY_LABEL:
+ gtk_label_set_label (self->secondary_label, g_value_get_string (value));
+ break;
+
+ case PROP_SHOW_ARROW:
+ cc_list_row_set_show_arrow (self, g_value_get_boolean (value));
+ break;
+
+ case PROP_SHOW_SWITCH:
+ cc_list_row_set_show_switch (self, g_value_get_boolean (value));
+ break;
+
+ case PROP_ACTIVE:
+ g_signal_handlers_block_by_func (self->enable_switch,
+ cc_list_row_switch_active_cb, self);
+ gtk_switch_set_active (self->enable_switch,
+ g_value_get_boolean (value));
+ self->switch_active = g_value_get_boolean (value);
+ g_signal_handlers_unblock_by_func (self->enable_switch,
+ cc_list_row_switch_active_cb, self);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_list_row_class_init (CcListRowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->get_property = cc_list_row_get_property;
+ object_class->set_property = cc_list_row_set_property;
+
+ properties[PROP_SECONDARY_LABEL] =
+ g_param_spec_string ("secondary-label",
+ "Secondary Label",
+ "Set Secondary Label",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_SHOW_ARROW] =
+ g_param_spec_boolean ("show-arrow",
+ "Show Arrow",
+ "Whether to show an arrow at the end of the row",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_SHOW_SWITCH] =
+ g_param_spec_boolean ("show-switch",
+ "Show Switch",
+ "Whether to show a switch at the end of row",
+ FALSE,
+ G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_ACTIVE] =
+ g_param_spec_boolean ("active",
+ "Active",
+ "The active state of the switch",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/control-center/"
+ "common/cc-list-row.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcListRow, secondary_label);
+ gtk_widget_class_bind_template_child (widget_class, CcListRow, arrow);
+ gtk_widget_class_bind_template_child (widget_class, CcListRow, enable_switch);
+
+ gtk_widget_class_bind_template_callback (widget_class, cc_list_row_switch_active_cb);
+}
+
+static void
+cc_list_row_init (CcListRow *self)
+{
+ g_resources_register (cc_common_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+void
+cc_list_row_set_show_arrow (CcListRow *self,
+ gboolean show_arrow)
+{
+ g_return_if_fail (CC_IS_LIST_ROW (self));
+ g_return_if_fail (!self->show_switch);
+
+ if (self->show_arrow == show_arrow)
+ return;
+
+ self->show_arrow = show_arrow;
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SHOW_ARROW]);
+}
+
+void
+cc_list_row_set_show_switch (CcListRow *self,
+ gboolean show_switch)
+{
+ g_return_if_fail (CC_IS_LIST_ROW (self));
+
+ self->show_switch = !!show_switch;
+
+ gtk_widget_set_visible (GTK_WIDGET (self->enable_switch), self->show_switch);
+ gtk_widget_set_visible (GTK_WIDGET (self->arrow), !self->show_switch);
+ gtk_widget_set_visible (GTK_WIDGET (self->secondary_label), !self->show_switch);
+
+ adw_action_row_set_activatable_widget (ADW_ACTION_ROW (self),
+ self->show_switch ? GTK_WIDGET (self->enable_switch) : NULL);
+}
+
+gboolean
+cc_list_row_get_active (CcListRow *self)
+{
+ g_return_val_if_fail (CC_IS_LIST_ROW (self), FALSE);
+ g_return_val_if_fail (self->show_switch, FALSE);
+
+ return self->switch_active;
+}
+
+void
+cc_list_row_set_secondary_label (CcListRow *self,
+ const gchar *label)
+{
+ g_return_if_fail (CC_IS_LIST_ROW (self));
+ g_return_if_fail (!self->show_switch);
+
+ if (!label)
+ label = "";
+
+ if (g_str_equal (label, gtk_label_get_label (self->secondary_label)))
+ return;
+
+ gtk_label_set_text (self->secondary_label, label);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SECONDARY_LABEL]);
+}
+
+void
+cc_list_row_set_secondary_markup (CcListRow *self,
+ const gchar *markup)
+{
+ g_return_if_fail (CC_IS_LIST_ROW (self));
+ g_return_if_fail (!self->show_switch);
+
+ if (!markup)
+ markup = "";
+
+ if (g_str_equal (markup, gtk_label_get_label (self->secondary_label)))
+ return;
+
+ gtk_label_set_markup (self->secondary_label, markup);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SECONDARY_LABEL]);
+}
+
+void
+cc_list_row_set_switch_sensitive (CcListRow *self,
+ gboolean sensitive)
+{
+ g_return_if_fail (CC_IS_LIST_ROW (self));
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->enable_switch), sensitive);
+}
diff --git a/panels/common/cc-list-row.h b/panels/common/cc-list-row.h
new file mode 100644
index 0000000..6e4c62e
--- /dev/null
+++ b/panels/common/cc-list-row.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-list-row.h
+ *
+ * Copyright 2019 Purism SPC
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <adwaita.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_LIST_ROW (cc_list_row_get_type())
+G_DECLARE_FINAL_TYPE (CcListRow, cc_list_row, CC, LIST_ROW, AdwActionRow)
+
+void cc_list_row_set_show_arrow (CcListRow *self,
+ gboolean show_arrow);
+void cc_list_row_set_show_switch (CcListRow *self,
+ gboolean show_switch);
+gboolean cc_list_row_get_active (CcListRow *self);
+void cc_list_row_set_secondary_label (CcListRow *self,
+ const gchar *label);
+void cc_list_row_set_secondary_markup (CcListRow *self,
+ const gchar *markup);
+void cc_list_row_set_switch_sensitive (CcListRow *self,
+ gboolean sensitive);
+
+G_END_DECLS
diff --git a/panels/common/cc-list-row.ui b/panels/common/cc-list-row.ui
new file mode 100644
index 0000000..f668a10
--- /dev/null
+++ b/panels/common/cc-list-row.ui
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcListRow" parent="AdwActionRow">
+ <property name="activatable">True</property>
+
+ <!-- Secondary Label -->
+ <child type="suffix">
+ <object class="GtkLabel" id="secondary_label">
+ <property name="valign">center</property>
+ <property name="ellipsize">end</property>
+ <property name="selectable" bind-source="CcListRow" bind-property="activatable" bind-flags="sync-create|invert-boolean" />
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+
+ <!-- Switch -->
+ <child type="suffix">
+ <object class="GtkSwitch" id="enable_switch">
+ <property name="visible">False</property>
+ <property name="valign">center</property>
+ <signal name="notify::active" handler="cc_list_row_switch_active_cb" swapped="yes"/>
+ </object>
+ </child>
+
+ <!-- Arrow -->
+ <child type="suffix">
+ <object class="GtkImage" id="arrow">
+ <property name="visible" bind-source="CcListRow" bind-property="show-arrow" bind-flags="sync-create"/>
+ <property name="valign">center</property>
+ <property name="icon-name">go-next-symbolic</property>
+ </object>
+ </child>
+
+ </template>
+</interface>
diff --git a/panels/common/cc-permission-infobar.c b/panels/common/cc-permission-infobar.c
new file mode 100644
index 0000000..78e2b07
--- /dev/null
+++ b/panels/common/cc-permission-infobar.c
@@ -0,0 +1,112 @@
+/* cc-permission-infobar.c
+ *
+ * Copyright (C) 2020 Red Hat, Inc
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Felipe Borges <felipeborges@gnome.org>
+ *
+ */
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "cc-permission-infobar"
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <glib/gi18n.h>
+
+#include "cc-permission-infobar.h"
+
+struct _CcPermissionInfobar
+{
+ AdwBin parent_instance;
+
+ GtkRevealer *revealer;
+ GtkLabel *title;
+ GtkLockButton *lock_button;
+};
+
+G_DEFINE_TYPE (CcPermissionInfobar, cc_permission_infobar, ADW_TYPE_BIN)
+
+static void
+on_permission_changed (CcPermissionInfobar *self)
+{
+ GPermission *permission;
+ gboolean is_authorized;
+
+ permission = gtk_lock_button_get_permission (self->lock_button);
+ is_authorized = g_permission_get_allowed (permission);
+
+ gtk_revealer_set_reveal_child (self->revealer, !is_authorized);
+}
+
+static void
+cc_permission_infobar_class_init (CcPermissionInfobarClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/control-center/"
+ "common/cc-permission-infobar.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcPermissionInfobar, revealer);
+ gtk_widget_class_bind_template_child (widget_class, CcPermissionInfobar, title);
+ gtk_widget_class_bind_template_child (widget_class, CcPermissionInfobar, lock_button);
+}
+
+static void
+cc_permission_infobar_init (CcPermissionInfobar *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ /* Set the default title. */
+ cc_permission_infobar_set_title (self, NULL);
+}
+
+void
+cc_permission_infobar_set_permission (CcPermissionInfobar *self,
+ GPermission *permission)
+{
+ g_return_if_fail (CC_IS_PERMISSION_INFOBAR (self));
+
+ gtk_lock_button_set_permission (self->lock_button, permission);
+
+ g_signal_connect_object (permission, "notify",
+ G_CALLBACK (on_permission_changed),
+ self,
+ G_CONNECT_SWAPPED);
+ on_permission_changed (self);
+}
+
+/**
+ * cc_permission_infobar_set_title:
+ * @self: a #CcPermissionInfobar
+ * @title: (nullable): title to display in the infobar, or %NULL for the default
+ *
+ * Set the title text to display in the infobar.
+ */
+void
+cc_permission_infobar_set_title (CcPermissionInfobar *self,
+ const gchar *title)
+{
+ g_return_if_fail (CC_IS_PERMISSION_INFOBAR (self));
+
+ if (title == NULL)
+ title = _("Unlock to Change Settings");
+
+ gtk_label_set_text (self->title, title);
+}
diff --git a/panels/common/cc-permission-infobar.h b/panels/common/cc-permission-infobar.h
new file mode 100644
index 0000000..4d7064d
--- /dev/null
+++ b/panels/common/cc-permission-infobar.h
@@ -0,0 +1,37 @@
+/* cc-permission-infobar.h
+ *
+ * Copyright (C) 2020 Red Hat, Inc
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Felipe Borges <felipeborges@gnome.org>
+ *
+ */
+#pragma once
+
+#include <adwaita.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_PERMISSION_INFOBAR (cc_permission_infobar_get_type())
+G_DECLARE_FINAL_TYPE (CcPermissionInfobar, cc_permission_infobar, CC, PERMISSION_INFOBAR, AdwBin)
+
+void cc_permission_infobar_set_permission (CcPermissionInfobar *self,
+ GPermission *permission);
+
+void cc_permission_infobar_set_title (CcPermissionInfobar *self,
+ const gchar *title);
+
+G_END_DECLS
diff --git a/panels/common/cc-permission-infobar.ui b/panels/common/cc-permission-infobar.ui
new file mode 100644
index 0000000..a2830b9
--- /dev/null
+++ b/panels/common/cc-permission-infobar.ui
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcPermissionInfobar" parent="AdwBin">
+ <property name="valign">start</property>
+ <child>
+ <object class="GtkRevealer" id="revealer">
+ <property name="hexpand">True</property>
+ <property name="reveal-child">True</property>
+ <child>
+ <object class="GtkInfoBar">
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">10</property>
+ <property name="margin-bottom">10</property>
+ <property name="margin-start">10</property>
+ <property name="margin-end">10</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">system-lock-screen-symbolic</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="hexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="title">
+ <property name="halign">start</property>
+ <property name="wrap">True</property>
+ <!-- Actual string set in code -->
+ <property name="label"></property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="halign">start</property>
+ <property name="wrap">True</property>
+ <property name="label" translatable="yes">Some settings must be unlocked before they can be changed.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkCenterBox">
+ <property name="margin-top">10</property>
+ <property name="margin-bottom">10</property>
+ <property name="margin-start">10</property>
+ <property name="margin-end">10</property>
+ <child type="end">
+ <object class="GtkLockButton" id="lock_button">
+ <property name="receives-default">True</property>
+ <property name="label" translatable="yes">Unlock…</property>
+ <property name="valign">GTK_ALIGN_CENTER</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/common/cc-time-editor.c b/panels/common/cc-time-editor.c
new file mode 100644
index 0000000..572fc85
--- /dev/null
+++ b/panels/common/cc-time-editor.c
@@ -0,0 +1,372 @@
+/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */
+/* cc-time-editor.c
+ *
+ * Copyright 2020 Purism SPC
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "cc-time-editor"
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnome-desktop/gnome-wall-clock.h>
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#include "cc-time-entry.h"
+#include "cc-time-editor.h"
+
+
+#define TIMEOUT_INITIAL 500
+#define TIMEOUT_REPEAT 50
+
+#define FILECHOOSER_SCHEMA "org.gtk.Settings.FileChooser"
+#define CLOCK_SCHEMA "org.gnome.desktop.interface"
+#define CLOCK_FORMAT_KEY "clock-format"
+#define SECONDS_PER_MINUTE (60)
+#define SECONDS_PER_HOUR (60 * 60)
+#define SECONDS_PER_DAY (60 * 60 * 24)
+
+
+struct _CcTimeEditor
+{
+ AdwBin parent_instance;
+
+ GtkButton *am_pm_button;
+ GtkStack *am_pm_stack;
+ GtkLabel *am_label;
+ GtkLabel *pm_label;
+ GtkButton *hour_up_button;
+ GtkButton *hour_down_button;
+ GtkButton *minute_up_button;
+ GtkButton *minute_down_button;
+ CcTimeEntry *time_entry;
+
+ GtkButton *clicked_button; /* The button currently being clicked */
+ GSettings *clock_settings;
+ GSettings *filechooser_settings;
+
+ guint timer_id;
+};
+
+G_DEFINE_TYPE (CcTimeEditor, cc_time_editor, ADW_TYPE_BIN)
+
+
+enum {
+ TIME_CHANGED,
+ N_SIGNALS
+};
+
+static guint signals[N_SIGNALS];
+
+static void
+time_editor_clock_changed_cb (CcTimeEditor *self)
+{
+ GDesktopClockFormat value;
+ gboolean is_am_pm;
+
+ g_assert (CC_IS_TIME_EDITOR (self));
+
+ value = g_settings_get_enum (self->clock_settings, CLOCK_FORMAT_KEY);
+
+ is_am_pm = value == G_DESKTOP_CLOCK_FORMAT_12H;
+ cc_time_entry_set_am_pm (self->time_entry, is_am_pm);
+ gtk_widget_set_visible (GTK_WIDGET (self->am_pm_button), is_am_pm);
+
+ if (is_am_pm)
+ {
+ if (cc_time_entry_get_is_am (self->time_entry))
+ gtk_stack_set_visible_child (self->am_pm_stack, GTK_WIDGET (self->am_label));
+ else
+ gtk_stack_set_visible_child (self->am_pm_stack, GTK_WIDGET (self->pm_label));
+ }
+}
+
+static void
+time_editor_time_changed_cb (CcTimeEditor *self)
+{
+ g_assert (CC_IS_TIME_EDITOR (self));
+
+ time_editor_clock_changed_cb (self);
+ g_signal_emit (self, signals[TIME_CHANGED], 0);
+}
+
+static void
+editor_change_time_clicked_cb (CcTimeEditor *self,
+ GtkButton *button)
+{
+ g_assert (CC_IS_TIME_EDITOR (self));
+
+ if (button == NULL)
+ return;
+
+ if (button == self->hour_up_button)
+ {
+ gtk_editable_set_position (GTK_EDITABLE (self->time_entry), 0);
+ g_signal_emit_by_name (self->time_entry, "change-value", GTK_SCROLL_STEP_UP);
+ }
+ else if (button == self->hour_down_button)
+ {
+ gtk_editable_set_position (GTK_EDITABLE (self->time_entry), 0);
+ g_signal_emit_by_name (self->time_entry, "change-value", GTK_SCROLL_STEP_DOWN);
+ }
+ else if (button == self->minute_up_button)
+ {
+ gtk_editable_set_position (GTK_EDITABLE (self->time_entry), 3);
+ g_signal_emit_by_name (self->time_entry, "change-value", GTK_SCROLL_STEP_UP);
+ }
+ else if (button == self->minute_down_button)
+ {
+ gtk_editable_set_position (GTK_EDITABLE (self->time_entry), 3);
+ g_signal_emit_by_name (self->time_entry, "change-value", GTK_SCROLL_STEP_DOWN);
+ }
+}
+
+static gboolean
+editor_change_time_repeat (CcTimeEditor *self)
+{
+ if (self->clicked_button == NULL)
+ {
+ self->timer_id = 0;
+
+ return G_SOURCE_REMOVE;
+ }
+
+ editor_change_time_clicked_cb (self, self->clicked_button);
+
+ return G_SOURCE_CONTINUE;
+}
+
+static gboolean
+editor_change_time_cb (CcTimeEditor *self)
+{
+ g_assert (CC_IS_TIME_EDITOR (self));
+ g_clear_handle_id (&self->timer_id, g_source_remove);
+
+ editor_change_time_clicked_cb (self, self->clicked_button);
+ self->timer_id = g_timeout_add (TIMEOUT_REPEAT,
+ (GSourceFunc)editor_change_time_repeat,
+ self);
+ return G_SOURCE_REMOVE;
+}
+
+static gboolean
+editor_change_time_pressed_cb (CcTimeEditor *self,
+ gint n_press,
+ gdouble x,
+ gdouble y,
+ GtkGestureClick *click_gesture)
+{
+ GtkWidget *button;
+
+ g_assert (CC_IS_TIME_EDITOR (self));
+
+ button = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (click_gesture));
+
+ self->clicked_button = GTK_BUTTON (button);
+ /* Keep changing time until the press is released */
+ self->timer_id = g_timeout_add (TIMEOUT_INITIAL,
+ (GSourceFunc)editor_change_time_cb,
+ self);
+ editor_change_time_clicked_cb (self, GTK_BUTTON (button));
+ return FALSE;
+}
+
+static gboolean
+editor_change_time_released_cb (CcTimeEditor *self)
+{
+ self->clicked_button = NULL;
+ g_clear_handle_id (&self->timer_id, g_source_remove);
+
+ return FALSE;
+}
+
+static void
+editor_am_pm_button_clicked_cb (CcTimeEditor *self)
+{
+ gboolean is_am;
+
+ g_assert (CC_IS_TIME_EDITOR (self));
+ g_assert (cc_time_entry_get_am_pm (self->time_entry));
+
+ is_am = cc_time_entry_get_is_am (self->time_entry);
+ /* Toggle AM PM */
+ cc_time_entry_set_is_am (self->time_entry, !is_am);
+ time_editor_clock_changed_cb (self);
+}
+
+static void
+editor_am_pm_stack_changed_cb (CcTimeEditor *self)
+{
+ GtkWidget *label;
+ const gchar *text;
+
+ g_assert (CC_IS_TIME_EDITOR (self));
+
+ label = gtk_stack_get_visible_child (self->am_pm_stack);
+ text = gtk_label_get_text (GTK_LABEL (label));
+ gtk_accessible_update_property (GTK_ACCESSIBLE (self->am_pm_button),
+ GTK_ACCESSIBLE_PROPERTY_LABEL, text,
+ -1);
+}
+
+static void
+cc_time_editor_constructed (GObject *object)
+{
+ CcTimeEditor *self = (CcTimeEditor *)object;
+ GDateTime *date;
+ char *label;
+
+ G_OBJECT_CLASS (cc_time_editor_parent_class)->constructed (object);
+
+ /* Set localized identifier for AM */
+ date = g_date_time_new_utc (1, 1, 1, 0, 0, 0);
+ label = g_date_time_format (date, "%p");
+ gtk_label_set_label (self->am_label, label);
+ g_date_time_unref (date);
+ g_free (label);
+
+ /* Set localized identifier for PM */
+ date = g_date_time_new_utc (1, 1, 1, 12, 0, 0);
+ label = g_date_time_format (date, "%p");
+ gtk_label_set_label (self->pm_label, label);
+ g_date_time_unref (date);
+ g_free (label);
+}
+
+static void
+cc_time_editor_finalize (GObject *object)
+{
+ CcTimeEditor *self = (CcTimeEditor *)object;
+
+ g_clear_handle_id (&self->timer_id, g_source_remove);
+ g_clear_object (&self->clock_settings);
+ g_clear_object (&self->filechooser_settings);
+
+ G_OBJECT_CLASS (cc_time_editor_parent_class)->finalize (object);
+}
+
+static void
+cc_time_editor_class_init (CcTimeEditorClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->constructed = cc_time_editor_constructed;
+ object_class->finalize = cc_time_editor_finalize;
+
+ signals[TIME_CHANGED] =
+ g_signal_new ("time-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ 0, NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 0);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/control-center/"
+ "common/cc-time-editor.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcTimeEditor, am_pm_button);
+ gtk_widget_class_bind_template_child (widget_class, CcTimeEditor, am_pm_stack);
+ gtk_widget_class_bind_template_child (widget_class, CcTimeEditor, am_label);
+ gtk_widget_class_bind_template_child (widget_class, CcTimeEditor, pm_label);
+ gtk_widget_class_bind_template_child (widget_class, CcTimeEditor, hour_up_button);
+ gtk_widget_class_bind_template_child (widget_class, CcTimeEditor, hour_down_button);
+ gtk_widget_class_bind_template_child (widget_class, CcTimeEditor, minute_up_button);
+ gtk_widget_class_bind_template_child (widget_class, CcTimeEditor, minute_down_button);
+ gtk_widget_class_bind_template_child (widget_class, CcTimeEditor, time_entry);
+
+ gtk_widget_class_bind_template_callback (widget_class, editor_change_time_pressed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, editor_change_time_released_cb);
+ gtk_widget_class_bind_template_callback (widget_class, editor_am_pm_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, editor_am_pm_stack_changed_cb);
+
+ g_type_ensure (CC_TYPE_TIME_ENTRY);
+}
+
+static void
+cc_time_editor_init (CcTimeEditor *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->clock_settings = g_settings_new (CLOCK_SCHEMA);
+ self->filechooser_settings = g_settings_new (FILECHOOSER_SCHEMA);
+
+ g_signal_connect_object (self->clock_settings, "changed::" CLOCK_FORMAT_KEY,
+ G_CALLBACK (time_editor_clock_changed_cb), self,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_swapped (self->time_entry, "time-changed",
+ G_CALLBACK (time_editor_time_changed_cb), self);
+ time_editor_clock_changed_cb (self);
+}
+
+CcTimeEditor *
+cc_time_editor_new (void)
+{
+ return g_object_new (CC_TYPE_TIME_EDITOR, NULL);
+}
+
+void
+cc_time_editor_set_time (CcTimeEditor *self,
+ guint hour,
+ guint minute)
+{
+ g_return_if_fail (CC_IS_TIME_EDITOR (self));
+
+ cc_time_entry_set_time (self->time_entry, hour, minute);
+}
+
+guint
+cc_time_editor_get_hour (CcTimeEditor *self)
+{
+ g_return_val_if_fail (CC_IS_TIME_EDITOR (self), 0);
+
+ return cc_time_entry_get_hour (self->time_entry);
+}
+
+guint
+cc_time_editor_get_minute (CcTimeEditor *self)
+{
+ g_return_val_if_fail (CC_IS_TIME_EDITOR (self), 0);
+
+ return cc_time_entry_get_minute (self->time_entry);
+}
+
+gboolean
+cc_time_editor_get_am_pm (CcTimeEditor *self)
+{
+ g_return_val_if_fail (CC_IS_TIME_EDITOR (self), TRUE);
+
+ return TRUE;
+}
+
+void
+cc_time_editor_set_am_pm (CcTimeEditor *self,
+ gboolean is_am_pm)
+{
+ g_return_if_fail (CC_IS_TIME_EDITOR (self));
+
+ cc_time_entry_set_am_pm (self->time_entry, is_am_pm);
+}
diff --git a/panels/common/cc-time-editor.h b/panels/common/cc-time-editor.h
new file mode 100644
index 0000000..f33b10a
--- /dev/null
+++ b/panels/common/cc-time-editor.h
@@ -0,0 +1,45 @@
+/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */
+/* cc-time-editor.h
+ *
+ * Copyright 2020 Purism SPC
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <adwaita.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_TIME_EDITOR (cc_time_editor_get_type ())
+
+G_DECLARE_FINAL_TYPE (CcTimeEditor, cc_time_editor, CC, TIME_EDITOR, AdwBin)
+
+CcTimeEditor *cc_time_editor_new (void);
+void cc_time_editor_set_time (CcTimeEditor *self,
+ guint hour,
+ guint minute);
+guint cc_time_editor_get_hour (CcTimeEditor *self);
+guint cc_time_editor_get_minute (CcTimeEditor *self);
+gboolean cc_time_editor_get_am_pm (CcTimeEditor *self);
+void cc_time_editor_set_am_pm (CcTimeEditor *self,
+ gboolean is_am_pm);
+
+G_END_DECLS
diff --git a/panels/common/cc-time-editor.ui b/panels/common/cc-time-editor.ui
new file mode 100644
index 0000000..155d830
--- /dev/null
+++ b/panels/common/cc-time-editor.ui
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcTimeEditor" parent="AdwBin">
+ <child>
+ <object class="GtkGrid">
+ <property name="row-spacing">6</property>
+ <property name="column-spacing">6</property>
+
+ <!-- Increment Hour Button -->
+ <child>
+ <object class="GtkButton" id="hour_up_button">
+ <property name="valign">center</property>
+ <property name="halign">center</property>
+ <property name="icon-name">go-up-symbolic</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ <style>
+ <class name="titlebutton"/>
+ <class name="circular"/>
+ <class name="flat"/>
+ </style>
+ <accessibility>
+ <property name="label" translatable="yes">Increment Hour</property>
+ </accessibility>
+ <child>
+ <object class="GtkGestureClick">
+ <property name="propagation-phase">capture</property>
+ <signal name="pressed" handler="editor_change_time_pressed_cb" swapped="yes"/>
+ <signal name="released" handler="editor_change_time_released_cb" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- Increment Minute Button -->
+ <child>
+ <object class="GtkButton" id="minute_up_button">
+ <property name="valign">center</property>
+ <property name="halign">center</property>
+ <property name="icon-name">go-up-symbolic</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ <style>
+ <class name="titlebutton"/>
+ <class name="circular"/>
+ <class name="flat"/>
+ </style>
+ <accessibility>
+ <property name="label" translatable="yes">Increment Minute</property>
+ </accessibility>
+ <child>
+ <object class="GtkGestureClick">
+ <property name="propagation-phase">capture</property>
+ <signal name="pressed" handler="editor_change_time_pressed_cb" swapped="yes"/>
+ <signal name="released" handler="editor_change_time_released_cb" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="CcTimeEntry" id="time_entry">
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ <property name="column-span">2</property>
+ </layout>
+ <accessibility>
+ <property name="label" translatable="yes">Time</property>
+ </accessibility>
+ </object>
+ </child>
+
+ <!-- Decrement Hour Button -->
+ <child>
+ <object class="GtkButton" id="hour_down_button">
+ <property name="valign">center</property>
+ <property name="halign">center</property>
+ <property name="icon-name">go-down-symbolic</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ <style>
+ <class name="titlebutton"/>
+ <class name="circular"/>
+ <class name="flat"/>
+ </style>
+ <accessibility>
+ <property name="label" translatable="yes">Decrement Hour</property>
+ </accessibility>
+ <child>
+ <object class="GtkGestureClick">
+ <property name="propagation-phase">capture</property>
+ <signal name="pressed" handler="editor_change_time_pressed_cb" swapped="yes"/>
+ <signal name="released" handler="editor_change_time_released_cb" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- Decrement Minute Button -->
+ <child>
+ <object class="GtkButton" id="minute_down_button">
+ <property name="valign">center</property>
+ <property name="halign">center</property>
+ <property name="icon-name">go-down-symbolic</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ <style>
+ <class name="titlebutton"/>
+ <class name="circular"/>
+ <class name="flat"/>
+ </style>
+ <accessibility>
+ <property name="label" translatable="yes">Decrement Minute</property>
+ </accessibility>
+ <child>
+ <object class="GtkGestureClick">
+ <property name="propagation-phase">capture</property>
+ <signal name="pressed" handler="editor_change_time_pressed_cb" swapped="yes"/>
+ <signal name="released" handler="editor_change_time_released_cb" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- AM/PM Button -->
+ <child>
+ <object class="GtkButton" id="am_pm_button">
+ <property name="valign">center</property>
+ <signal name="clicked" handler="editor_am_pm_button_clicked_cb" swapped="yes"/>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">1</property>
+ </layout>
+ <child>
+ <object class="GtkStack" id="am_pm_stack">
+ <signal name="notify::visible-child" handler="editor_am_pm_stack_changed_cb" swapped="yes"/>
+ <child>
+ <object class="GtkLabel" id="am_label">
+ <attributes>
+ <attribute name="scale" value="1.4"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="pm_label">
+ <attributes>
+ <attribute name="scale" value="1.4"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/common/cc-time-entry.c b/panels/common/cc-time-entry.c
new file mode 100644
index 0000000..421a98b
--- /dev/null
+++ b/panels/common/cc-time-entry.c
@@ -0,0 +1,660 @@
+/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */
+/* cc-time-entry.c
+ *
+ * Copyright 2020 Purism SPC
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "cc-time-entry"
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#include "cc-time-entry.h"
+
+#define SEPARATOR_INDEX 2
+#define END_INDEX 4
+#define EMIT_CHANGED_TIMEOUT 100
+
+
+struct _CcTimeEntry
+{
+ GtkWidget parent_instance;
+
+ GtkWidget *text;
+
+ guint insert_text_id;
+ guint time_changed_id;
+ int hour; /* Range: 0-23 in 24H and 1-12 in 12H with is_am set/unset */
+ int minute;
+ gboolean is_am_pm;
+ gboolean is_am; /* AM if TRUE. PM if FALSE. valid iff is_am_pm set */
+};
+
+
+static void editable_insert_text_cb (GtkText *text,
+ char *new_text,
+ gint new_text_length,
+ gint *position,
+ CcTimeEntry *self);
+
+static void gtk_editable_interface_init (GtkEditableInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (CcTimeEntry, cc_time_entry, GTK_TYPE_WIDGET,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE, gtk_editable_interface_init));
+
+enum {
+ CHANGE_VALUE,
+ TIME_CHANGED,
+ N_SIGNALS
+};
+
+static guint signals[N_SIGNALS];
+
+static gboolean
+emit_time_changed (CcTimeEntry *self)
+{
+ self->time_changed_id = 0;
+
+ g_signal_emit (self, signals[TIME_CHANGED], 0);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+time_entry_fill_time (CcTimeEntry *self)
+{
+ g_autofree gchar *str = NULL;
+
+ g_assert (CC_IS_TIME_ENTRY (self));
+
+ str = g_strdup_printf ("%02d∶%02d", self->hour, self->minute);
+
+ g_signal_handlers_block_by_func (self->text, editable_insert_text_cb, self);
+ gtk_editable_set_text (GTK_EDITABLE (self->text), str);
+ g_signal_handlers_unblock_by_func (self->text, editable_insert_text_cb, self);
+}
+
+static void
+cursor_position_changed_cb (CcTimeEntry *self)
+{
+ int current_pos;
+
+ g_assert (CC_IS_TIME_ENTRY (self));
+
+ current_pos = gtk_editable_get_position (GTK_EDITABLE (self));
+
+ g_signal_handlers_block_by_func (self->text, cursor_position_changed_cb, self);
+
+ /* If cursor is on ‘:’ move to the next field */
+ if (current_pos == SEPARATOR_INDEX)
+ gtk_editable_set_position (GTK_EDITABLE (self->text), current_pos + 1);
+
+ /* If cursor is after the last digit and without selection, move to last digit */
+ if (current_pos > END_INDEX &&
+ !gtk_editable_get_selection_bounds (GTK_EDITABLE (self->text), NULL, NULL))
+ gtk_editable_set_position (GTK_EDITABLE (self->text), END_INDEX);
+
+ g_signal_handlers_unblock_by_func (self->text, cursor_position_changed_cb, self);
+}
+
+static void
+entry_selection_changed_cb (CcTimeEntry *self)
+{
+ GtkEditable *editable;
+
+ g_assert (CC_IS_TIME_ENTRY (self));
+
+ editable = GTK_EDITABLE (self->text);
+
+ g_signal_handlers_block_by_func (self->text, cursor_position_changed_cb, self);
+
+ /* If cursor is after the last digit and without selection, move to last digit */
+ if (gtk_editable_get_position (editable) > END_INDEX &&
+ !gtk_editable_get_selection_bounds (editable, NULL, NULL))
+ gtk_editable_set_position (editable, END_INDEX);
+
+ g_signal_handlers_unblock_by_func (self->text, cursor_position_changed_cb, self);
+}
+
+static void
+editable_insert_text_cb (GtkText *text,
+ char *new_text,
+ gint new_text_length,
+ gint *position,
+ CcTimeEntry *self)
+{
+ g_assert (CC_IS_TIME_ENTRY (self));
+
+ if (new_text_length == -1)
+ new_text_length = strlen (new_text);
+
+ if (new_text_length == 5)
+ {
+ const gchar *text = gtk_editable_get_text (GTK_EDITABLE (self));
+ guint16 text_length;
+
+ text_length = g_utf8_strlen (text, -1);
+
+ /* Return if the text matches XX:XX template (where X is a number) */
+ if (text_length == 0 &&
+ strstr (new_text, "0123456789:") == new_text + new_text_length &&
+ strchr (new_text, ':') == strrchr (new_text, ':'))
+ return;
+ }
+
+ /* Insert text if single digit number */
+ if (new_text_length == 1 &&
+ strspn (new_text, "0123456789"))
+ {
+ int pos, number;
+
+ pos = *position;
+ number = *new_text - '0';
+
+ if (pos == 0)
+ self->hour = self->hour % 10 + number * 10;
+ else if (pos == 1)
+ self->hour = self->hour / 10 * 10 + number;
+ else if (pos == 3)
+ self->minute = self->minute % 10 + number * 10;
+ else if (pos == 4)
+ self->minute = self->minute / 10 * 10 + number;
+
+ if (self->is_am_pm)
+ self->hour = CLAMP (self->hour, 1, 12);
+ else
+ self->hour = CLAMP (self->hour, 0, 23);
+
+ self->minute = CLAMP (self->minute, 0, 59);
+
+ g_signal_stop_emission_by_name (text, "insert-text");
+ time_entry_fill_time (self);
+ *position = pos + 1;
+
+ g_clear_handle_id (&self->time_changed_id, g_source_remove);
+ self->time_changed_id = g_timeout_add (EMIT_CHANGED_TIMEOUT,
+ (GSourceFunc)emit_time_changed, self);
+ return;
+ }
+
+ /* Warn otherwise */
+ g_signal_stop_emission_by_name (text, "insert-text");
+ gtk_widget_error_bell (GTK_WIDGET (self));
+}
+
+
+static gboolean
+change_value_cb (GtkWidget *widget,
+ GVariant *arguments,
+ gpointer user_data)
+{
+ CcTimeEntry *self = CC_TIME_ENTRY (widget);
+ GtkScrollType type;
+ int position;
+
+ g_assert (CC_IS_TIME_ENTRY (self));
+
+ type = g_variant_get_int32 (arguments);
+ position = gtk_editable_get_position (GTK_EDITABLE (self));
+
+ if (position > SEPARATOR_INDEX)
+ {
+ if (type == GTK_SCROLL_STEP_UP)
+ self->minute++;
+ else
+ self->minute--;
+
+ if (self->minute >= 60)
+ self->minute = 0;
+ else if (self->minute <= -1)
+ self->minute = 59;
+ }
+ else
+ {
+ if (type == GTK_SCROLL_STEP_UP)
+ self->hour++;
+ else
+ self->hour--;
+
+ if (self->is_am_pm)
+ {
+ if (self->hour > 12)
+ self->hour = 1;
+ else if (self->hour < 1)
+ self->hour = 12;
+ }
+ else
+ {
+ if (self->hour >= 24)
+ self->hour = 0;
+ else if (self->hour <= -1)
+ self->hour = 23;
+ }
+ }
+
+ time_entry_fill_time (self);
+ gtk_editable_set_position (GTK_EDITABLE (self), position);
+
+ g_clear_handle_id (&self->time_changed_id, g_source_remove);
+ self->time_changed_id = g_timeout_add (EMIT_CHANGED_TIMEOUT,
+ (GSourceFunc)emit_time_changed, self);
+
+ return GDK_EVENT_STOP;
+}
+
+static void
+value_changed_cb (CcTimeEntry *self,
+ GtkScrollType type)
+{
+ g_autoptr(GVariant) value;
+
+ g_assert (CC_IS_TIME_ENTRY (self));
+
+ value = g_variant_new_int32 (type);
+
+ change_value_cb (GTK_WIDGET (self), value, NULL);
+}
+
+static void
+on_text_cut_clipboard_cb (GtkText *text,
+ CcTimeEntry *self)
+{
+ gtk_widget_error_bell (GTK_WIDGET (self));
+ g_signal_stop_emission_by_name (text, "cut-clipboard");
+}
+
+static void
+on_text_delete_from_cursor_cb (GtkText *text,
+ GtkDeleteType *type,
+ gint count,
+ CcTimeEntry *self)
+{
+ gtk_widget_error_bell (GTK_WIDGET (self));
+ g_signal_stop_emission_by_name (text, "delete-from-cursor");
+}
+
+static void
+on_text_move_cursor_cb (GtkText *text,
+ GtkMovementStep step,
+ gint count,
+ gboolean extend,
+ CcTimeEntry *self)
+{
+ int current_pos;
+
+ current_pos = gtk_editable_get_position (GTK_EDITABLE (self));
+
+ /* If cursor is on ‘:’ move backward/forward depending on the current movement */
+ if ((step == GTK_MOVEMENT_LOGICAL_POSITIONS ||
+ step == GTK_MOVEMENT_VISUAL_POSITIONS) &&
+ current_pos + count == SEPARATOR_INDEX)
+ count > 0 ? count++ : count--;
+
+ g_signal_handlers_block_by_func (text, on_text_move_cursor_cb, self);
+ gtk_editable_set_position (GTK_EDITABLE (text), current_pos + count);
+ g_signal_handlers_unblock_by_func (text, on_text_move_cursor_cb, self);
+
+ g_signal_stop_emission_by_name (text, "move-cursor");
+}
+
+static void
+on_text_paste_clipboard_cb (GtkText *text,
+ CcTimeEntry *self)
+{
+ gtk_widget_error_bell (GTK_WIDGET (self));
+ g_signal_stop_emission_by_name (text, "paste-clipboard");
+}
+
+static void
+on_text_toggle_overwrite_cb (GtkText *text,
+ CcTimeEntry *self)
+{
+ gtk_widget_error_bell (GTK_WIDGET (self));
+ g_signal_stop_emission_by_name (text, "toggle-overwrite");
+}
+
+static gboolean
+on_key_pressed_cb (GtkEventControllerKey *key_controller,
+ guint keyval,
+ guint keycode,
+ GdkModifierType state,
+ CcTimeEntry *self)
+{
+ /* Allow entering numbers */
+ if (!(state & GDK_SHIFT_MASK) &&
+ ((keyval >= GDK_KEY_KP_0 && keyval <= GDK_KEY_KP_9) ||
+ (keyval >= GDK_KEY_0 && keyval <= GDK_KEY_9)))
+ return GDK_EVENT_PROPAGATE;
+
+ /* Allow navigation keys */
+ if ((keyval >= GDK_KEY_Left && keyval <= GDK_KEY_Down) ||
+ (keyval >= GDK_KEY_KP_Left && keyval <= GDK_KEY_KP_Down) ||
+ keyval == GDK_KEY_Home ||
+ keyval == GDK_KEY_End ||
+ keyval == GDK_KEY_Menu)
+ return GDK_EVENT_PROPAGATE;
+
+ if (state & (GDK_CONTROL_MASK | GDK_ALT_MASK))
+ return GDK_EVENT_PROPAGATE;
+
+ if (keyval == GDK_KEY_Tab)
+ {
+ /* If focus is on Hour field skip to minute field */
+ if (gtk_editable_get_position (GTK_EDITABLE (self)) <= 1)
+ {
+ gtk_editable_set_position (GTK_EDITABLE (self), SEPARATOR_INDEX + 1);
+
+ return GDK_EVENT_STOP;
+ }
+
+ return GDK_EVENT_PROPAGATE;
+ }
+
+ /* Shift-Tab */
+ if (keyval == GDK_KEY_ISO_Left_Tab)
+ {
+ /* If focus is on Minute field skip back to Hour field */
+ if (gtk_editable_get_position (GTK_EDITABLE (self)) >= 2)
+ {
+ gtk_editable_set_position (GTK_EDITABLE (self), 0);
+
+ return GDK_EVENT_STOP;
+ }
+
+ return GDK_EVENT_PROPAGATE;
+ }
+
+ return GDK_EVENT_STOP;
+}
+
+static GtkEditable *
+cc_time_entry_get_delegate (GtkEditable *editable)
+{
+ CcTimeEntry *self = CC_TIME_ENTRY (editable);
+ return GTK_EDITABLE (self->text);
+}
+
+static void
+gtk_editable_interface_init (GtkEditableInterface *iface)
+{
+ iface->get_delegate = cc_time_entry_get_delegate;
+}
+
+static void
+cc_time_entry_constructed (GObject *object)
+{
+ CcTimeEntry *self = CC_TIME_ENTRY (object);
+ PangoAttrList *list;
+ PangoAttribute *attribute;
+
+ G_OBJECT_CLASS (cc_time_entry_parent_class)->constructed (object);
+
+ time_entry_fill_time (CC_TIME_ENTRY (object));
+
+ list = pango_attr_list_new ();
+
+ attribute = pango_attr_size_new (PANGO_SCALE * 32);
+ pango_attr_list_insert (list, attribute);
+
+ attribute = pango_attr_weight_new (PANGO_WEIGHT_LIGHT);
+ pango_attr_list_insert (list, attribute);
+
+ /* Use tabular(monospace) letters */
+ attribute = pango_attr_font_features_new ("tnum");
+ pango_attr_list_insert (list, attribute);
+
+ gtk_text_set_attributes (GTK_TEXT (self->text), list);
+
+ pango_attr_list_unref (list);
+}
+
+static void
+cc_time_entry_dispose (GObject *object)
+{
+ CcTimeEntry *self = CC_TIME_ENTRY (object);
+
+ gtk_editable_finish_delegate (GTK_EDITABLE (self));
+ g_clear_pointer (&self->text, gtk_widget_unparent);
+
+ G_OBJECT_CLASS (cc_time_entry_parent_class)->dispose (object);
+}
+
+static void
+cc_time_entry_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ if (gtk_editable_delegate_get_property (object, property_id, value, pspec))
+ return;
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+cc_time_entry_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ if (gtk_editable_delegate_set_property (object, property_id, value, pspec))
+ return;
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+cc_time_entry_class_init (CcTimeEntryClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->constructed = cc_time_entry_constructed;
+ object_class->dispose = cc_time_entry_dispose;
+ object_class->get_property = cc_time_entry_get_property;
+ object_class->set_property = cc_time_entry_set_property;
+
+ signals[CHANGE_VALUE] =
+ g_signal_new ("change-value",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_ACTION,
+ 0, NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 1,
+ GTK_TYPE_SCROLL_TYPE);
+
+ signals[TIME_CHANGED] =
+ g_signal_new ("time-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ 0, NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 0);
+
+ gtk_editable_install_properties (object_class, 1);
+
+ gtk_widget_class_set_css_name (widget_class, "entry");
+ gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
+
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_Up, 0,
+ change_value_cb, "i", GTK_SCROLL_STEP_UP);
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_KP_Up, 0,
+ change_value_cb, "i", GTK_SCROLL_STEP_UP);
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_Down, 0,
+ change_value_cb, "i", GTK_SCROLL_STEP_DOWN);
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_KP_Down, 0,
+ change_value_cb, "i", GTK_SCROLL_STEP_DOWN);
+}
+
+static void
+cc_time_entry_init (CcTimeEntry *self)
+{
+ GtkEventController *key_controller;
+
+ key_controller = gtk_event_controller_key_new ();
+ gtk_event_controller_set_propagation_phase (key_controller, GTK_PHASE_CAPTURE);
+ g_signal_connect (key_controller, "key-pressed", G_CALLBACK (on_key_pressed_cb), self);
+ gtk_widget_add_controller (GTK_WIDGET (self), key_controller);
+
+ self->text = g_object_new (GTK_TYPE_TEXT,
+ "input-purpose", GTK_INPUT_PURPOSE_DIGITS,
+ "input-hints", GTK_INPUT_HINT_NO_EMOJI,
+ "overwrite-mode", TRUE,
+ "xalign", 0.5,
+ "max-length", 5,
+ NULL);
+ gtk_widget_set_parent (self->text, GTK_WIDGET (self));
+ gtk_editable_init_delegate (GTK_EDITABLE (self));
+ g_object_connect (self->text,
+ "signal::cut-clipboard", on_text_cut_clipboard_cb, self,
+ "signal::delete-from-cursor", on_text_delete_from_cursor_cb, self,
+ "signal::insert-text", editable_insert_text_cb, self,
+ "signal::move-cursor", on_text_move_cursor_cb, self,
+ "swapped-signal::notify::cursor-position", cursor_position_changed_cb, self,
+ "swapped-signal::notify::selection-bound", entry_selection_changed_cb, self,
+ "signal::paste-clipboard", on_text_paste_clipboard_cb, self,
+ "signal::toggle-overwrite", on_text_toggle_overwrite_cb, self,
+ NULL);
+ g_signal_connect (self, "change-value",
+ G_CALLBACK (value_changed_cb), self);
+}
+
+GtkWidget *
+cc_time_entry_new (void)
+{
+ return g_object_new (CC_TYPE_TIME_ENTRY, NULL);
+}
+
+void
+cc_time_entry_set_time (CcTimeEntry *self,
+ guint hour,
+ guint minute)
+{
+ gboolean is_am_pm;
+
+ g_return_if_fail (CC_IS_TIME_ENTRY (self));
+
+ if (cc_time_entry_get_hour (self) == hour &&
+ cc_time_entry_get_minute (self) == minute)
+ return;
+
+ is_am_pm = cc_time_entry_get_am_pm (self);
+ cc_time_entry_set_am_pm (self, FALSE);
+
+ self->hour = CLAMP (hour, 0, 23);
+ self->minute = CLAMP (minute, 0, 59);
+
+ cc_time_entry_set_am_pm (self, is_am_pm);
+
+ g_signal_emit (self, signals[TIME_CHANGED], 0);
+ time_entry_fill_time (self);
+}
+
+guint
+cc_time_entry_get_hour (CcTimeEntry *self)
+{
+ g_return_val_if_fail (CC_IS_TIME_ENTRY (self), 0);
+
+ if (!self->is_am_pm)
+ return self->hour;
+
+ if (self->is_am && self->hour == 12)
+ return 0;
+ else if (self->is_am || self->hour == 12)
+ return self->hour;
+ else
+ return self->hour + 12;
+}
+
+guint
+cc_time_entry_get_minute (CcTimeEntry *self)
+{
+ g_return_val_if_fail (CC_IS_TIME_ENTRY (self), 0);
+
+ return self->minute;
+}
+
+gboolean
+cc_time_entry_get_is_am (CcTimeEntry *self)
+{
+ g_return_val_if_fail (CC_IS_TIME_ENTRY (self), FALSE);
+
+ if (self->is_am_pm)
+ return self->is_am;
+
+ return self->hour < 12;
+}
+
+void
+cc_time_entry_set_is_am (CcTimeEntry *self,
+ gboolean is_am)
+{
+ g_return_if_fail (CC_IS_TIME_ENTRY (self));
+
+ self->is_am = !!is_am;
+ g_signal_emit (self, signals[TIME_CHANGED], 0);
+}
+
+gboolean
+cc_time_entry_get_am_pm (CcTimeEntry *self)
+{
+ g_return_val_if_fail (CC_IS_TIME_ENTRY (self), FALSE);
+
+ return self->is_am_pm;
+}
+
+void
+cc_time_entry_set_am_pm (CcTimeEntry *self,
+ gboolean is_am_pm)
+{
+ g_return_if_fail (CC_IS_TIME_ENTRY (self));
+
+ if (self->is_am_pm == !!is_am_pm)
+ return;
+
+ if (self->hour < 12)
+ self->is_am = TRUE;
+ else
+ self->is_am = FALSE;
+
+ if (is_am_pm)
+ {
+ if (self->hour == 0)
+ self->hour = 12;
+ else if (self->hour > 12)
+ self->hour = self->hour - 12;
+ }
+ else
+ {
+ if (self->hour == 12 && self->is_am)
+ self->hour = 0;
+ else if (!self->is_am)
+ self->hour = self->hour + 12;
+ }
+
+ self->is_am_pm = !!is_am_pm;
+ time_entry_fill_time (self);
+}
diff --git a/panels/common/cc-time-entry.h b/panels/common/cc-time-entry.h
new file mode 100644
index 0000000..f416143
--- /dev/null
+++ b/panels/common/cc-time-entry.h
@@ -0,0 +1,47 @@
+/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */
+/* cc-time-entry.h
+ *
+ * Copyright 2020 Purism SPC
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_TIME_ENTRY (cc_time_entry_get_type ())
+G_DECLARE_FINAL_TYPE (CcTimeEntry, cc_time_entry, CC, TIME_ENTRY, GtkWidget)
+
+GtkWidget *cc_time_entry_new (void);
+void cc_time_entry_set_time (CcTimeEntry *self,
+ guint hour,
+ guint minute);
+guint cc_time_entry_get_minute (CcTimeEntry *self);
+guint cc_time_entry_get_hour (CcTimeEntry *self);
+gboolean cc_time_entry_get_is_am (CcTimeEntry *self);
+void cc_time_entry_set_is_am (CcTimeEntry *self,
+ gboolean is_am);
+gboolean cc_time_entry_get_am_pm (CcTimeEntry *self);
+void cc_time_entry_set_am_pm (CcTimeEntry *self,
+ gboolean is_am_pm);
+
+G_END_DECLS
diff --git a/panels/common/cc-util.c b/panels/common/cc-util.c
new file mode 100644
index 0000000..9418d56
--- /dev/null
+++ b/panels/common/cc-util.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2012 Giovanni Campagna <scampa.giovanni@gmail.com>
+ *
+ * The Control Center 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.
+ *
+ * The Control Center 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 the Control Center; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+
+
+#include "cc-util.h"
+
+/* Combining diacritical mark?
+ * Basic range: [0x0300,0x036F]
+ * Supplement: [0x1DC0,0x1DFF]
+ * For Symbols: [0x20D0,0x20FF]
+ * Half marks: [0xFE20,0xFE2F]
+ */
+#define IS_CDM_UCS4(c) (((c) >= 0x0300 && (c) <= 0x036F) || \
+ ((c) >= 0x1DC0 && (c) <= 0x1DFF) || \
+ ((c) >= 0x20D0 && (c) <= 0x20FF) || \
+ ((c) >= 0xFE20 && (c) <= 0xFE2F))
+
+#define IS_SOFT_HYPHEN(c) ((c) == 0x00AD)
+
+/* Copied from tracker/src/libtracker-fts/tracker-parser-glib.c under the GPL
+ * And then from gnome-shell/src/shell-util.c
+ *
+ * Originally written by Aleksander Morgado <aleksander@gnu.org>
+ */
+char *
+cc_util_normalize_casefold_and_unaccent (const char *str)
+{
+ g_autofree gchar *normalized = NULL;
+ gchar *tmp;
+ int i = 0, j = 0, ilen;
+
+ if (str == NULL)
+ return NULL;
+
+ normalized = g_utf8_normalize (str, -1, G_NORMALIZE_NFKD);
+ tmp = g_utf8_casefold (normalized, -1);
+
+ ilen = strlen (tmp);
+
+ while (i < ilen)
+ {
+ gunichar unichar;
+ gchar *next_utf8;
+ gint utf8_len;
+
+ /* Get next character of the word as UCS4 */
+ unichar = g_utf8_get_char_validated (&tmp[i], -1);
+
+ /* Invalid UTF-8 character or end of original string. */
+ if (unichar == (gunichar) -1 ||
+ unichar == (gunichar) -2)
+ {
+ break;
+ }
+
+ /* Find next UTF-8 character */
+ next_utf8 = g_utf8_next_char (&tmp[i]);
+ utf8_len = next_utf8 - &tmp[i];
+
+ if (IS_CDM_UCS4 (unichar) || IS_SOFT_HYPHEN (unichar))
+ {
+ /* If the given unichar is a combining diacritical mark,
+ * just update the original index, not the output one */
+ i += utf8_len;
+ continue;
+ }
+
+ /* If already found a previous combining
+ * diacritical mark, indexes are different so
+ * need to copy characters. As output and input
+ * buffers may overlap, need to use memmove
+ * instead of memcpy */
+ if (i != j)
+ {
+ memmove (&tmp[j], &tmp[i], utf8_len);
+ }
+
+ /* Update both indexes */
+ i += utf8_len;
+ j += utf8_len;
+ }
+
+ /* Force proper string end */
+ tmp[j] = '\0';
+
+ return tmp;
+}
+
+char *
+cc_util_get_smart_date (GDateTime *date)
+{
+ g_autoptr(GDateTime) today = NULL;
+ g_autoptr(GDateTime) local = NULL;
+ GTimeSpan span;
+
+ /* Set today date */
+ local = g_date_time_new_now_local ();
+ today = g_date_time_new_local (g_date_time_get_year (local),
+ g_date_time_get_month (local),
+ g_date_time_get_day_of_month (local),
+ 0, 0, 0);
+
+ span = g_date_time_difference (today, date);
+ if (span <= 0)
+ {
+ return g_strdup (_("Today"));
+ }
+ else if (span <= G_TIME_SPAN_DAY)
+ {
+ return g_strdup (_("Yesterday"));
+ }
+ else
+ {
+ if (g_date_time_get_year (date) == g_date_time_get_year (today))
+ {
+ /* Translators: This is a date format string in the style of "Feb 24". */
+ return g_date_time_format (date, _("%b %e"));
+ }
+ else
+ {
+ /* Translators: This is a date format string in the style of "Feb 24, 2013". */
+ return g_date_time_format (date, _("%b %e, %Y"));
+ }
+ }
+}
+
+/* Copied from src/plugins/properties/bacon-video-widget-properties.c
+ * in totem */
+char *
+cc_util_time_to_string_text (gint64 msecs)
+{
+ g_autofree gchar *hours = NULL;
+ g_autofree gchar *mins = NULL;
+ g_autofree gchar *secs = NULL;
+ gint sec, min, hour, _time;
+
+ _time = (int) (msecs / 1000);
+ sec = _time % 60;
+ _time = _time - sec;
+ min = (_time % (60*60)) / 60;
+ _time = _time - (min * 60);
+ hour = _time / (60*60);
+
+ hours = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE, "%d hour", "%d hours", hour), hour);
+ mins = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE, "%d minute", "%d minutes", min), min);
+ secs = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE, "%d second", "%d seconds", sec), sec);
+
+ if (hour > 0)
+ {
+ if (min > 0 && sec > 0)
+ {
+ /* 5 hours 2 minutes 12 seconds */
+ return g_strdup_printf (C_("hours minutes seconds", "%s %s %s"), hours, mins, secs);
+ }
+ else if (min > 0)
+ {
+ /* 5 hours 2 minutes */
+ return g_strdup_printf (C_("hours minutes", "%s %s"), hours, mins);
+ }
+ else
+ {
+ /* 5 hours */
+ return g_strdup_printf (C_("hours", "%s"), hours);
+ }
+ }
+ else if (min > 0)
+ {
+ if (sec > 0)
+ {
+ /* 2 minutes 12 seconds */
+ return g_strdup_printf (C_("minutes seconds", "%s %s"), mins, secs);
+ }
+ else
+ {
+ /* 2 minutes */
+ return g_strdup_printf (C_("minutes", "%s"), mins);
+ }
+ }
+ else if (sec > 0)
+ {
+ /* 10 seconds */
+ return g_strdup (secs);
+ }
+ else
+ {
+ /* 0 seconds */
+ return g_strdup (_("0 seconds"));
+ }
+}
diff --git a/panels/common/cc-util.h b/panels/common/cc-util.h
new file mode 100644
index 0000000..131c2af
--- /dev/null
+++ b/panels/common/cc-util.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2012 Giovanni Campagna <scampa.giovanni@gmail.com>
+ *
+ * The Control Center 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.
+ *
+ * The Control Center 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 the Control Center; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+
+#pragma once
+
+#include <glib.h>
+
+char * cc_util_normalize_casefold_and_unaccent (const char *str);
+char * cc_util_get_smart_date (GDateTime *date);
+char * cc_util_time_to_string_text (gint64 msecs);
diff --git a/panels/common/common.gresource.xml b/panels/common/common.gresource.xml
new file mode 100644
index 0000000..b8c2946
--- /dev/null
+++ b/panels/common/common.gresource.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/common">
+ <file preprocess="xml-stripblanks">cc-language-chooser.ui</file>
+ <file preprocess="xml-stripblanks">cc-language-row.ui</file>
+ <file preprocess="xml-stripblanks">cc-list-row.ui</file>
+ <file preprocess="xml-stripblanks">cc-time-editor.ui</file>
+ <file preprocess="xml-stripblanks">cc-permission-infobar.ui</file>
+ </gresource>
+</gresources>
diff --git a/panels/common/gnome-control-center.rules.in b/panels/common/gnome-control-center.rules.in
new file mode 100644
index 0000000..22cf785
--- /dev/null
+++ b/panels/common/gnome-control-center.rules.in
@@ -0,0 +1,13 @@
+polkit.addRule(function(action, subject) {
+ if ((action.id == "org.freedesktop.locale1.set-locale" ||
+ action.id == "org.freedesktop.locale1.set-keyboard" ||
+ action.id == "org.freedesktop.ModemManager1.Device.Control" ||
+ action.id == "org.freedesktop.hostname1.set-static-hostname" ||
+ action.id == "org.freedesktop.hostname1.set-hostname" ||
+ action.id == "org.gnome.controlcenter.datetime.configure") &&
+ subject.local &&
+ subject.active &&
+ subject.isInGroup ("@PRIVILEGED_GROUP@")) {
+ return polkit.Result.YES;
+ }
+});
diff --git a/panels/common/gnome-settings-bus.h b/panels/common/gnome-settings-bus.h
new file mode 100644
index 0000000..122289f
--- /dev/null
+++ b/panels/common/gnome-settings-bus.h
@@ -0,0 +1,14 @@
+/* Stub to replace gnome-settings-daemon's
+ * gnome-settings-bus.h helpers */
+
+#include <gdk/x11/gdkx.h>
+
+#ifdef GDK_WINDOWING_WAYLAND
+
+static inline gboolean
+gnome_settings_is_wayland (void)
+{
+ return !GDK_IS_X11_DISPLAY (gdk_display_get_default ());
+}
+
+#endif /* GDK_WINDOWING_WAYLAND */
diff --git a/panels/common/gsd-device-manager.c b/panels/common/gsd-device-manager.c
new file mode 100644
index 0000000..6283ccb
--- /dev/null
+++ b/panels/common/gsd-device-manager.c
@@ -0,0 +1,688 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2014 Red Hat
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Carlos Garnacho <carlosg@gnome.org>
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <gudev/gudev.h>
+
+#include "gsd-device-manager.h"
+#include "gsd-common-enums.h"
+#include "gnome-settings-bus.h"
+#include "gsd-input-helper.h"
+
+#ifdef GDK_WINDOWING_X11
+#include <gdk/x11/gdkx.h>
+#endif
+#ifdef GDK_WINDOWING_WAYLAND
+#include <gdk/wayland/gdkwayland.h>
+#endif
+
+typedef struct
+{
+ gchar *name;
+ gchar *device_file;
+ gchar *vendor_id;
+ gchar *product_id;
+ gchar *group;
+ GsdDeviceType type;
+ guint width;
+ guint height;
+} GsdDevicePrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GsdDevice, gsd_device, G_TYPE_OBJECT)
+
+typedef struct
+{
+ GObject parent_instance;
+ GHashTable *devices;
+ GUdevClient *udev_client;
+} GsdDeviceManagerPrivate;
+
+enum {
+ PROP_NAME = 1,
+ PROP_DEVICE_FILE,
+ PROP_VENDOR_ID,
+ PROP_PRODUCT_ID,
+ PROP_TYPE,
+ PROP_WIDTH,
+ PROP_HEIGHT,
+ PROP_GROUP
+};
+
+enum {
+ DEVICE_ADDED,
+ DEVICE_REMOVED,
+ DEVICE_CHANGED,
+ N_SIGNALS
+};
+
+/* Index matches GsdDeviceType */
+const gchar *udev_ids[] = {
+ "ID_INPUT_MOUSE",
+ "ID_INPUT_KEYBOARD",
+ "ID_INPUT_TOUCHPAD",
+ "ID_INPUT_TABLET",
+ "ID_INPUT_TOUCHSCREEN",
+ "ID_INPUT_TABLET_PAD",
+};
+
+static guint signals[N_SIGNALS] = { 0 };
+
+G_DEFINE_TYPE_WITH_PRIVATE (GsdDeviceManager, gsd_device_manager, G_TYPE_OBJECT)
+
+static void
+gsd_device_init (GsdDevice *device)
+{
+}
+
+static void
+gsd_device_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GsdDevicePrivate *priv;
+
+ priv = gsd_device_get_instance_private (GSD_DEVICE (object));
+
+ switch (prop_id) {
+ case PROP_NAME:
+ priv->name = g_value_dup_string (value);
+ break;
+ case PROP_DEVICE_FILE:
+ priv->device_file = g_value_dup_string (value);
+ break;
+ case PROP_VENDOR_ID:
+ priv->vendor_id = g_value_dup_string (value);
+ break;
+ case PROP_PRODUCT_ID:
+ priv->product_id = g_value_dup_string (value);
+ break;
+ case PROP_TYPE:
+ priv->type = g_value_get_flags (value);
+ break;
+ case PROP_WIDTH:
+ priv->width = g_value_get_uint (value);
+ break;
+ case PROP_HEIGHT:
+ priv->height = g_value_get_uint (value);
+ break;
+ case PROP_GROUP:
+ priv->group = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gsd_device_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsdDevicePrivate *priv;
+
+ priv = gsd_device_get_instance_private (GSD_DEVICE (object));
+
+ switch (prop_id) {
+ case PROP_NAME:
+ g_value_set_string (value, priv->name);
+ break;
+ case PROP_DEVICE_FILE:
+ g_value_set_string (value, priv->device_file);
+ break;
+ case PROP_VENDOR_ID:
+ g_value_set_string (value, priv->vendor_id);
+ break;
+ case PROP_PRODUCT_ID:
+ g_value_set_string (value, priv->product_id);
+ break;
+ case PROP_TYPE:
+ g_value_set_flags (value, priv->type);
+ break;
+ case PROP_WIDTH:
+ g_value_set_uint (value, priv->width);
+ break;
+ case PROP_HEIGHT:
+ g_value_set_uint (value, priv->height);
+ break;
+ case PROP_GROUP:
+ g_value_set_string (value, priv->group);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gsd_device_finalize (GObject *object)
+{
+ GsdDevicePrivate *priv;
+
+ priv = gsd_device_get_instance_private (GSD_DEVICE (object));
+
+ g_free (priv->name);
+ g_free (priv->vendor_id);
+ g_free (priv->product_id);
+ g_free (priv->device_file);
+ g_free (priv->group);
+
+ G_OBJECT_CLASS (gsd_device_parent_class)->finalize (object);
+}
+
+static void
+gsd_device_class_init (GsdDeviceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = gsd_device_set_property;
+ object_class->get_property = gsd_device_get_property;
+ object_class->finalize = gsd_device_finalize;
+
+ g_object_class_install_property (object_class,
+ PROP_NAME,
+ g_param_spec_string ("name",
+ "Name",
+ "Name",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_DEVICE_FILE,
+ g_param_spec_string ("device-file",
+ "Device file",
+ "Device file",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_VENDOR_ID,
+ g_param_spec_string ("vendor-id",
+ "Vendor ID",
+ "Vendor ID",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_PRODUCT_ID,
+ g_param_spec_string ("product-id",
+ "Product ID",
+ "Product ID",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_TYPE,
+ g_param_spec_flags ("type",
+ "Device type",
+ "Device type",
+ GSD_TYPE_DEVICE_TYPE, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_WIDTH,
+ g_param_spec_uint ("width",
+ "Width",
+ "Width",
+ 0, G_MAXUINT, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_HEIGHT,
+ g_param_spec_uint ("height",
+ "Height",
+ "Height",
+ 0, G_MAXUINT, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_GROUP,
+ g_param_spec_string ("group",
+ "Group",
+ "Group",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+gsd_device_manager_finalize (GObject *object)
+{
+ GsdDeviceManager *manager = GSD_DEVICE_MANAGER (object);
+ GsdDeviceManagerPrivate *priv = gsd_device_manager_get_instance_private (manager);
+
+ g_hash_table_destroy (priv->devices);
+ g_object_unref (priv->udev_client);
+
+ G_OBJECT_CLASS (gsd_device_manager_parent_class)->finalize (object);
+}
+
+static GList *
+gsd_device_manager_real_list_devices (GsdDeviceManager *manager,
+ GsdDeviceType type)
+{
+ GsdDeviceManagerPrivate *priv = gsd_device_manager_get_instance_private (manager);
+ GsdDeviceType device_type;
+ GList *devices = NULL;
+ GHashTableIter iter;
+ GsdDevice *device;
+
+ g_hash_table_iter_init (&iter, priv->devices);
+
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &device)) {
+ device_type = gsd_device_get_device_type (device);
+
+ if ((device_type & type) == type)
+ devices = g_list_prepend (devices, device);
+ }
+
+ return devices;
+}
+
+static GsdDevice *
+gsd_device_manager_real_lookup_device (GsdDeviceManager *manager,
+ GdkDevice *gdk_device)
+{
+ GsdDeviceManagerPrivate *priv = gsd_device_manager_get_instance_private (manager);
+ GdkDisplay *display = gdk_device_get_display (gdk_device);
+ const gchar *node_path = NULL;
+ GHashTableIter iter;
+ GsdDevice *device;
+
+#ifdef GDK_WINDOWING_X11
+ if (GDK_IS_X11_DISPLAY (display))
+ node_path = xdevice_get_device_node (gdk_x11_device_get_id (gdk_device));
+#endif
+#ifdef GDK_WINDOWING_WAYLAND
+ if (GDK_IS_WAYLAND_DISPLAY (display))
+ node_path = g_strdup (gdk_wayland_device_get_node_path (gdk_device));
+#endif
+ if (!node_path)
+ return NULL;
+
+ g_hash_table_iter_init (&iter, priv->devices);
+
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &device)) {
+ if (g_strcmp0 (node_path,
+ gsd_device_get_device_file (device)) == 0) {
+ return device;
+ }
+ }
+
+ return NULL;
+}
+
+static void
+gsd_device_manager_class_init (GsdDeviceManagerClass *klass)
+{
+ GsdDeviceManagerClass *manager_class = GSD_DEVICE_MANAGER_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gsd_device_manager_finalize;
+ manager_class->list_devices = gsd_device_manager_real_list_devices;
+ manager_class->lookup_device = gsd_device_manager_real_lookup_device;
+
+ signals[DEVICE_ADDED] =
+ g_signal_new ("device-added",
+ GSD_TYPE_DEVICE_MANAGER,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GsdDeviceManagerClass, device_added),
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 1,
+ GSD_TYPE_DEVICE | G_SIGNAL_TYPE_STATIC_SCOPE);
+
+ signals[DEVICE_REMOVED] =
+ g_signal_new ("device-removed",
+ GSD_TYPE_DEVICE_MANAGER,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GsdDeviceManagerClass, device_removed),
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 1,
+ GSD_TYPE_DEVICE | G_SIGNAL_TYPE_STATIC_SCOPE);
+
+ signals[DEVICE_CHANGED] =
+ g_signal_new ("device-changed",
+ GSD_TYPE_DEVICE_MANAGER,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GsdDeviceManagerClass, device_changed),
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 1,
+ GSD_TYPE_DEVICE | G_SIGNAL_TYPE_STATIC_SCOPE);
+}
+
+static GsdDeviceType
+udev_device_get_device_type (GUdevDevice *device)
+{
+ GsdDeviceType type = 0;
+ gint i;
+
+ for (i = 0; i < G_N_ELEMENTS (udev_ids); i++) {
+ if (g_udev_device_get_property_as_boolean (device, udev_ids[i]))
+ type |= (1 << i);
+ }
+
+ return type;
+}
+
+static gboolean
+device_is_evdev (GUdevDevice *device)
+{
+ const gchar *device_file;
+
+ device_file = g_udev_device_get_device_file (device);
+
+ if (!device_file || strstr (device_file, "/event") == NULL)
+ return FALSE;
+
+ return g_udev_device_get_property_as_boolean (device, "ID_INPUT");
+}
+
+static GsdDevice *
+create_device (GUdevDevice *udev_device, GUdevDevice *parent)
+{
+ const gchar *vendor, *product, *name, *group;
+ guint width, height;
+
+ name = g_udev_device_get_sysfs_attr (parent, "name");
+ vendor = g_udev_device_get_property (udev_device, "ID_VENDOR_ID");
+ product = g_udev_device_get_property (udev_device, "ID_MODEL_ID");
+
+ if (!vendor || !product) {
+ vendor = g_udev_device_get_sysfs_attr (udev_device, "device/id/vendor");
+ product = g_udev_device_get_sysfs_attr (udev_device, "device/id/product");
+ }
+
+ width = g_udev_device_get_property_as_int (udev_device, "ID_INPUT_WIDTH_MM");
+ height = g_udev_device_get_property_as_int (udev_device, "ID_INPUT_HEIGHT_MM");
+
+ group = g_udev_device_get_property (udev_device, "LIBINPUT_DEVICE_GROUP");
+
+ return g_object_new (GSD_TYPE_DEVICE,
+ "name", name,
+ "device-file", g_udev_device_get_device_file (udev_device),
+ "type", udev_device_get_device_type (udev_device),
+ "vendor-id", vendor,
+ "product-id", product,
+ "width", width,
+ "height", height,
+ "group", group,
+ NULL);
+}
+
+static void
+add_device (GsdDeviceManager *manager,
+ GUdevDevice *udev_device)
+{
+ GsdDeviceManagerPrivate *priv = gsd_device_manager_get_instance_private (manager);
+ g_autoptr(GUdevDevice) parent = NULL;
+ GsdDevice *device;
+ const gchar *syspath;
+
+ parent = g_udev_device_get_parent (udev_device);
+
+ if (!parent)
+ return;
+
+ device = create_device (udev_device, parent);
+ syspath = g_udev_device_get_sysfs_path (udev_device);
+ g_hash_table_insert (priv->devices, g_strdup (syspath), device);
+ g_signal_emit_by_name (manager, "device-added", device);
+}
+
+static void
+remove_device (GsdDeviceManager *manager,
+ GUdevDevice *udev_device)
+{
+ GsdDeviceManagerPrivate *priv = gsd_device_manager_get_instance_private (manager);
+ GsdDevice *device;
+ const gchar *syspath;
+
+ syspath = g_udev_device_get_sysfs_path (udev_device);
+ device = g_hash_table_lookup (priv->devices, syspath);
+
+ if (!device)
+ return;
+
+ g_hash_table_steal (priv->devices, syspath);
+ g_signal_emit_by_name (manager, "device-removed", device);
+
+ g_object_unref (device);
+}
+
+static void
+udev_event_cb (GUdevClient *client,
+ gchar *action,
+ GUdevDevice *device,
+ GsdDeviceManager *manager)
+{
+ if (!device_is_evdev (device))
+ return;
+
+ if (g_strcmp0 (action, "add") == 0) {
+ add_device (manager, device);
+ } else if (g_strcmp0 (action, "remove") == 0) {
+ remove_device (manager, device);
+ }
+}
+
+static void
+gsd_device_manager_init (GsdDeviceManager *manager)
+{
+ GsdDeviceManagerPrivate *priv = gsd_device_manager_get_instance_private (manager);
+ const gchar *subsystems[] = { "input", NULL };
+ g_autoptr(GList) devices = NULL;
+ GList *l;
+
+ priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_object_unref);
+
+ priv->udev_client = g_udev_client_new (subsystems);
+ g_signal_connect (priv->udev_client, "uevent",
+ G_CALLBACK (udev_event_cb), manager);
+
+ devices = g_udev_client_query_by_subsystem (priv->udev_client,
+ subsystems[0]);
+
+ for (l = devices; l; l = l->next) {
+ g_autoptr(GUdevDevice) device = l->data;
+
+ if (device_is_evdev (device))
+ add_device (manager, device);
+ }
+}
+
+GsdDeviceManager *
+gsd_device_manager_get (void)
+{
+ GsdDeviceManager *manager;
+ GdkDisplay *display;
+
+ display = gdk_display_get_default ();
+ g_return_val_if_fail (display != NULL, NULL);
+
+ manager = g_object_get_data (G_OBJECT (display), "gsd-device-manager-data");
+
+ if (!manager) {
+ manager = g_object_new (GSD_TYPE_DEVICE_MANAGER,
+ NULL);
+
+ g_object_set_data_full (G_OBJECT (display), "gsd-device-manager-data",
+ manager, (GDestroyNotify) g_object_unref);
+ }
+
+ return manager;
+}
+
+GList *
+gsd_device_manager_list_devices (GsdDeviceManager *manager,
+ GsdDeviceType type)
+{
+ g_return_val_if_fail (GSD_IS_DEVICE_MANAGER (manager), NULL);
+
+ return GSD_DEVICE_MANAGER_GET_CLASS (manager)->list_devices (manager, type);
+}
+
+GsdDeviceType
+gsd_device_get_device_type (GsdDevice *device)
+{
+ GsdDevicePrivate *priv;
+
+ g_return_val_if_fail (GSD_IS_DEVICE (device), 0);
+
+ priv = gsd_device_get_instance_private (device);
+
+ return priv->type;
+}
+
+void
+gsd_device_get_device_ids (GsdDevice *device,
+ const gchar **vendor,
+ const gchar **product)
+{
+ GsdDevicePrivate *priv;
+
+ g_return_if_fail (GSD_IS_DEVICE (device));
+
+ priv = gsd_device_get_instance_private (device);
+
+ if (vendor)
+ *vendor = priv->vendor_id;
+ if (product)
+ *product = priv->product_id;
+}
+
+GSettings *
+gsd_device_get_settings (GsdDevice *device)
+{
+ const gchar *schema = NULL, *vendor, *product;
+ GsdDeviceType type;
+ g_autofree gchar *path = NULL;
+
+ g_return_val_if_fail (GSD_IS_DEVICE (device), NULL);
+
+ type = gsd_device_get_device_type (device);
+
+ if (type & (GSD_DEVICE_TYPE_TOUCHSCREEN | GSD_DEVICE_TYPE_TABLET)) {
+ gsd_device_get_device_ids (device, &vendor, &product);
+
+ if (type & GSD_DEVICE_TYPE_TOUCHSCREEN) {
+ schema = "org.gnome.desktop.peripherals.touchscreen";
+ path = g_strdup_printf ("/org/gnome/desktop/peripherals/touchscreens/%s:%s/",
+ vendor, product);
+ } else if (type & GSD_DEVICE_TYPE_TABLET) {
+ schema = "org.gnome.desktop.peripherals.tablet";
+ path = g_strdup_printf ("/org/gnome/desktop/peripherals/tablets/%s:%s/",
+ vendor, product);
+ }
+ } else if (type & (GSD_DEVICE_TYPE_MOUSE | GSD_DEVICE_TYPE_TOUCHPAD)) {
+ schema = "org.gnome.desktop.peripherals.mouse";
+ } else if (type & GSD_DEVICE_TYPE_KEYBOARD) {
+ schema = "org.gnome.desktop.peripherals.keyboard";
+ } else {
+ return NULL;
+ }
+
+ if (path) {
+ return g_settings_new_with_path (schema, path);
+ } else {
+ return g_settings_new (schema);
+ }
+}
+
+const gchar *
+gsd_device_get_name (GsdDevice *device)
+{
+ GsdDevicePrivate *priv;
+
+ g_return_val_if_fail (GSD_IS_DEVICE (device), NULL);
+
+ priv = gsd_device_get_instance_private (device);
+
+ return priv->name;
+}
+
+const gchar *
+gsd_device_get_device_file (GsdDevice *device)
+{
+ GsdDevicePrivate *priv;
+
+ g_return_val_if_fail (GSD_IS_DEVICE (device), NULL);
+
+ priv = gsd_device_get_instance_private (device);
+
+ return priv->device_file;
+}
+
+gboolean
+gsd_device_get_dimensions (GsdDevice *device,
+ guint *width,
+ guint *height)
+{
+ GsdDevicePrivate *priv;
+
+ g_return_val_if_fail (GSD_IS_DEVICE (device), FALSE);
+
+ priv = gsd_device_get_instance_private (device);
+
+ if (width)
+ *width = priv->width;
+ if (height)
+ *height = priv->height;
+
+ return priv->width > 0 && priv->height > 0;
+}
+
+GsdDevice *
+gsd_device_manager_lookup_gdk_device (GsdDeviceManager *manager,
+ GdkDevice *gdk_device)
+{
+ GsdDeviceManagerClass *klass;
+
+ g_return_val_if_fail (GSD_IS_DEVICE_MANAGER (manager), NULL);
+ g_return_val_if_fail (GDK_IS_DEVICE (gdk_device), NULL);
+
+ klass = GSD_DEVICE_MANAGER_GET_CLASS (manager);
+ if (!klass->lookup_device)
+ return NULL;
+
+ return klass->lookup_device (manager, gdk_device);
+}
+
+gboolean
+gsd_device_shares_group (GsdDevice *device1,
+ GsdDevice *device2)
+{
+ GsdDevicePrivate *priv1, *priv2;
+
+ priv1 = gsd_device_get_instance_private (GSD_DEVICE (device1));
+ priv2 = gsd_device_get_instance_private (GSD_DEVICE (device2));
+
+ /* Don't group NULLs together */
+ if (!priv1->group && !priv2->group)
+ return FALSE;
+
+ return g_strcmp0 (priv1->group, priv2->group) == 0;
+}
diff --git a/panels/common/gsd-device-manager.h b/panels/common/gsd-device-manager.h
new file mode 100644
index 0000000..f48b5ad
--- /dev/null
+++ b/panels/common/gsd-device-manager.h
@@ -0,0 +1,86 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2014 Carlos Garnacho <carlosg@gnome.org>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#pragma once
+
+#include <gdk/gdk.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define GSD_TYPE_DEVICE (gsd_device_get_type ())
+G_DECLARE_DERIVABLE_TYPE (GsdDevice, gsd_device, GSD, DEVICE, GObject)
+
+#define GSD_TYPE_DEVICE_MANAGER (gsd_device_manager_get_type ())
+G_DECLARE_DERIVABLE_TYPE (GsdDeviceManager, gsd_device_manager, GSD, DEVICE_MANAGER, GObject)
+
+typedef enum {
+ GSD_DEVICE_TYPE_MOUSE = 1 << 0,
+ GSD_DEVICE_TYPE_KEYBOARD = 1 << 1,
+ GSD_DEVICE_TYPE_TOUCHPAD = 1 << 2,
+ GSD_DEVICE_TYPE_TABLET = 1 << 3,
+ GSD_DEVICE_TYPE_TOUCHSCREEN = 1 << 4,
+ GSD_DEVICE_TYPE_PAD = 1 << 5
+} GsdDeviceType;
+
+struct _GsdDeviceClass {
+ GObjectClass parent_class;
+};
+
+struct _GsdDeviceManagerClass
+{
+ GObjectClass parent_class;
+
+ GList * (* list_devices) (GsdDeviceManager *manager,
+ GsdDeviceType type);
+
+ void (* device_added) (GsdDeviceManager *manager,
+ GsdDevice *device);
+ void (* device_removed) (GsdDeviceManager *manager,
+ GsdDevice *device);
+ void (* device_changed) (GsdDeviceManager *manager,
+ GsdDevice *device);
+
+ GsdDevice * (* lookup_device) (GsdDeviceManager *manager,
+ GdkDevice *gdk_device);
+};
+
+GsdDeviceManager * gsd_device_manager_get (void);
+GList * gsd_device_manager_list_devices (GsdDeviceManager *manager,
+ GsdDeviceType type);
+
+const gchar * gsd_device_get_name (GsdDevice *device);
+GsdDeviceType gsd_device_get_device_type (GsdDevice *device);
+void gsd_device_get_device_ids (GsdDevice *device,
+ const gchar **vendor,
+ const gchar **product);
+GSettings * gsd_device_get_settings (GsdDevice *device);
+
+const gchar * gsd_device_get_device_file (GsdDevice *device);
+gboolean gsd_device_get_dimensions (GsdDevice *device,
+ guint *width,
+ guint *height);
+
+GsdDevice * gsd_device_manager_lookup_gdk_device (GsdDeviceManager *manager,
+ GdkDevice *gdk_device);
+gboolean gsd_device_shares_group (GsdDevice *device1,
+ GsdDevice *device2);
+
+G_END_DECLS
diff --git a/panels/common/gsd-input-helper.c b/panels/common/gsd-input-helper.c
new file mode 100644
index 0000000..025070e
--- /dev/null
+++ b/panels/common/gsd-input-helper.c
@@ -0,0 +1,108 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Bastien Nocera <hadess@hadess.net>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gdk/gdk.h>
+#include <gdk/x11/gdkx.h>
+
+#include <sys/types.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/XInput2.h>
+
+#include "gsd-input-helper.h"
+#include "gsd-device-manager.h"
+
+static gboolean
+device_type_is_present (GsdDeviceType type)
+{
+ g_autoptr(GList) l = gsd_device_manager_list_devices (gsd_device_manager_get (),
+ type);
+ return l != NULL;
+}
+
+gboolean
+touchscreen_is_present (void)
+{
+ return device_type_is_present (GSD_DEVICE_TYPE_TOUCHSCREEN);
+}
+
+gboolean
+touchpad_is_present (void)
+{
+ return device_type_is_present (GSD_DEVICE_TYPE_TOUCHPAD);
+}
+
+gboolean
+mouse_is_present (void)
+{
+ return device_type_is_present (GSD_DEVICE_TYPE_MOUSE);
+}
+
+char *
+xdevice_get_device_node (int deviceid)
+{
+ GdkDisplay *display;
+ Atom prop;
+ Atom act_type;
+ int act_format;
+ unsigned long nitems, bytes_after;
+ unsigned char *data;
+ char *ret;
+
+ display = gdk_display_get_default ();
+ gdk_display_sync (display);
+
+ prop = XInternAtom (GDK_DISPLAY_XDISPLAY (display), "Device Node", False);
+ if (!prop)
+ return NULL;
+
+ gdk_x11_display_error_trap_push (display);
+
+ if (!XIGetProperty (GDK_DISPLAY_XDISPLAY (display),
+ deviceid, prop, 0, 1000, False,
+ AnyPropertyType, &act_type, &act_format,
+ &nitems, &bytes_after, &data) == Success) {
+ gdk_x11_display_error_trap_pop_ignored (display);
+ return NULL;
+ }
+ if (gdk_x11_display_error_trap_pop (display))
+ goto out;
+
+ if (nitems == 0)
+ goto out;
+
+ if (act_type != XA_STRING)
+ goto out;
+
+ /* Unknown string format */
+ if (act_format != 8)
+ goto out;
+
+ ret = g_strdup ((char *) data);
+
+ XFree (data);
+ return ret;
+
+out:
+ XFree (data);
+ return NULL;
+}
diff --git a/panels/common/gsd-input-helper.h b/panels/common/gsd-input-helper.h
new file mode 100644
index 0000000..8fda1e6
--- /dev/null
+++ b/panels/common/gsd-input-helper.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Bastien Nocera <hadess@hadess.net>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+G_BEGIN_DECLS
+
+#include <glib.h>
+
+gboolean touchpad_is_present (void);
+gboolean touchscreen_is_present (void);
+gboolean mouse_is_present (void);
+
+char * xdevice_get_device_node (int deviceid);
+
+G_END_DECLS
diff --git a/panels/common/hostname-helper.c b/panels/common/hostname-helper.c
new file mode 100644
index 0000000..a8f7c41
--- /dev/null
+++ b/panels/common/hostname-helper.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <string.h>
+
+#include "hostname-helper.h"
+
+static char *
+allowed_chars (void)
+{
+ GString *s;
+ char i;
+
+ s = g_string_new (NULL);
+ for (i = 'a'; i <= 'z'; i++)
+ g_string_append_c (s, i);
+ for (i = 'A'; i <= 'Z'; i++)
+ g_string_append_c (s, i);
+ for (i = '0'; i <= '9'; i++)
+ g_string_append_c (s, i);
+ g_string_append_c (s, '-');
+
+ return g_string_free (s, FALSE);
+}
+
+static char *
+remove_leading_dashes (char *input)
+{
+ char *start;
+
+ for (start = input; *start && (*start == '-'); start++)
+ ;
+
+ memmove (input, start, strlen (start) + 1);
+
+ return input;
+}
+
+static gboolean
+is_empty (const char *input)
+{
+ if (input == NULL ||
+ *input == '\0')
+ return TRUE;
+ return FALSE;
+}
+
+static char *
+remove_trailing_dashes (char *input)
+{
+ int len;
+
+ len = strlen (input);
+ while (len--) {
+ if (input[len] == '-')
+ input[len] = '\0';
+ else
+ break;
+ }
+ return input;
+}
+
+static char *
+remove_apostrophes (char *input)
+{
+ char *apo;
+
+ while ((apo = strchr (input, '\'')) != NULL)
+ memmove (apo, apo + 1, strlen (apo));
+ return input;
+}
+
+static char *
+remove_duplicate_dashes (char *input)
+{
+ char *dashes;
+
+ while ((dashes = strstr (input, "--")) != NULL)
+ memmove (dashes, dashes + 1, strlen (dashes));
+ return input;
+}
+
+#define CHECK if (is_empty (result)) return g_strdup ("localhost")
+
+char *
+pretty_hostname_to_static (const char *pretty,
+ gboolean for_display)
+{
+ g_autofree gchar *result = NULL;
+ g_autofree gchar *valid_chars = NULL;
+ g_autofree gchar *composed = NULL;
+
+ g_return_val_if_fail (pretty != NULL, NULL);
+ g_return_val_if_fail (g_utf8_validate (pretty, -1, NULL), NULL);
+
+ g_debug ("Input: '%s'", pretty);
+
+ composed = g_utf8_normalize (pretty, -1, G_NORMALIZE_ALL_COMPOSE);
+ g_debug ("\tcomposed: '%s'", composed);
+ /* Transform the pretty hostname to ASCII */
+ result = g_str_to_ascii (composed, NULL);
+ g_debug ("\ttranslit: '%s'", result);
+
+ CHECK;
+
+ /* Remove apostrophes */
+ remove_apostrophes (result);
+ g_debug ("\tapostrophes: '%s'", result);
+
+ CHECK;
+
+ /* Remove all the not-allowed chars */
+ valid_chars = allowed_chars ();
+ g_strcanon (result, valid_chars, '-');
+ g_debug ("\tcanon: '%s'", result);
+
+ CHECK;
+
+ /* Remove the leading dashes */
+ remove_leading_dashes (result);
+ g_debug ("\tleading: '%s'", result);
+
+ CHECK;
+
+ /* Remove trailing dashes */
+ remove_trailing_dashes (result);
+ g_debug ("\ttrailing: '%s'", result);
+
+ CHECK;
+
+ /* Remove duplicate dashes */
+ remove_duplicate_dashes (result);
+ g_debug ("\tduplicate: '%s'", result);
+
+ CHECK;
+
+ /* Lower case */
+ if (!for_display)
+ return g_ascii_strdown (result, -1);
+
+ return g_steal_pointer (&result);
+}
+#undef CHECK
+
+/* Max length of an SSID in bytes */
+#define SSID_MAX_LEN 32
+char *
+pretty_hostname_to_ssid (const char *pretty)
+{
+ const char *p, *prev;
+
+ if (pretty == NULL || *pretty == '\0') {
+ pretty = g_get_host_name ();
+ if (g_strcmp0 (pretty, "localhost") == 0)
+ pretty = NULL;
+ }
+
+ if (pretty == NULL) {
+ /* translators: This is the default hotspot name, need to be less than 32-bytes */
+ gchar *ret = g_strdup (C_("hotspot", "Hotspot"));
+ g_assert (strlen (ret) <= SSID_MAX_LEN);
+ return ret;
+ }
+
+ g_return_val_if_fail (g_utf8_validate (pretty, -1, NULL), NULL);
+
+ p = pretty;
+ prev = NULL;
+ while ((p = g_utf8_find_next_char (p, NULL)) != NULL) {
+ if (p == prev)
+ break;
+
+ if (p - pretty > SSID_MAX_LEN) {
+ return g_strndup (pretty, prev - pretty);
+ }
+ if (p - pretty == SSID_MAX_LEN) {
+ return g_strndup (pretty, p - pretty);
+ }
+
+ if (*p == '\0')
+ break;
+
+ prev = p;
+ }
+
+ return g_strdup (pretty);
+}
diff --git a/panels/common/hostname-helper.h b/panels/common/hostname-helper.h
new file mode 100644
index 0000000..3d2a143
--- /dev/null
+++ b/panels/common/hostname-helper.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+char *pretty_hostname_to_static (const char *pretty,
+ gboolean for_display);
+char *pretty_hostname_to_ssid (const char *pretty);
diff --git a/panels/common/meson.build b/panels/common/meson.build
new file mode 100644
index 0000000..13557c1
--- /dev/null
+++ b/panels/common/meson.build
@@ -0,0 +1,126 @@
+common_inc = include_directories('.')
+
+common_sources = []
+
+enums = 'gsd-common-enums'
+enums_header = files('gsd-device-manager.h')
+
+common_sources += gnome.mkenums(
+ enums + '.h',
+ sources: enums_header,
+ fhead: '#pragma once\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n',
+ fprod: '/* enumerations from "@filename@" */\n',
+ vhead: 'GType @enum_name@_get_type (void) G_GNUC_CONST;\n#define GSD_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n',
+ ftail: 'G_END_DECLS\n'
+)
+
+common_sources += gnome.mkenums(
+ enums + '.c',
+ sources: enums_header,
+ fhead: '#include "gsd-device-manager.h"\n#include "gsd-common-enums.h"\n',
+ fprod: '\n/* enumerations from "@filename@" */',
+ vhead: 'GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {',
+ vprod: ' { @VALUENAME@, "@VALUENAME@", "@valuenick@" },',
+ vtail: ' { 0, NULL, NULL }\n };\n etype = g_@type@_register_static ("@EnumName@", values);\n }\n return etype;\n}\n'
+)
+
+resource_data = files(
+ 'cc-language-chooser.ui',
+ 'cc-language-row.ui',
+ 'cc-list-row.ui',
+ 'cc-time-editor.ui',
+ 'cc-permission-infobar.ui',
+)
+
+common_sources += gnome.compile_resources(
+ 'cc-common-resources',
+ 'common.gresource.xml',
+ c_name: 'cc_common',
+ dependencies: resource_data,
+ export: true
+)
+
+generates_sources_dep = declare_dependency(
+ sources: common_sources,
+)
+
+sources = files(
+ 'cc-hostname-entry.c',
+ 'cc-time-entry.c',
+ 'hostname-helper.c',
+)
+
+libwidgets = static_library(
+ 'widgets',
+ sources: sources,
+ include_directories: top_inc,
+ dependencies: common_deps + [ generates_sources_dep, polkit_gobject_dep ]
+)
+libwidgets_dep = declare_dependency(
+ include_directories: common_inc,
+ link_with: libwidgets
+)
+
+sources = common_sources + files(
+ 'cc-common-language.c',
+ 'cc-language-chooser.c',
+ 'cc-language-row.c',
+ 'cc-list-row.c',
+ 'cc-time-editor.c',
+ 'cc-permission-infobar.c',
+ 'cc-util.c'
+)
+
+deps = common_deps + [
+ generates_sources_dep,
+ gnome_desktop_dep,
+ dependency('fontconfig')
+]
+
+liblanguage = static_library(
+ 'language',
+ sources: sources,
+ include_directories: top_inc,
+ dependencies: deps
+)
+
+liblanguage_dep = declare_dependency(
+ include_directories: common_inc,
+ link_with: liblanguage
+)
+
+gsd_headers = [
+ 'gsd-device-manager.h',
+ 'gsd-input-helper.h'
+]
+
+gsd_sources = [
+ 'gsd-device-manager.c',
+ 'gsd-input-helper.c'
+]
+
+sources = common_sources + files(gsd_sources)
+
+deps = common_deps + [ gudev_dep ]
+
+libdevice = static_library(
+ 'device',
+ sources: sources,
+ include_directories: top_inc,
+ dependencies: deps
+)
+
+libdevice_dep = declare_dependency(
+ include_directories: common_inc,
+ link_with: libdevice
+)
+
+polkit_conf = configuration_data()
+polkit_conf.set('PRIVILEGED_GROUP', get_option('privileged_group'))
+configure_file(
+ input: 'gnome-control-center.rules.in',
+ output: 'gnome-control-center.rules',
+ configuration: polkit_conf,
+ install_dir: join_paths(control_center_datadir, 'polkit-1', 'rules.d')
+)
+
diff --git a/panels/datetime/backward b/panels/datetime/backward
new file mode 100644
index 0000000..8594be6
--- /dev/null
+++ b/panels/datetime/backward
@@ -0,0 +1,128 @@
+# This file is in the public domain, so clarified as of
+# 2009-05-17 by Arthur David Olson.
+
+# This file provides links between current names for time zones
+# and their old names. Many names changed in late 1993.
+
+# Link TARGET LINK-NAME
+Link Africa/Nairobi Africa/Asmera
+Link Africa/Abidjan Africa/Timbuktu
+Link America/Argentina/Catamarca America/Argentina/ComodRivadavia
+Link America/Adak America/Atka
+Link America/Argentina/Buenos_Aires America/Buenos_Aires
+Link America/Argentina/Catamarca America/Catamarca
+Link America/Atikokan America/Coral_Harbour
+Link America/Argentina/Cordoba America/Cordoba
+Link America/Tijuana America/Ensenada
+Link America/Indiana/Indianapolis America/Fort_Wayne
+Link America/Indiana/Indianapolis America/Indianapolis
+Link America/Argentina/Jujuy America/Jujuy
+Link America/Indiana/Knox America/Knox_IN
+Link America/Kentucky/Louisville America/Louisville
+Link America/Argentina/Mendoza America/Mendoza
+Link America/Toronto America/Montreal
+Link America/Rio_Branco America/Porto_Acre
+Link America/Argentina/Cordoba America/Rosario
+Link America/Tijuana America/Santa_Isabel
+Link America/Denver America/Shiprock
+Link America/Port_of_Spain America/Virgin
+Link Pacific/Auckland Antarctica/South_Pole
+Link Asia/Ashgabat Asia/Ashkhabad
+Link Asia/Kolkata Asia/Calcutta
+Link Asia/Shanghai Asia/Chongqing
+Link Asia/Shanghai Asia/Chungking
+Link Asia/Dhaka Asia/Dacca
+Link Asia/Shanghai Asia/Harbin
+Link Asia/Urumqi Asia/Kashgar
+Link Asia/Kathmandu Asia/Katmandu
+Link Asia/Macau Asia/Macao
+Link Asia/Yangon Asia/Rangoon
+Link Asia/Ho_Chi_Minh Asia/Saigon
+Link Asia/Jerusalem Asia/Tel_Aviv
+Link Asia/Thimphu Asia/Thimbu
+Link Asia/Makassar Asia/Ujung_Pandang
+Link Asia/Ulaanbaatar Asia/Ulan_Bator
+Link Atlantic/Faroe Atlantic/Faeroe
+Link Europe/Oslo Atlantic/Jan_Mayen
+Link Australia/Sydney Australia/ACT
+Link Australia/Sydney Australia/Canberra
+Link Australia/Lord_Howe Australia/LHI
+Link Australia/Sydney Australia/NSW
+Link Australia/Darwin Australia/North
+Link Australia/Brisbane Australia/Queensland
+Link Australia/Adelaide Australia/South
+Link Australia/Hobart Australia/Tasmania
+Link Australia/Melbourne Australia/Victoria
+Link Australia/Perth Australia/West
+Link Australia/Broken_Hill Australia/Yancowinna
+Link America/Rio_Branco Brazil/Acre
+Link America/Noronha Brazil/DeNoronha
+Link America/Sao_Paulo Brazil/East
+Link America/Manaus Brazil/West
+Link America/Halifax Canada/Atlantic
+Link America/Winnipeg Canada/Central
+# This line is commented out, as the name exceeded the 14-character limit
+# and was an unused misnomer.
+#Link America/Regina Canada/East-Saskatchewan
+Link America/Toronto Canada/Eastern
+Link America/Edmonton Canada/Mountain
+Link America/St_Johns Canada/Newfoundland
+Link America/Vancouver Canada/Pacific
+Link America/Regina Canada/Saskatchewan
+Link America/Whitehorse Canada/Yukon
+Link America/Santiago Chile/Continental
+Link Pacific/Easter Chile/EasterIsland
+Link America/Havana Cuba
+Link Africa/Cairo Egypt
+Link Europe/Dublin Eire
+Link Europe/London Europe/Belfast
+Link Europe/Chisinau Europe/Tiraspol
+Link Europe/London GB
+Link Europe/London GB-Eire
+Link Etc/GMT GMT+0
+Link Etc/GMT GMT-0
+Link Etc/GMT GMT0
+Link Etc/GMT Greenwich
+Link Asia/Hong_Kong Hongkong
+Link Atlantic/Reykjavik Iceland
+Link Asia/Tehran Iran
+Link Asia/Jerusalem Israel
+Link America/Jamaica Jamaica
+Link Asia/Tokyo Japan
+Link Pacific/Kwajalein Kwajalein
+Link Africa/Tripoli Libya
+Link America/Tijuana Mexico/BajaNorte
+Link America/Mazatlan Mexico/BajaSur
+Link America/Mexico_City Mexico/General
+Link Pacific/Auckland NZ
+Link Pacific/Chatham NZ-CHAT
+Link America/Denver Navajo
+Link Asia/Shanghai PRC
+Link Pacific/Honolulu Pacific/Johnston
+Link Pacific/Pohnpei Pacific/Ponape
+Link Pacific/Pago_Pago Pacific/Samoa
+Link Pacific/Chuuk Pacific/Truk
+Link Pacific/Chuuk Pacific/Yap
+Link Europe/Warsaw Poland
+Link Europe/Lisbon Portugal
+Link Asia/Taipei ROC
+Link Asia/Seoul ROK
+Link Asia/Singapore Singapore
+Link Europe/Istanbul Turkey
+Link Etc/UCT UCT
+Link America/Anchorage US/Alaska
+Link America/Adak US/Aleutian
+Link America/Phoenix US/Arizona
+Link America/Chicago US/Central
+Link America/Indiana/Indianapolis US/East-Indiana
+Link America/New_York US/Eastern
+Link Pacific/Honolulu US/Hawaii
+Link America/Indiana/Knox US/Indiana-Starke
+Link America/Detroit US/Michigan
+Link America/Denver US/Mountain
+Link America/Los_Angeles US/Pacific
+Link Pacific/Pago_Pago US/Samoa
+Link Etc/UTC UTC
+Link Etc/UTC Universal
+Link Europe/Moscow W-SU
+Link Etc/UTC Zulu \ No newline at end of file
diff --git a/panels/datetime/cc-datetime-panel.c b/panels/datetime/cc-datetime-panel.c
new file mode 100644
index 0000000..c1e6aaa
--- /dev/null
+++ b/panels/datetime/cc-datetime-panel.c
@@ -0,0 +1,1098 @@
+/*
+ * Copyright (C) 2010 Intel, Inc
+ * Copyright (C) 2013 Kalev Lember <kalevlember@gmail.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ *
+ */
+
+#include "config.h"
+#include "cc-time-editor.h"
+#include "cc-datetime-panel.h"
+#include "cc-datetime-resources.h"
+
+#include <langinfo.h>
+#include <sys/time.h>
+#include "cc-timezone-map.h"
+#include "timedated.h"
+#include "date-endian.h"
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+
+#include <gdesktop-enums.h>
+#include <string.h>
+#include <stdlib.h>
+#include <libintl.h>
+
+#include <glib/gi18n.h>
+#include <libgnome-desktop/gnome-languages.h>
+#include <libgnome-desktop/gnome-wall-clock.h>
+#include <polkit/polkit.h>
+
+/* FIXME: This should be "Etc/GMT" instead */
+#define DEFAULT_TZ "Europe/London"
+#define GETTEXT_PACKAGE_TIMEZONES GETTEXT_PACKAGE "-timezones"
+
+enum {
+ CITY_COL_CITY_HUMAN_READABLE,
+ CITY_COL_ZONE,
+ CITY_NUM_COLS
+};
+
+#define DATETIME_PERMISSION "org.gnome.controlcenter.datetime.configure"
+#define DATETIME_TZ_PERMISSION "org.freedesktop.timedate1.set-timezone"
+#define LOCATION_SETTINGS "org.gnome.system.location"
+#define LOCATION_ENABLED "enabled"
+
+#define CLOCK_SCHEMA "org.gnome.desktop.interface"
+#define CLOCK_FORMAT_KEY "clock-format"
+
+#define FILECHOOSER_SCHEMA "org.gtk.Settings.FileChooser"
+
+#define DATETIME_SCHEMA "org.gnome.desktop.datetime"
+#define AUTO_TIMEZONE_KEY "automatic-timezone"
+
+struct _CcDateTimePanel
+{
+ CcPanel parent_instance;
+
+ GtkWidget *map;
+
+ GList *toplevels;
+
+ TzLocation *current_location;
+
+ GtkTreeModelFilter *city_filter;
+
+ GDateTime *date;
+
+ GSettings *clock_settings;
+ GSettings *datetime_settings;
+ GSettings *filechooser_settings;
+ GDesktopClockFormat clock_format;
+ GtkFrame *aspectmap;
+ GtkWidget *auto_datetime_row;
+ GtkWidget *auto_timezone_row;
+ GtkWidget *auto_timezone_switch;
+ GtkListStore *city_liststore;
+ GtkTreeModelSort *city_modelsort;
+ GtkWidget *date_grid;
+ GtkWidget *datetime_button;
+ GtkWidget *datetime_dialog;
+ GtkWidget *datetime_label;
+ GtkWidget *day_spinbutton;
+ GtkWidget *timeformat_row;
+ GtkWidget *h_spinbutton;
+ GtkLockButton *lock_button;
+ GtkListBox *date_box;
+ GtkListBoxRow *day_row;
+ AdwComboRow *month_row;
+ GtkListBoxRow *year_row;
+ GtkWidget *network_time_switch;
+ GtkWidget *time_editor;
+ GtkWidget *timezone_button;
+ GtkWidget *timezone_dialog;
+ GtkWidget *timezone_label;
+ GtkWidget *timezone_searchentry;
+ GtkWidget *year_spinbutton;
+
+ GnomeWallClock *clock_tracker;
+
+ Timedate1 *dtm;
+ GCancellable *cancellable;
+
+ GPermission *permission;
+ GPermission *tz_permission;
+ GSettings *location_settings;
+
+ int month; /* index starts from 1 */
+};
+
+CC_PANEL_REGISTER (CcDateTimePanel, cc_date_time_panel)
+
+static void update_time (CcDateTimePanel *self);
+
+static void
+cc_date_time_panel_dispose (GObject *object)
+{
+ CcDateTimePanel *panel = CC_DATE_TIME_PANEL (object);
+
+ if (panel->cancellable)
+ {
+ g_cancellable_cancel (panel->cancellable);
+ g_clear_object (&panel->cancellable);
+ }
+
+ if (panel->toplevels)
+ {
+ g_list_free_full (panel->toplevels, (GDestroyNotify) gtk_window_destroy);
+ panel->toplevels = NULL;
+ }
+
+ g_clear_object (&panel->clock_tracker);
+ g_clear_object (&panel->dtm);
+ g_clear_object (&panel->permission);
+ g_clear_object (&panel->tz_permission);
+ g_clear_object (&panel->location_settings);
+ g_clear_object (&panel->clock_settings);
+ g_clear_object (&panel->datetime_settings);
+ g_clear_object (&panel->filechooser_settings);
+
+ g_clear_pointer (&panel->date, g_date_time_unref);
+
+ G_OBJECT_CLASS (cc_date_time_panel_parent_class)->dispose (object);
+}
+
+static const char *
+cc_date_time_panel_get_help_uri (CcPanel *panel)
+{
+ return "help:gnome-help/clock";
+}
+
+static void clock_settings_changed_cb (CcDateTimePanel *panel,
+ gchar *key);
+
+static char *
+format_clock_name_cb (AdwEnumListItem *item,
+ gpointer user_data)
+{
+
+ switch (adw_enum_list_item_get_value (item))
+ {
+ case G_DESKTOP_CLOCK_FORMAT_24H:
+ return g_strdup (_("24-hour"));
+ case G_DESKTOP_CLOCK_FORMAT_12H:
+ return g_strdup (_("AM / PM"));
+ default:
+ return NULL;
+ }
+}
+
+static void
+change_clock_settings (GObject *gobject,
+ GParamSpec *pspec,
+ CcDateTimePanel *self)
+{
+ GDesktopClockFormat value;
+ AdwEnumListItem *item;
+
+ g_signal_handlers_block_by_func (self->clock_settings, clock_settings_changed_cb,
+ self);
+
+ item = ADW_ENUM_LIST_ITEM (adw_combo_row_get_selected_item (ADW_COMBO_ROW (self->timeformat_row)));
+ value = adw_enum_list_item_get_value (item);
+
+ g_settings_set_enum (self->clock_settings, CLOCK_FORMAT_KEY, value);
+ g_settings_set_enum (self->filechooser_settings, CLOCK_FORMAT_KEY, value);
+ self->clock_format = value;
+
+ update_time (self);
+
+ g_signal_handlers_unblock_by_func (self->clock_settings, clock_settings_changed_cb,
+ self);
+}
+
+static void
+clock_settings_changed_cb (CcDateTimePanel *self,
+ gchar *key)
+{
+ GDesktopClockFormat value;
+
+ value = g_settings_get_enum (self->clock_settings, CLOCK_FORMAT_KEY);
+ self->clock_format = value;
+
+ g_signal_handlers_block_by_func (self->timeformat_row, change_clock_settings, self);
+
+ adw_combo_row_set_selected (ADW_COMBO_ROW (self->timeformat_row), value);
+
+ cc_time_editor_set_am_pm (CC_TIME_EDITOR (self->time_editor),
+ value == G_DESKTOP_CLOCK_FORMAT_12H);
+ update_time (self);
+
+ g_signal_handlers_unblock_by_func (self->timeformat_row, change_clock_settings, self);
+}
+
+
+/* Update the widgets based on the system time */
+static void
+update_time (CcDateTimePanel *self)
+{
+ g_autofree gchar *label = NULL;
+ gboolean use_ampm;
+
+ if (self->clock_format == G_DESKTOP_CLOCK_FORMAT_12H)
+ use_ampm = TRUE;
+ else
+ use_ampm = FALSE;
+
+ cc_time_editor_set_time (CC_TIME_EDITOR (self->time_editor),
+ g_date_time_get_hour (self->date),
+ g_date_time_get_minute (self->date));
+
+ /* Update the time on the listbow row */
+ if (use_ampm)
+ {
+ /* Translators: This is the full date and time format used in 12-hour mode. */
+ label = g_date_time_format (self->date, _("%e %B %Y, %l:%M %p"));
+ }
+ else
+ {
+ /* Translators: This is the full date and time format used in 24-hour mode. */
+ label = g_date_time_format (self->date, _("%e %B %Y, %R"));
+ }
+
+ self->month = g_date_time_get_month (self->date);
+ adw_combo_row_set_selected (self->month_row, self->month - 1);
+ gtk_label_set_text (GTK_LABEL (self->datetime_label), label);
+}
+
+static void
+set_time_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcDateTimePanel *self = user_data;
+ g_autoptr(GError) error = NULL;
+
+ if (!timedate1_call_set_time_finish (self->dtm,
+ res,
+ &error))
+ {
+ /* TODO: display any error in a user friendly way */
+ g_warning ("Could not set system time: %s", error->message);
+ }
+ else
+ {
+ update_time (self);
+ }
+}
+
+static void
+set_timezone_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcDateTimePanel *self = user_data;
+ g_autoptr(GError) error = NULL;
+
+ if (!timedate1_call_set_timezone_finish (self->dtm,
+ res,
+ &error))
+ {
+ /* TODO: display any error in a user friendly way */
+ g_warning ("Could not set system timezone: %s", error->message);
+ }
+}
+
+static void
+set_using_ntp_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcDateTimePanel *self = user_data;
+ g_autoptr(GError) error = NULL;
+
+ if (!timedate1_call_set_ntp_finish (self->dtm,
+ res,
+ &error))
+ {
+ /* TODO: display any error in a user friendly way */
+ g_warning ("Could not set system to use NTP: %s", error->message);
+ }
+}
+
+static void
+queue_set_datetime (CcDateTimePanel *self)
+{
+ gint64 unixtime;
+
+ /* timedated expects number of microseconds since 1 Jan 1970 UTC */
+ unixtime = g_date_time_to_unix (self->date);
+
+ timedate1_call_set_time (self->dtm,
+ unixtime * 1000000,
+ FALSE,
+ TRUE,
+ self->cancellable,
+ set_time_cb,
+ self);
+}
+
+static void
+queue_set_ntp (CcDateTimePanel *self)
+{
+ gboolean using_ntp;
+ /* for now just do it */
+ using_ntp = gtk_switch_get_active (GTK_SWITCH (self->network_time_switch));
+
+ timedate1_call_set_ntp (self->dtm,
+ using_ntp,
+ TRUE,
+ self->cancellable,
+ set_using_ntp_cb,
+ self);
+}
+
+static void
+queue_set_timezone (CcDateTimePanel *self)
+{
+ /* for now just do it */
+ if (self->current_location)
+ {
+ timedate1_call_set_timezone (self->dtm,
+ self->current_location->zone,
+ TRUE,
+ self->cancellable,
+ set_timezone_cb,
+ self);
+ }
+}
+
+static void
+change_date (CcDateTimePanel *self)
+{
+ guint y, d;
+ g_autoptr(GDateTime) old_date = NULL;
+
+ y = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (self->year_spinbutton));
+ d = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (self->day_spinbutton));
+
+ old_date = self->date;
+ self->date = g_date_time_new_local (y, self->month, d,
+ g_date_time_get_hour (old_date),
+ g_date_time_get_minute (old_date),
+ g_date_time_get_second (old_date));
+ cc_time_editor_set_time (CC_TIME_EDITOR (self->time_editor),
+ g_date_time_get_hour (self->date),
+ g_date_time_get_minute (self->date));
+
+ queue_set_datetime (self);
+}
+
+static gboolean
+city_changed_cb (CcDateTimePanel *self,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ GtkEntryCompletion *completion)
+{
+ GtkWidget *entry;
+ g_autofree gchar *zone = NULL;
+
+ gtk_tree_model_get (model, iter,
+ CITY_COL_ZONE, &zone, -1);
+ cc_timezone_map_set_timezone (CC_TIMEZONE_MAP (self->map), zone);
+
+ entry = gtk_entry_completion_get_entry (completion);
+ gtk_editable_set_text (GTK_EDITABLE (entry), "");
+
+ return TRUE;
+}
+
+static char *
+translated_city_name (TzLocation *loc)
+{
+ g_autofree gchar *zone_translated = NULL;
+ g_auto(GStrv) split_translated = NULL;
+ g_autofree gchar *country = NULL;
+ gchar *name;
+ gint length;
+
+ /* Load the translation for it */
+ zone_translated = g_strdup (dgettext (GETTEXT_PACKAGE_TIMEZONES, loc->zone));
+ g_strdelimit (zone_translated, "_", ' ');
+ split_translated = g_regex_split_simple ("[\\x{2044}\\x{2215}\\x{29f8}\\x{ff0f}/]",
+ zone_translated,
+ 0, 0);
+
+ length = g_strv_length (split_translated);
+
+ country = gnome_get_country_from_code (loc->country, NULL);
+ /* Translators: "city, country" */
+ name = g_strdup_printf (C_("timezone loc", "%s, %s"),
+ split_translated[length-1],
+ country);
+
+ return name;
+}
+
+static void
+update_timezone (CcDateTimePanel *self)
+{
+ g_autofree gchar *bubble_text = NULL;
+ g_autofree gchar *city_country = NULL;
+ g_autofree gchar *label = NULL;
+ g_autofree gchar *time_label = NULL;
+ g_autofree gchar *utc_label = NULL;
+ g_autofree gchar *tz_desc = NULL;
+ gboolean use_ampm;
+
+ if (self->clock_format == G_DESKTOP_CLOCK_FORMAT_12H)
+ use_ampm = TRUE;
+ else
+ use_ampm = FALSE;
+
+ city_country = translated_city_name (self->current_location);
+
+ /* Update the timezone on the listbow row */
+ /* Translators: "timezone (details)" */
+ label = g_strdup_printf (C_("timezone desc", "%s (%s)"),
+ g_date_time_get_timezone_abbreviation (self->date),
+ city_country);
+ gtk_label_set_text (GTK_LABEL (self->timezone_label), label);
+
+ /* Translators: UTC here means the Coordinated Universal Time.
+ * %:::z will be replaced by the offset from UTC e.g. UTC+02 */
+ utc_label = g_date_time_format (self->date, _("UTC%:::z"));
+
+ if (use_ampm)
+ {
+ /* Translators: This is the time format used in 12-hour mode. */
+ time_label = g_date_time_format (self->date, _("%l:%M %p"));
+ }
+ else
+ {
+ /* Translators: This is the time format used in 24-hour mode. */
+ time_label = g_date_time_format (self->date, _("%R"));
+ }
+
+ /* Update the text bubble in the timezone map */
+ /* Translators: "timezone (utc shift)" */
+ tz_desc = g_strdup_printf (C_("timezone map", "%s (%s)"),
+ g_date_time_get_timezone_abbreviation (self->date),
+ utc_label);
+ bubble_text = g_strdup_printf ("<b>%s</b>\n"
+ "<small>%s</small>\n"
+ "<b>%s</b>",
+ tz_desc,
+ city_country,
+ time_label);
+ cc_timezone_map_set_bubble_text (CC_TIMEZONE_MAP (self->map), bubble_text);
+}
+
+static void
+location_changed_cb (CcDateTimePanel *self,
+ TzLocation *location)
+{
+ g_autoptr(GDateTime) old_date = NULL;
+ g_autoptr(GTimeZone) timezone = NULL;
+
+ g_debug ("location changed to %s/%s", location->country, location->zone);
+
+ self->current_location = location;
+
+ timezone = g_time_zone_new_identifier (location->zone);
+ if (!timezone)
+ {
+ g_warning ("Could not find timezone \"%s\", using UTC instead", location->zone);
+ timezone = g_time_zone_new_utc ();
+ }
+
+ old_date = self->date;
+ self->date = g_date_time_to_timezone (old_date, timezone);
+ cc_time_editor_set_time (CC_TIME_EDITOR (self->time_editor),
+ g_date_time_get_hour (self->date),
+ g_date_time_get_minute (self->date));
+
+ update_timezone (self);
+ queue_set_timezone (self);
+}
+
+static void
+get_initial_timezone (CcDateTimePanel *self)
+{
+ const gchar *timezone;
+
+ timezone = timedate1_get_timezone (self->dtm);
+
+ if (timezone == NULL ||
+ !cc_timezone_map_set_timezone (CC_TIMEZONE_MAP (self->map), timezone))
+ {
+ g_warning ("Timezone '%s' is unhandled, setting %s as default", timezone ? timezone : "(null)", DEFAULT_TZ);
+ cc_timezone_map_set_timezone (CC_TIMEZONE_MAP (self->map), DEFAULT_TZ);
+ }
+ self->current_location = cc_timezone_map_get_location (CC_TIMEZONE_MAP (self->map));
+ update_timezone (self);
+}
+
+static void
+load_cities (TzLocation *loc,
+ GtkListStore *city_store)
+{
+ g_autofree gchar *human_readable = NULL;
+
+ human_readable = translated_city_name (loc);
+ gtk_list_store_insert_with_values (city_store, NULL, 0,
+ CITY_COL_CITY_HUMAN_READABLE, human_readable,
+ CITY_COL_ZONE, loc->zone,
+ -1);
+}
+
+static void
+load_regions_model (GtkListStore *cities)
+{
+ g_autoptr(TzDB) db = NULL;
+
+ db = tz_load_db ();
+ g_ptr_array_foreach (db->locations, (GFunc) load_cities, cities);
+}
+
+static void
+day_changed (CcDateTimePanel *panel)
+{
+ change_date (panel);
+}
+
+static void
+month_year_changed (CcDateTimePanel *self)
+{
+ guint y;
+ guint num_days;
+ GtkAdjustment *adj;
+ GtkSpinButton *day_spin;
+
+ y = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (self->year_spinbutton));
+
+ /* Check the number of days in that month */
+ num_days = g_date_get_days_in_month (self->month, y);
+
+ day_spin = GTK_SPIN_BUTTON (self->day_spinbutton);
+ adj = GTK_ADJUSTMENT (gtk_spin_button_get_adjustment (day_spin));
+ gtk_adjustment_set_upper (adj, num_days + 1);
+
+ if (gtk_spin_button_get_value_as_int (day_spin) > num_days)
+ gtk_spin_button_set_value (day_spin, num_days);
+
+ change_date (self);
+}
+
+static void
+on_month_row_selected_changed_cb (AdwComboRow *month_row,
+ GParamSpec *pspec,
+ CcDateTimePanel *self)
+{
+ unsigned int i;
+
+ g_assert (CC_IS_DATE_TIME_PANEL (self));
+ g_assert (ADW_IS_COMBO_ROW (month_row));
+
+ i = adw_combo_row_get_selected (month_row);
+ g_assert (i >= 0 && i < 12);
+
+ self->month = i + 1;
+ month_year_changed (self);
+}
+
+static void
+on_clock_changed (CcDateTimePanel *panel,
+ GParamSpec *pspec)
+{
+ g_date_time_unref (panel->date);
+ panel->date = g_date_time_new_now_local ();
+ update_time (panel);
+ update_timezone (panel);
+}
+
+static gboolean
+change_ntp (CcDateTimePanel *self)
+{
+ queue_set_ntp (self);
+
+ /* The new state will be visible once we see the reply. */
+ return TRUE;
+}
+
+static void
+on_ntp_changed (CcDateTimePanel *self)
+{
+ gboolean ntp_on;
+
+ g_object_get (self->dtm, "ntp", &ntp_on, NULL);
+
+ g_signal_handlers_block_by_func (self->network_time_switch, change_ntp, self);
+
+ g_object_set (self->network_time_switch,
+ "state", ntp_on,
+ NULL);
+
+ g_signal_handlers_unblock_by_func (self->network_time_switch, change_ntp, self);
+}
+
+static gboolean
+is_ntp_available (CcDateTimePanel *self)
+{
+ g_autoptr(GVariant) value = NULL;
+ gboolean ntp_available = TRUE;
+
+ /* We need to access this directly so that we can default to TRUE if
+ * it is not set.
+ */
+ value = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self->dtm), "CanNTP");
+ if (value)
+ {
+ if (g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN))
+ ntp_available = g_variant_get_boolean (value);
+ }
+
+ return ntp_available;
+}
+
+static void
+on_permission_changed (CcDateTimePanel *self)
+{
+ gboolean allowed, location_allowed, tz_allowed, auto_timezone, using_ntp;
+
+ allowed = (self->permission != NULL && g_permission_get_allowed (self->permission));
+ location_allowed = g_settings_get_boolean (self->location_settings, LOCATION_ENABLED);
+ tz_allowed = (self->tz_permission != NULL && g_permission_get_allowed (self->tz_permission));
+ using_ntp = gtk_switch_get_active (GTK_SWITCH (self->network_time_switch));
+ auto_timezone = gtk_switch_get_active (GTK_SWITCH (self->auto_timezone_switch));
+
+ /* All the widgets but the lock button and the 24h setting */
+ gtk_widget_set_sensitive (self->auto_datetime_row, allowed);
+ gtk_widget_set_sensitive (self->auto_timezone_row, location_allowed && (allowed || tz_allowed));
+ gtk_widget_set_sensitive (self->datetime_button, allowed && !using_ntp);
+ gtk_widget_set_sensitive (self->timezone_button, (allowed || tz_allowed) && (!auto_timezone || !location_allowed));
+
+ /* Hide the subdialogs if we no longer have permissions */
+ if (!allowed)
+ gtk_widget_hide (GTK_WIDGET (self->datetime_dialog));
+ if (!allowed && !tz_allowed)
+ gtk_widget_hide (GTK_WIDGET (self->timezone_dialog));
+}
+
+static void
+on_location_settings_changed (CcDateTimePanel *panel)
+{
+ on_permission_changed (panel);
+}
+
+static void
+on_can_ntp_changed (CcDateTimePanel *self)
+{
+ gtk_widget_set_visible (self->auto_datetime_row, is_ntp_available (self));
+}
+
+static void
+on_timezone_changed (CcDateTimePanel *self)
+{
+ g_signal_handlers_block_by_func (self->map, location_changed_cb, self);
+ get_initial_timezone (self);
+ g_signal_handlers_unblock_by_func (self->map, location_changed_cb, self);
+}
+
+static void
+on_timedated_properties_changed (CcDateTimePanel *self,
+ GVariant *changed_properties,
+ const gchar **invalidated_properties)
+{
+ guint i;
+
+ if (invalidated_properties != NULL)
+ for (i = 0; invalidated_properties[i] != NULL; i++) {
+ g_autoptr(GVariant) variant = NULL;
+ g_autoptr(GError) error = NULL;
+
+ /* See https://bugs.freedesktop.org/show_bug.cgi?id=37632 for the reason why we're doing this */
+ variant = g_dbus_proxy_call_sync (G_DBUS_PROXY (self->dtm),
+ "org.freedesktop.DBus.Properties.Get",
+ g_variant_new ("(ss)", "org.freedesktop.timedate1", invalidated_properties[i]),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+ if (variant == NULL)
+ g_warning ("Failed to get property '%s': %s", invalidated_properties[i], error->message);
+ else {
+ GVariant *v;
+
+ g_variant_get (variant, "(v)", &v);
+ g_dbus_proxy_set_cached_property (G_DBUS_PROXY (self->dtm), invalidated_properties[i], v);
+ }
+ }
+}
+
+static void
+run_dialog (CcDateTimePanel *self,
+ GtkWidget *dialog)
+{
+ GtkWidget *parent;
+
+ parent = cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (self)));
+
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent));
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+static gboolean
+tz_switch_to_row_transform_func (GBinding *binding,
+ const GValue *source_value,
+ GValue *target_value,
+ CcDateTimePanel *self)
+{
+ gboolean active;
+ gboolean allowed;
+ gboolean location_allowed;
+
+ active = g_value_get_boolean (source_value);
+ allowed = (self->permission != NULL && g_permission_get_allowed (self->permission)) ||
+ (self->tz_permission != NULL && g_permission_get_allowed (self->tz_permission));
+ location_allowed = g_settings_get_boolean (self->location_settings, LOCATION_ENABLED);
+
+ g_value_set_boolean (target_value, allowed && (!active || !location_allowed));
+
+ return TRUE;
+}
+
+static gboolean
+switch_to_row_transform_func (GBinding *binding,
+ const GValue *source_value,
+ GValue *target_value,
+ CcDateTimePanel *self)
+{
+ gboolean active;
+ gboolean allowed;
+
+ active = g_value_get_boolean (source_value);
+ allowed = (self->permission != NULL && g_permission_get_allowed (self->permission));
+
+ g_value_set_boolean (target_value, !active && allowed);
+
+ return TRUE;
+}
+
+static void
+bind_switch_to_row (CcDateTimePanel *self,
+ GtkWidget *gtkswitch,
+ GtkWidget *listrow)
+{
+ g_object_bind_property_full (gtkswitch, "active",
+ listrow, "sensitive",
+ G_BINDING_SYNC_CREATE,
+ (GBindingTransformFunc) switch_to_row_transform_func,
+ NULL, self, NULL);
+}
+
+static void
+list_box_row_activated (CcDateTimePanel *self,
+ GtkListBoxRow *row)
+
+{
+ if (row == GTK_LIST_BOX_ROW (self->datetime_button))
+ {
+ run_dialog (self, self->datetime_dialog);
+ }
+ else if (row == GTK_LIST_BOX_ROW (self->timezone_button))
+ {
+ run_dialog (self, self->timezone_dialog);
+ }
+}
+
+static void
+time_changed_cb (CcDateTimePanel *self,
+ CcTimeEditor *editor)
+{
+ g_autoptr(GDateTime) old_date = NULL;
+
+ g_assert (CC_IS_DATE_TIME_PANEL (self));
+ g_assert (CC_IS_TIME_EDITOR (editor));
+
+ old_date = self->date;
+ self->date = g_date_time_new_local (g_date_time_get_year (old_date),
+ g_date_time_get_month (old_date),
+ g_date_time_get_day_of_month (old_date),
+ cc_time_editor_get_hour (CC_TIME_EDITOR (self->time_editor)),
+ cc_time_editor_get_minute (CC_TIME_EDITOR (self->time_editor)),
+ g_date_time_get_second (old_date));
+
+ update_time (self);
+ queue_set_datetime (self);
+}
+
+static void
+setup_timezone_dialog (CcDateTimePanel *self)
+{
+ g_autoptr(GtkEntryCompletion) completion = NULL;
+
+ /* set up timezone map */
+ self->map = (GtkWidget *) cc_timezone_map_new ();
+ gtk_frame_set_child (self->aspectmap, self->map);
+
+ /* Create the completion object */
+ completion = gtk_entry_completion_new ();
+ gtk_entry_set_completion (GTK_ENTRY (self->timezone_searchentry), completion);
+
+ gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (self->city_modelsort));
+
+ gtk_entry_completion_set_text_column (completion, CITY_COL_CITY_HUMAN_READABLE);
+}
+
+static void
+setup_datetime_dialog (CcDateTimePanel *self)
+{
+ GtkAdjustment *adjustment;
+ GdkDisplay *display;
+ g_autoptr(GtkCssProvider) provider = NULL;
+ guint num_days;
+
+ /* Big time buttons */
+ provider = gtk_css_provider_new ();
+ gtk_css_provider_load_from_data (GTK_CSS_PROVIDER (provider),
+ ".gnome-control-center-datetime-setup-time>spinbutton,\n"
+ ".gnome-control-center-datetime-setup-time>label {\n"
+ " font-size: 250%;\n"
+ "}\n"
+ ".gnome-control-center-datetime-setup-time>spinbutton>entry {\n"
+ " padding: 8px 13px;\n"
+ "}", -1);
+ display = gdk_display_get_default ();
+ gtk_style_context_add_provider_for_display (display,
+ GTK_STYLE_PROVIDER (provider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+ /* Day */
+ num_days = g_date_get_days_in_month (g_date_time_get_month (self->date),
+ g_date_time_get_year (self->date));
+ adjustment = (GtkAdjustment*) gtk_adjustment_new (g_date_time_get_day_of_month (self->date), 1,
+ num_days + 1, 1, 10, 1);
+ gtk_spin_button_set_adjustment (GTK_SPIN_BUTTON (self->day_spinbutton),
+ adjustment);
+ g_signal_connect_object (G_OBJECT (self->day_spinbutton), "value-changed",
+ G_CALLBACK (day_changed), self, G_CONNECT_SWAPPED);
+
+ /* Year */
+ adjustment = (GtkAdjustment*) gtk_adjustment_new (g_date_time_get_year (self->date),
+ 1, G_MAXDOUBLE, 1,
+ 10, 1);
+ gtk_spin_button_set_adjustment (GTK_SPIN_BUTTON (self->year_spinbutton),
+ adjustment);
+ g_signal_connect_object (G_OBJECT (self->year_spinbutton), "value-changed",
+ G_CALLBACK (month_year_changed), self, G_CONNECT_SWAPPED);
+
+ /* Month */
+ self->month = g_date_time_get_month (self->date);
+ adw_combo_row_set_selected (self->month_row, self->month - 1);
+}
+
+static int
+sort_date_box (GtkListBoxRow *a,
+ GtkListBoxRow *b,
+ CcDateTimePanel *self)
+{
+ GtkListBoxRow *month_row;
+
+ g_assert (CC_IS_DATE_TIME_PANEL (self));
+
+ month_row = GTK_LIST_BOX_ROW (self->month_row);
+
+ switch (date_endian_get_default (FALSE)) {
+ case DATE_ENDIANESS_BIG:
+ /* year, month, day */
+ if (a == self->year_row || b == self->day_row)
+ return -1;
+ if (a == self->day_row || b == self->year_row)
+ return 1;
+
+ case DATE_ENDIANESS_LITTLE:
+ /* day, month, year */
+ if (a == self->day_row || b == self->year_row)
+ return -1;
+ if (a == self->year_row || b == self->day_row)
+ return 1;
+
+ case DATE_ENDIANESS_MIDDLE:
+ /* month, day, year */
+ if (a == month_row || b == self->year_row)
+ return -1;
+ if (a == self->year_row || b == month_row)
+ return 1;
+
+ case DATE_ENDIANESS_YDM:
+ /* year, day, month */
+ if (a == self->year_row || b == month_row)
+ return -1;
+ if (a == month_row || b == self->year_row)
+ return 1;
+ }
+
+ return 0;
+}
+
+static void
+cc_date_time_panel_class_init (CcDateTimePanelClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+
+ object_class->dispose = cc_date_time_panel_dispose;
+
+ panel_class->get_help_uri = cc_date_time_panel_get_help_uri;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/datetime/cc-datetime-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, aspectmap);
+ gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, auto_datetime_row);
+ gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, auto_timezone_row);
+ gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, auto_timezone_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, city_liststore);
+ gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, city_modelsort);
+ gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, date_box);
+ gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, datetime_button);
+ gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, datetime_dialog);
+ gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, datetime_label);
+ gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, day_row);
+ gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, day_spinbutton);
+ gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, timeformat_row);
+ gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, lock_button);
+ gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, month_row);
+ gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, network_time_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, time_editor);
+ gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, timezone_button);
+ gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, timezone_dialog);
+ gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, timezone_label);
+ gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, timezone_searchentry);
+ gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, year_row);
+ gtk_widget_class_bind_template_child (widget_class, CcDateTimePanel, year_spinbutton);
+
+ gtk_widget_class_bind_template_callback (widget_class, list_box_row_activated);
+ gtk_widget_class_bind_template_callback (widget_class, time_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, change_clock_settings);
+ gtk_widget_class_bind_template_callback (widget_class, format_clock_name_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_month_row_selected_changed_cb);
+
+ bind_textdomain_codeset (GETTEXT_PACKAGE_TIMEZONES, "UTF-8");
+
+ g_type_ensure (CC_TYPE_TIME_EDITOR);
+}
+
+static void
+cc_date_time_panel_init (CcDateTimePanel *self)
+{
+ g_autoptr(GError) error = NULL;
+
+ g_resources_register (cc_datetime_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->cancellable = g_cancellable_new ();
+ error = NULL;
+ self->dtm = timedate1_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "org.freedesktop.timedate1",
+ "/org/freedesktop/timedate1",
+ self->cancellable,
+ &error);
+ if (self->dtm == NULL) {
+ g_warning ("could not get proxy for DateTimeMechanism: %s", error->message);
+ return;
+ }
+
+ gtk_list_box_set_sort_func (self->date_box,
+ (GtkListBoxSortFunc)sort_date_box,
+ self, NULL);
+ gtk_list_box_invalidate_sort (self->date_box);
+
+ /* add the lock button */
+ self->permission = polkit_permission_new_sync (DATETIME_PERMISSION, NULL, NULL, NULL);
+ self->tz_permission = polkit_permission_new_sync (DATETIME_TZ_PERMISSION, NULL, NULL, NULL);
+ if (self->permission != NULL)
+ {
+ g_signal_connect_object (self->permission, "notify",
+ G_CALLBACK (on_permission_changed), self, G_CONNECT_SWAPPED);
+ }
+ else
+ {
+ g_warning ("Your system does not have the '%s' PolicyKit files installed. Please check your installation",
+ DATETIME_PERMISSION);
+ }
+ gtk_lock_button_set_permission (GTK_LOCK_BUTTON (self->lock_button), self->permission);
+
+ self->location_settings = g_settings_new (LOCATION_SETTINGS);
+ g_signal_connect_object (self->location_settings, "changed",
+ G_CALLBACK (on_location_settings_changed), self, G_CONNECT_SWAPPED);
+ on_location_settings_changed (self);
+
+ self->date = g_date_time_new_now_local ();
+
+ /* Top level windows from GtkBuilder that need to be destroyed explicitly */
+ self->toplevels = g_list_append (self->toplevels, self->datetime_dialog);
+ self->toplevels = g_list_append (self->toplevels, self->timezone_dialog);
+
+ setup_timezone_dialog (self);
+ setup_datetime_dialog (self);
+
+ /* set up network time switch */
+ bind_switch_to_row (self,
+ self->network_time_switch,
+ self->datetime_button);
+ g_signal_connect_object (self->dtm, "notify::ntp",
+ G_CALLBACK (on_ntp_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->network_time_switch, "state-set",
+ G_CALLBACK (change_ntp), self, G_CONNECT_SWAPPED);
+ on_ntp_changed (self);
+
+ gtk_widget_set_visible (self->auto_datetime_row, is_ntp_available (self));
+
+ /* Timezone settings */
+ g_object_bind_property_full (self->auto_timezone_switch, "active",
+ self->timezone_button, "sensitive",
+ G_BINDING_SYNC_CREATE,
+ (GBindingTransformFunc) tz_switch_to_row_transform_func,
+ NULL, self, NULL);
+
+ self->datetime_settings = g_settings_new (DATETIME_SCHEMA);
+ g_settings_bind (self->datetime_settings, AUTO_TIMEZONE_KEY,
+ self->auto_timezone_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ /* Clock settings */
+ self->clock_settings = g_settings_new (CLOCK_SCHEMA);
+
+ /* setup the time itself */
+ self->clock_tracker = g_object_new (GNOME_TYPE_WALL_CLOCK, NULL);
+ g_signal_connect_object (self->clock_tracker, "notify::clock", G_CALLBACK (on_clock_changed), self, G_CONNECT_SWAPPED);
+
+ clock_settings_changed_cb (self, CLOCK_FORMAT_KEY);
+ g_signal_connect_object (self->clock_settings, "changed::" CLOCK_FORMAT_KEY,
+ G_CALLBACK (clock_settings_changed_cb), self, G_CONNECT_SWAPPED);
+
+ update_time (self);
+
+ load_regions_model (GTK_LIST_STORE (self->city_liststore));
+
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (self->city_modelsort), CITY_COL_CITY_HUMAN_READABLE,
+ GTK_SORT_ASCENDING);
+
+ /* After the initial setup, so we can be sure that
+ * the model is filled up */
+ get_initial_timezone (self);
+
+ g_signal_connect_object (gtk_entry_get_completion (GTK_ENTRY (self->timezone_searchentry)),
+ "match-selected", G_CALLBACK (city_changed_cb), self, G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self->map, "location-changed",
+ G_CALLBACK (location_changed_cb), self, G_CONNECT_SWAPPED);
+
+ /* Watch changes of timedated remote service properties */
+ g_signal_connect_object (self->dtm, "g-properties-changed",
+ G_CALLBACK (on_timedated_properties_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->dtm, "notify::can-ntp",
+ G_CALLBACK (on_can_ntp_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->dtm, "notify::timezone",
+ G_CALLBACK (on_timezone_changed), self, G_CONNECT_SWAPPED);
+ /* We ignore UTC <--> LocalRTC changes at the moment */
+
+ self->filechooser_settings = g_settings_new (FILECHOOSER_SCHEMA);
+}
diff --git a/panels/datetime/cc-datetime-panel.h b/panels/datetime/cc-datetime-panel.h
new file mode 100644
index 0000000..a726e6b
--- /dev/null
+++ b/panels/datetime/cc-datetime-panel.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2010 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ *
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_DATE_TIME_PANEL (cc_date_time_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcDateTimePanel, cc_date_time_panel, CC, DATE_TIME_PANEL, CcPanel)
+
+G_END_DECLS
diff --git a/panels/datetime/cc-datetime-panel.ui b/panels/datetime/cc-datetime-panel.ui
new file mode 100644
index 0000000..fa5a6c9
--- /dev/null
+++ b/panels/datetime/cc-datetime-panel.ui
@@ -0,0 +1,263 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <object class="GtkListStore" id="city_liststore">
+ <columns>
+ <!-- column-name city-human-readable -->
+ <column type="gchararray"/>
+ <!-- column-name zone -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkTreeModelSort" id="city_modelsort">
+ <property name="model">city_liststore</property>
+ </object>
+ <object class="GtkDialog" id="datetime_dialog">
+ <property name="title" translatable="yes">Date &amp; Time</property>
+ <property name="modal">True</property>
+ <property name="hide-on-close">True</property>
+ <property name="use_header_bar">1</property>
+ <child>
+ <object class="GtkBox" id="dialog_vbox2">
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <property name="margin_top">28</property>
+ <property name="margin_bottom">28</property>
+ <property name="margin_start">12</property>
+ <property name="margin_end">12</property>
+ <property name="spacing">18</property>
+ <child>
+ <object class="CcTimeEditor" id="time_editor">
+ <property name="halign">center</property>
+ <signal name="time-changed" handler="time_changed_cb" swapped="yes"/>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwClamp">
+ <property name="maximum-size">600</property>
+
+ <child>
+ <object class="GtkListBox" id="date_box">
+ <property name="width-request">320</property>
+ <property name="selection-mode">none</property>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+
+ <!-- Year row -->
+ <child>
+ <object class="AdwActionRow" id="year_row">
+ <property name="title" translatable="yes">Year</property>
+ <property name="activatable-widget">year_spinbutton</property>
+
+ <child>
+ <object class="GtkSpinButton" id="year_spinbutton">
+ <property name="valign">center</property>
+ <property name="width-chars">4</property>
+ <property name="numeric">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- Month row -->
+ <child>
+ <object class="AdwComboRow" id="month_row">
+ <property name="title" translatable="yes">Month</property>
+ <signal name="notify::selected" handler="on_month_row_selected_changed_cb" object="CcDateTimePanel" swapped="no" />
+ <property name="model">
+ <object class="GtkStringList">
+ <items>
+ <item translatable="yes">January</item>
+ <item translatable="yes">February</item>
+ <item translatable="yes">March</item>
+ <item translatable="yes">April</item>
+ <item translatable="yes">May</item>
+ <item translatable="yes">June</item>
+ <item translatable="yes">July</item>
+ <item translatable="yes">August</item>
+ <item translatable="yes">September</item>
+ <item translatable="yes">October</item>
+ <item translatable="yes">November</item>
+ <item translatable="yes">December</item>
+ </items>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <!-- Day row -->
+ <child>
+ <object class="AdwActionRow" id="day_row">
+ <property name="title" translatable="yes">Day</property>
+ <property name="activatable-widget">day_spinbutton</property>
+ <child>
+ <object class="GtkSpinButton" id="day_spinbutton">
+ <property name="valign">center</property>
+ <property name="width-chars">3</property>
+ <property name="numeric">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <object class="GtkDialog" id="timezone_dialog">
+ <property name="title" translatable="yes">Time Zone</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="use_header_bar">1</property>
+ <property name="hide-on-close">True</property>
+ <child internal-child="headerbar">
+ <object class="GtkHeaderBar" id="dialog_header_bar">
+ <property name="show-title-buttons">True</property>
+ <child type="title">
+ <object class="GtkEntry" id="timezone_searchentry">
+ <property name="halign">center</property>
+ <property name="margin_start">5</property>
+ <property name="margin_end">5</property>
+ <property name="width_chars">40</property>
+ <property name="primary_icon_name">edit-find-symbolic</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">False</property>
+ <property name="placeholder_text" translatable="yes">Search for a city</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="dialog_vbox7">
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkFrame" id="aspectmap">
+ <property name="margin_start">5</property>
+ <property name="margin_end">5</property>
+ <property name="margin_top">5</property>
+ <property name="margin_bottom">5</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <template class="CcDateTimePanel" parent="CcPanel">
+
+ <child type="titlebar-end">
+ <object class="GtkLockButton" id="lock_button">
+ <property name="valign">center</property>
+ </object>
+ </child>
+
+ <child type="content">
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="AdwActionRow" id="auto_datetime_row">
+ <property name="title" translatable="yes">Automatic _Date &amp;amp; Time</property>
+ <property name="subtitle" translatable="yes">Requires internet access</property>
+ <property name="use_underline">True</property>
+ <property name="activatable_widget">network_time_switch</property>
+ <child>
+ <object class="GtkSwitch" id="network_time_switch">
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Enable</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="datetime_button">
+ <property name="title" translatable="yes">Date &amp;amp; _Time</property>
+ <property name="use_underline">True</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="list_box_row_activated" swapped="yes"/>
+ <child>
+ <object class="GtkLabel" id="datetime_label">
+ <property name="xalign">0</property>
+ <property name="label">20 June 2012, 6:45 AM</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="valign">center</property>
+ <property name="icon-name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="AdwActionRow" id="auto_timezone_row">
+ <property name="title" translatable="yes">Automatic Time _Zone</property>
+ <property name="subtitle" translatable="yes">Requires location services enabled and internet access</property>
+ <property name="use_underline">True</property>
+ <property name="activatable_widget">auto_timezone_switch</property>
+ <child>
+ <object class="GtkSwitch" id="auto_timezone_switch">
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Enabled</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="timezone_button">
+ <property name="title" translatable="yes">Time Z_one</property>
+ <property name="use_underline">True</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="list_box_row_activated" swapped="yes"/>
+ <child>
+ <object class="GtkLabel" id="timezone_label">
+ <property name="ellipsize">end</property>
+ <property name="xalign">0</property>
+ <property name="label">GMT+1 (London, United Kingdom)</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="valign">center</property>
+ <property name="icon-name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="AdwComboRow" id="timeformat_row">
+ <property name="title" translatable="yes">Time _Format</property>
+ <property name="use_underline">True</property>
+ <signal name="notify::selected-item" handler="change_clock_settings" object="CcDateTimePanel" swapped="no"/>
+ <property name="model">
+ <object class="AdwEnumListModel">
+ <property name="enum_type">GDesktopClockFormat</property>
+ </object>
+ </property>
+ <property name="expression">
+ <closure type="gchararray" function="format_clock_name_cb"/>
+ </property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/datetime/cc-timezone-map.c b/panels/datetime/cc-timezone-map.c
new file mode 100644
index 0000000..863b4c9
--- /dev/null
+++ b/panels/datetime/cc-timezone-map.c
@@ -0,0 +1,530 @@
+/*
+ * Copyright (C) 2010 Intel, Inc
+ *
+ * Portions from Ubiquity, Copyright (C) 2009 Canonical Ltd.
+ * Written by Evan Dandrea <evand@ubuntu.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ *
+ */
+
+#include "cc-timezone-map.h"
+#include <math.h>
+#include <string.h>
+#include "tz.h"
+
+#define PIN_HOT_POINT_X 8
+#define PIN_HOT_POINT_Y 15
+
+#define DATETIME_RESOURCE_PATH "/org/gnome/control-center/datetime"
+
+typedef struct
+{
+ gdouble offset;
+ guchar red;
+ guchar green;
+ guchar blue;
+ guchar alpha;
+} CcTimezoneMapOffset;
+
+struct _CcTimezoneMap
+{
+ GtkWidget parent_instance;
+
+ GdkTexture *orig_background;
+ GdkTexture *orig_background_dim;
+
+ GdkTexture *background;
+ GdkTexture *pin;
+
+ TzDB *tzdb;
+ TzLocation *location;
+
+ gchar *bubble_text;
+};
+
+G_DEFINE_TYPE (CcTimezoneMap, cc_timezone_map, GTK_TYPE_WIDGET)
+
+enum
+{
+ LOCATION_CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+static GdkTexture *
+texture_from_resource (const gchar *resource_path,
+ GError **error)
+{
+ g_autofree gchar *full_path = g_strdup_printf ("resource://%s", resource_path);
+ g_autoptr(GFile) file = g_file_new_for_uri (full_path);
+ g_autoptr(GdkTexture) texture = gdk_texture_new_from_file (file, error);
+
+ return g_steal_pointer (&texture);
+}
+
+static void
+cc_timezone_map_dispose (GObject *object)
+{
+ CcTimezoneMap *self = CC_TIMEZONE_MAP (object);
+
+ g_clear_object (&self->orig_background);
+ g_clear_object (&self->orig_background_dim);
+ g_clear_object (&self->background);
+ g_clear_object (&self->pin);
+ g_clear_pointer (&self->bubble_text, g_free);
+
+ G_OBJECT_CLASS (cc_timezone_map_parent_class)->dispose (object);
+}
+
+static void
+cc_timezone_map_finalize (GObject *object)
+{
+ CcTimezoneMap *self = CC_TIMEZONE_MAP (object);
+
+ g_clear_pointer (&self->tzdb, tz_db_free);
+
+ G_OBJECT_CLASS (cc_timezone_map_parent_class)->finalize (object);
+}
+
+/* GtkWidget functions */
+static void
+cc_timezone_map_measure (GtkWidget *widget,
+ GtkOrientation orientation,
+ gint for_size,
+ gint *minimum,
+ gint *natural,
+ gint *minimum_baseline,
+ gint *natural_baseline)
+{
+ CcTimezoneMap *map = CC_TIMEZONE_MAP (widget);
+ gint size;
+
+ switch (orientation)
+ {
+ case GTK_ORIENTATION_HORIZONTAL:
+ size = gdk_texture_get_width (map->orig_background);
+ break;
+
+ case GTK_ORIENTATION_VERTICAL:
+ size = gdk_texture_get_height (map->orig_background);
+ break;
+ }
+
+ if (minimum != NULL)
+ *minimum = size;
+ if (natural != NULL)
+ *natural = size;
+}
+
+static void
+cc_timezone_map_size_allocate (GtkWidget *widget,
+ gint width,
+ gint height,
+ gint baseline)
+{
+ CcTimezoneMap *map = CC_TIMEZONE_MAP (widget);
+ GdkTexture *texture;
+
+ if (!gtk_widget_is_sensitive (widget))
+ texture = map->orig_background_dim;
+ else
+ texture = map->orig_background;
+
+ g_clear_object (&map->background);
+ map->background = g_object_ref (texture);
+
+ GTK_WIDGET_CLASS (cc_timezone_map_parent_class)->size_allocate (widget,
+ width,
+ height,
+ baseline);
+}
+
+static gdouble
+convert_longitude_to_x (gdouble longitude, gint map_width)
+{
+ const gdouble xdeg_offset = -6;
+ gdouble x;
+
+ x = (map_width * (180.0 + longitude) / 360.0)
+ + (map_width * xdeg_offset / 180.0);
+
+ return x;
+}
+
+static gdouble
+radians (gdouble degrees)
+{
+ return (degrees / 360.0) * G_PI * 2;
+}
+
+static gdouble
+convert_latitude_to_y (gdouble latitude, gdouble map_height)
+{
+ gdouble bottom_lat = -59;
+ gdouble top_lat = 81;
+ gdouble top_per, y, full_range, top_offset, map_range;
+
+ top_per = top_lat / 180.0;
+ y = 1.25 * log (tan (G_PI_4 + 0.4 * radians (latitude)));
+ full_range = 4.6068250867599998;
+ top_offset = full_range * top_per;
+ map_range = fabs (1.25 * log (tan (G_PI_4 + 0.4 * radians (bottom_lat))) - top_offset);
+ y = fabs (y - top_offset);
+ y = y / map_range;
+ y = y * map_height;
+ return y;
+}
+
+static void
+draw_text_bubble (CcTimezoneMap *map,
+ GtkSnapshot *snapshot,
+ gint width,
+ gint height,
+ gdouble pointx,
+ gdouble pointy)
+{
+ static const double corner_radius = 9.0;
+ static const double margin_top = 12.0;
+ static const double margin_bottom = 12.0;
+ static const double margin_left = 24.0;
+ static const double margin_right = 24.0;
+
+ GskRoundedRect rounded_rect;
+ PangoRectangle text_rect;
+ PangoLayout *layout;
+ GdkRGBA rgba;
+ double x;
+ double y;
+ double bubble_width;
+ double bubble_height;
+
+ if (!map->bubble_text)
+ return;
+
+ layout = gtk_widget_create_pango_layout (GTK_WIDGET (map), NULL);
+
+ /* Layout the text */
+ pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
+ pango_layout_set_spacing (layout, 3);
+ pango_layout_set_markup (layout, map->bubble_text, -1);
+
+ pango_layout_get_pixel_extents (layout, NULL, &text_rect);
+
+ /* Calculate the bubble size based on the text layout size */
+ bubble_width = text_rect.width + margin_left + margin_right;
+ bubble_height = text_rect.height + margin_top + margin_bottom;
+
+ if (pointx < width / 2)
+ x = pointx + 25;
+ else
+ x = pointx - bubble_width - 25;
+
+ y = pointy - bubble_height / 2;
+
+ /* Make sure it fits in the visible area */
+ x = CLAMP (x, 0, width - bubble_width);
+ y = CLAMP (y, 0, height - bubble_height);
+
+ gtk_snapshot_save (snapshot);
+
+ gsk_rounded_rect_init (&rounded_rect,
+ &GRAPHENE_RECT_INIT (x, y, bubble_width, bubble_height),
+ &GRAPHENE_SIZE_INIT (corner_radius, corner_radius),
+ &GRAPHENE_SIZE_INIT (corner_radius, corner_radius),
+ &GRAPHENE_SIZE_INIT (corner_radius, corner_radius),
+ &GRAPHENE_SIZE_INIT (corner_radius, corner_radius));
+
+ gtk_snapshot_push_rounded_clip (snapshot, &rounded_rect);
+
+ rgba = (GdkRGBA) {
+ .red = 0.2,
+ .green = 0.2,
+ .blue = 0.2,
+ .alpha = 0.7,
+ };
+ gtk_snapshot_append_color (snapshot,
+ &rgba,
+ &GRAPHENE_RECT_INIT (x, y, bubble_width, bubble_height));
+
+
+ rgba = (GdkRGBA) {
+ .red = 1.0,
+ .green = 1.0,
+ .blue = 1.0,
+ .alpha = 1.0,
+ };
+ gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x + margin_left, y + margin_top));
+ gtk_snapshot_append_layout (snapshot, layout, &rgba);
+
+ gtk_snapshot_pop (snapshot);
+ gtk_snapshot_restore (snapshot);
+
+ g_object_unref (layout);
+}
+
+static void
+cc_timezone_map_snapshot (GtkWidget *widget,
+ GtkSnapshot *snapshot)
+{
+ CcTimezoneMap *map = CC_TIMEZONE_MAP (widget);
+ gdouble pointx, pointy;
+ gint width, height;
+
+ width = gtk_widget_get_width (widget);
+ height = gtk_widget_get_height (widget);
+
+ /* paint background */
+ gtk_snapshot_append_texture (snapshot,
+ map->background,
+ &GRAPHENE_RECT_INIT (0, 0, width, height));
+
+ if (map->location)
+ {
+ pointx = convert_longitude_to_x (map->location->longitude, width);
+ pointy = convert_latitude_to_y (map->location->latitude, height);
+
+ pointx = CLAMP (floor (pointx), 0, width);
+ pointy = CLAMP (floor (pointy), 0, height);
+
+ draw_text_bubble (map, snapshot, width, height, pointx, pointy);
+
+ if (map->pin)
+ {
+ gtk_snapshot_append_texture (snapshot,
+ map->pin,
+ &GRAPHENE_RECT_INIT (pointx - PIN_HOT_POINT_X,
+ pointy - PIN_HOT_POINT_Y,
+ gdk_texture_get_width (map->pin),
+ gdk_texture_get_height (map->pin)));
+ }
+ }
+}
+
+static void
+update_cursor (GtkWidget *widget)
+{
+ const gchar *cursor_name = NULL;
+
+ if (!gtk_widget_get_realized (widget))
+ return;
+
+ if (gtk_widget_is_sensitive (widget))
+ cursor_name = "pointer";
+
+ gtk_widget_set_cursor_from_name (widget, cursor_name);
+}
+
+static void
+cc_timezone_map_state_flags_changed (GtkWidget *widget,
+ GtkStateFlags prev_state)
+{
+ update_cursor (widget);
+
+ if (GTK_WIDGET_CLASS (cc_timezone_map_parent_class)->state_flags_changed)
+ GTK_WIDGET_CLASS (cc_timezone_map_parent_class)->state_flags_changed (widget, prev_state);
+}
+
+
+static void
+cc_timezone_map_class_init (CcTimezoneMapClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_timezone_map_dispose;
+ object_class->finalize = cc_timezone_map_finalize;
+
+ widget_class->measure = cc_timezone_map_measure;
+ widget_class->size_allocate = cc_timezone_map_size_allocate;
+ widget_class->snapshot = cc_timezone_map_snapshot;
+ widget_class->state_flags_changed = cc_timezone_map_state_flags_changed;
+
+ signals[LOCATION_CHANGED] = g_signal_new ("location-changed",
+ CC_TYPE_TIMEZONE_MAP,
+ G_SIGNAL_RUN_FIRST,
+ 0,
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1,
+ G_TYPE_POINTER);
+}
+
+
+static gint
+sort_locations (TzLocation *a,
+ TzLocation *b)
+{
+ if (a->dist > b->dist)
+ return 1;
+
+ if (a->dist < b->dist)
+ return -1;
+
+ return 0;
+}
+
+static void
+set_location (CcTimezoneMap *map,
+ TzLocation *location)
+{
+ g_autoptr(TzInfo) info = NULL;
+
+ map->location = location;
+
+ info = tz_info_from_location (map->location);
+
+ gtk_widget_queue_draw (GTK_WIDGET (map));
+
+ g_signal_emit (map, signals[LOCATION_CHANGED], 0, map->location);
+}
+
+static gboolean
+map_clicked_cb (GtkGestureClick *self,
+ gint n_press,
+ gdouble x,
+ gdouble y,
+ CcTimezoneMap *map)
+{
+ const GPtrArray *array;
+ gint width, height;
+ GList *distances = NULL;
+ gint i;
+
+ /* work out the coordinates */
+
+ array = tz_get_locations (map->tzdb);
+
+ width = gtk_widget_get_width (GTK_WIDGET (map));
+ height = gtk_widget_get_height (GTK_WIDGET (map));
+
+ for (i = 0; i < array->len; i++)
+ {
+ gdouble pointx, pointy, dx, dy;
+ TzLocation *loc = array->pdata[i];
+
+ pointx = convert_longitude_to_x (loc->longitude, width);
+ pointy = convert_latitude_to_y (loc->latitude, height);
+
+ dx = pointx - x;
+ dy = pointy - y;
+
+ loc->dist = dx * dx + dy * dy;
+ distances = g_list_prepend (distances, loc);
+
+ }
+ distances = g_list_sort (distances, (GCompareFunc) sort_locations);
+
+
+ set_location (map, (TzLocation*) distances->data);
+
+ g_list_free (distances);
+
+ return TRUE;
+}
+
+static void
+cc_timezone_map_init (CcTimezoneMap *map)
+{
+ GtkGesture *click_gesture;
+ GError *err = NULL;
+
+ map->orig_background = texture_from_resource (DATETIME_RESOURCE_PATH "/bg.png", &err);
+ if (!map->orig_background)
+ {
+ g_warning ("Could not load background image: %s",
+ (err) ? err->message : "Unknown error");
+ g_clear_error (&err);
+ }
+
+ map->orig_background_dim = texture_from_resource (DATETIME_RESOURCE_PATH "/bg_dim.png", &err);
+ if (!map->orig_background_dim)
+ {
+ g_warning ("Could not load background image: %s",
+ (err) ? err->message : "Unknown error");
+ g_clear_error (&err);
+ }
+
+ map->pin = texture_from_resource (DATETIME_RESOURCE_PATH "/pin.png", &err);
+ if (!map->pin)
+ {
+ g_warning ("Could not load pin icon: %s",
+ (err) ? err->message : "Unknown error");
+ g_clear_error (&err);
+ }
+
+ map->tzdb = tz_load_db ();
+
+ click_gesture = gtk_gesture_click_new ();
+ g_signal_connect (click_gesture, "pressed", G_CALLBACK (map_clicked_cb), map);
+ gtk_widget_add_controller (GTK_WIDGET (map), GTK_EVENT_CONTROLLER (click_gesture));
+}
+
+CcTimezoneMap *
+cc_timezone_map_new (void)
+{
+ return g_object_new (CC_TYPE_TIMEZONE_MAP, NULL);
+}
+
+gboolean
+cc_timezone_map_set_timezone (CcTimezoneMap *map,
+ const gchar *timezone)
+{
+ GPtrArray *locations;
+ guint i;
+ g_autofree gchar *real_tz = NULL;
+ gboolean ret;
+
+ real_tz = tz_info_get_clean_name (map->tzdb, timezone);
+
+ locations = tz_get_locations (map->tzdb);
+ ret = FALSE;
+
+ for (i = 0; i < locations->len; i++)
+ {
+ TzLocation *loc = locations->pdata[i];
+
+ if (!g_strcmp0 (loc->zone, real_tz ? real_tz : timezone))
+ {
+ set_location (map, loc);
+ ret = TRUE;
+ break;
+ }
+ }
+
+ if (ret)
+ gtk_widget_queue_draw (GTK_WIDGET (map));
+
+ return ret;
+}
+
+void
+cc_timezone_map_set_bubble_text (CcTimezoneMap *map,
+ const gchar *text)
+{
+ g_free (map->bubble_text);
+ map->bubble_text = g_strdup (text);
+
+ gtk_widget_queue_draw (GTK_WIDGET (map));
+}
+
+TzLocation *
+cc_timezone_map_get_location (CcTimezoneMap *map)
+{
+ return map->location;
+}
diff --git a/panels/datetime/cc-timezone-map.h b/panels/datetime/cc-timezone-map.h
new file mode 100644
index 0000000..f4c99e5
--- /dev/null
+++ b/panels/datetime/cc-timezone-map.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2010 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ *
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include "tz.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_TIMEZONE_MAP (cc_timezone_map_get_type ())
+G_DECLARE_FINAL_TYPE (CcTimezoneMap, cc_timezone_map, CC, TIMEZONE_MAP, GtkWidget)
+
+CcTimezoneMap *cc_timezone_map_new (void);
+
+gboolean cc_timezone_map_set_timezone (CcTimezoneMap *map,
+ const gchar *timezone);
+void cc_timezone_map_set_bubble_text (CcTimezoneMap *map,
+ const gchar *text);
+TzLocation * cc_timezone_map_get_location (CcTimezoneMap *map);
+
+G_END_DECLS
diff --git a/panels/datetime/data/bg.png b/panels/datetime/data/bg.png
new file mode 100644
index 0000000..43e4016
--- /dev/null
+++ b/panels/datetime/data/bg.png
Binary files differ
diff --git a/panels/datetime/data/bg_dim.png b/panels/datetime/data/bg_dim.png
new file mode 100644
index 0000000..8db7a19
--- /dev/null
+++ b/panels/datetime/data/bg_dim.png
Binary files differ
diff --git a/panels/datetime/data/pin.png b/panels/datetime/data/pin.png
new file mode 100644
index 0000000..c347a9e
--- /dev/null
+++ b/panels/datetime/data/pin.png
Binary files differ
diff --git a/panels/datetime/date-endian.c b/panels/datetime/date-endian.c
new file mode 100644
index 0000000..435a423
--- /dev/null
+++ b/panels/datetime/date-endian.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Bastien Nocera <hadess@hadess.net>
+ *
+ */
+
+#include <errno.h>
+#include <langinfo.h>
+#include <locale.h>
+#include <glib.h>
+#include <string.h>
+
+#include "date-endian.h"
+
+/* We default to returning DATE_ENDIANESS_LITTLE because that's
+ * what 3.4 billion people use */
+#define DEFAULT_ENDIANESS DATE_ENDIANESS_LITTLE
+
+typedef enum {
+ ITEM_NONE = 0,
+ ITEM_DAY,
+ ITEM_MONTH,
+ ITEM_YEAR
+} Item;
+
+static gboolean
+has_item (Item *items,
+ Item item)
+{
+ guint i;
+
+ for (i = 0; i < 3; i++) {
+ if (items[i] == ITEM_NONE)
+ return FALSE;
+ if (items[i] == item)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+DateEndianess
+date_endian_get_default (gboolean verbose)
+{
+ const char *fmt;
+ const char *p;
+ Item items[3];
+ guint i;
+
+ fmt = nl_langinfo (D_FMT);
+ g_return_val_if_fail (fmt != NULL, DEFAULT_ENDIANESS);
+
+ if (verbose)
+ g_print ("%s", fmt);
+
+ if (g_str_equal (fmt, "%F"))
+ return DATE_ENDIANESS_BIG;
+
+ i = 0;
+ memset (&items, 0, sizeof(items));
+
+ /* Assume ASCII only */
+ for (p = fmt; *p != '\0'; p++) {
+ char c;
+
+ /* Look for '%' */
+ if (*p != '%')
+ continue;
+
+ /* Only assert when we're sure we don't have another '%' */
+ if (i >= 4) {
+ g_warning ("Could not parse format '%s', too many formats", fmt);
+ return DEFAULT_ENDIANESS;
+ }
+
+ c = *(p + 1);
+ /* Ignore alternative formats */
+ if (c == 'O' || c == '-' || c == 'E')
+ c = *(p + 2);
+ if (c == '\0') {
+ g_warning ("Count not parse format '%s', unterminated '%%'", fmt);
+ return DEFAULT_ENDIANESS;
+ }
+ switch (c) {
+ case 'A':
+ case 'd':
+ case 'e':
+ if (has_item (items, ITEM_DAY) == FALSE) {
+ items[i] = ITEM_DAY;
+ i++;
+ }
+ break;
+ case 'm':
+ case 'b':
+ case 'B':
+ if (has_item (items, ITEM_MONTH) == FALSE) {
+ items[i] = ITEM_MONTH;
+ i++;
+ }
+ break;
+ case 'y':
+ case 'Y':
+ if (has_item (items, ITEM_YEAR) == FALSE) {
+ items[i] = ITEM_YEAR;
+ i++;
+ }
+ break;
+ case 'a':
+ /* Ignore */
+ ;
+ }
+ }
+
+ if (items[0] == ITEM_DAY &&
+ items[1] == ITEM_MONTH &&
+ items[2] == ITEM_YEAR)
+ return DATE_ENDIANESS_LITTLE;
+ if (items[0] == ITEM_YEAR &&
+ items[1] == ITEM_MONTH &&
+ items[2] == ITEM_DAY)
+ return DATE_ENDIANESS_BIG;
+ if (items[0] == ITEM_MONTH &&
+ items[1] == ITEM_DAY &&
+ items[2] == ITEM_YEAR)
+ return DATE_ENDIANESS_MIDDLE;
+ if (items[0] == ITEM_YEAR &&
+ items[1] == ITEM_DAY &&
+ items[2] == ITEM_MONTH)
+ return DATE_ENDIANESS_YDM;
+
+ g_warning ("Could not parse format '%s'", fmt);
+
+ return DEFAULT_ENDIANESS;
+}
+
+DateEndianess
+date_endian_get_for_lang (const char *lang,
+ gboolean verbose)
+{
+ locale_t locale;
+ locale_t old_locale;
+ DateEndianess endian;
+
+ locale = newlocale (LC_TIME_MASK, lang, (locale_t) 0);
+ if (locale == (locale_t) 0)
+ g_warning ("Failed to create locale %s: %s", lang, g_strerror (errno));
+ else
+ old_locale = uselocale (locale);
+
+ endian = date_endian_get_default (verbose);
+
+ if (locale != (locale_t) 0) {
+ uselocale (old_locale);
+ freelocale (locale);
+ }
+
+ return endian;
+}
+
+const char *
+date_endian_to_string (DateEndianess endianess)
+{
+ switch (endianess) {
+ case DATE_ENDIANESS_LITTLE:
+ return "Little (DD-MM-YYYY)";
+ case DATE_ENDIANESS_BIG:
+ return "Big (YYYY-MM-DD)";
+ case DATE_ENDIANESS_MIDDLE:
+ return "Middle (MM-DD-YYYY)";
+ case DATE_ENDIANESS_YDM:
+ return "YDM (YYYY-DD-MM)";
+ default:
+ g_assert_not_reached ();
+ }
+}
diff --git a/panels/datetime/date-endian.h b/panels/datetime/date-endian.h
new file mode 100644
index 0000000..396cd34
--- /dev/null
+++ b/panels/datetime/date-endian.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Bastien Nocera <hadess@hadess.net>
+ *
+ */
+
+/* From http://en.wikipedia.org/wiki/Date_notation_by_country */
+typedef enum {
+ DATE_ENDIANESS_BIG, /* Big-endian (year, month, day), e.g. 03-04-05 */
+ DATE_ENDIANESS_LITTLE, /* Little-endian (day, month, year), e.g. 05/04/03 */
+ DATE_ENDIANESS_MIDDLE, /* Middle-endian (month, day, year), e.g. 04/05/03 */
+ DATE_ENDIANESS_YDM /* YDM-endian (year, day, month), e.g. 03/05/04 */
+} DateEndianess;
+
+DateEndianess date_endian_get_default (gboolean verbose);
+DateEndianess date_endian_get_for_lang (const char *lang,
+ gboolean verbose);
+const char * date_endian_to_string (DateEndianess endianess);
diff --git a/panels/datetime/datetime.gresource.xml b/panels/datetime/datetime.gresource.xml
new file mode 100644
index 0000000..11cef79
--- /dev/null
+++ b/panels/datetime/datetime.gresource.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/datetime">
+ <file preprocess="xml-stripblanks">cc-datetime-panel.ui</file>
+ <file>backward</file>
+ <file alias="bg.png">data/bg.png</file>
+ <file alias="bg_dim.png">data/bg_dim.png</file>
+ <file alias="pin.png">data/pin.png</file>
+ </gresource>
+</gresources>
diff --git a/panels/datetime/gnome-datetime-panel.desktop.in.in b/panels/datetime/gnome-datetime-panel.desktop.in.in
new file mode 100644
index 0000000..6a38445
--- /dev/null
+++ b/panels/datetime/gnome-datetime-panel.desktop.in.in
@@ -0,0 +1,16 @@
+[Desktop Entry]
+Name=Date & Time
+Comment=Change the date and time, including time zone
+Exec=gnome-control-center datetime
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-time-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;X-GNOME-Settings-Panel;X-GNOME-DetailsSettings;
+OnlyShowIn=GNOME;
+# Translators: Search terms to find the Date and Time panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=Clock;Timezone;Location;
+# Notifications are emitted by gnome-settings-daemon
+X-GNOME-UsesNotifications=true
diff --git a/panels/datetime/icons/meson.build b/panels/datetime/icons/meson.build
new file mode 100644
index 0000000..63f5900
--- /dev/null
+++ b/panels/datetime/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-time-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/datetime/icons/scalable/org.gnome.Settings-time-symbolic.svg b/panels/datetime/icons/scalable/org.gnome.Settings-time-symbolic.svg
new file mode 100644
index 0000000..907f7d5
--- /dev/null
+++ b/panels/datetime/icons/scalable/org.gnome.Settings-time-symbolic.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <g fill="#2e3436">
+ <path d="m 8 0 c -4.40625 0 -8 3.59375 -8 8 s 3.59375 8 8 8 s 8 -3.59375 8 -8 s -3.59375 -8 -8 -8 z m 0 2 c 3.324219 0 6 2.671875 6 6 c 0 3.324219 -2.675781 6 -6 6 s -6 -2.675781 -6 -6 c 0 -3.328125 2.675781 -6 6 -6 z m 0 0"/>
+ <path d="m 4.929688 4.953125 c -0.132813 0.003906 -0.257813 0.058594 -0.351563 0.152344 c -0.191406 0.195312 -0.1875 0.511719 0.007813 0.707031 l 3.113281 3.042969 c 0.105469 0.097656 0.246093 0.144531 0.386719 0.128906 h 2.914062 c 0.277344 0 0.5 -0.222656 0.5 -0.5 c 0 -0.273437 -0.222656 -0.5 -0.5 -0.5 h -2.761719 l -2.953125 -2.886719 c -0.09375 -0.09375 -0.222656 -0.144531 -0.355468 -0.144531 z m 0 0"/>
+ </g>
+</svg>
diff --git a/panels/datetime/meson.build b/panels/datetime/meson.build
new file mode 100644
index 0000000..a3c8c16
--- /dev/null
+++ b/panels/datetime/meson.build
@@ -0,0 +1,112 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+polkit = 'org.gnome.controlcenter.@0@.policy'.format(cappletname)
+
+i18n.merge_file(
+ input: polkit + '.in',
+ output: polkit,
+ po_dir: po_dir,
+ install: true,
+ install_dir: join_paths(control_center_datadir, 'polkit-1', 'actions')
+)
+
+resource_data = files(
+ 'data/bg_dim.png',
+ 'data/bg.png',
+ 'data/pin.png',
+ 'backward',
+ 'cc-datetime-panel.ui',
+)
+
+resources = gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname,
+ dependencies: resource_data,
+ export: true
+)
+
+sources = files(
+ 'cc-datetime-panel.c',
+ 'cc-timezone-map.c',
+ 'date-endian.c',
+ 'tz.c'
+)
+
+gdbus = 'timedated'
+gdbus_iface_xml = gdbus + '1-interface.xml'
+
+# This requires running d-bus session and accessible timedate1 daemon
+# FIXME: need to find a way how to filter out unnecessary d-bus stuff (introspectable, properties)
+#timedated1-interface.xml:
+# gdbus introspect \
+# --xml \
+# --system \
+# --dest org.freedesktop.timedate1 \
+# --object-path /org/freedesktop/timedate1 \
+# > timedated1-interface.xml
+'''
+gdbus_iface = custom_target(
+ gdbus_iface_xml,
+ output: gdbus_iface_xml,
+ capture: true,
+ command: [
+ find_program('gdbus'),
+ 'introspect',
+ '--xml',
+ '--system',
+ '--dest', 'org.freedesktop.timedate1',
+ '--object-path', '/org/freedesktop/timedate1'
+ ],
+)
+'''
+
+sources += gnome.gdbus_codegen(
+ gdbus,
+ gdbus_iface_xml,
+ interface_prefix: 'org.freedesktop.'
+)
+
+deps = common_deps + [
+ gdk_pixbuf_dep,
+ gnome_desktop_dep,
+ polkit_gobject_dep
+]
+
+cflags += [
+ '-DGNOMECC_DATA_DIR="@0@"'.format(control_center_pkgdatadir)
+]
+
+datetime_panel_lib = static_library(
+ cappletname,
+ sources: sources + resources,
+ include_directories: [ top_inc, common_inc ],
+ dependencies: deps,
+ c_args: cflags
+)
+panels_libs += datetime_panel_lib
+
+datetime_panel_lib_dep = declare_dependency(
+ sources : resources,
+ include_directories : [top_inc, include_directories('.')],
+ link_with : datetime_panel_lib
+)
+
+subdir('po-timezones')
+subdir('icons')
diff --git a/panels/datetime/org.gnome.controlcenter.datetime.policy.in b/panels/datetime/org.gnome.controlcenter.datetime.policy.in
new file mode 100644
index 0000000..f9c115f
--- /dev/null
+++ b/panels/datetime/org.gnome.controlcenter.datetime.policy.in
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE policyconfig PUBLIC
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
+
+<policyconfig>
+ <vendor>The GNOME Project</vendor>
+ <vendor_url>http://www.gnome.org/</vendor_url>
+
+ <action id="org.gnome.controlcenter.datetime.configure">
+ <description>Change system time and date settings</description>
+ <message>To change time or date settings, you need to authenticate.</message>
+ <defaults>
+ <allow_any>no</allow_any>
+ <allow_inactive>no</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ <annotate key="org.freedesktop.policykit.imply">org.freedesktop.timedate1.set-time org.freedesktop.timedate1.set-timezone org.freedesktop.timedate1.set-local-rtc org.freedesktop.timedate1.set-ntp</annotate>
+ </action>
+
+</policyconfig>
diff --git a/panels/datetime/po-timezones/LINGUAS b/panels/datetime/po-timezones/LINGUAS
new file mode 100644
index 0000000..7e5e226
--- /dev/null
+++ b/panels/datetime/po-timezones/LINGUAS
@@ -0,0 +1,69 @@
+am
+ar
+as
+ast
+bg
+bn
+bn_IN
+bs
+ca
+cs
+cy
+da
+de
+el
+en_GB
+es
+et
+fa
+fi
+fr
+gl
+gu
+he
+hi
+hr
+hu
+id
+ilo
+is
+it
+ja
+ka
+kn
+ko
+ku
+lo
+lt
+lv
+mai
+mk
+ml
+mr
+ms
+nb
+nds
+nl
+nn
+or
+pa
+pl
+pt
+pt_BR
+ro
+ru
+si
+sk
+sl
+sq
+sr
+sr@latin
+sv
+ta
+te
+tr
+uk
+ur
+vi
+zh_CN
+zh_TW
diff --git a/panels/datetime/po-timezones/README b/panels/datetime/po-timezones/README
new file mode 100644
index 0000000..4f37317
--- /dev/null
+++ b/panels/datetime/po-timezones/README
@@ -0,0 +1,3 @@
+Those translations are copied from system-config-date
+http://git.fedorahosted.org/git/?p=system-config-date.git;a=tree;f=po/timezones
+and should not be modified by the GNOME translation teams.
diff --git a/panels/datetime/po-timezones/am.po b/panels/datetime/po-timezones/am.po
new file mode 100644
index 0000000..f9749ec
--- /dev/null
+++ b/panels/datetime/po-timezones/am.po
@@ -0,0 +1,3350 @@
+# Translations into the Amharic Language.
+# Copyright (C) 2004 Free Software Foundation, Inc.
+# This file is distributed under the same license as the timezones package.
+# Ge'ez Frontier Foundation <am-translate@geez.org>, 2005.
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2005-01-24 10:03+EDT\n"
+"Last-Translator: Ge'ez Frontier Foundation <locales@geez.org>\n"
+"Language-Team: Amharic <am-translate@geez.org>\n"
+"Language: am\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "አፍሪካ/አቢጃን"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "አፍሪካ/አክራ"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "አፍሪካ/አዲስ አበባ"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "አፍሪካ/አልጀርስ"
+
+#: timezones.h:5
+#, fuzzy
+msgid "Africa/Asmara"
+msgstr "አፍሪካ/አሥመራ"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "አፍሪካ/አሥመራ"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "አፍሪካ/ባማኮ"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "አፍሪካ/ባንጉዊ"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "አፍሪካ/ባንጁል"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "አፍሪካ/ቢሳዎ"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "አፍሪካ/ብላንቲረ"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "አፍሪካ/ብራዛቪል"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "አፍሪካ/ቡጁምቡራ"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "አፍሪካ/ካይሮ"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "አፍሪካ/ካዛብላንካ"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "አፍሪካ/ኬውታ"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "አፍሪካ/ኮናክሪ"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "አፍሪካ/ዳካር"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "አፍሪካ/ዳሬሰላም"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "አፍሪካ/ጅቡቲ"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "አፍሪካ/ዱዋላ"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "አፍሪካ/ኤል አኢውን"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "አፍሪካ/ፍሪታውን"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "አፍሪካ/ጋቦሮን"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "አፍሪካ/ሀራሬ"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "አፍሪካ/ጆሀንስበርግ"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "አፍሪካ/ካምፓላ"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "አፍሪካ/ካርቱም"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "አፍሪካ/ኪጋሊ"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "አፍሪካ/ኪንሻሳ"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "አፍሪካ/ሌጎስ"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "አፍሪካ/ሊብሬቪል"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "አፍሪካ/ሎሜ"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "አፍሪካ/ሉዋንዳ"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "አፍሪካ/ሉቡምባሺ"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "አፍሪካ/ሉሳካ"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "አፍሪካ/ማላቡ"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "አፍሪካ/ማፑቶ"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "አፍሪካ/ማሴሩ"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "አፍሪካ/ምባባኔ"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "አፍሪካ/ሞቃዲሹ"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "አፍሪካ/ሞንሮቪያ"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "አፍሪካ/ናይሮቢ"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "አፍሪካ/ኒጃሜና"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "አፍሪካ/ኒያሜይ"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "አፍሪካ/ኑዋክቾት"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "አፍሪካ/ኡጋዱጉ"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "አፍሪካ/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "አፍሪካ/ሳኦ-ቶሜ"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "አፍሪካ/ቲምቡክቱ"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "አፍሪካ/ትሪፖሊ"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "አፍሪካ/ቱኒዝ"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "አፍሪካ/ዊንድሆዌክ"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "አሜሪካ/አዳክ"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+#, fuzzy
+msgid "Aleutian Islands"
+msgstr "አውስትሬሊያ/Queensland"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "አሜሪካ/አንኮራጅ"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+#, fuzzy
+msgid "Alaska Time"
+msgstr "US/Alaska"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "አሜሪካ/አንጉኢላ"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "አሜሪካ/አንቲጉዋ"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "አሜሪካ/አራጉአኢና"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+#, fuzzy
+msgid "America/Argentina/Buenos_Aires"
+msgstr "አሜሪካ/ቡኤኖስ_ኤይሪስ"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+#, fuzzy
+msgid "America/Argentina/Catamarca"
+msgstr "አሜሪካ/ካታማርካ"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+#, fuzzy
+msgid "America/Argentina/ComodRivadavia"
+msgstr "አሜሪካ/አሜሪካ"
+
+#: timezones.h:78
+#, fuzzy
+msgid "America/Argentina/Cordoba"
+msgstr "አሜሪካ/ኮርዶባ"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+#, fuzzy
+msgid "America/Argentina/Jujuy"
+msgstr "አሜሪካ/ጁጁይ"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+#, fuzzy
+msgid "America/Argentina/La_Rioja"
+msgstr "አሜሪካ/አራጉአኢና"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+#, fuzzy
+msgid "America/Argentina/Mendoza"
+msgstr "አሜሪካ/ሜንዶዛ"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+#, fuzzy
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "አሜሪካ/አሜሪካ/ማሬንጎ"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+#, fuzzy
+msgid "America/Argentina/Salta"
+msgstr "አሜሪካ/አንቲጉዋ"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+#, fuzzy
+msgid "America/Argentina/San_Juan"
+msgstr "አሜሪካ/አንቲጉዋ"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+#, fuzzy
+msgid "America/Argentina/San_Luis"
+msgstr "አሜሪካ/አንቲጉዋ"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+#, fuzzy
+msgid "America/Argentina/Tucuman"
+msgstr "አሜሪካ/አንቲጉዋ"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+#, fuzzy
+msgid "America/Argentina/Ushuaia"
+msgstr "አሜሪካ/አራጉአኢና"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "አሜሪካ/አሩባ"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "አሜሪካ/አሱንኮን"
+
+#: timezones.h:110
+#, fuzzy
+msgid "America/Atikokan"
+msgstr "America/Atka"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "America/Atka"
+
+#: timezones.h:114
+#, fuzzy
+msgid "America/Bahia"
+msgstr "አሜሪካ/ቦአ-ቪስታ"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "አሜሪካ/ቦአ-ቪስታ"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "አሜሪካ/ባርቤዶስ"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "አሜሪካ/በለም"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "አሜሪካ/ቤሊዝ"
+
+#: timezones.h:125
+#, fuzzy
+msgid "America/Blanc-Sablon"
+msgstr "አሜሪካ/ካንኩን"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "አሜሪካ/ቦአ-ቪስታ"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "አሜሪካ/ቦጎታ"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "አሜሪካ/ቦይስ"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "አሜሪካ/ቡኤኖስ_ኤይሪስ"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "አሜሪካ/ካምብሪጅ_ቤይ"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+#, fuzzy
+msgid "America/Campo_Grande"
+msgstr "አሜሪካ/ኬይማን"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "አሜሪካ/ካንኩን"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "አሜሪካ/ካራካስ"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "አሜሪካ/ካታማርካ"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "አሜሪካ/ካኤን"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "አሜሪካ/ኬይማን"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "አሜሪካ/ቺካጐ"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+#, fuzzy
+msgid "Central Time"
+msgstr "US/Central"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "አሜሪካ/ቺኽዋኽዋ"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+#, fuzzy
+msgid "America/Coral_Harbour"
+msgstr "አሜሪካ/ኩራካኦ"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "አሜሪካ/ኮርዶባ"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "አሜሪካ/ኮስታሪካ"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "አሜሪካ/ኩባ"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "አሜሪካ/ኩራካኦ"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "አሜሪካ/ዴንማርክ"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "አሜሪካ/ዳውሰን"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "አሜሪካ/ዳውሰን_ክሪክ"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "አሜሪካ/ዴንቨር"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+#, fuzzy
+msgid "Mountain Time"
+msgstr "US/Mountain"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "አሜሪካ/ዲትሮይት"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "አሜሪካ/ዶሚኒካ"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "አሜሪካ/ኤድመንተን"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "አሜሪካ/ኢሩኔፕ"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "አሜሪካ/ኤልሳልቫዶር"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "አሜሪካ/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "አሜሪካ/ፎርታለዛ"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "አሜሪካ/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "አሜሪካ/ግሌስ_ቤይ"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "አሜሪካ/ጐድታኽብ"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "አሜሪካ/ጉዝ_ቤይ"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "አሜሪካ/ግራንድ_ቱርክ"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "አሜሪካ/ግረናዳ"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "አሜሪካ/ጉአደሉፔ"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "አሜሪካ/ጓቲማላ"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "አሜሪካ/ጓያኪል"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "አሜሪካ/ጉያና"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "አሜሪካ/ሀሊፋክስ"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "አሜሪካ/ሀቫና"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "አሜሪካ/ሄርሞሲሎ"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "አሜሪካ/አሜሪካ"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "አሜሪካ/አሜሪካ/ክኖክስ"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "አሜሪካ/አሜሪካ/ማሬንጎ"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+#, fuzzy
+msgid "America/Indiana/Petersburg"
+msgstr "አሜሪካ/አሜሪካ/ማሬንጎ"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "አሜሪካ/ኢንዲያናፖሊስ"
+
+#: timezones.h:227
+#, fuzzy
+msgid "America/Indiana/Tell_City"
+msgstr "አሜሪካ/አሜሪካ/ቬቫይ"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "አሜሪካ/አሜሪካ/ቬቫይ"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+#, fuzzy
+msgid "America/Indiana/Vincennes"
+msgstr "አሜሪካ/አሜሪካ/ቬቫይ"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+#, fuzzy
+msgid "America/Indiana/Winamac"
+msgstr "አሜሪካ/አሜሪካ/ቬቫይ"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "አሜሪካ/ኢኑቪክ"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "አሜሪካ/ኢካሊኡት"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "አሜሪካ/ጃማይካ"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "አሜሪካ/ጁጁይ"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "አሜሪካ/ጁነአኡ"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "አሜሪካ/አሜሪካ/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+#, fuzzy
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "አሜሪካ/አሜሪካ/Louisville"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "አሜሪካ/አሜሪካ/ሞንቲሴሎ"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "አሜሪካ/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "አሜሪካ/ላ_ፓዝ"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "አሜሪካ/ሊማ"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "አሜሪካ/ሎስ_አንጀለስ"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+#, fuzzy
+msgid "Pacific Time"
+msgstr "ፓሲፊክ/ኒዌ"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "አሜሪካ/ሉዊስቪለ"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "አሜሪካ/ማቺዎ"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "አሜሪካ/ማናጉዋ"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "አሜሪካ/ማናኡስ"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+#, fuzzy
+msgid "America/Marigot"
+msgstr "አሜሪካ/ማቺዎ"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "አሜሪካ/ማርቲኒክ"
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "አሜሪካ/ማናኡስ"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "አሜሪካ/ማዛቲአን"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "አሜሪካ/ሜንዶዛ"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "አሜሪካ/መኖሚኔ"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "አሜሪካ/ሜሪዳ"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "አሜሪካ/ሜክሲኮ_ሲቲ"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "አሜሪካ/ሚኩእሎን"
+
+#: timezones.h:289
+#, fuzzy
+msgid "America/Moncton"
+msgstr "አሜሪካ/ኤድመንተን"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "አሜሪካ/ሞንተሪ"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "አሜሪካ/ሞንተቪዴዮ"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "አሜሪካ/ሞንትሪያል"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "አሜሪካ/ሞንትሰራት"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "አሜሪካ/ናሳው"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "አሜሪካ/ኒውዮርክ"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+#, fuzzy
+msgid "Eastern Time"
+msgstr "US/Eastern"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "አሜሪካ/ኒፒጎን"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "አሜሪካ/ኖሜ"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "አሜሪካ/ኖሮሃ"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+#, fuzzy
+msgid "Atlantic islands"
+msgstr "አትላንቲክ/ካናሪ"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "አሜሪካ/አሜሪካ"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+#, fuzzy
+msgid "America/North_Dakota/New_Salem"
+msgstr "አሜሪካ/አሜሪካ"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "አሜሪካ/ማናጉዋ"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "አሜሪካ/ፓናማ"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "አሜሪካ/ፓንግኒርቱንግ"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "አሜሪካ/ፓራማሪቦ"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "አሜሪካ/ፎኔክስ"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "አሜሪካ/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "አሜሪካ/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "አሜሪካ/ፖርት ኦፍ ስፔን"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "አሜሪካ/ፖርቶ ቨልሆ"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "አሜሪካ/ፖርቶሪኮ"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "አሜሪካ/ሬኒ ሪቨር"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "አሜሪካ/ራንኪን ኢንሌት"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "አሜሪካ/ሪሲፋይ"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "አሜሪካ/ሬጂና"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+#, fuzzy
+msgid "America/Resolute"
+msgstr "አሜሪካ/በለም"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "አሜሪካ/ሪኦ ብራንኮ"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "America/Rosario"
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "አሜሪካ/ሳንቲያጎ"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+#, fuzzy
+msgid "America/Santarem"
+msgstr "አሜሪካ/ሳንቲያጎ"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "አሜሪካ/ሳንቲያጎ"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "አሜሪካ/ሳንቶ ዶሚንጎ"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "አሜሪካ/ሳኦ ፓውሎ"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "አሜሪካ/ስኮረስቢሱንድ"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "አሜሪካ/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+#, fuzzy
+msgid "America/St_Barthelemy"
+msgstr "አሜሪካ/በለም"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "አሜሪካ/ሴንት ጆንስ"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "አሜሪካ/ሴንት ኪትስ"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "አሜሪካ/ሴንት ሉቺያ"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "አሜሪካ/ሴንት ቶማስ"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "አሜሪካ/ሴንት ቪንሰንት"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "አሜሪካ/ስዊፍት ከረንት"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "አሜሪካ/ተጉቺጋልፓ"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "አሜሪካ/ቱለ"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "አሜሪካ/ተንደር ቤይ"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "አሜሪካ/ቲጁአና"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+#, fuzzy
+msgid "America/Toronto"
+msgstr "አሜሪካ/ቶርቶላ"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "አሜሪካ/ቶርቶላ"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "አሜሪካ/ቫንኩቨር"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "America/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "አሜሪካ/ሁዋይትሆርስ"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "አሜሪካ/ዊኒፔግ"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "አሜሪካ/ያኩታት"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "አሜሪካ/የሎውናይፍ"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "አንታርክቲካ/ቼሲ"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "አንታርክቲካ/ዴቪስ"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "አንታርክቲካ/ዱሞንትዱርቪል"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+#, fuzzy
+msgid "Antarctica/Macquarie"
+msgstr "አንታርክቲካ/ማክሙርዶ"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "አንታርክቲካ/ማውሰን"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "አንታርክቲካ/ማክሙርዶ"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "አንታርክቲካ/ፓልመር"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+#, fuzzy
+msgid "Antarctica/Rothera"
+msgstr "Antarctica/South_Pole"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antarctica/South_Pole"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "አንታርክቲካ/ስዮዋ"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "አንታርክቲካ/ቮስቱክ"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Arctic/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "እስያ/ኤደን"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "እስያ/አልማቲ"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "እስያ/አማን"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "እስያ/አናዲር"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "እስያ/አክታው"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "እስያ/አክቶቤ"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "እስያ/አሽጋባት"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "እስያ/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "እስያ/ባግዳድ"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "እስያ/ባህሬን"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "እስያ/ባኩ"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "እስያ/ባንኮክ"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "እስያ/ቤይሩት"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "እስያ/ቢሽኬክ"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "እስያ/ብሩኒ"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "እስያ/ካልኩታ"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "እስያ/ቾይባልሳን"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "እስያ/ቾንግኪንግ"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Asia/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "እስያ/ኮሎምቦ"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "እስያ/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "እስያ/ዳማስከስ"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "እስያ/ዳካ"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "እስያ/ዲሊ"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "እስያ/ዱባይ"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "እስያ/ዱስሃንቤ"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "እስያ/ጋዛ"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "እስያ/ባርቢን"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+#, fuzzy
+msgid "Asia/Ho_Chi_Minh"
+msgstr "እስያ/ቾንግኪንግ"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "እስያ/ሆንግ ኮንግ"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "እስያ/ሆቭድ"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "እስያ/ኢርኩትስክ"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Asia/Istanbul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "እስያ/ጃካርታ"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "እስያ/ጃያፑራ"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "እስያ/እየሩሳሌም"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "እስያ/ካቡል"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "እስያ/ካምቻትካ"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "እስያ/ካራቺ"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "እስያ/ካሽጋር"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+#, fuzzy
+msgid "Asia/Kathmandu"
+msgstr "እስያ/ካትማንዱ"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "እስያ/ካትማንዱ"
+
+#: timezones.h:518
+#, fuzzy
+msgid "Asia/Kolkata"
+msgstr "እስያ/ጃካርታ"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "እስያ/ክራስኖያሽክ"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "እስያ/ኳላልምፑር"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "እስያ/ኩቺንግ"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "እስያ/ኩዌት"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "እስያ/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "እስያ/ማካው"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "እስያ/ማጋዳን"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "እስያ/ማካሳር"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "እስያ/ማኒላ"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "እስያ/ሙስካት"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "እስያ/ኒኮሲያ"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "እስያ/ኢርኩትስክ"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "እስያ/ኖቮሲቢርስክ"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "እስያ/ኖቮሲቢርስክ"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+#, fuzzy
+msgid "Moscow+03 - Novosibirsk"
+msgstr "እስያ/ኖቮሲቢርስክ"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "እስያ/ኦምስክ"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "እስያ/ኦራል"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "እስያ/ፕኖም_ፔንኽ"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "እስያ/ፖንቲአንካ"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "እስያ/ፒዮንግያንግ"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "እስያ/ኳታር"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "እስያ/ኪዝያሎርዳ"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "እስያ/ራንጎን"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "እስያ/ሪያድኽ"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "እስያ/ሪያድ87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "እስያ/ሪያድ88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "እስያ/ሪያድ89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "እስያ/ሳይጎን"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "እስያ/ሳክሃሊን"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "እስያ/ሳማርካንድ"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "እስያ/ሴውል"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "እስያ/ሻንጋይ"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "እስያ/ሲንጋፖር"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "እስያ/ታኢፓይ"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "እስያ/ታሽኬንት"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "እስያ/ቲብሊሲ"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "እስያ/ቴሂራን"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "እስያ/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "እስያ/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "እስያ/ቲምፕሁ"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "እስያ/ቶኪዮ"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "እስያ/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "እስያ/ኡላንባታር"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "እስያ/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "እስያ/ኡሩምኪ"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "እስያ/ቫይንቲአን"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "እስያ/ቭላዲቮስቱክ"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "እስያ/ያኩትስክ"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "እስያ/የካተሪንበርግ"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "እስያ/የረቫን"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "አትላንቲክ/አዞረስ"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "አትላንቲክ/ቤርሙዳ"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "አትላንቲክ/ካናሪ"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "አትላንቲክ/ኬፕ_ቫርዴ"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "አትላንቲክ/ፋእሮይ"
+
+#: timezones.h:616
+#, fuzzy
+msgid "Atlantic/Faroe"
+msgstr "አትላንቲክ/ፋእሮይ"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlantic/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "አትላንቲክ/ማዴኢራ"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "አትላንቲክ/ሬይክጃቪክ"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "አትላንቲክ/ደቡብ ጂዎርጂያ"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "አትላንቲክ/ስታንሊ"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "አትላንቲክ/ሴንት ሄሌና"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "አውስትሬሊያ/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "አውስትሬሊያ/አዴላኢደ"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+#, fuzzy
+msgid "South Australia"
+msgstr "አውስትሬሊያ/ACT"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "አውስትሬሊያ/ቢሪስባን"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "አውስትሬሊያ/ብሮከን ሂል"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "አውስትሬሊያ/Canberra"
+
+#: timezones.h:636
+#, fuzzy
+msgid "Australia/Currie"
+msgstr "አውስትሬሊያ/Canberra"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "አውስትሬሊያ/ዳርዊን"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+#, fuzzy
+msgid "Australia/Eucla"
+msgstr "አውስትሬሊያ/Queensland"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+#, fuzzy
+msgid "Western Australia - Eucla area"
+msgstr "አውስትሬሊያ/Queensland"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "አውስትሬሊያ/ሆባርት"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "አውስትሬሊያ/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "አውስትሬሊያ/ሊንደማን"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "አውስትሬሊያ/ሎርድ ሆዌ"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "አውስትሬሊያ/ሜልቦኡመ"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+#, fuzzy
+msgid "Victoria"
+msgstr "አውስትሬሊያ/Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "አውስትሬሊያ/North"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "አውስትሬሊያ/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "አውስትሬሊያ/ፕርዝ"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "አውስትሬሊያ/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "አውስትሬሊያ/South"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "አውስትሬሊያ/ሲድኒ"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "አውስትሬሊያ/Tasmania"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "አውስትሬሊያ/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "አውስትሬሊያ/West"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "አውስትሬሊያ/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "ብራዚል/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "ብራዚል/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "ብራዚል/East"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "ብራዚል/West"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "ካናዳCanada/Atlantic"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "ካናዳCanada/Central"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "ካናዳ/Eastern"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "ካናዳ/East-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "ካናዳ/Mountain"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "ካናዳ/Newfoundland"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "ካናዳ/Pacific"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "ካናዳ/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "ካናዳ/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Chile/Continental"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Chile/EasterIsland"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "ኩባ"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "ግብጽ"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Eire"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "ወዘተ/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "ወዘተ/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "ወዘተ/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "ወዘተ/GMT"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "ወዘተ/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "ወዘተ/GMT"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "ወዘተ/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "ወዘተ/GMT"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "ወዘተ/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "ወዘተ/GMT"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "ወዘተ/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "ወዘተ/GMT"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "ወዘተ/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "ወዘተ/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "ወዘተ/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "ወዘተ/GMT"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "ወዘተ/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "ወዘተ/GMT"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "ወዘተ/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "ወዘተ/GMT"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "ወዘተ/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "ወዘተ/GMT"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "ወዘተ/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "ወዘተ/GMT"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "ወዘተ/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "ወዘተ/GMT"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "ወዘተ/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "ወዘተ/GMT"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "ወዘተ/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "ወዘተ/GMT"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "ወዘተ/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "ወዘተ/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "ወዘተ/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "ወዘተ/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "አውሮፓ/አምስተርዳም"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "አውሮፓ/አንዶራ"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "አውሮፓ/አቴንስ"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "አውሮፓ/ቤልፋስት"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "አውሮፓ/በልግሬድ"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "አውሮፓ/በርሊን"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "አውሮፓ/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "አውሮፓ/ብራስልስ"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "አውሮፓ/ቡቻረስት"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "አውሮፓ/ቡዳፒስት"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "አውሮፓ/ቺሲናው"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "አውሮፓ/ኮፐንሀገን"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "አውሮፓ/ዱብሊን"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "አውሮፓ/ጊብራልታር"
+
+#: timezones.h:744
+#, fuzzy
+msgid "Europe/Guernsey"
+msgstr "አውሮፓ/አቴንስ"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "አውሮፓ/ሀልሲንኪ"
+
+#: timezones.h:746
+#, fuzzy
+msgid "Europe/Isle_of_Man"
+msgstr "አውሮፓ/ኦስሎ"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "አውሮፓ/ኢስታንቡል"
+
+#: timezones.h:748
+#, fuzzy
+msgid "Europe/Jersey"
+msgstr "አውሮፓ/ፓርስ"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "አውሮፓ/ካሊኒንጋርድ"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "አውሮፓ/ካይቭ"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "አውሮፓ/ሊስቦን"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "አውሮፓ/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "አውሮፓ/ሎንዶን"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "አውሮፓ/ሉክዘምበርግ"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "አውሮፓ/ማርድሪድ"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "አውሮፓ/ማልታ"
+
+#: timezones.h:765
+#, fuzzy
+msgid "Europe/Mariehamn"
+msgstr "አውሮፓ/ማርድሪድ"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "አውሮፓ/ሚንስክ"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "አውሮፓ/ሞናኮ"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "አውሮፓ/ማስኮ"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "አውሮፓ/Nicosia"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "አውሮፓ/ኦስሎ"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "አውሮፓ/ፓርስ"
+
+#: timezones.h:774
+#, fuzzy
+msgid "Europe/Podgorica"
+msgstr "አውሮፓ/አንዶራ"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "አውሮፓ/ፓራጓይ"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "አውሮፓ/ሪጋ"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "አውሮፓ/ሮም"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "አውሮፓ/ሳማራ"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "አውሮፓ/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "አውሮፓ/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "አውሮፓ/ሲምፈሮፖል"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "አውሮፓ/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "አውሮፓ/ሶፊያ"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "አውሮፓ/ስቶኮልም"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "አውሮፓ/ታሊን"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "አውሮፓ/ቲራን"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "አውሮፓ/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "አውሮፓ/ኡዝጎሩድ"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "አውሮፓ/ቫዱዝ"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "አውሮፓ/Vatican"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "አውሮፓ/ቫይና"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "አውሮፓ/ቪልኒኡስ"
+
+#: timezones.h:799
+#, fuzzy
+msgid "Europe/Volgograd"
+msgstr "አውሮፓ/በልግሬድ"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "አውሮፓ/ዋርሶ"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "አውሮፓ/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "አውሮፓ/ዛፖሮዝሂይ"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "አውሮፓ/ዙሪክ"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Factory"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Eire"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "ሆንግኮንግ"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "አይስላንድ"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "ሕንድ/አንታናአሪቮ"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "ሕንድ/ቻጎስ"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "ሕንድ/ገና"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "ሕንድ/ኮኮስ"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "ሕንድ/ኮሞሮ"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "ሕንድ/ከርጉኤለን"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "ሕንድ/ማሂ"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "ሕንድ/ማልዲቪስ"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "ሕንድ/ሞሪሽየስ"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "ሕንድ/ማዮቴ"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "ሕንድ/ሪዩኒየን"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "ኢራን"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "እስራኤል"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "ጃማይካ"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "ጃፓን"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "ሊቢያ"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Mexico/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Mexico/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Mexico/General"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Mideast/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Mideast/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Mideast/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "ፓሲፊክ/አፒያ"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "ፓሲፊክ/ኦክላንድ"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "ፓሲፊክ/ቻትሃም"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+#, fuzzy
+msgid "Chatham Islands"
+msgstr "Chile/EasterIsland"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "ፓሲፊክ/ትሩክ"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+#, fuzzy
+msgid "Pacific/Easter"
+msgstr "ፓሲፊክ/ኢስተር"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "ፓሲፊክ/ኤፋተ"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "ፓሲፊክ/እንደርቡርይ"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "ፓሲፊክ/ፋካኦፎ"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "ፓሲፊክ/ፊጂ"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "ፓሲፊክ/ፉናፉቲ"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "ፓሲፊክ/ጋላፓጎስ"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "ፓሲፊክ/ጋምባየር"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "ፓሲፊክ/ጉዋዳልካናል"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "ፓሲፊክ/ጉዋም"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "ፓሲፊክ/ሆኖሉሉ"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+#, fuzzy
+msgid "Hawaii"
+msgstr "US/Hawaii"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "ፓሲፊክ/ጆንስቶን"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "ፓሲፊክ/ኪሪቲማቲ"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "ፓሲፊክ/ኮስራይ"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+#, fuzzy
+msgid "Kosrae"
+msgstr "እስራኤል"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "ፓሲፊክ/ክዋጃላይን"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "ፓሲፊክ/ማጁሮ"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "ፓሲፊክ/ማሩኩሳስ"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "ፓሲፊክ/ሚድዌ"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "ፓሲፊክ/ናውሩ"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "ፓሲፊክ/ኒዌ"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "ፓሲፊክ/ኑርፎልክ"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "ፓሲፊክ/ኖኡሜአ"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "ፓሲፊክ/ፓጎ_ፓጎ"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "ፓሲፊክ/ፓላው"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "ፓሲፊክ/ፒትኬም"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "ፓሲፊክ/ፖኔፕ"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "ፓሲፊክ/ፖኔፕ"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "ፓሲፊክ/ፖርት_ሞረስቢ"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "ፓሲፊክ/ራሮቶንጋ"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "ፓሲፊክ/ሳይፓን"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "ፓሲፊክ/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "ፓሲፊክ/ታሂቲ"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "ፓሲፊክ/ታራዋ"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+#, fuzzy
+msgid "Gilbert Islands"
+msgstr "Chile/EasterIsland"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "ፓሲፊክ/ቶንጋታፑ"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "ፓሲፊክ/ትሩክ"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "ፓሲፊክ/ዌክ"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "ፓሲፊክ/ዋሊስ"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "ፓሲፊክ/ያፕ"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "ፖላንድ"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "ፖርቱጋል"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "ሲንጋፖር"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "ቱርክ"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "US/Alaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "US/Aleutian"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "US/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "US/Central"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "US/Eastern"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "US/East-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "US/Hawaii"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "US/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "US/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "US/Mountain"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "US/Pacific"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "US/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
+
+#, fuzzy
+#~ msgid "US/Pacific-New"
+#~ msgstr "US/Pacific"
+
+#~ msgid "SystemV/AST4"
+#~ msgstr "SystemV/AST4"
+
+#~ msgid "SystemV/AST4ADT"
+#~ msgstr "SystemV/AST4ADT"
+
+#~ msgid "SystemV/CST6"
+#~ msgstr "SystemV/CST6"
+
+#~ msgid "SystemV/CST6CDT"
+#~ msgstr "SystemV/CST6CDT"
+
+#~ msgid "SystemV/EST5"
+#~ msgstr "SystemV/EST5"
+
+#~ msgid "SystemV/EST5EDT"
+#~ msgstr "SystemV/EST5EDT"
+
+#~ msgid "SystemV/HST10"
+#~ msgstr "SystemV/HST10"
+
+#~ msgid "SystemV/MST7"
+#~ msgstr "SystemV/MST7"
+
+#~ msgid "SystemV/MST7MDT"
+#~ msgstr "SystemV/MST7MDT"
+
+#~ msgid "SystemV/PST8"
+#~ msgstr "SystemV/PST8"
+
+#~ msgid "SystemV/PST8PDT"
+#~ msgstr "SystemV/PST8PDT"
+
+#~ msgid "SystemV/YST9"
+#~ msgstr "SystemV/YST9"
+
+#~ msgid "SystemV/YST9YDT"
+#~ msgstr "SystemV/YST9YDT"
diff --git a/panels/datetime/po-timezones/ar.po b/panels/datetime/po-timezones/ar.po
new file mode 100644
index 0000000..3041dd3
--- /dev/null
+++ b/panels/datetime/po-timezones/ar.po
@@ -0,0 +1,3254 @@
+# translation of timezones.po to Arabic
+# This file is distributed under the same license as the PACKAGE package.
+# Copyright (C) 2009 THE PACKAGE'S COPYRIGHT HOLDER.
+# ahmad khalifa <ahmadkhalifa@hotmail.com>, 2004.
+# Ahmad Khalifa <ahmadkhalifa@hotmail.com>, 2004.
+# Tareq Al Jurf <taljurf@fedoraproject.org>, 2009.
+# Muhammed Al-Fakhori <mhmd.alfakhori@gmail.com>, 2009.
+# Abdalrahim Fakhouri <abdilra7eem@yahoo.com>, 2010.
+# Khaled Hosny <khaledhosny@eglug.org>, 2011.
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2011-01-08 15:09+0300\n"
+"Last-Translator: Khaled Hosny <khaledhosny@eglug.org>\n"
+"Language-Team: Arabic <fedora-trans-ar@redhat.com>\n"
+"Language: ar\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "أفريقيا/أبيدجان"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "أفريقيا/أكرا"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "أفريقيا/أديس_أبابا"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "أفريقيا/الجزائر"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "أفريقيا/أسمرة"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "أفريقيا/أسمرة"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "أفريقيا/باماكو"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "أفريقيا/بانغي"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "أفريقيا/بانجول"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "أفريقيا/بيساو"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "إفريقيا/بلانتيري"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "أفريقيا/برازافيل"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "أفريقيا/بوجمبورا"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "أفريقيا/القاهرة"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "أفريقيا/الدار البيضاء"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "أفريقيا/سبتة"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "سبتة ومليلية"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "أفريقيا/كوناكري"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "أفريقيا/داكار"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "أفريقيا/دار_السلام"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "أفريقيا/جيبوتي"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "أفريقيا/دوالا"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "أفريقيا/العيون"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "أفريقيا/فريتاون"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "أفريقيا/جابورون"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "أفريقيا/هراري"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "أفريقيا/جوهانسبرج"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "أفريقيا/كمبالا"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "أفريقيا/الخرطوم"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "أفريقيا/كيجالي"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "أفريقيا/كنشاسا"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "غرب جمهورية الكونغو الديمقراطية"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "أفريقيا/لاغوس"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "أفريقيا/ليبرفيل"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "أفريقيا/لومي"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "أفريقيا/لواندا"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "أفريقيا/لوبومباشي"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "شرق جمهورية الكونغو الديمقراطية"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "أفريقيا/لوساكا"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "أفريقيا/مالابو"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "أفريقيا/مابوتو"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "أفريقيا/ماسيرو"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "أفريقيا/مبابان"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "أفريقيا/مقديشو"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "أفريقيا/مونروفيا"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "أفريقيا/نيروبي"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "أفريقيا/نجامينا"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "أفريقيا/نيامي"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "أفريقيا/نواكشوط"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "أفريقيا/واجادوجو"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "أفريقيا/بورتو_نوفو"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "أفريقيا/ساو_تومي"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "أفريقيا/تِمبَكتو"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "أفريقيا/طرابلس"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "أفريقيا/تونس"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "أفريقيا/ويندهوك"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "أمريكا/أداك"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "جزر ألوشيان"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "أمريكا/أنكوراج"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "US/ألاسكا"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "أمريكا/أنجويلا"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "أمريكا/أنتيجوا"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "أمريكا/أراجواينا"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "توكانتينز"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "أمريكا/الأرجنتين/بوينوس_آيريس"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "بوينس ايرس (بكالوريوس، قوات التحالف)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "أمريكا/الأرجنتين/كاتاماركا"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "كاتاماركا (CT)، وشوبوت (CT)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "أمريكا/الأرجنتين/كومودريفادافيا"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "أمريكا/الأرجنتين/كوردوبا"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "معظم المواقع (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "أمريكا/الأرجنتين/جوجوي"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "خوخي (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "أمريكا/الأرجنتين/ﻻريوجا"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "اريوخا (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "أمريكا/الأرجنتين/مندوزا"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "مندوزا (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "أمريكا/الأرجنتين/ريو_جاليجوس"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "سانتا كروز (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "أمريكا/الأرجنتين/سالتا"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "أمريكا/الأرجنتين/سا_خوان"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "سان خوان (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "أمريكا/الأرجنتين/سان_لويس"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "سان لويس (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "أمريكا/الأرجنتين/توكومان"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "توكومان"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "أمريكا/الأرجنتين/أوشوايا"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "تييرا ديل فويغو (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "أمريكا/أروبا"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "أمريكا/أسونسيون"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "أمريكا/أتيكوكان"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "التوقيت الشرقي - Atikokan، وأونتاريو، وساوثمبتون الأول، نونافوت"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "أمريكا/أتكا"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "أمريكا/باهيا"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "باهيا"
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "أمريكا/باهيا"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "أمريكا/باربادوس"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "أمريكا/بيليم"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "أمابا والبريد بارا"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "أمريكا/بيليز"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "أمريكا/بلانك-سابلون"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "التوقيت الأطلسي - كيبيك - انخفاض نورث شور"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "أمريكا/بوا_فيزتا"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "رومانيا"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "أمريكا/بوغوتا"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "أمريكا/بويز"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "التوقيت الجبلي - جنوب شرق ولاية ايداهو وأوريغون"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "أمريكا/بوينوس_آيريس"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "أمريكا/كامبريدج_باي"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "التوقيت الجبلي - غرب نونافوت"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "أمريكا/كامبو_جراندي"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "ماتو غروسو دو سول"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "أمريكا/كانكون"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "التوقيت المركزي - كوينتانا رو"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "أمريكا/كاراكاس"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "أمريكا/كاتاماركا"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "أمريكا/كايّن"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "أمريكا/كايمن"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "أمريكا/شيكاغو"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "التوقيت المركزي"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "أمريكا/شيواوا"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "التوقيت الجبلي المكسيكيّ - تشيهواهوا"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "أمريكا/كورال_هاربور"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "أمريكا/كوردوبا"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "أمريكا/كوستا_ريكا"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "أمريكا/كويابا"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "ماتو غروسو"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "أمريكا/كوراكاو"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "أمريكا/دانماركشافن"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "الساحل الشرقي الى الشمال من Scoresbysund"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "أمريكا/دوسُن"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "بتوقيت المحيط الهادئ - الشمال يوكون"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "أمريكا/دوسُن_كرييك"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr "التوقيت الجبلي - داوسون كريك & فورت سانت جون، كولومبيا البريطانية"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "أمريكا/دنفر"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "التوقيت الجبلي"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "أمريكا/ديترويت"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "التوقيت الشرقي - ميتشيغان - معظم المواقع"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "أمريكا/دومينيكا"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "أمريكا/إدمنتون"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "التوقيت الجبلي - ألبرتا، وكولومبيا البريطانية وشرق غرب ساسكاتشوان"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "أمريكا/إيريونيب"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "دبليو أمازوناس"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "أمريكا/إلسَلفادور"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "أمريكا/إنسنادا"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "أمريكا/فورتاليزا"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "شمال شرق البرازيل (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "أمريكا/فورت_واين"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "أمريكا/جليس_باي"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+"التوقيت الأطلسي - نوفا سكوشيا - الأماكن التي لم تراع التوقيت الصيفي "
+"1966-1971"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "أمريكا/جَدثاب"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "معظم المواقع"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "أمريكا/جوّس_باي"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "التوقيت الأطلسي - لابرادور - معظم المواقع"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "أمريكا/جراند_تِرْك"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "أمريكا/جرينادا"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "أمريكا/جوادالوبي"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "أمريكا/جواتيمالا"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "أمريكا/جواياكويل"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "اليابسة"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "أمريكا/جويانا"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "أمريكا/هاليفاكس"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "التوقيت الأطلسي - نوفا سكوتيا (معظم الأماكن)، جزيرة الأمير إدوارد"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "أمريكا/هافانا"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "أمريكا/هيرموزيلو"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "التوقيت الجبلي - سونورا"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "أمريكا/إنديانا/إنديانابوليس"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "التوقيت الشرقي - إنديانا - معظم المواقع"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "أمريكا/إنديانا/نوكس"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "التوقيت المركزي - إنديانا - مقاطعة ستارك"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "أمريكا/إنديانا/ماريجنو"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "التوقيت الشرقي - إنديانا - مقاطعة كراوفورد"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "أمريكا/إنديانا/بيتيرسبورغ"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "التوقيت الشرقي - إنديانا - مقاطعة بايك"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "أمريكا/إنديانابوليس"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "أمريكا/إنديانا/تيل_سيتي"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "التوقيت المركزي - إنديانا - مقاطعة بيري"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "أمريكا/إنديانا/فيفاي"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "التوقيت الشرقي - إنديانا - مقاطعة سويسرا "
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "أمريكا/إنديانا/فينسينيس"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "التوقيت الشرقي - إنديانا - Daviess، دوبوا، نوكس & مارتن المقاطعات"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "أمريكا/إنديانا/ويناماك"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "التوقيت الشرقي - إنديانا - مقاطعة بولاسكي"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "أمريكا/إنوفيك"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "التوقيت الجبلي - غرب الأقاليم الشمالية الغربية"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "أمريكا/إكالويت"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "التوقيت الشرقي - شرق نونافوت - معظم المواقع"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "أمريكا/جامايكا"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "أمريكا/جوجوي"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "أمريكا/جونو"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "توقيت ألاسكا - ألاسكا استعطى"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "أمريكا/كِنْتاكي/لويسفيلل"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "التوقيت الشرقي - كنتاكي - منطقة لويسفيل"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "أمريكا/كِنْتاكي/مونتيسيللو"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "التوقيت الشرقي - كنتاكي - ومقاطعة وين"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "أمريكا/نوكس_إن"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "أمريكا/ﻻ_باز"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "أمريكا/ليما"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "أمريكا/لوس_أنجلوس"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "بتوقيت المحيط الهادئ"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "أمريكا/لويسفيلل"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "أمريكا/ماسيو"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "ألاغواس، وسيرغيبي"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "أمريكا/ماناجوا"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "أمريكا/ماناوس"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "ي أمازوناس"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "أمريكا/ماريجوت"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "أمريكا/مارتينيك"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "أمريكا/ماتاموروس"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+"التوقيت المركزي لأمريكا - كواهويلا، دورانغو، نويفو ليون، تاماوليباس بالقرب "
+"من الحدود الأمريكيّة"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "أمريكا/مازاتلان"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "التوقيت الجبلي - ق باها، ناياريت، وسينالوا"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "أمريكا/مندوزا"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "أمريكا/مينومين"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+"التوقيت المركزي - ميتشيغان - ديكينسون، Gogebic، حديد وMenominee المقاطعات"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "أمريكا/ميريدا"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "التوقيت المركزي - كامبيتشي، يوكاتان"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "أمريكا/مكسيكو_سيتى"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "التوقيت المركزي - معظم المواقع"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "أمريكا/ميكويلون"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "أمريكا/مونكتون"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "التوقيت الأطلسي - نيو برونزويك"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "أمريكا/مونتيرى"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr "التوقيت المركزي المكسيكيّ - كواهويلا، دورانغو، نويفو ليون، تاماوليباس"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "أمريكا/مونتفيديو"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "أمريكا/مونتريال"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "التوقيت الشرقي - كيبيك - معظم المواقع"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "أمريكا/مونتسِرات"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "أمريكا/ناساو"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "أمريكا/نيو_يورك"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "التوقيت الشرقي"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "أمريكا/نيبيجون"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+"التوقيت الشرقي - أونتاريو وكيبيك - الأماكن التي لم تراع التوقيت الصيفي "
+"1967-1973"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "أمريكا/نوم"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "بتوقيت ألاسكا - غرب ألاسكا"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "أمريكا/نورونها"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "جزر المحيط الأطلسي"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "أمريكا/شمال_داكوتا/منتصف"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "التوقيت المركزي - داكوتا الشمالية - مقاطعة أوليفر"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "أمريكا/شمال_داكوتا/نيو_سالم"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+"التوقيت المركزي - داكوتا الشمالية - مقاطعة مورتون (باستثناء منطقة ماندان)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "أمريكا/أوجيناغا"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "توقيت الجبال الأمريكيّة - تشيهواهوا"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "أمريكا/باناما"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "أمريكا/بانجنيرتونج"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "التوقيت الشرقي - Pangnirtung، نونافوت"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "أمريكا/باراماريبو"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "أمريكا/فينِكْس"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "التوقيت الجبلي - أريزونا"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "أمريكا/بورت_أو_برينس"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "أمريكا/بورتو_آكرى"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "أمريكا/بورت_أوف_سباين"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "أمريكا/بورتو_فيلهو"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "روندونيا"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "أمريكا/بويرتو_ريكو"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "أمريكا/رْايني_ريفر"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "التوقيت المركزي - ريني ريفر & فورت فرانسيس، أونتاريو"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "أمريكا/رانكين_إنلت"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "التوقيت المركزي - وسط نونافوت"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "أمريكا/ريسايف"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "بيرنامبوكو"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "أمريكا/ريجينا"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "التوقيت المركزي - ساسكاتشوان - معظم المواقع"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "أمريكا/ريزوليوت"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "التوقيت الشرقي - حازمة، نونافوت"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "أمريكا/ريو_برانكو"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "فدان"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "أمريكا/روسااريو"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "امريكا/سانتا إيزابيل"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "توقيت \"الهادي\" المكسيكيّ - باجا كاليفورنيا"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "امريكا/سانتاريم"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "دبليو بارا"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "أمريكا/سانتياجو"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "أمريكا/سانتو_دومينجو"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "أمريكا/ساو_باولو"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "S & SE البرازيل (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "أمريكا/سكورزبايساند"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "جرين لاند/ إتّوكورتوكيت و Scoresbysund"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "أمريكا/شيبروك"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "التوقيت الجبلي - نافاجو"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "أمريكا/سانت_بارثيليمي"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "أمريكا/سانت_جونز"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "توقيت نيوفاوندلاند، بما في ذلك جنوب شرق لابرادور"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "أمريكا/سانت_كيتس"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "أمريكا/سانت_لوسيا"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "أمريكا/سانت_توماس"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "أمريكا/سانت_فينسنت"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "أمريكا/سويفت_كارانت"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "التوقيت المركزي - ساسكاتشوان - الغرب الاوسط"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "أمريكا/تيجوسيجالبا"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "أمريكا/ثول"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "ثول / بِفّتك"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "أمريكا/ثاندر_باي"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "التوقيت الشرقي - ثندر باي، أونتاريو"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "أمريكا/تيوانا"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "توقيت \"الهادي\" الأمريكيّ - باجا كاليفورنيا"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "أمريكا/تورونتو"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "التوقيت الشرقي - أونتاريو - أهم المواقع"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "أمريكا/تورتولا"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "أمريكا/فانكوفر"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "بتوقيت المحيط الهادي - غرب كولومبيا البريطانية"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "أمريكا/فيرجين"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "أمريكا/وايتهورس"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "بتوقيت المحيط الهادئ - جنوب يوكون"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "أمريكا/وينيبيج"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "التوقيت المركزي - مانيتوبا وأونتاريو الغربية"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "أمريكا/ياكوتات"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "بتوقيت ألاسكا - ألاسكا رقبة بانهاديل"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "أمريكا/يِلونايف"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "التوقيت الجبلي - وسط الأقاليم الشمالية الغربية"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "أنتارتيكا/كاسى"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "محطة كيسي، شبه جزيرة بيلي "
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "أنتارتيكا/دافيس"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "محطة ديفيس، فيستفولد هيلز"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "أنتارتيكا/دومنتدىأورفيل"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "دومون - محطة d'Urville، تير آديلي"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "أنتارتيكا (القارة المتجمدة)/ماكواري"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "محطة جزيرة ماكواري، جزيرة ماكواري"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "القطب الجنوبي / ماوسن"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "ماوسن محطة خليج هولم"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "أنتارتيكا/مكموردو"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "محطة ماكموردو، جزيرة روس"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "أنتارتيكا/بالمر"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "محطة بالمر،جزيرة انفيرس "
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "أنتارتيكا/روثيرا"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "روثيرا محطة الجزيرة اديلايد"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "أنتارتيكا/القطب_الجنوبي"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "روثيرا محطة الجزيرة اديلايد"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "أنتارتيكا/سيأُوا"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "محطة سيووا، E Ongul I"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "أنتارتيكا/فوستوك"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "محطة فوستوك، دإ القطب المغناطيسي"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "أنتارتيكا/لونجيإربيين"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "آسيا/عدن"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "آسيا/ألماتي"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "آسيا/عمّان"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "آسيا/أنادير"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "موسكو +08 - بحر برينغ"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "آسيا/أكتوا"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "أتيرو (أتيرو، غورييف)، مانكيستو"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "آسيا/أكتوبي"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "أكتوبي"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "آسيا/عشق آباد"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "آسيا/عشق آباد"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "آسيا/بغداد"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "آسيا/البحرين"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "آسيا/باكو"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "آسيا/بانكوك"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "آسيا/بيروت"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "آسيا/بشكيك"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "آسيا/بروناى"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "آسيا/كلكاتّا"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "آسيا/شويبالسان"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "دورنود، سخباتار"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "آسيا/تشونغتشينغ"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "وسط الصين - سيتشوان ويونان وقوانغشى، وشنشى، وقويتشو، الخ."
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "آسيا/تشونغتشينغ"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "آسيا/كولومبو"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "آسيا/دكّا"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "آسيا/دمشق"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "آسيا/دكّا"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "آسيا/ديلى"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "آسيا/دبى"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "آسيا/دوشنبه"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "آسيا/غزة"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "آسيا/هاربِن"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "هيلونغجيانغ (باستثناء موخه) وجيلين"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "آسيا/هو_تشي_مين"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "آسيا/هونج_كونج"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "آسيا/هوفد"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "بايان - Olgiy، Govi - ألتاي، هوود، Uvs، Zavkhan"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "آسيا/إركوتسك"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "موسكو +05 - بحيرة بايكال"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "آسيا/إسطنبول"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "آسيا/جاكارتا"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "جاوة وسومطرة"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "آسيا/جيابورا"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "إيريان جايا & مولوكاس"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "آسيا/القدس"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "آسيا/كابُل"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "آسيا/كامشَاتكا"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "موسكو +08 - كامشتكا"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "آسيا/كراتشي"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "آسيا/كاشغر"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "غرب التبت وتركستان الشرقية"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "آسيا/كاتماندو"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "آسيا/كاتماندو"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "آسيا/كلكتا"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "آسيا/كراسنويارسك"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "موسكو +04 - نهر ينيسي"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "آسيا/كوالالمبور"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "شبه جزيرة ماليزيا"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "آسيا/كوتشينج"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "الصباح وسراوق"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "آسيا/الكويت"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "آسيا/ماكاو"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "آسيا/ماكاو"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "آسيا/ماغادان"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "موسكو +08 - ماغادان"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "آسيا/مكاسّار"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "شرق وجنوب جزيرة بورنيو، سيليبيس وبالي ونوسا تينجارا، في تيمور الغربية"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "آسيا/مانيلا"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "آسيا/مسقط"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "آسيا/نيقوسيا"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "آسيا/نوفوكوزنتسك"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "موسكو +03 - نوفوكوزنتسك"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "آسيا/نوفوسيبيرسك"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "موسكو +03 - نوفوسيبيرسك"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "آسيا/أُمْسك"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "موسكو +03 - غرب سيبيريا"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "آسيا/أورال"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "غرب كازاخستان"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "آسيا/بنوم_بنه"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "آسيا/بونتياناك"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "غرب ووسط بورنيو"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "آسيا/بيونجيانج"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "آسيا/قطر"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "آسيا/كيزيلوردا"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "كيزيلوردا"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "آسيا/رانجون"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "آسيا/الرياض"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "آسيا/الرياض87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "آسيا/الرياض88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "آسيا/الرياض89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "آسيا/سايجون"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "آسيا/سخالين"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "موسكو +07 - جزيرة سخالين"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "آسيا/سمرقند"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "غرب أوزبكستان"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "آسيا/سيول"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "آسيا/شنغهاي"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "شرق الصين - بكين وقوانغدونغ وشنغهاى، الخ."
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "آسيا/سنغافورة"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "آسيا/تايباي"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "آسيا/طشقند"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "شرق أوزبكستان"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "آسيا/تبليسي"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "آسيا/طهران"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "آسيا/تل_أبيب"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "آسيا/تيمفو"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "آسيا/تيمفو"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "آسيا/طوكيو"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "آسيا/أوجونج_باندانج"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "آسيا/أولان_باتور"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "آسيا/أولان_باتور"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "آسيا/أورومتشي"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "أغلب التبت وتركستان الشرقية"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "آسيا/فيينتيان"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "آسيا/فلاديفستك"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "موسكو +07 - نهر آمور"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "آسيا/ياكوتسك"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "موسكو +06 - نهر لينا"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "آسيا/يكاترينبورج"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "موسكو +02 - الأورال"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "آسيا/يريفان"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "الأطلنطي/الأزور"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "الأزور"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "الأطلنطي/برمودا"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "الأطلنطي/الخالدات"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "جزر الخالدات"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "الأطلنطي/كيب_فيرد"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "الأطلنطي/فيرو"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "الأطلنطي/فارو"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "الأطلنطي/جان_ماين"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "الأطلنطي/ماديرا"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "جزر ماديرا"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "الأطلنطي/ريتشافك"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "الأطلنطي/جنوب_جورجيا"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "الأطلنطي/ستانلي"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "الأطلنطي/سانت_هيلينا"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "أستراليا/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "أستراليا/أديلايد"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "جنوب أستراليا"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "أستراليا/بريسباين"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "Queensland - most locations"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "أستراليا/بروكن_هيل"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "نيو ساوث ويلز - Yancowinna"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "أستراليا/كانبِرا"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "أستراليا/كوري"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "تسمانيا - جزيرة الملك"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "أستراليا/داروين"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "الإقليم الشمالي"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "أستراليا/ايوكلا"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "غرب أستراليا - منطقة ايكولا"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "أستراليا/هوبارت"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "تسمانيا - معظم المواقع"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "أستراليا/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "أستراليا/ليندمان"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "كوينزلاند - هوليداي جزر"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "أستراليا/لورد_هاو"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "جزيرة لورد هاو"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "أستراليا/ملبورن"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "فيكتوريا"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "أستراليا/شمال"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "أستراليا/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "أستراليا/بيرث"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "غرب أستراليا - معظم المواقع"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "أستراليا/كوينزلاند"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "أستراليا/جنوب"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "أستراليا/سيدني"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "نيو ساوث ويلز - معظم المواقع"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "أستراليا/تازمانيا"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "أستراليا/فيكتوريا"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "أستراليا/غرب"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "أستراليا/يانكوينا"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "البرازيل/أكري"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "البرازيل/دينورونها"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "البرازيل/شرق"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "البرازيل/غرب"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "كندا/الأطلنطي"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "كندا/وسط"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "كندا/شرقي"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "كندا/شرق-ساسكاتشون"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "كندا/جبل"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "كندا/أرض_جديدة"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "كندا/هادئ"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "كندا/ساسكاتشون"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "كندا/يوكون"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "شيلي/كونتيننتال"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "شيلي/إيسترأيلاند"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "كوبا"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "مصر"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "آير"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/غرينتش"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "أوروبا/أمستردام"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "أوروبا/أندورا"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "أوروبا/أثينا"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "أوروبا/بلفاست"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "أوروبا/بلجراد"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "أوروبا/برلين"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "أوروبا/براتيسلافا"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "أوروبا/بروكسل"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "أوروبا/بوخارست"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "أوروبا/بودابست"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "أوروبا/شيزيناو"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "أوروبا/كوبنهاجن"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "أوروبا/دوبلن"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "أوروبا/جبل_طارق"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "أوروبا/جويرنسي"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "أوروبا/هلسينكي"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "أوروبا/أيسل_أوف_مان"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "أوروبا/إسطنبول"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "أوروبا/جيرزي"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "أوروبا/كالينينجراد"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "موسكو، 01 - كالينينجراد"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "أوروبا/كييف"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "أوروبا/ليسبون"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "أوروبا/ليوبليانا"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "أوروبا/لندن"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "أوروبا/لوكسمبرج"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "أوروبا/مدريد"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "أوروبا/مالطا"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "أوروبا/ماريهامن"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "أوروبا/مينسك"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "أوروبا/موناكو"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "أوروبا/موسكو"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "موسكو +00 - غرب روسيا"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "أوروبا/نيقوسيا"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "أوروبا/أوسلو"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "أوروبا/باريس"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "أوروبا/بودجوريكا"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "أوروبا/براج"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "أوروبا/ريجا"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "أوروبا/روما"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "أوروبا/سمارا"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "موسكو - سمارا، أودمورتيا"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "أوروبا/سان_مارينو"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "أوروبا/سراييفو"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "أوروبا/سمفروبول"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "وسط القرم"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "أوروبا/سكوبيه"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "أوروبا/صوفيا"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "أوروبا/ستوكهولم"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "أوروبا/تالين"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "أوروبا/تيرانا"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "أوروبا/تيراسبول"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "أوروبا/أوزجورود"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "رتهينِا"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "أوروبا/فادوز"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "أوروبا/الفاتيكان"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "أوروبا/فيينا"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "أوروبا/فيلنيوس"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "أوروبا/بلجراد"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "موسكو +00 - بحر قزوين"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "أوروبا/وارسو"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "أوروبا/زغرب"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "أوروبا/زابوروجييه"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "زابوروجييه، إيلوغانسك / إيلوهانسك"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "أوروبا/زيورخ"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "مصنع"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-آير"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "جرينتش"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "هونج كونج"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "أيسلاند"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "هندي/أنتاناناريفو"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "هندي/شاجوس"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "هندي/كريستماس"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "هندي/كوكوس"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "هندي/كومورو"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "هندي/كيرجيولن"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "هندي/ماهي"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "هندي/مالديف"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "هندي/موريشيوس"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "هندي/مايوتي"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "هندي/رييونيون"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "إيران"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "فلسطين"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "جامايكا"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "يابان"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "كوجالين"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "ليبيا"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "مكسيك/بايانورتي"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "مكسيك/باياسور"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "مكسيك/عام"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "شرق_أوسط/الرياض87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "شرق_أوسط/الرياض88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "شرق_أوسط/الرياض89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "نافايو"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "هادئ/أبيا"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "هادئ/أوكلاند"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "هادئ/شاثام"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "جزر تشاتام"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "هادئ/تروك"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+#, fuzzy
+msgid "Chuuk (Truk) and Yap"
+msgstr "تراك (شوك) وياب"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "هادئ/إيستر"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "جزيرة الفصح وسالا غوميز ذ"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "هادئ/إفاتي"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "هادئ/إندربوري"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "جزر طائر الفينيق"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "هادئ/فاكاوفو"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "هادئ/فيجي"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "هادئ/فونافوتي"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "هادئ/جالاباجوس"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "جزر غالاباغوس"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "هادئ/جامبيير"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "جزر غامبير"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "هادئ/جوادالكانال"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "هادئ/جوام"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "هادئ/هونولولو"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "هاواي"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "هادئ/جونستون"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "جزيرة جونستون"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "هادئ/كيريتيماتي"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "جزر الخط"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "هادئ/كوسراي"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "كوسراي"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "هادئ/كواجالين"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "هادئ/ماجورو"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "هادئ/ماركويساس"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "جزر الماركيز"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "هادئ/ميدواي"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "جزر ميدواي"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "هادئ/ناورو"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "هادئ/نيو"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "هادئ/نورفولك"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "هادئ/نوميا"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "هادئ/باجو_باجو"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "هادئ/بالاو"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "هادئ/بيتكايرن"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "هادئ/بونابي"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+#, fuzzy
+msgid "Pohnpei (Ponape)"
+msgstr "بوهنباي"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "هادئ/بونابي"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "هادئ/بورت_مورسبي"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "هادئ/راروتونجا"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "هادئ/سايبان"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "هادئ/ساموا"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "هادئ/تاهيتي"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "جزر المجتمع"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "هادئ/تاراوا"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "جزر جيلبرت"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "هادئ/تونجاتابو"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "هادئ/تروك"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "هادئ/وايك"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "جزيرة وايك"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "هادئ/واليس"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "هادئ/ياب"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "بولندا"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "البرتغال"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "بسكيرولز"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "سنغافورة"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "تركيا"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "US/ألاسكا"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "US/أليوتيان"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "US/أريزونا"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "US/وسط"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "US/شرقي"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "US/شرق-إنديانا"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "US/هاواي"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "US/إنديانا-ستاركي"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "US/ميتشيجان"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "US/جبل"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "US/هادئ"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "US/ساموا"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
diff --git a/panels/datetime/po-timezones/as.po b/panels/datetime/po-timezones/as.po
new file mode 100644
index 0000000..5e25538
--- /dev/null
+++ b/panels/datetime/po-timezones/as.po
@@ -0,0 +1,3273 @@
+# translation of timezones.tip.as.po to Assamese
+# This file is distributed under the same license as the PACKAGE package.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER.
+#
+# Amitakhya Phukan <amitakhya.phukan@gmail.com>, 2006.
+# Amitakhya Phukan <aphukan@redhat.com>, 2006, 2007, 2010.
+# Amitakhya Phukan <aphukan@fedoraproject.org>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones.tip.as\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-04-01 15:07+0530\n"
+"Last-Translator: Amitakhya Phukan <aphukan@redhat.com>\n"
+"Language-Team: Assamese <>\n"
+"Language: as\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Lokalize 1.0\n"
+"Plural-Forms: nplurals=2; plural=(n!=1)\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "আফ্ৰিকা/অবিজান"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "আফ্ৰিকা/আক্ৰা"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "আফ্ৰিকা/আডিস আবাবা (_A)"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "আফ্ৰিকা/এলজিয়াৰ্স"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "আফ্ৰিকা/আস্মেৰা"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "আফ্ৰিকা/আস্মেৰা"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "আফ্ৰিকা/বামাকো"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "আফ্ৰিকা/বাঙ্গুই"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "আফ্ৰিকা/বানজুল"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "আফ্ৰিকা/বিচাউ"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "আফ্ৰিকা/ব্লেনটায়াৰ"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "আফ্ৰিকা/ব্ৰাজাভিল"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "আফ্ৰিকা/বুজুমবুৰা"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "আফ্ৰিকা/কায়ৰো"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "আফ্ৰিকা/কাচাব্লাঙ্কা"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "আফ্ৰিকা/থেউটা"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "চেউটা & মেলিলা"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "আফ্ৰিকা/কোনাক্ৰি"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "আফ্ৰিকা/ডাকাৰ"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "আফ্ৰিকা/ডাৰ_এস_চালাম"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "আফ্ৰিকা/জিবুতি"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "আফ্ৰিকা/ডুয়ালা"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "আফ্ৰিকা/এল আউইন (_A)"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "আফ্ৰিকা/ফ্ৰিটাউন"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "আফ্ৰিকা/গ্যাবাৰোন"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "আফ্ৰিকা/হাৰাৰে"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "আফ্ৰিকা/জোহানেচ্বাৰ্গ"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "আফ্ৰিকা/কাম্পালা"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "আফ্ৰিকা/খাৰতৌম"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "আফ্ৰিকা/কিগালি"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "আফ্ৰিকা/কিন্চাচা"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "পশ্চিম গণতান্ত্ৰিক প্ৰজাতন্ত্ৰ কঙ্গো"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "আফ্ৰিকা/লাগোচ্"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "আফ্ৰিকা/লিবাৰভিল"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "আফ্ৰিকা/লোমে"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "আফ্ৰিকা/লুয়ান্ডা"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "আফ্ৰিকা/লুবুম্বাশি"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "পূৰ্ব গণতান্ত্ৰিক প্ৰজাতন্ত্ৰ কঙ্গো"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "আফ্ৰিকা/লুচাকা"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "আফ্ৰিকা/মালাবো"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "আফ্ৰিকা/মাপুতো"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "আফ্ৰিকা/মাচেৰু"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "আফ্ৰিকা/আমবাবানে"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "আফ্ৰিকা/মোগাডিশু"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "আফ্ৰিকা/মোন্ৰোভিয়া"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "আফ্ৰিকা/নায়ৰোবি"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "আফ্ৰিকা/আনজামেনা"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "আফ্ৰিকা/নিয়ামে"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "আফ্ৰিকা/নোয়াকশোট"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "আফ্ৰিকা/ওয়াগাডুগু"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "আফ্ৰিকা/পোৰ্টো-নোভো"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "আফ্ৰিকা/সাও_টোমে"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "আফ্ৰিকা/টিম্বাকটু"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "আফ্ৰিকা/ট্ৰিপোলি"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "আফ্ৰিকা/টিউনিস"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "আফ্ৰিকা/ভিন্টহুক"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "আমেৰিকা/আদাক"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "আলুতিয়ান দ্বীপপুঞ্জ"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "আমেৰিকা/এঙ্কোৰেজ"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "আলাস্কা সময়ৰ"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "আমেৰিকা/এঙ্গিলা"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "আমেৰিকা/এন্টিগা"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "আমেৰিকা/আৰাগুয়েনা"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "টোকান্টিন্স"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "আমেৰিকা/আৰ্জেনটিনা/বুয়েনোচ্ আয়াৰ্চ (_A)"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "বুয়েনোচ্‌ আয়াৰ্চ (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "আমেৰিকা/আৰ্জেনটিনা/কাটামাৰ্কা"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "কাটামাৰ্কা (CT), ছুবুত (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "আমেৰিকা/আৰ্জেনটিনা/কোমোডৰিভাডাভিয়া"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "আমেৰিকা/আৰ্জেনটিনা/কোৰ্ডোবা"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "অধিকাংশ স্থান (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "আমেৰিকা/আৰ্জেনটিনা/জুজুই"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "জুজুই (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "আমেৰিকা/আৰ্জেনটিনা/লা ৰিওজা (_R)"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "লা ৰিওৱা (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "আমেৰিকা/আৰ্জেনটিনা/মেন্ডোজা"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "মেন্ডোজা (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "আমেৰিকা/আৰ্জেনটিনা/ৰিও গেলিগোচ্ (_G)"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "ছান্টা ক্ৰুজ (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "আমেৰিকা/আৰ্জেনটিনা/ছাল্টা"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "আমেৰিকা/আৰ্জেনটিনা/চান হুৱান (_J)"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "ছান হুৱান (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "আমেৰিকা/আৰ্জেনটিনা/ছান লুই (_L)"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "ছান লুই (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "আমেৰিকা/আৰ্জেনটিনা/টুকুমান"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "টুকুমান (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "আমেৰিকা/আৰ্জেনটিনা/উশুয়াইয়া"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "টিয়েৰা ডেল ফুয়েগো (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "আমেৰিকা/আৰুবা"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "আমেৰিকা/এচানছিয়ান"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "আমেৰিকা/আটিকোকান"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "পূৰ্বৰ মানপ্ৰাপ্ত সময় - আটিকোকান, অ'ন্টাৰিঅ' আৰু দক্ষিণ হেম্পটন দ্বীপ, নুনাভুট"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "আমেৰিকা/আটকা"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "আমেৰিকা/বাহিয়া"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "বাহিয়া"
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "আমেৰিকা/বাহিয়া"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "আমেৰিকা/বাৰবাডোচ্"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "আমেৰিকা/বেলেম"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "আমাপা, পূৰ্ব পাৰা"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "আমেৰিকা/বেলিজে"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "আমেৰিকা/ব্লাঙ্ক-চাবলোন"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "আতলান্তিক মানপ্ৰাপ্ত সময় - কিউবেক - লোৱাৰ উত্তৰ শ্বোৰ"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "আমেৰিকা/বোয়া_ভিস্টা"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "ৰোৰাইমা"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "আমেৰিকা/বোগোটা"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "আমেৰিকা/বোয়স"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "মাউন্টেন সময় - দক্ষিণ আইডাহো & পূৰ্ব ওৰেগন"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "আমেৰিকা/বুয়েনোচ্ আয়াৰ্চ (_A)"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "আমেৰিকা/কেমব্ৰিজ বে (_B)"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "মাউন্টেন সময় - পশ্চিম নুনাভুট"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "আমেৰিকা/কাম্পো গ্ৰান্ডে (_G)"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "মাটো গ্ৰোচো দো চুল"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "আমেৰিকা/কেনকুন"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "মধ্য সময় - কিন্টানা ৰু"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "আমেৰিকা/কেৰাকাস"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "আমেৰিকা/কাটামাৰ্কা"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "আমেৰিকা/কেয়েন"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "আমেৰিকা/কেমেন"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "আমেৰিকা/শিকাগো"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "মধ্য সময়"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "আমেৰিকা/চিহুৱাহুৱা"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+#, fuzzy
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "মাউন্টেন সময় - চিহুৱাহুৱা"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "আমেৰিকা/কোৰেল হাৰ্বাৰ (_H)"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "আমেৰিকা/কোৰ্ডোবা"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "আমেৰিকা/কোস্টা ৰিকা (_R)"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "আমেৰিকা/কুইয়াবা"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "মাটো গ্ৰোচো"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "আমেৰিকা/কুৰাকাও"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "আমেৰিকা/ডানমাৰ্কচৱান"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "পূৰ্বী তট, স্কোৰ্চবাইছান্ডৰ উত্তৰ"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "আমেৰিকা/ড'চ'ন"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "প্ৰশান্ত মহাসাগৰীয় সময় -উত্তৰ ইউকোন"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "আমেৰিকা/ড'চ'ন ক্ৰিক (_C)"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr "মাউন্টেন মানপ্ৰাপ্ত সময় - ড'চ'ন ক্ৰিক আৰু ফোৰ্ট চেন্ট জন, চুই্ব ক'ল'ম্বিয়া"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "আমেৰিকা/ডেনভাৰ"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "মাউন্টেন সময়"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "আমেৰিকা/ডেট্ৰইট"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "পূৰ্ব সময় - মিচিগন - অধিকাংশ স্থান"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "আমেৰিকা/ডোমিনিকা"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "আমেৰিকা/এডমনটন"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "মাউন্টেন সময় - এলবাৰ্টা, পূৰ্ব চুই্ব ক'ল'ম্বিয়া আৰু পশ্চিম চাচকাচুয়ান"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "আমেৰিকা/ইৰুনেপে"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "পঃ আমাজোনাচ"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "আমেৰিকা/এল ছালভাডোৰ (_S)"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "আমেৰিকা/এনচেনাডা"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "আমেৰিকা/ফোৰ্টালেজা"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "উঃপূঃ ব্ৰাজিল (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "আমেৰিকা/ফোৰ্ট ওয়েইন (_W)"
+
+# not appropriate imho
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "আমেৰিকা/গ্লেস বে (_B)"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+"আতলান্তিক সময় - নোভা স্কোছিয়া - ১৯৬৬-১৯৭১ ত দিবালোক সংৰক্ষণকাৰী সময় ব্যৱহাৰ নকৰা "
+"স্থান"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "আমেৰিকা/গডথাব"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "অধিকাংশ স্থান"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "আমেৰিকা/গূজ বে (_B)"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "আতলান্তিক সময় - লেব্ৰেডৰ - অধিকাংশ স্থান"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "আমেৰিকা/গ্ৰ্যান্ড টাৰ্ক (_T)"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "আমেৰিকা/গ্ৰেনাডা"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "আমেৰিকা/গুয়াডেলুপ"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "আমেৰিকা/গুয়াটেমালা"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "আমেৰিকা/গায়াকুইল"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "মূল ভুখণ্ড"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "আমেৰিকা/গায়ানা"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "আমেৰিকা/হেলিফ্যাক্স"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "আতলান্তিক সময় - নোভা স্কোছিয়া (অধিকাংশ স্থান), PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "আমেৰিকা/হাভানা"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "আমেৰিকা/হাৰ্মোসিলো"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "মাউন্টেন মানপ্ৰাপ্ত সময় - চোনোৰা"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "আমেৰিকা/ইন্ডিয়ানা/ইন্ডিয়ানাপোলিস"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "পূৰ্বীয় সময় - ইন্ডিয়ানা - অধিকাংশ স্থান"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "আমেৰিকা/ইন্ডিয়ানা/নোক্স"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "মধ্য সময় - ইন্ডিয়ানা - স্টাৰ্ক কাউন্টি"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "আমেৰিকা/ইন্ডিয়ানা/মাৰেঙ্গো"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "পূৰ্বীয় সময় - ইন্ডিয়ানা - ক্ৰফোৰ্ড কাউন্টি"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "আমেৰিকা/ইন্ডিয়ানা/পিটাৰ্সবাৰ্গ"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "পূৰ্বীয় সময় - ইন্ডিয়ানা - পাইক কাউন্টি"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "আমেৰিকা/ইন্ডিয়ানাপোলিস"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "আমেৰিকা/ইন্ডিয়ানা/টেল_চিটি"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "মধ্য সময় - ইন্ডিয়ানা - পেৰি কাউন্টি"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "আমেৰিকা/ইন্ডিয়ানা/ভিভে"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "পূৰ্বীয় সময় - ইন্ডিয়ানা - চুইৎজাৰ্লেন্ড কাউন্টি"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "আমেৰিকা/ইন্ডিয়ানা/ভিনসেন"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "পূৰ্বীয় সময় - ইন্ডিয়ানা - ডেভিচ, ডুবোইচ, নক্স আৰু মাৰ্টিন কাউন্টি"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "আমেৰিকা/ইন্ডিয়ানা/ৱিনামাক"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "পূৰ্বীয় সময় - ইন্ডিয়ানা - পুলাস্কি কাউন্টি"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "আমেৰিকা/ইনুভিক"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "মাউন্টেন সময় - পশ্চিম উত্তৰপশ্চিম প্ৰদেশ"
+
+# not sure
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "আমেৰিকা/ইকালুইট"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "পূৰ্বীয় সময় - পূৰ্ব নুনাভুট - অধিকাংশ স্থান"
+
+# not sure
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "আমেৰিকা/জামাইকা"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "আমেৰিকা/জুজুই"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "আমেৰিকা/জুনিউ"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "আলাস্কা সময় - আলাস্কা পেন-হেন্ডেল"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "আমেৰিকা/কেন্টাকি/লুইভিল"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "পূৰ্বীয় সময় - কেন্টাকি - লুইভিল অঞ্চল"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "আমেৰিকা/কেন্টাকি/মোন্টিচেলো"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "পূৰ্বীয় সময় - কেন্টাকি - ৱেইন কাউন্টি"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "আমেৰিকা/নোক্স ইন (_I)"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "আমেৰিকা/লা পাজ (_P)"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "আমেৰিকা/লিমা"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "আমেৰিকা/লস এঞ্জেল্চ্ (_A)"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "প্ৰশান্ত মহাসাগৰীয় সময়"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "আমেৰিকা/লুইভিল"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "আমেৰিকা/মাচিও"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "আলাগোৱাচ, চাৰ্গিপে"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "আমেৰিকা/মানাগুয়া"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "আমেৰিকা/মানাউস"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "পূঃ আমাজোনাচ"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "আমেৰিকা/মাৰিগট"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "আমেৰিকা/মাৰ্টিনিক"
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "আমেৰিকা/মানাউস"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+#, fuzzy
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr "মধ্য সময় - কোয়াহুইলা, ডুৰাংগো, নুয়েভো লিঅ'ন, টাম্পাউলিপাচ"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "আমেৰিকা/মাজাতলান"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "মাউন্টেন সময় - দঃ বাজা, নায়াৰিত, চিনালোয়া"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "আমেৰিকা/মেন্ডোজা"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "আমেৰিকা/মেনোমিনি"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "মধ্য সময় - মিচিগন - ডিকিনচন, গোগেবিক, আচইৰন আৰু মেনোমিনি কাউন্টি"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "আমেৰিকা/মেৰিডা"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "মধ্য সময় - কেম্পেচে, ইউকাটান"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "আমেৰিকা/মেক্সিকো সিটি (_C)"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "মধ্য সময় - অধিকাংশ স্থান"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "আমেৰিকা/মিকেলন"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "আমেৰিকা/মঙ্কটন"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "আতলান্তিক সময় -নিউ ব্ৰান্সউইক"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "আমেৰিকা/মণ্টেৰি"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+#, fuzzy
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr "মধ্য সময় - কোয়াহুইলা, ডুৰাংগো, নুয়েভো লিঅ'ন, টাম্পাউলিপাচ"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "আমেৰিকা/মন্টেভিডিও"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "আমেৰিকা/মনট্ৰিল"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "পূৰ্বীয় সময় - কিউবেক - অধিকাংশ স্থান"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "আমেৰিকা/মন্টচেৰাত"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "আমেৰিকা/নাসাউ"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "আমেৰিকা/নিউ ইয়োৰ্ক (_Y)"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "পূৰ্বীয় সময়"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "আমেৰিকা/নিপিগন"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+"পূৰ্বীয় সময় - অ'ন্টাৰিঅ' & কিউবেক - ১৯৬৭-১৯৭৩-ত দিবালোক সংৰক্ষণকাৰী সময় ব্যৱহাৰ "
+"নকৰা স্থান"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "আমেৰিকা/নোম"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "আলাস্কা সময় - পশ্চিম আলাস্কা"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "আমেৰিকা/নোৰোনহা"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "আতলান্তিক দ্বীপপুঞ্জ"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "আমেৰিকা/উত্তৰ ডাকোটা (_D)/চেন্টাৰ"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "মধ্য সময় - উত্তৰ ডাকোটা - অলিভাৰ কাউন্টি"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "আমেৰিকা/উত্তৰ_ডাকোটা/নিউ_সেলাম"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "মধ্য সময় - উত্তৰ ডাকোটা - মৰ্টন কাউন্টি (মেন্ডান অঞ্চলৰ বাহিৰে)"
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "আমেৰিকা/মানাগুয়া"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+#, fuzzy
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "মাউন্টেন সময় - চিহুৱাহুৱা"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "আমেৰিকা/পানামা"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "আমেৰিকা/পাংনিৰতুং"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "পূৰ্বীয় সময় - পাংগনিৰটুংগ, নুনাভুট"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "আমেৰিকা/পাৰামাৰিবো"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "আমেৰিকা/ফিনিক্স"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "মাউন্টেন মানপ্ৰাপ্ত সময় - এৰিজোনা"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "আমেৰিকা/পোৰ্ট_ও_প্ৰিন্স"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "আমেৰিকা/পোৰ্তো একৰ (_A)"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "আমেৰিকা/পোৰ্ট_অফ_স্পেন"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "আমেৰিকা/পোৰ্তো_ভেলহো"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "ৰোন্ডোনিয়া"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "আমেৰিকা/পুয়েৰ্তো ৰিকো (_R)"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "আমেৰিকা/ৰেইনি ৰিভাৰ (_R)"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "মধ্য সময় - ৰেইনি ৰিভাৰ আৰু ফোৰ্ট ফ্ৰান্সেচ, অ'ন্টাৰিঅ'"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "আমেৰিকা/ৰেঙ্কিন ইনলেট (_I)"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "মধ্য সময় - মধ্য নুনাভুট"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "আমেৰিকা/ৰিসাইফে"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "পাৰ্নেমবুকো"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "আমেৰিকা/ৰেজিনা"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "মধ্য মানপ্ৰাপ্ত সময় - সাস্কাচুয়ান - অধিকাংশ স্থান"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "আমেৰিকা/ৰিছোলিউট"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "পূৰ্বীয় মানপ্ৰাপ্ত সময় - ৰেচোলিউট, নুনাভুট"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "আমেৰিকা/ৰিও ব্ৰাঙ্কো (_B)"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "একৰ"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "আমেৰিকা/ৰোজাৰিও"
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "আমেৰিকা/ছান্টাৰেম"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "আমেৰিকা/ছান্টাৰেম"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "পঃ পাৰা"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "আমেৰিকা/চান্টিয়াগো"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "আমেৰিকা/চান্টো ডোমিঙ্গো (_D)"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "আমেৰিকা/চাও পাওলো(_P)"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "দঃ আৰু দঃপূঃ ব্ৰাজিল (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "আমেৰিকা/স্কোৰ্সবিছান্ড"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "স্কোৰ্চবাইছান্দ / ইটোকোৰ্টোৰমিট"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "আমেৰিকা/শিপৰক"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "মাউন্টেন সময় - নাভাজো"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "আমেৰিকা/St_Barthelemy"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "আমেৰিকা/চেন্ট জন্চ্ (_J)"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "নিউফাউন্ডলেন্ড সময়, দঃপূঃ লেব্ৰেডৰ সহ"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "আমেৰিকা/চেন্ট কিট্চ্ (_K)"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "আমেৰিকা/চেন্ট্ লুূচিয়া (_L)"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "আমেৰিকা/চেন্ট্ থোমাচ্ (_T)"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "আমেৰিকা/চেন্ট্ ভিনচেন্ট্ (_V)"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "আমেৰিকা/চ্যুইফ্ট্ কাৰেন্ট্ (_C)"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "মধ্য মানপ্ৰাপ্ত সময় - চাস্কাচুয়ান - মধ্যপশ্চিম"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "আমেৰিকা/তেগুচিগাল্পা"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "আমেৰিকা/থুল"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "থুলে / পিটুফিক"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "আমেৰিকা/থান্ডাৰ বে (_B)"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "পূৰ্বীয় সময় - থান্ডাৰ বে, অ'ন্টাৰিঅ'"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "আমেৰিকা/থেওয়ানা"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "আমেৰিকা/টৰোন্টো"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "পূৰ্বীয় সময় - অ'ন্টাৰিঅ' - অধিকাংশ স্থান"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "আমেৰিকা/টৰটলা"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "আমেৰিকা/ভ্যাংকুভাৰ"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "প্ৰশান্ত মহাসাগীয় সময় - পশ্চিম ব্ৰিটিশ্ব ক'ল'ম্বিয়া"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "আমেৰিকা/ভাৰ্জিন"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "আমেৰিকা/ওয়াইটহৰ্স"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "প্ৰশান্ত মহাসাগীয় সময় - দক্ষিণ ইউকন"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "আমেৰিকা/উইনিপেগ"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "মধ্য সময় - মানিটোবা & পশ্চিম অ'ন্টাৰিঅ'"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "আমেৰিকা/ইয়াকুতাত"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "আলাস্কা - আলাস্কা পেনহেন্ডেল নেক"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "আমেৰিকা/ইয়েল্লোনাইফ"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "মাউন্টেন সময় - মধ্য উত্তৰপশ্চিম প্ৰদেশ"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "এন্টাৰ্কটিকা/কেসি"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "কেচি স্টেছন, বেইলি উপদ্বীপ"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "এন্টাৰ্কটিকা/ডেভিচ্"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "ডেভিচ স্টেছন, ভেস্টফোল্ড হিল্চ্‌"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "এন্টাৰ্কটিকা/দুমোন্ত দ্য উৰভিল"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "দুমোন্ত দ উৰভিল স্টেছন, টেৰে এডেলি"
+
+#: timezones.h:425
+#, fuzzy
+msgid "Antarctica/Macquarie"
+msgstr "এন্টাৰ্কটিকা/মেকমাৰ্ডো"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+#, fuzzy
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "মেকমাৰ্ডো স্টেছন, ৰোচ দ্বীপ"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "এন্টাৰ্কটিকা/মচন"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "মোচন স্টেছন, হোল্ম বে"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "এন্টাৰ্কটিকা/মেকমাৰ্ডো"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "মেকমাৰ্ডো স্টেছন, ৰোচ দ্বীপ"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "এন্টাৰ্কটিকা/পাল্মাৰ"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "পাল্মাৰ স্টেছন, এন্ভাৰ্চ দ্বীপ"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "এন্টাৰ্কটিকা/ৰোথেৰা"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "ৰোথেৰা স্টেছন, এডেলেইড দ্বীপ"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "এন্টাৰ্কটিকা/দক্ষিণ মেৰু (_P)"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "এমুন্ডচেন-স্কট স্টেছন, দক্ষিণ মেৰু"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "এন্টাৰ্কটিকা/চিওয়া"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "চিওয়া স্টেছন, ই ওঙ্গুল দ্বীপ"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "এন্টাৰ্কটিকা/ভোস্টক"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "ভোস্টক স্টেছন, দঃ মেগ্নেটিক মেৰু"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "আৰ্কটিক/লংইয়াৰ্বেন"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "এছিয়া/এডেন"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "এছিয়া/আলমাটি"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "এছিয়া/আম্মান"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "এছিয়া/আনাদিৰ"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+#, fuzzy
+msgid "Moscow+08 - Bering Sea"
+msgstr "মস্কো+১০ - বেৰিং সাগৰ"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "এছিয়া/আকতু"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "অতিৰাউ (অতিৰাউ, গুৰ্য়েভ), মাংগিস্তাউ (মানকিস্তাউ)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "এছিয়া/আকতোবে"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "আকতোবে (আকতোবে)"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "এছিয়া/আশ‌গাবাত"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "এছিয়া/আশখাবাদ"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "এছিয়া/বাগদাদ"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "এছিয়া/বাহৰেন"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "এছিয়া/বাকু"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "এছিয়া/ব্যাঙ্কক"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "এছিয়া/বেইৰুট"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "এছিয়া/বিশকেক"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "এছিয়া/ব্ৰুনেই"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "এছিয়া/কলকাতা"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "এছিয়া/চৈবালছান"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "ডোৰনোড, চুখবাতাৰ"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "এছিয়া/চোংকিং"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "মধ্য চীন - চিচুয়ান, ইউনান, গুয়াংজি, সাংগজি, গিজু, প্ৰভৃতি"
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "এছিয়া/চুংকিং"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "এছিয়া/কোলোম্বো"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "এছিয়া/ঢাকা"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "এছিয়া/ডামাচ্কাচ্"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "এছিয়া/ঢাকা"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "এছিয়া/ডিলি"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "এছিয়া/দুবাই"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "এছিয়া/দুশানবে"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "এছিয়া/গাজা"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "এছিয়া/হাৰ্বিন"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "হেইলোজিয়াং (মোহেৰ বাহিৰে), জিলিন"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "এছিয়া/হো_চি_মিন"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "এছিয়া/হং কং (_K)"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "এছিয়া/হোভড"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "বায়ান-ওলগিই, গোভি-অল্টাই, হোভড, উভচ, জাভখান"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "এছিয়া/ইৰকুট্স্ক্"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "মস্কো+০৫ - লেক বৈকাল"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "এছিয়া/ইস্তানবুল"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "এছিয়া/জাকাৰ্তা"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "জাভা & চুমাত্ৰা"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "এছিয়া/জায়াপুৰা"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "ইৰিয়ান জায়া & মোলুক্কাস"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "এছিয়া/জেৰুচেলাম"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "এছিয়া/কাবুল"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "এছিয়া/কামচাটকা"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+#, fuzzy
+msgid "Moscow+08 - Kamchatka"
+msgstr "মস্কো+০৯ - কামচাটকা"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "এছিয়া/কৰাচী"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "এছিয়া/কাশগাৰা"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "পশ্চিম তিব্বত & জিংজিয়াং"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "এছিয়া/কাটমান্ডুু"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "এছিয়া/কাটমান্ডু"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "এছিয়া/কোলকাতা"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "এছিয়া/ক্ৰাসনোয়াৰ্স্ক"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "মস্কো+০৪ - ইয়েনিচেই নদী"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "এছিয়া/কুয়ালা লাম্পুৰ (_L)"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "মালায়েছিয়া উপদ্বীপ"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "এছিয়া/কুচিং"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "চাবাক & চাৰাৱাক"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "এছিয়া/কুৱেইত"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "এছিয়া/মাকাও"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "এছিয়া/মাকাও"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "এছিয়া/মাগাদান"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "মস্কো+০৮ - মাগাদান"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "এছিয়া/মাকাচ্চাৰ"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "পূৰ্ব & দক্ষিণ বোৰ্নিও, চেলেবেচ, বালি, নুচা টেংগেৰা, পশ্চিম তিমুৰ"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "এছিয়া/মেনিলা"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "এছিয়া/মাসকাট"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "এছিয়া/নিকোসিয়া"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "এছিয়া/ইৰকুট্স্ক্"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "মস্কো+০৩ - নোভোচিবাৰ্স্ক"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "এছিয়া/নোভোসিবাৰ্স্ক"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "মস্কো+০৩ - নোভোচিবাৰ্স্ক"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "এছিয়া/ওমস্ক"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "মস্কো+০৩ - পশ্চিম চাইবেৰিয়া"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "এছিয়া/ওৰাল"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "পশ্চিম কাজাখস্তান"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "এছিয়া/নোম ফেন (_P)"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "এছিয়া/পন্টিয়ানাক"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "পশ্চিম & মধ্য বোৰ্নিও"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "এছিয়া/পিয়োংইয়াং"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "এছিয়া/কাতাৰ"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "এছিয়া/কিজিলোৰ্দা"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "কিজিলোৰ্দা (কিজিলোৰ্দা, কিজিল-ওৰ্দা)"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "এছিয়া/ইয়াংগন"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "এছিয়া/ৰিয়াধ"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "এছিয়া/ৰিয়াধ৮৭"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "এছিয়া/ৰিয়াধ৮৮"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "এছিয়া/ৰিয়াধ৮৯"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "এছিয়া/সায়গন"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "এছিয়া/শাকালিন"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "মস্কো+০৭ - চাখালিন দ্বীপ"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "এছিয়া/সামাৰখান্দ"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "পশ্চিম উজ্বেকিস্তান"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "এছিয়া/চিওল"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "এছিয়া/সাংঘাই"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "পূৰ্ব চীন - বেইজিং, গুয়াংডন, সাংঘাই প্ৰভৃতি"
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "এছিয়া/সিঙ্গাপুৰ"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "এছিয়া/তাইপে"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "এছিয়া/তাসকেন্ত"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "পূৰ্ব উজ্বেকিস্তান"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "এছিয়া/তবিলিছি"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "এছিয়া/তেহেৰান"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "এছিয়া/তেল আভিভ (_A)"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "এছিয়া/থিম্বু"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "এছিয়া/থিম্পু"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "এছিয়া/টোকিও"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "এছিয়া/উজুং পান্দাং (_P)"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "এছিয়া/উলানবাতোৰ"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "এছিয়া/উলান বাতোৰ (_B)"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "এছিয়া/উৰুমকি"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "অধিকাংশ তিব্বত & জিংজিয়াং"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "এছিয়া/ভিয়েনতিয়েন"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "এছিয়া/ভ্লাডিভোস্টক"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "মস্কো+০৭ - আমুৰ নদী"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "এছিয়া/ইয়াকুটস"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "মস্কো+০৬ - লেনা নদী"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "এছিয়া/ইয়াকাতাৰিনবুৰ্গ"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "মস্কো+০২ - উৰাল"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "এছিয়া/ইয়াৰ্ভান"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "আটলান্টিক/এজোৰে"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "এজোৰেছ"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "আটলান্টিক/বাৰমুডা"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "আটলান্টিক/কেনাৰি"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "কেনাৰি দ্বীপপুঞ্জ"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "আটলান্টিক/কেপ ভাৰ্ডি (_V)"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "আটলান্টিক/ফেৰো"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "আটলান্টিক/ফেৰো"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "আটলান্টিক/জান মায়েন (_M)"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "আটলান্টিক/মাদিইৰা"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "মাদেইৰা দ্বীপপুঞ্জ"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "আটলান্টিক/ৰিকয়াভিক"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "আটলান্টিক/চাউথ জৰ্জিয়া (_G)"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "আটলান্টিক/স্টেনলি"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "আটলান্টিক/চেন্ট্ হেলেনা (_H)"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "অস্ট্ৰেলিয়া/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "অস্ট্ৰেলিয়া/এডিলেড"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "দক্ষিণ অস্ট্ৰেলিয়া"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "অস্ট্ৰেলিয়া/ব্ৰিসবেন"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "কুইন্সলেন্ড - অধিকাংশ স্থান"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "অস্ট্ৰেলিয়া/ব্ৰোকেন হিল (_H)"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "নিউ দক্ষিণ ৱেল্চ্‌ - ইয়ানকোউইনা"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "অস্ট্ৰেলিয়া/কেনবেৰা"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "অস্ট্ৰেলিয়া/কাৰি"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "তাস্মানিয়া - কিং দ্বীপ"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "অস্ট্ৰেলিয়া/ডাৰউইন"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "উত্তৰ অঞ্চল"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "অস্ট্ৰেলিয়া/ইউক্লা"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "পশ্চিম অস্ট্ৰেলিয়া - ইউক্লা অঞ্চল"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "অস্ট্ৰেলিয়া/হোবাৰ্ট"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "তাস্মানিয়া - অধিকাংশ স্থান"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "অস্ট্ৰেলিয়া/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "অস্ট্ৰেলিয়া/লিন্ডামেন"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "কুইন্সলেন্ড - হলিডে দ্বীপপুঞ্জ"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "অস্ট্ৰেলিয়া/লৰ্ড হাউই (_H)"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "লৰ্ড হ'ৱি দ্বীপ"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "অস্ট্ৰেলিয়া/মেলবোৰ্ন"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "ভিক্টোৰিয়া"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "অস্ট্ৰেলিয়া/উত্তৰ"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "অস্ট্ৰেলিয়া/নিউ সাইথ ওয়েলস"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "অস্ট্ৰেলিয়া/পাৰ্থ"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "পশ্চিম অস্ট্ৰেলিয়া - অধিকাংশ স্থান"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "অস্ট্ৰেলিয়া/কুইন্সলেন্ড"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "অস্ট্ৰেলিয়া/দক্ষিণ"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "অস্ট্ৰেলিয়া/চিড্নি"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "নিউ দক্ষিণ ৱেল্চ্‌ - অধিকাংশ স্থান"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "অস্ট্ৰেলিয়া/তাচ্মানিয়া"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "অস্ট্ৰেলিয়া/ভিক্টোৰিয়া"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "অস্ট্ৰেলিয়া/পশ্চিম"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "অস্ট্ৰেলিয়া/ইয়ানকোউইনা"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "ব্ৰাজিল/একৰ"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "ব্ৰাজিল/ডিনহোনহা"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "ব্ৰাজিল/পূৰ্ব"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "ব্ৰাজিল/পশ্চিম"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "কানাডা/আটলান্টিক"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "কানাডা/চেন্ট্ৰেল"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "কানাডা/পূৰ্ব"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "কানাডা/পূৰ্ব-সাসকাচুয়ান"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "কানাডা/মাউন্টেন"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "কানাডা/নিউফাউন্ডলেন্ড"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "কানাডা/পেচিফিক"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "কানাডা/সাসকাচুয়ান"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "কানাডা/ইউকোন"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "চিলি/কন্টিনেন্টাল"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "চিলি/ইস্টাৰআইলেন্ড"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "কিউবা"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "মিচৰ"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "আয়াৰ"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/গ্ৰিনউইচ"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/জুলু"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "ইউৰোপ/আমস্টাৰডাম"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "ইউৰোপ/এন্ডোৰা"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "ইউৰোপ/এথেন্স"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "ইউৰোপ/বেলফাস্ট"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "ইউৰোপ/বেলগ্ৰেড"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "ইউৰোপ/বাৰ্লিন"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "ইউৰোপ/ব্ৰাতিসলাভা"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "ইউৰোপ/ব্ৰাসেলস"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "ইউৰোপ/বুখাৰেস্ট"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "ইউৰোপ/বুডাপেস্ট"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "ইউৰোপ/চিশিনাউ"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "ইউৰোপ/কোপেনহেগেন"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "ইউৰোপ/ডাবলিন"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "ইউৰোপ/জিব্ৰালটাৰ"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "ইউৰোপ/গুয়েৰ্ন্সে"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "ইউৰোপ/হেলসিঙ্কি"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "ইউৰোপ/আইল_অফ_মেন"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "ইউৰোপ/ইস্তানবুল"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "ইউৰোপ/জাৰ্সি"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "ইউৰোপ/কালিনিনগ্ৰাড"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "মস্কো-০১ - কালিনগ্ৰাড"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "ইউৰোপ/কিভ"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "ইউৰোপ/লিচ্বন্"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "ইউৰোপ/লুবলইয়ানা"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "ইউৰোপ/লণ্ডন"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "ইউৰোপ/লুক্সেমবুৰ্গ"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "ইউৰোপ/মাদ্ৰিদ"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "ইউৰোপ/মল্টা"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "ইউৰোপ/মাৰিহাম"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "ইউৰোপ/মিনস্ক"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "ইউৰোপ/মোনেকো"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "ইউৰোপ/মস্কো"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "মস্কো+০০ - পশ্চিম ৰাছিয়া"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "ইউৰোপ/নিকোসিয়া"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "ইউৰোপ/ওসলো"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "ইউৰোপ/পেৰিশ্ব"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "ইউৰোপ/প'ডগোৰিকা"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "ইউৰোপ/প্ৰাগ"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "ইউৰোপ/ৰিগা"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "ইউৰোপ/ৰোম"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "ইউৰোপ/সামাৰা"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+#, fuzzy
+msgid "Moscow - Samara, Udmurtia"
+msgstr "মস্কো+০১ - চামাৰা, উদমুৰ্তিয়া"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "ইউৰোপ/চান মাৰিনো (_M)"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "ইউৰোপ/সাৰায়েভো"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "ইউৰোপ/সিম্ফিৰোপেল"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "মধ্য ক্ৰিমিয়া"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "ইউৰোপ/স্কপয়া"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "ইউৰোপ/সোফিয়া"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "ইউৰোপ/স্টকহোম"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "ইউৰোপ/ট্যালিন"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "ইউৰোপ/তিৰানা"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "ইউৰোপ/তিৰাসপোল"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "ইউৰোপ/উজগোৰোদ"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "ৰুথেনিয়া"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "ইউৰোপ/ভাদুজ"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "ইউৰোপ/ভ্যাটিকেন"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "ইউৰোপ/ভিয়েনা"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "ইউৰোপ/ভিলনিয়াস"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "ইউৰোপ/ভোল্গোগ্ৰাড"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "মস্কো+০০ - কাস্পিয়ান সাগৰ"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "ইউৰোপ/ওয়াৰস"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "ইউৰোপ/জাগ্ৰেব"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "ইউৰোপ/জাপোৰোযেই"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "জেফোৰিজিয়া, পূ লুগানস্ক / জেফোৰিজিয়া, পূ লুহানস্ক"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "ইউৰোপ/জুৰিখ"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "ফ্যাক্টৰি"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "গ্ৰেট ব্ৰিটেন"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "গ্ৰেট ব্ৰিটেন-আয়াৰ"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "গ্ৰিনউইচ"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "হং কং"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "আইসলেন্ড"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "ভাৰত মহাসাগৰ/আন্তানানাৰিভো"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "ভাৰত মহাসাগৰ/চাগোস"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "ভাৰত মহাসাগৰ/ক্ৰিস্টমাস"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "ভাৰত মহাসাগৰ/কোকোস"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "ভাৰত মহাসাগৰ/কোমোৰো"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "ভাৰত মহাসাগৰ/কাৰগুয়েলেন"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "ভাৰত মহাসাগৰ/মাহে"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "ভাৰত মহাসাগৰ/মালদিভ"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "ভাৰত মহাসাগৰ/মৰিশাস"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "ভাৰত মহাসাগৰ/মেয়োতে"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "ভাৰত মহাসাগৰ/ৰিউনিয়ন"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "ইৰাণ"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "ইজ্ৰায়েল"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "জামাইকা"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "জাপান"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "কয়াজালিইন"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "লিবিয়া"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "মেক্সিকো/বাহানোৰ্তে"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "মেক্সিকো/বাহাসুৰ"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "মেক্সিকো/সাধাৰণ"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "মধ্যপ্ৰাচ্য/ৰিয়াধ৮৭"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "মধ্যপ্ৰাচ্য/ৰিয়াধ৮৮"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "মধ্যপ্ৰাচ্য/ৰিয়াধ৮৯"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "নাভাজো"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "প্ৰশান্ত মহাসাগৰ/এপিয়া"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "প্ৰশান্ত মহাসাগৰ/অকলেন্ড"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "প্ৰশান্ত মহাসাগৰ/চ্যাটহাম"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "কেটহেম দ্বীপপুঞ্জ"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "প্ৰশান্ত মহাসাগৰ/ট্ৰুক"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+#, fuzzy
+msgid "Chuuk (Truk) and Yap"
+msgstr "ট্ৰুক (চুক) আৰু ইয়াপ"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "প্ৰশান্ত মহাসাগৰ/ঈষ্টাৰ"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "ইস্টাৰ দ্বীপ & চালা ই গোমেজ"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "প্ৰশান্ত মহাসাগৰ/এফাতে"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "প্ৰশান্ত মহাসাগৰ/এন্ডাৰবুৰি"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "ফিনিক্স দ্বীপপুঞ্জ"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "প্ৰশান্ত মহাসাগৰ/ফাকাওফো"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "প্ৰশান্ত মহাসাগৰ/ফিজি"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "প্ৰশান্ত মহাসাগৰ/ফুনাফুতি"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "প্ৰশান্ত মহাসাগৰ/গালাপাগোস"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "গেলাপাগোচ দ্বীপপুঞ্জ"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "প্ৰশান্ত মহাসাগৰ/গ্যামবিয়াৰ"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "গেম্বিয়াৰ দ্বীপপুঞ্জ"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "প্ৰশান্ত মহাসাগৰ/গুয়াডালকানাল"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "প্ৰশান্ত মহাসাগৰ/গুয়াম"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "প্ৰশান্ত মহাসাগৰ/হনোলুলু"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "হাৱাই"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "প্ৰশান্ত মহাসাগৰ/জনস্টন"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "জনস্টন এটোল"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "প্ৰশান্ত মহাসাগৰ/কিৰিতিমাটি"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "লাইন দ্বীপপুঞ্জ"
+
+# is this kiribati?
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "প্ৰশান্ত মহাসাগৰ/কোসৰে"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "কোসৰেই"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "প্ৰশান্ত মহাসাগৰ/কয়াজালিইন"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "প্ৰশান্ত মহাসাগৰ/মাজুৰো"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "প্ৰশান্ত মহাসাগৰ/মাৰকিসাস"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "মাৰ্কুইচাচ দ্বীপপুঞ্জ"
+
+# not sure
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "প্ৰশান্ত মহাসাগৰ/মিডওয়ে"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "মিডৱে দ্বীপপুঞ্জ"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "প্ৰশান্ত মহাসাগৰ/নাউৰু"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "প্ৰশান্ত মহাসাগৰ/নিউ"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "প্ৰশান্ত মহাসাগৰ/নোৰফোল্ক"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "প্ৰশান্ত মহাসাগৰ/নুমিয়া"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "প্ৰশান্ত মহাসাগৰ/পাগো_পাগো"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "প্ৰশান্ত মহাসাগৰ/পালাউ"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "প্ৰশান্ত মহাসাগৰ/পিটকেয়াৰ্ন"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "প্ৰশান্ত মহাসাগৰ/পোনাপে"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+#, fuzzy
+msgid "Pohnpei (Ponape)"
+msgstr "পোনাপে (পোনপেই)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "প্ৰশান্ত মহাসাগৰ/পোনাপে"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "প্ৰশান্ত মহাসাগৰ/পোৰ্ট-মোৰ্সবি"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "প্ৰশান্ত মহাসাগৰ/ৰাৰোটোঙ্গা"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "প্ৰশান্ত মহাসাগৰ/সাইপান"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "প্ৰশান্ত মহাসাগৰ/সামোয়া"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "প্ৰশান্ত মহাসাগৰ/তাহিতি"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "চোচাইটি দ্বীপপুঞ্জ"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "প্ৰশান্ত মহাসাগৰ/তাৰাওয়া"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "গিলবাৰ্ট দ্বীপপুঞ্জ"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "প্ৰশান্ত মহাসাগৰ/টোঙ্গাটাপু"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "প্ৰশান্ত মহাসাগৰ/ট্ৰুক"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "প্ৰশান্ত মহাসাগৰ/ওয়েক"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "ৱেক দ্বীপ"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "প্ৰশান্ত মহাসাগৰ/ওয়ালিচ"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "প্ৰশান্ত মহাসাগৰ/ইয়াপ"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "পোলেন্ড"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "পৰ্তুগাল"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "সিঙ্গাপুৰ"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "তুৰস্ক"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "যুক্তৰাষ্ট্ৰ/আলাস্কা"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "যুক্তৰাষ্ট্ৰ/আলিউছিয়ান"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "যুক্তৰাষ্ট্ৰ/আৰিজোনা"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "যুক্তৰাষ্ট্ৰ/চেন্ট্ৰেল"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "যুক্তৰাষ্ট্ৰ/ইচ্টাৰ্ন"
+
+# msgstr "যুক্তৰাষ্ট্র/পূর্ববর্তী"
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "যুক্তৰাষ্ট্ৰ/পূৰ্ব-ইন্ডিয়ানা"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "যুক্তৰাষ্ট্ৰ/হাওয়াই"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "যুক্তৰাষ্ট্ৰ/ইন্ডিয়ানা-স্টাৰ্ক"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "যুক্তৰাষ্ট্ৰ/মিশিগান"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "যুক্তৰাষ্ট্ৰ/মাউন্টেন"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "যুক্তৰাষ্ট্ৰ/পেসিফিক"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "যুক্তৰাষ্ট্ৰ/সামোয়া"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "জুলু"
+
+#~ msgid "US/Pacific-New"
+#~ msgstr "যুক্তৰাষ্ট্র/প্যাসিফিক-নিউ"
diff --git a/panels/datetime/po-timezones/ast.po b/panels/datetime/po-timezones/ast.po
new file mode 100644
index 0000000..2bf061a
--- /dev/null
+++ b/panels/datetime/po-timezones/ast.po
@@ -0,0 +1,3250 @@
+# translation of timezones.tip.ast.po to Asturian
+# translation of ast.po to
+# Copyright (C) 2004, 2006, 2008 Free Software Foundation, Inc.
+#
+# Astur <malditoastur@gmail.com>, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones.tip.ast\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-10-13 17:28+0100\n"
+"Last-Translator: Iñigo Varela <ivarela@softastur.org>\n"
+"Language-Team: Asturian <alministradores@softastur.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ast\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: asturian\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "África/Abiyán"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "África/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "África/Addis_Abeba"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "África/Alxeria"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "África/Asmera"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "África/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "África/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "África/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "África/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "África/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "África/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "África/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "África/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "África/El_Cairu"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "África/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "África/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "Ceuta & Melilla"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "África/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "África/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "África/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "África/Djibouti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "África/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "África/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "África/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "África/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "África/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "África/Johannesburgu"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "África/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "África/Khartoum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "África/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "África/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "west Dem. Rep. of Congo"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "África/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "África/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "África/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "África/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "África/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "east Dem. Rep. of Congo"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "África/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "África/Malabu"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "África/Maputu"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "África/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "África/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "África/Mogadixu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "África/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "África/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "África/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "África/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "África/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "África/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "África/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "África/Santo_Tomé"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "África/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "África/Trípoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "África/Túnez"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "África/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "América/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Islles Aleutianesds"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "América/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Alaska Time"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "América/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "América/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "América/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "Tocantins"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "América/Arxentina/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Buenos Aires (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "América/Arxentina/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "Catamarca (CT), Chubut (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "América/Arxentina/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "América/Arxentina/Córdoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "América/Arxentina/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Jujuy (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "América/Arxentina/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "La Rioja (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "América/Arxentina/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "Mendoza (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "América/Arxentina/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "Santa Cruz (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "América/Arxentina/Salta"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "América/Arxentina/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "San Juan (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "América/Arxentina/San_Luis"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "San Luis (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "América/Arxentina/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "Tucuman (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "América/Arxentina/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "Tierra del Fuego (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "América/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "América/Asunción"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "América/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "América/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "América/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "Bahia"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "América/Bahia_Banderas"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "Mexican Central Time - Bahia de Banderas"
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "América/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "América/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "Amapa, E Para"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "América/Belize"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "América/Blanc-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "Atlantic Standard Time - Quebec - Lower North Shore"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "América/Boa Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "Roraima"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "América/Bogotá"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "América/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "Mountain Time - south Idaho & east Oregon"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "América/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "América/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "Mountain Time - west Nunavut"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "América/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "Mato Grosso do Sul"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "América/Cancún"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "Central Time - Quintana Roo"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "América/Caraques"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "América/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "América/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "América/Caimán"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "América/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "Central Time"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "América/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "Mexican Mountain Time - Chihuahua away from US border"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "América/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "América/Córdoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "América/Costa_Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "América/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "Mato Grosso"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "América/Curacao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "América//Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "east coast, north of Scoresbysund"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "América/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "Pacific Time - north Yukon"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "América/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid "Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr "Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "América/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "Mountain Time"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "América/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "Eastern Time - Michigan - most locations"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "América/Dominica"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "América/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "América/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "W Amazones"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "América/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "América/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "América/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "NE Brazil (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "América/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "América/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "América/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195
+#: timezones.h:364
+#: timezones.h:453
+#: timezones.h:591
+#: timezones.h:754
+#: timezones.h:852
+#: timezones.h:894
+msgid "most locations"
+msgstr "most locations"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "América/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "Atlantic Time - Labrador - most locations"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "América/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "América/Granada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "América/Guadalupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "América/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "América/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205
+#: timezones.h:757
+#: timezones.h:763
+msgid "mainland"
+msgstr "mainland"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "América/Guyana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "América/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "Atlantic Time - Nova Scotia (most places), PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "América/Habana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "América/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "Mountain Standard Time - Sonora"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "América/Indiana/Indianápolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "Eastern Time - Indiana - most locations"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "América/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "Central Time - Indiana - Starke County"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "América/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "Eastern Time - Indiana - Crawford County"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "América/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "Eastern Time - Indiana - Pike County"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "América/Indianápolis"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "América/Indiana/Tell_City"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "Central Time - Indiana - Perry County"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "América/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "Eastern Time - Indiana - Switzerland County"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "América/Indiana/Vencennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "América/Indiana/Winamac"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "Eastern Time - Indiana - Pulaski County"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "América/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "Mountain Time - west Northwest Territories"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "América/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "Eastern Time - east Nunavut - most locations"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "América/Xamaica"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "América/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "América/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "Alaska Time - Alaska panhandle"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "América//Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Eastern Time - Kentucky - Louisville area"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "América/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "Eastern Time - Kentucky - Wayne County"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "América/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "América/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "América/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "América/Los_Anxeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "Pacific Time"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "América/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "América/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "Alagoas, Sergipe"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "América/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "América/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "E Amazones"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "América/Marigot"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "América/Martinica"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "América/Matamoros"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid "US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr "US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "América/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "Mountain Time - S Baja, Nayarit, Sinaloa"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "América/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "América/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "América/Mendoza"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "Central Time - Campeche, Yucatan"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "América/Ciudá_de_Méxicu"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "Central Time - most locations"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "América/Miquelon"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "América/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "Atlantic Time - New Brunswick"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "América/Monterréi"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid "Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from US border"
+msgstr "Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from US border"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "América/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "América/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "Eastern Time - Quebec - most locations"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "América/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "América/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "América/Nueva_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "Eastern Time"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "América/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid "Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr "Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "América/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "Alaska Time - west Alaska"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "América/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "Atlantic islands"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "América/Dakota del Norte/Centru"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "Central Time - North Dakota - Oliver County"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "América/Dakota del Norte/Nueva Salem"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "Central Time - North Dakota - Morton County (except Mandan area)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "América/Ojinaga"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "US Mountain Time - Chihuahua near US border"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "América/Panamá"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "América/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "Eastern Time - Pangnirtung, Nunavut"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "América/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "América/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "Mountain Standard Time - Arizona"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "América/Puertu-Príncipe"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "América/Puertu_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "América/Puertu_España"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "América/Puertu_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "Rondonia"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "América/Puertu_Ricu"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "América/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "Central Time - Rainy River & Fort Frances, Ontario"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "América/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "Central Time - central Nunavut"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "América/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "Pernambuco"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "América/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "Central Standard Time - Saskatchewan - most locations"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "América/Resolute"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "Eastern Standard Time - Resolute, Nunavut"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "América/Río Blanco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "Acre"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "América/Rosario"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "América/Santa_Isabel"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "Mexican Pacific Time - Baja California away from US border"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "América/Santarem"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "W Para"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "América/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "América/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "América/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "América/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "Scoresbysund / Ittoqqortoormiit"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "América/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "Mountain Time - Navajo"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "América/San_Bartolomé"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "América/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "Newfoundland Time, including SE Labrador"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "América/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "América/St_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "América/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "América/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "América/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "Central Standard Time - Saskatchewan - midwest"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "América/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "América/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "Thule / Pituffik"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "América/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "Eastern Time - Thunder Bay, Ontario"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "América/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "US Pacific Time - Baja California near US border"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "América/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "Eastern Time - Ontario - most locations"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "América/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "América/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "Pacific Time - west British Columbia"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "América/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "América/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "Pacific Time - south Yukon"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "América/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "Central Time - Manitoba & west Ontario"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "América/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "Alaska Time - Alaska panhandle neck"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "América/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "Mountain Time - central Northwest Territories"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antártida/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "Casey Station, Bailey Peninsula"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antártida/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "Davis Station, Vestfold Hills"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antártida/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "Dumont-d'Urville Station, Terre Adelie"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "Antártida/Macquarie"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "Macquarie Island Station, Macquarie Island"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antártida/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "Mawson Station, Holme Bay"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antártida/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "McMurdo Station, Ross Island"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antártida/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "Palmer Station, Anvers Island"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antárctica/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "Rothera Station, Adelaide Island"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antártida/Polo_sur"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "Amundsen-Scott Station, South Pole"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antártida/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "Syowa Station, E Ongul I"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antártida/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "Vostok Station, S Magnetic Pole"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Árticu/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Asia/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Asia/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Asia/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Asia/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "Moscow+08 - Bering Sea"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Asia/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Asia/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "Aqtobe (Aktobe)"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Asia/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Asia/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Asia/Bagdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Asia/Baḥréin"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Asia/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Asia/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Asia/Beirut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Asia/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Asia/Brunéi"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Asia/Calcuta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Asia/Choibalsán"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "Dornod, Sukhbaatar"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Asia/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Asia/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Asia/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Asia/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Asia/Damascu"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Asia/Dhaka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Asia/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Asia/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Asia/Dushanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Asia/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Asia/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "Heilongjiang (except Mohe), Jilin"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Asia/Ho_Chi_Minh"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Asia/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Asia/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Asia/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Moscow+05 - Lake Baikal"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Asia/Estambul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Asia/Yakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "Java & Sumatra"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Asia/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "Irian Jaya & the Moluccas"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Asia/Xerusalén"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Asia/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Asia/Kamchatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "Moscow+08 - Kamchatka"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Asia/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Asia/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "west Tibet & Xinjiang"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "Asia/Katmandú"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Asia/Katmandú"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "Asia/Calcuta"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Asia/Krasnoyarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "Moscow+04 - Yenisei River"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Asia/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "peninsular Malaysia"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Asia/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "Sabah & Sarawak"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Asia/Kuwait"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Asia/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Asia/Macao"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Asia/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "Moscow+08 - Magadan"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Asia/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Asia/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Asia/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Asia/Nicosia"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "Asia/Novokuznetsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Moscow+03 - Novokuznetsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Asia/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Moscow+03 - Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Asia/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "Moscow+03 - west Siberia"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Asia/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "West Kazakhstan"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Asia/Phnom_Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Asia/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "west & central Borneo"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Asia/Pyongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Asia/Qatar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Asia/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Asia/Rangún"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Asia/Riyadh"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Asia/Riyadh87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Asia/Riyadh88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Asia/Riyadh89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Asia/Saigón"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Asia/Sakhalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "Moscow+07 - Sakhalin Island"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Asia/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "west Uzbekistan"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Asia/Seúl"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Asia/Xanghái"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "east China - Beijing, Guangdong, Shanghai, etc."
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Asia/Singapur"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Asia/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Asia/Tashkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "east Uzbekistan"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Asia/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Asia/Teḥrán"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Asia/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Asia/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Asia/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Asia/Tokiu"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Asia/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Asia/Ulan_Bator"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Asia/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Asia/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "most of Tibet & Xinjiang"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Asia/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Asia/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "Moscow+07 - Amur River"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Asia/Yakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "Moscow+06 - Lena River"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Asia/Yekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "Moscow+02 - Urales"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Asia/Yerevan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlánticu/Azores"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "Azores"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlánticu/Bermudes"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlánticu/Canaries"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "Canary Islands"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlánticu/Cabu_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlánticu/Feroe"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "Atlánticu/Feroe"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlánticu/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlánticu/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "Islles Madeira"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlánticu/Reikiavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlánticu/Xeorxa_del_Sur"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlánticu/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlánticu/St_Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Australia/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Australia/Adelaida"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "South Australia"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Australia/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "Queensland - most locations"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Australia/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "New South Wales - Yancowinna"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Australia/Camberra"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Australia/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "Tasmania - King Island"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Australia/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "Northern Territory"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "Australia/Eucla"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "Western Australia - Eucla area"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Australia/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "Tasmania - most locations"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Australia/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Australia/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "Queensland - Holiday Islands"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Australia/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "Lord Howe Island"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Australia/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Australia/Norte"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Australia/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Australia/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "Western Australia - most locations"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Australia/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Australia/Sur"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Australia/Sidney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "New South Wales - most locations"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Australia/Tasmania"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Australia/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Australia/Oeste"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Australia/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brasil/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brasil/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brasil/Este"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brasil/Oeste"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Canadá/Atlánticu"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Canadá/Central"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Canadá/Oriental"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Canadá/East-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Canadá/Mountain"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Canadá/Newfoundland"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Canadá/Pacíficu"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Canadá/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Canadá/Saskatchewan"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Chile/Continental"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Chile/Islla_de_Pascua"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Cuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Exiptu"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Irlanda"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulú"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Europa/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Europa/Andorra"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Europa/Atenes"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Europa/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Europa/Belgráu"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Europa/Berlín"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Europa/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Europa/Bruxeles"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Europa/Bucarest"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Europa/Budapest"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Europa/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Europa/Copenague"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Europa/Dublín"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Europa/Xibraltar"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Europa/Guernsey"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Europa/Helsinki"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Europa/Islla_de_Man"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Europa/Estambul"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Europa/Xerséi"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Europa/Kaliningráu"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Moscow-01 - Kaliningrad"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Europa/Kiev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Europa/Lisboa"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Europa/Liubliana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Europa/Londres"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Europa/Luxemburgu"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Europa/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Europa/Malta"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Europa/Mariehamn"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Europa/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Europa/Mónacu"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Europa/Moscú"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "Moscow+00 - west Russia"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Europa/Nicosia"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Europa/Oslu"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Europa/París"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Europa/Podgorica"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Europa/Praga"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Europa/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Europa/Roma"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Europa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Moscow - Samara, Udmurtia"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Europa/San_Marín"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Europa/Sarayevu"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Europa/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "central Crimea"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Europa/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Europa/Sofía"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Europa/Estocolmu"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Europa/Tallinn"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Europa/Tirana"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Europa/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Europa/Uzhgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "Ruthenia"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Europa/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Europa/Vaticanu"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Europa/Viena"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Europa/Vilnius"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Europa/Volgográu"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "Moscow+00 - Caspian Sea"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Europa/Varsovia"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Europa/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Europa/Zaporozheye"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Europa/Zúrich"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Factory"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Eire"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hong-Kong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Islandia"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Índicu/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Índicu/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Índicu/Christmas"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Índicu/Cocos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Índicu/Comores"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Índicu/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Índicu/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Índicu/Maldives"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Índicu/Mauricio"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Índicu/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Índicu/Reunión"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Irán"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Israel"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Xamaica"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Xapón"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835
+#: timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Libia"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Méxicu/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Méxicu/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Méxicu/Xeneral"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Oriente_Mediu/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Oriente_Mediu/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Oriente_Mediu/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Pacíficu/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Pacíficu/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Pacíficu/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "Chatham Islands"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "Pacíficu/Chuuk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "Chuuk (Truk) and Yap"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Pacíficu/Islla de Pascua"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "Easter Island & Sala y Gomez"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Pacíficu/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Pacíficu/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "Phoenix Islands"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Pacíficu/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Pacíficu/Fiji"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Pacíficu/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Pacíficu/Galápagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "Islles Galápagos"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Pacíficu/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "Islles Gambier"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Pacíficu/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Pacíficu/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Pacíficu/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "Hawaii"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Pacíficu/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "Johnston Atoll"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Pacíficu/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "Line Islands"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Pacíficu/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "Kosrae"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Pacíficu/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Pacíficu/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Pacíficu/Marqueses"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "Islles Marqueses"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Pacíficu/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "Islles Midway"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Pacíficu/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Pacíficu/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Pacíficu/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Pacíficu/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Pacíficu/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Pacíficu/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Pacíficu/Pitcairn"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "Pacíficu/Pohnpei"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "Pohnpei (Ponape)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Pacíficu/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Pacíficu/Puerto_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Pacíficu/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Pacíficu/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Pacíficu/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Pacíficu/Tahití"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "Islles Society"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Pacíficu/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "Islles Gilbert"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Pacíficu/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Pacíficu/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Pacíficu/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "Wake Island"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Pacíficu/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Pacíficu/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Polonia"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugal"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapur"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Turquía"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "EEXX/Alaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "EEXX/Aleutianas"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "EEXX/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "EEXX/Central"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "EEXX/Oriental"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "EEXX/Indiana-Este"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "EEXX/Hawai"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "EEXX/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "EEXX/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "EEXX/Mountain"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "EEXX/Pacíficu"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "EEXX/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulú"
+
+#~ msgid "US/Pacific-New"
+#~ msgstr "EEXX/Nuevu Pacíficu"
+#~ msgid "zone.tab"
+#~ msgstr "zone.tab"
+
diff --git a/panels/datetime/po-timezones/bg.po b/panels/datetime/po-timezones/bg.po
new file mode 100644
index 0000000..9b89f81
--- /dev/null
+++ b/panels/datetime/po-timezones/bg.po
@@ -0,0 +1,3275 @@
+# translation of timezones.po to Bulgarian
+# This file is distributed under the same license as the PACKAGE package.
+# Copyright (C) 2006 THE PACKAGE'S COPYRIGHT HOLDER.
+#
+# Николай Сърмаджиев,преносим <nikolayds@msn.com>, 2004.
+# Doncho N. Gunchev <gunchev@gmail.com>, 2007.
+# Miroslav Ivanov <satyr@globalnet.bg>, 2007.
+# Miroslav Ivanov <kiro.kopeleto@gmail.com>, 2007.
+# Alexander Todorov <atodorov@redhat.com>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2008-03-10 21:50+0100\n"
+"Last-Translator: Alexander Todorov <atodorov@redhat.com>\n"
+"Language-Team: Bulgarian <dict@fsa-bg.org>\n"
+"Language: bg\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Африка/Абиджан"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Африка/Акра"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Африка/Адис_Абеба"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Африка/Алжир"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "Африка/Асмара"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Африка/Асмера"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Африка/Бамако"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Африка/Банги"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Африка/Банов"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Африка/Бисау"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Африка/Блантир"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Африка/Бразавил"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Африка/Буюнбура"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Африка/Кайро"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Африка/Казабланка"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Африка/Сеулта"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Африка/Конакри"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Африка/Дакар"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Африка/Дар_ес_Салам"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Африка/Джибути"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Африка/Дуала"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Африка/Ел_Аюн"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Африка/Фрийтаун"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Африка/Габороне"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Африка/Хараре"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Африка/Йоханесбург"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Африка/Кампала"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Африка/Хартум"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Африка/Кигали"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Африка/Киншаса"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Африка/Лагос"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Африка/Лебервил"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Африка/Ломе"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Африка/Луанда"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Африка/Лубумбаши"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Африка/Лусака"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Африка/Малабо"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Африка/Мапуту"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Африка/Масеру"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Африка/Мбабане"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Африка/Могадишу"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Африка/Монровия"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Африка/Найроби"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Африка/Нджамена"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Африка/Немей"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Африка/Нуакшот"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Африка/Уагадугу"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Африка/Порто-Ново"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Африка/Сао_Томе"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Африка/Тимбукту"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Африка/Триполи"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Африка/Тунис"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Африка/Уиндхоек"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Америка/Адак"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+#, fuzzy
+msgid "Aleutian Islands"
+msgstr "Австралия/Куинсленд"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Америка/Анкоридж"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+#, fuzzy
+msgid "Alaska Time"
+msgstr "САЩ/Аляска"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Америка/Агнила"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Америка/Антигуа"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Америка/Арагуайна"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Америка/Аржентина/Буенос_Айрес"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Америка/Аржентина/Катамарка"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Америка/Аржентина/Комодоро_Ривадавия"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Америка/Аржентина/Кордова"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Америка/Аржентина/Юию"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Америка/Аржентина/Риоха"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Америка/Аржентина/Мендоза"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Америка/Аржентина/Рио_Галегос"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+#, fuzzy
+msgid "America/Argentina/Salta"
+msgstr "Америка/Аржентина/Сан_Хуан"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Америка/Аржентина/Сан_Хуан"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+#, fuzzy
+msgid "America/Argentina/San_Luis"
+msgstr "Америка/Аржентина/Сан_Хуан"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Америка/Аржентина/Тукуман"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Америка/Аржентина/Ушуая"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Америка/Аруба"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Америка/Асунсион"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Америка/Атикокан"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Америка/Атка"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Америка/Байя"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "Америка/Байя"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Америка/Барбейдос"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Америка/Белем"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Америка/Белийз"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "Америка/Блан-Саблон"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Америка/Боа_Виста"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Америка/Богота"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Америка/Бойсе"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Америка/Буенос_Айрес"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Америка/Кеймбридж_Бей"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "Америка/Кампо-Гранде"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Америка/Канкун"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Америка/Каракас"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Америка/Катамарка"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Америка/Каене"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Америка/Кайман"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Америка/Чикаго"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+#, fuzzy
+msgid "Central Time"
+msgstr "САЩ/Централно"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Америка/Чихуахуа"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "Америка/Корал_Харбър"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Америка/Кордова"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Америка/Коста_Рика"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Америка/Куиаба"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Америка/Каракао"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Америка/Денмаркшавн"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Америка/Даунсон"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Америка/Даунсон_Криик"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Америка/Денвър"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+#, fuzzy
+msgid "Mountain Time"
+msgstr "САЩ/Планинско"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Америка/Детройт"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Америка/Доминика"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Америка/Едмънтън"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Америка/Еирунепе"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Америка/Ел_Салвадор"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Америка/Енсенада"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Америка/Форталеза"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Америка/Форт_Уейн"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Америка/Глайс_Бей"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Америка/Годтаб"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Америка/Гууз_Бей"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Америка/Гранд_Турк"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Америка/Гранада"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Америка/Гваделупа"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Америка/Гватемала"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Америка/Гуякуил"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Америка/Гвиана"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Америка/Халифакс"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Америка/Хавана"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Америка/Ермосильо"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Америка/Индиана/Индианаполис"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Америка/Индиана/Кнокс"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Америка/Индиана/Маренго"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "Америка/Индиана/Питърсбърг"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Америка/Индианаполис"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "Америка/Индиана/град Телл"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Америка/Индиана/Вевай"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "Америка/Индиана/Винсен"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "Америка/Индиана/гр. Винамац"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Америка/Инувик"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Америка/Икалуит"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Америка/Ямайка"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Америка/Юию"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Америка/Юнеу"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Америка/Кентъки/Луисвил"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+#, fuzzy
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Америка/Кентъки/Луисвил"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Америка/Кентъки/Монтичело"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Америка/Кнокс_Ин"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Америка/Ла_Паз"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Америка/Лима"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Америка/Лос_Анджелис"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+#, fuzzy
+msgid "Pacific Time"
+msgstr "Тих_Океан/Ниуе"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Америка/Луисвил"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Америка/Масейо"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Америка/Манагуа"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Америка/Манагуа"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "Америка/о-в Св. Мартин/гр. Мариго"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Америка/Мартиника"
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "Америка/Манагуа"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Америка/Мазатлан"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Америка/Мендоза"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Америка/Меномине"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Америка/Мерида"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Америка/Мексико_Сити"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Америка/Микелон"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "Америка/Монктън"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Америка/Монтерей"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Америка/Монтевидео"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Америка/Монреал"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Америка/Монсерат"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Америка/Насау"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Америка/Ню_Йорк"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+#, fuzzy
+msgid "Eastern Time"
+msgstr "САЩ/Източно"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Америка/Нипигон"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Америка/Номе"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Америка/Норона"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+#, fuzzy
+msgid "Atlantic islands"
+msgstr "Атлантик/Канари"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Америка/Северна_Дакота/Център"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "Америка/Северна_Дакота/Ню_Сейлъм"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "Америка/Манагуа"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Америка/Панама"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Америка/Пангниртунг"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Америка/Парамарибо"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Америка/Финикс"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Америка/Порт-о-Пренс"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Америка/Порт_Акра"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Америка/Порт_о_Испания"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Америка/Порто_Вельо"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Америка/Пуерто_Рико"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Америка/Рейни_Ривър"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Америка/Ранкин_Инлет"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Америка/Рециф"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Америка/Реджина"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "Америка/Нунавут/село Резолют"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Америка/Рио_Бранко"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Америка/Росарио"
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "Америка/Сантяго"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+#, fuzzy
+msgid "America/Santarem"
+msgstr "Америка/Сантяго"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Америка/Сантяго"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Америка/Санто_Доминго"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Америка/Сао_Пауло"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Америка/Скоресбисънд"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Америка/Шипрок"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "Америка/о-ви Свети Бартоломей"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Америка/Св_Джоунс"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Америка/Св_Киц"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Америка/Св_Луция"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Америка/Св_Тома"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Америка/Св_Винсент"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Америка/Суифт_Кърент"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Америка/Тегусигалпа"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Америка/Туле"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Америка/Тъндър_Бей"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Америка/Тихуана"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "Америка/Торонто"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Америка/Тортола"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Америка/Ванкувър"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Америка/Вирджин"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Америка/Уайтхорс"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Америка/Уинипек"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Америка/Якутат"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Америка/Йелоунайф"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Антарктика/Кейси"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Антарктика/Девиз"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Антарктика/ДюмонДюУрвил"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+#, fuzzy
+msgid "Antarctica/Macquarie"
+msgstr "Антарктика/МакМърдо"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Антарктика/Маусън"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Антарктика/МакМърдо"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Антарктика/Палмър"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Антарктика/Ротера"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Антарктика/Южен_Полюс"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Антарктика/Сиова"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Антарктика/Восток"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Антарктика/Лонгиейрбиен"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Азия/Аден"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Азия/Алма_Ати"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Азия/Аман"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Азия/Анадир"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Азия/Актау"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Азия/Аятове"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Азия/Ашхабад"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Азия/Ашхабад"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Азия/Багдад"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Азия/Бахрейн"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Азия/Баку"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Азия/Банкок"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Азия/Бейрут"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Азия/Бишкек"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Азия/Бруней"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Азия/Калкута"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Азия/Чойбалсан"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Азия/Хонконг"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Азия/Чунким"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Азия/Коломбо"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Азия/Дака"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Азия/Дамаск"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Азия/Дака"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Азия/Дили"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Азия/Дубай"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Азия/Душанбе"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Азия/Газа"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Азия/Харбин"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+#, fuzzy
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Азия/Хонконг"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Азия/Хонг_Конг"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Азия/Ховд"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Азия/Иркутск"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Азия/Истанбул"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Азия/Джакарта"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Азия/Джаяпура"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Азия/Йерусалим"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Азия/Кабул"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Азия/Камчатка"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Азия/Карачи"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Азия/Кашгар"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+#, fuzzy
+msgid "Asia/Kathmandu"
+msgstr "Азия/Катманду"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Азия/Катманду"
+
+#: timezones.h:518
+#, fuzzy
+msgid "Asia/Kolkata"
+msgstr "Азия/Джакарта"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Азия/Красноярск"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Азия/Куала_Лумпур"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Азия/Кучинг"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Азия/Кувейт"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Азия/Макао"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Азия/Макао"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Азия/Магадан"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Азия/Макасар"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Азия/Манила"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Азия/Мускат"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Азия/Никозия"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "Азия/Иркутск"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Азия/Новосибирск"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Азия/Новосибирск"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+#, fuzzy
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Азия/Новосибирск"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Азия/Омск"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Азия/Орел"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Азия/Пном_Пен"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Азия/Понтианак"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Азия/Пхенян"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Азия/Катар"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Азия/Кизилорда"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Азия/Рангун"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Азия/Рияд"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Азия/Рияд87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Азия/Рияд88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Азия/Рияд89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Азия/Хошимин"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Азия/Сахалин"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Азия/Самарканд"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Азия/Сеул"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Азия/Шанхай"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Азия/Сингапур"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Азия/Тайпей"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Азия/Ташкент"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Азия/Тбилиси"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Азия/Техеран"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Азия/Тел_Авив"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Азия/Тимбу"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Азия/Тимфу"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Азия/Токио"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Азия/Юнг_Падан"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Азия/Уан_Батор"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Азия/Улан_Батор"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Азия/Урумю"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Азия/Виемтян"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Азия/Владивосток"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Азия/Якутск"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Азия/Екатеринбург"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Азия/Ереван"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Атлантик/Азори"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Атлантик/Бермуда"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Атлантик/Канари"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Атлантик/Зелени_Нос"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Атлантик/Фериори"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "Атлантик/Фарьорски о-ви"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Атлантик/Ян_Майен"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Атлантик/Мадейра"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Атлантик/Рейкявик"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Атлантик/Южна_Джорджия"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Атлантик/Стенли"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Атлантик/Св_Елена"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Австралия/АКТ"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Австралия/Аделаида"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+#, fuzzy
+msgid "South Australia"
+msgstr "Австралия/АКТ"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Австралия/Бризбейн"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Австралия/Брокън_Хил"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Австралия/Канбера"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Австралия/Къри"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Австралия/Дарвин"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "Австралия/Еукла"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+#, fuzzy
+msgid "Western Australia - Eucla area"
+msgstr "Австралия/Еукла"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Австралия/Хобарт"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Австралия/ЛХИ"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Австралия/Линдеман"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Австралия/Лорд_Хове"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Австралия/Мелбърн"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+#, fuzzy
+msgid "Victoria"
+msgstr "Австралия/Виктория"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Австралия/Север"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Австралия/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Австралия/Перд"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Австралия/Куинсленд"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Австралия/Юг"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Австралия/Сидней"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Австралия/Тасмания"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Австралия/Виктория"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Австралия/Запад"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Австралия/Янковина"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Бразилия/Акре"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Бразилия/Де_Норона"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Бразилия/Изток"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Бразилия/Запад"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Канада/Атлантик"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Канада/Централна"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Канада/Източна"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Канада/ИзточенСаскачеуан"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Канада/Планинска"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Канада/Нюфаундленд"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Канада/Пасифик"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Канада/Саскачеуан"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Канада/Юкон"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "СЕТ"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Чили/Континентално"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Чили/Великденски_Острови"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Куба"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "ЕЕТ"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Египет"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Ейре"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "ЕSТ"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Гринуич"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Универсално"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Зулу"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Европа/Амстердам"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Европа/Андора"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Европа/Атина"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Европа/Белфаст"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Европа/Белград"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Европа/Берлин"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Европа/Братислава"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Европа/Брюксел"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Европа/Букурещ"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Европа/Будапеща"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Европа/Чисинау"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Европа/Копенхаген"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Европа/Дъблин"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Европа/Гибралтар"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Европа/Гернси"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Европа/Хелзинки"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Европа/о-в Ман"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Европа/Истанбул"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Европа/Джърси"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Европа/Калининград"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Европа/Киев"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Европа/Лисабон"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Европа/Любляна"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Европа/Лондон"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Европа/Люксембург"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Европа/Мадрид"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Европа/Малта"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Европа/Мариехамн"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Европа/Минск"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Европа/Монако"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Европа/Москва"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Европа/Никозия"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Европа/Осло"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Европа/Париж"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Европа/Подгорица"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Европа/Прага"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Европа/Рига"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Европа/Рим"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Европа/Самара"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Европа/Сан_Марино"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Европа/Сараево"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Европа/Симферопол"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Европа/Скопие"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Европа/СОФИЯ"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Европа/Стокхолм"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Европа/Талин"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Европа/Тирана"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Европа/Тирасопол"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Европа/Ужгород"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Европа/Вадуц"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Европа/Ватикана"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Европа/Виена"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Европа/Вилнюс"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Европа/Волгоград"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Европа/Варшава"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Европа/Загреб"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Европа/Запорожие"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Европа/Цюрих"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Фабричен"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "ВБ"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "ВБ-Ейре"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Гринуич"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Хонг_Конг"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Исландия"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Индийски/Антананариво"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Индийски/Чагос"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Индийски/Коледа"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Индийски/Кокос"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Индийски/Комори"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Индийски/Караулен"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Индийски/Махе"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Индийски/Малдиви"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Индийски/Мартиника"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Индийски/Маьоте"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Индийски/Реюнион"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Иран"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Израел"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Ямайка"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Япония"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Куаялеин"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Либия"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Мексико/Бая_Норте"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Мексико/БаяСур"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Мексико/Общо"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "БлизъкИзток/Рияд87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "БлизъкИзток/Рияд88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "БлизъкИзток/Рияд89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Навахо"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "НЗ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "НЗ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Тих Океан/Апия"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Тих Океан/Оукленд"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Тих Океан/Чатам"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+#, fuzzy
+msgid "Chatham Islands"
+msgstr "Чили/Великденски_Острови"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "Тих_Океан/Трук"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Тих Океан/Източен"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Тих_Океан/Ефате"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Тих_Океан/Ендербъри"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Тих_Океан/Факаофо"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Тих_Океан/Фиджи"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Тих_Океан/Фунафути"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Тих_Океан/Галапагос"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Тих_Океан/Гамбиер"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Тих_Океан/Гуадалканал"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Тих_Океан/Гуам"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Тих_Океан/Хонолулу"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+#, fuzzy
+msgid "Hawaii"
+msgstr "САЩ/Хаваи"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Тих_Океан/Джонстън"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Тих_Океан/Киритимати"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Тих_Океан/Косрае"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+#, fuzzy
+msgid "Kosrae"
+msgstr "Израел"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Тих_Океан/Куаялеин"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Тих_Океан/Майор"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Тих_Океан/Маркуесас"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Тих_Океан/Мидуей"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Тих_Океан/Науру"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Тих_Океан/Ниуе"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Тих_Океан/Норфолк"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Тих_Океан/Нумея"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Тих_Океан/Паго_Паго"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Тих_Океан/Палау"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Тих_Океан/Питкаим"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "Тих_Океан/Понапе"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Тих_Океан/Понапе"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Тих_Океан/Порт_Моресби"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Тих_Океан/Раротонга"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Тих_Океан/Сайпан"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Тих_Океан/Самоа"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Тих_Океан/Таити"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Тих_Океан/Тарава"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+#, fuzzy
+msgid "Gilbert Islands"
+msgstr "Чили/Великденски_Острови"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Тих_Океан/Тонгатапу"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Тих_Океан/Трук"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Тих_Океан/Уейк"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Тих_Океан/Уалис"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Тих_Океан/Яп"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Полша"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Португалия"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Сингапур"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Турция"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Универсално"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "САЩ/Аляска"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "САЩ/Аулетия"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "САЩ/Аризона"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "САЩ/Централно"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "САЩ/Източно"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "САЩ/Източна_Индиана"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "САЩ/Хаваи"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "САЩ/Индиана-Старк"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "САЩ/Мичиган"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "САЩ/Планинско"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "САЩ/Тихоокеанско"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "САЩ/Самоа"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Зулу"
+
+#~ msgid "US/Pacific-New"
+#~ msgstr "САЩ/Нова Тихоокеанска зона"
diff --git a/panels/datetime/po-timezones/bn.po b/panels/datetime/po-timezones/bn.po
new file mode 100644
index 0000000..a78ad11
--- /dev/null
+++ b/panels/datetime/po-timezones/bn.po
@@ -0,0 +1,3340 @@
+# BANGLA TRANSLATION OF TIMEZONES.POT
+# Copyright (C) 2004 RedHat Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# Runa Bhattahcarjee <runa@bengalinux.org>, 2004.
+# Runa Bhattacharjee <runab@redhat.com>, 2006.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: bn_IN\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2006-01-17 14:40+0530\n"
+"Last-Translator: Runa Bhattacharjee <runab@redhat.com>\n"
+"Language-Team: Bangla <redhat-translation@bengalinux.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.9.1\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "আফ্রিকা/অবিজান"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "আফ্রিকা/আক্রা"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "আফ্রিকা/আডিস_আবাবা"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "আফ্রিকা/এলজিয়ার্স"
+
+#: timezones.h:5
+#, fuzzy
+msgid "Africa/Asmara"
+msgstr "আফ্রিকা/আসমেরা"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "আফ্রিকা/আসমেরা"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "আফ্রিকা/বামাকো"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "আফ্রিকা/বাঙ্গুই"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "আফ্রিকা/বানজুল"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "আফ্রিকা/বিসাউ"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "আফ্রিকা/ব্ল্যানটায়ার"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "আফ্রিকা/ব্রাজাভিল"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "আফ্রিকা/বুজুমবুরা"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "আফ্রিকা/কায়রো"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "আফ্রিকা/কাসাব্লাঙ্কা"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "আফ্রিকা/থেউটা"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "আফ্রিকা/কোনাক্রি"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "আফ্রিকা/ডাকার"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "আফ্রিকা/ডার_এস_সালাম"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "আফ্রিকা/জিবুতি"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "আফ্রিকা/ডুয়ালা"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "আফ্রিকা/এল_আউইন"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "আফ্রিকা/ফ্রিটাউন"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "আফ্রিকা/গ্যাবারোন"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "আফ্রিকা/হারারে"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "আফ্রিকা/জোহানেসবার্গ"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "আফ্রিকা/কাম্পালা"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "আফ্রিকা/খারতৌম"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "আফ্রিকা/কিগালি"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "আফ্রিকা/কিনশাসা"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "আফ্রিকা/লেগোস"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "আফ্রিকা/লিবারভিল"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "আফ্রিকা/লোমে"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "আফ্রিকা/লুয়ান্ডা"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "আফ্রিকা/লুবুম্বাশি"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "আফ্রিকা/লুসাকা"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "আফ্রিকা/মালাবো"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "আফ্রিকা/মাপুতো"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "আফ্রিকা/মাসেরু"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "আফ্রিকা/আমবাবানে"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "আফ্রিকা/মোগাডিশু"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "আফ্রিকা/মোনরোভিয়া"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "আফ্রিকা/নায়রোবি"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "আফ্রিকা/আনজামেনা"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "আফ্রিকা/নিয়ামে"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "আফ্রিকা/নোয়াকশোট"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "আফ্রিকা/ওয়াগাডুগু"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "আফ্রিকা/পোর্টো-নোভো"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "আফ্রিকা/সাও_টোমে"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "আফ্রিকা/টিম্বাকটু"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "আফ্রিকা/ট্রিপোলি"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "আফ্রিকা/টিউনিস"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "আফ্রিকা/ভিন্টহুক"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "আমেরিকা/আদাক"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+#, fuzzy
+msgid "Aleutian Islands"
+msgstr "অস্ট্রেলিয়া/কুইন্সল্যান্ড"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "আমেরিকা/অ্যাঙ্কোরেজ"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+#, fuzzy
+msgid "Alaska Time"
+msgstr "যুক্তরাষ্ট্র/আলাস্কা"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "আমেরিকা/অ্যাঙ্গিলা"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "আমেরিকা/অ্যান্টিগা"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "আমেরিকা/আরাগুয়েনা"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "আমেরিকা/আর্জেনটিনা/বুয়েনোস_আয়ারস"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "আমেরিকা/আর্জেনটিনা/কেটামার্কা"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "আমেরিকা/আর্জেনটিনা/কোমোডরিভাডাভিয়া"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "আমেরিকা/আর্জেনটিনা/কোর্ডোবা"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "আমেরিকা/আর্জেনটিনা/জুজুই"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "আমেরিকা/আর্জেনটিনা/লা_রিওজা"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "আমেরিকা/আর্জেনটিনা/মেন্ডোজা"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "আমেরিকা/আর্জেনটিনা/রিও_গেলিগোস"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+#, fuzzy
+msgid "America/Argentina/Salta"
+msgstr "আমেরিকা/আর্জেনটিনা/সান_হুয়ান"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "আমেরিকা/আর্জেনটিনা/সান_হুয়ান"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+#, fuzzy
+msgid "America/Argentina/San_Luis"
+msgstr "আমেরিকা/আর্জেনটিনা/সান_হুয়ান"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "আমেরিকা/আর্জেনটিনা/টুকুমান"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "আমেরিকা/আর্জেনটিনা/উশুয়াইয়া"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "আমেরিকা/আরুবা"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "আমেরিকা/অ্যাসানশিয়ান"
+
+#: timezones.h:110
+#, fuzzy
+msgid "America/Atikokan"
+msgstr "আমেরিকা/আটকা"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "আমেরিকা/আটকা"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "আমেরিকা/বাহিয়া"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "আমেরিকা/বাহিয়া"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "আমেরিকা/বারবাডোস"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "আমেরিকা/বেলেম"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "আমেরিকা/বেলিজে"
+
+#: timezones.h:125
+#, fuzzy
+msgid "America/Blanc-Sablon"
+msgstr "আমেরিকা/কেনকুন"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "আমেরিকা/বোয়া_ভিস্টা"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "আমেরিকা/বোগোটা"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "আমেরিকা/বোয়স"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "আমেরিকা/বুয়েনোস_আয়ারস"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "আমেরিকা/কেমব্রিজ_বে"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "আমেরিকা/কাম্পো_গ্রান্ডে"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "আমেরিকা/কেনকুন"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "আমেরিকা/কেরাকাস"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "আমেরিকা/কেটামার্কা"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "আমেরিকা/সায়েন"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "আমেরিকা/কেমেন"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "আমেরিকা/শিকাগো"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+#, fuzzy
+msgid "Central Time"
+msgstr "যুক্তরাষ্ট্র/সেন্ট্রাল"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "আমেরিকা/চিহুয়াহুয়া"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "আমেরিকা/কোরাল_হার্বার"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "আমেরিকা/কোর্ডোবা"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "আমেরিকা/কোস্টা_রিকা"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "আমেরিকা/কুইয়াবা"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "আমেরিকা/কুরাকাও"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "আমেরিকা/ডানমার্কশওয়ান"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "আমেরিকা/ডসন"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "আমেরিকা/ডসন_ক্রিক"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "আমেরিকা/ডেনভার"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+#, fuzzy
+msgid "Mountain Time"
+msgstr "যুক্তরাষ্ট্র/মাউন্টেন"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "আমেরিকা/ডেট্রোয়েট"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "আমেরিকা/ডোমিনিকা"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "আমেরিকা/এডমনটন"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "আমেরিকা/ইরুনেপে"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "আমেরিকা/এল_সালভাডোর"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "আমেরিকা/এনসেনাডা"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "আমেরিকা/ফোর্টালেজা"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "আমেরিকা/ফোর্ট_ওয়েইন"
+
+# not appropriate imho
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "আমেরিকা/গ্লেস_বে"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "আমেরিকা/গডথাব"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "আমেরিকা/গূজ_বে"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "আমেরিকা/গ্র্যান্ড_টার্ক"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "আমেরিকা/গ্রেনাডা"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "আমেরিকা/গুয়াডেলুপ"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "আমেরিকা/গুয়াটেমালা"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "আমেরিকা/গায়াকুইল"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "আমেরিকা/গায়ানা"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "আমেরিকা/হ্যালিফ্যাক্স"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "আমেরিকা/হাভানা"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "আমেরিকা/হার্মোসিলো"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "আমেরিকা/ইন্ডিয়ানা/ইন্ডিয়ানাপোলিস"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "আমেরিকা/ইন্ডিয়ানা/নোক্স"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "আমেরিকা/ইন্ডিয়ানা/মারেঙ্গো"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+#, fuzzy
+msgid "America/Indiana/Petersburg"
+msgstr "আমেরিকা/ইন্ডিয়ানা/মারেঙ্গো"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "আমেরিকা/ইন্ডিয়ানাপোলিস"
+
+#: timezones.h:227
+#, fuzzy
+msgid "America/Indiana/Tell_City"
+msgstr "আমেরিকা/ইন্ডিয়ানা/ভিভে"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "আমেরিকা/ইন্ডিয়ানা/ভিভে"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+#, fuzzy
+msgid "America/Indiana/Vincennes"
+msgstr "আমেরিকা/ইন্ডিয়ানা/ভিভে"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+#, fuzzy
+msgid "America/Indiana/Winamac"
+msgstr "আমেরিকা/ইন্ডিয়ানা/ভিভে"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "আমেরিকা/ইনুভিক"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+# not sure
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "আমেরিকা/ইকালুইট"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+# not sure
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "আমেরিকা/জামাইকা"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "আমেরিকা/জুজুই"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "আমেরিকা/জুনিউ"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "আমেরিকা/কেন্টাকি/লুইভিল"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+#, fuzzy
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "আমেরিকা/কেন্টাকি/লুইভিল"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "আমেরিকা/কেন্টাকি/মোন্টিচেলো"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "আমেরিকা/নোক্স_ইন"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "আমেরিকা/লা_পাজ"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "আমেরিকা/লিমা"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "আমেরিকা/লস_অ্যাঞ্জেলস"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+#, fuzzy
+msgid "Pacific Time"
+msgstr "প্রশান্ত মহাসাগর/নিউ"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "আমেরিকা/লুইভিল"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "আমেরিকা/মাসিও"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "আমেরিকা/মানাগুয়া"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "আমেরিকা/মানাউস"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+#, fuzzy
+msgid "America/Marigot"
+msgstr "আমেরিকা/মাসিও"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "আমেরিকা/মার্টিনিক"
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "আমেরিকা/মানাউস"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "আমেরিকা/মাজাতলান"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "আমেরিকা/মেন্ডোজা"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "আমেরিকা/মেনোমিনি"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "আমেরিকা/মেরিডা"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "আমেরিকা/মেক্সিকো_সিটি"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "আমেরিকা/মিকেলন"
+
+#: timezones.h:289
+#, fuzzy
+msgid "America/Moncton"
+msgstr "আমেরিকা/এডমনটন"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "আমেরিকা/মন্টেরি"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "আমেরিকা/মন্টেভিডিও"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "আমেরিকা/মনট্রিল"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "আমেরিকা/মন্টসেরাত"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "আমেরিকা/নাসাউ"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "আমেরিকা/নিউ_ইয়োর্ক"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+#, fuzzy
+msgid "Eastern Time"
+msgstr "যুক্তরাষ্ট্র/ইস্টার্ন"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "আমেরিকা/নিপিগন"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "আমেরিকা/নোম"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "আমেরিকা/নোরোনহা"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+#, fuzzy
+msgid "Atlantic islands"
+msgstr "অ্যাটলান্টিক/ক্যানারি"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "আমেরিকা/নর্থ_ডাকোটা/সেন্টার"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+#, fuzzy
+msgid "America/North_Dakota/New_Salem"
+msgstr "আমেরিকা/নর্থ_ডাকোটা/সেন্টার"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "আমেরিকা/মানাগুয়া"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "আমেরিকা/পানামা"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "আমেরিকা/পাংনিরতুং"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "আমেরিকা/পারামারিবো"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "আমেরিকা/ফিনিক্স"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "আমেরিকা/পোর্ট_ও_প্রিন্স"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "আমেরিকা/পোর্তো_একর"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "আমেরিকা/পোর্ট_অফ_স্পেন"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "আমেরিকা/পোর্তো_ভেলহো"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "আমেরিকা/পুয়ের্তো_রিকো"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "আমেরিকা/রেইনি_রিভার"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "আমেরিকা/রেঙ্কিন_ইনলেট"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "আমেরিকা/রিসাইফে"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "আমেরিকা/রেজিনা"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+#, fuzzy
+msgid "America/Resolute"
+msgstr "আমেরিকা/বেলেম"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "আমেরিকা/রিও_ব্রাঙ্কো"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "আমেরিকা/রোজারিও"
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "আমেরিকা/সান্টিয়াগো"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+#, fuzzy
+msgid "America/Santarem"
+msgstr "আমেরিকা/সান্টিয়াগো"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "আমেরিকা/সান্টিয়াগো"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "আমেরিকা/সান্টো_ডোমিঙ্গো"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "আমেরিকা/সাও_পাওলো"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "আমেরিকা/স্কোর্সবিসান্ড"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "আমেরিকা/শিপরক"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+#, fuzzy
+msgid "America/St_Barthelemy"
+msgstr "আমেরিকা/বেলেম"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "আমেরিকা/সেন্ট_জনস"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "আমেরিকা/সেন্ট_কিটস"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "আমেরিকা/সেন্ট_লুসিয়া"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "আমেরিকা/সেন্ট_থোমাস"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "আমেরিকা/সেন্ট_ভিনসেন্ট"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "আমেরিকা/সুইফট_কারেন্ট"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "আমেরিকা/তেগুসিগালপা"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "আমেরিকা/থুল"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "আমেরিকা/থান্ডার_বে"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "আমেরিকা/থেওয়ানা"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "আমেরিকা/টরোন্টো"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "আমেরিকা/টরটলা"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "আমেরিকা/ভ্যাংকুভার"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "আমেরিকা/ভার্জিন"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "আমেরিকা/ওয়াইটহর্স"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "আমেরিকা/উইনিপেগ"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "আমেরিকা/ইয়াকুতাত"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "আমেরিকা/ইয়েলোনাইফ"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "অ্যান্টার্কটিকা/ক্যাসি"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "অ্যান্টার্কটিকা/ড্যাভিস"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "অ্যান্টার্কটিকা/দুমোন্ত দ্য উরভিল"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+#, fuzzy
+msgid "Antarctica/Macquarie"
+msgstr "অ্যান্টার্কটিকা/ম্যাকমার্ডো"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "অ্যান্টার্কটিকা/মসন"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "অ্যান্টার্কটিকা/ম্যাকমার্ডো"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "অ্যান্টার্কটিকা/পাল্মার"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "অ্যান্টার্কটিকা/রোথেরা"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "অ্যান্টার্কটিকা/দক্ষিণ_মেরু"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "অ্যান্টার্কটিকা/সিওয়া"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "অ্যান্টার্কটিকা/ভোস্টক"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "আর্কটিক/লংইয়ারবেন"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "এশিয়া/এডেন"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "এশিয়া/আলমাটি"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "এশিয়া/আম্মান"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "এশিয়া/আনাদির"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "এশিয়া/আকতু"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "এশিয়া/আকতোবে"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "এশিয়া/আশ‌গাবাত"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "এশিয়া/আশখাবাদ"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "এশিয়া/বাগদাদ"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "এশিয়া/বাহরেন"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "এশিয়া/বাকু"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "এশিয়া/ব্যাঙ্কক"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "এশিয়া/বেইরুট"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "এশিয়া/বিশকেক"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "এশিয়া/ব্রুনেই"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "এশিয়া/কলকাতা"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "এশিয়া/চৈবালছান"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "এশিয়া/চোংকিং"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "এশিয়া/চুংকিং"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "এশিয়া/কোলোম্বো"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "এশিয়া/ঢাকা"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "এশিয়া/ডামাসকাস"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "এশিয়া/ঢাকা"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "এশিয়া/ডিলি"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "এশিয়া/দুবাই"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "এশিয়া/দুশানবে"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "এশিয়া/গাজা"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "এশিয়া/হার্বিন"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+#, fuzzy
+msgid "Asia/Ho_Chi_Minh"
+msgstr "এশিয়া/চোংকিং"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "এশিয়া/হং _কং"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "এশিয়া/হোভড"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "এশিয়া/ইরকুটস"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "এশিয়া/ইস্তানবুল"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "এশিয়া/জাকার্তা"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "এশিয়া/জায়াপুরা"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "এশিয়া/জেরুসেলাম"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "এশিয়া/কাবুল"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "এশিয়া/কামচাটকা"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "এশিয়া/করাচী"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "এশিয়া/কাশগার"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+#, fuzzy
+msgid "Asia/Kathmandu"
+msgstr "এশিয়া/কাটমান্ডু"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "এশিয়া/কাটমান্ডু"
+
+#: timezones.h:518
+#, fuzzy
+msgid "Asia/Kolkata"
+msgstr "এশিয়া/জাকার্তা"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "এশিয়া/ক্রাসনোয়ার্স্ক"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "এশিয়া/কুয়ালা_লাম্পুর"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "এশিয়া/কুচিং"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "এশিয়া/কুয়েত"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "এশিয়া/মাকাও"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "এশিয়া/মাকাও"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "এশিয়া/মাগাদান"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "এশিয়া/মাকাসসার"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "এশিয়া/ম্যানিলা"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "এশিয়া/মাসকাট"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "এশিয়া/নিকোসিয়া"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "এশিয়া/ইরকুটস"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "এশিয়া/নোভোসিবার্স্ক"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "এশিয়া/নোভোসিবার্স্ক"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+#, fuzzy
+msgid "Moscow+03 - Novosibirsk"
+msgstr "এশিয়া/নোভোসিবার্স্ক"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "এশিয়া/ওমস্ক"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "এশিয়া/ওরাল"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "এশিয়া/নোম_ফেন"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "এশিয়া/পন্টিয়ানাক"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "এশিয়া/পিয়োংইয়াং"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "এশিয়া/কাতার"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "এশিয়া/কিজিলোর্দা"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "এশিয়া/ইয়াংগন"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "এশিয়া/রিয়াদ"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "এশিয়া/রিয়াদ৮৭"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "এশিয়া/রিয়াদ৮৮"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "এশিয়া/রিয়াদ৮৯"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "এশিয়া/সায়গন"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "এশিয়া/শাকালিন"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "এশিয়া/সামারখান্দ"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "এশিয়া/সিওল"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "এশিয়া/সাংঘাই"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "এশিয়া/সিঙ্গাপুর"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "এশিয়া/তাইপে"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "এশিয়া/তাসকেন্ত"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "এশিয়া/তবিলিশি"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "এশিয়া/তেহেরান"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "এশিয়া/তেল_আভিভ"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "এশিয়া/থিম্বু"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "এশিয়া/থিম্পু"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "এশিয়া/টোকিও"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "এশিয়া/উজুং_পান্দাং"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "এশিয়া/উলানবাতোর"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "এশিয়া/উলান_বাতোর"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "এশিয়া/উরুমকি"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "এশিয়া/ভিয়েনতিয়েন"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "এশিয়া/ভ্লাডিভোস্টক"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "এশিয়া/ইয়াকুটস"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "এশিয়া/ইয়াকাতারিনবুর্গ"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "এশিয়া/ইয়ারভান"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "অ্যাটলান্টিক/এজোরে"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "অ্যাটলান্টিক/বারমুডা"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "অ্যাটলান্টিক/ক্যানারি"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "অ্যাটলান্টিক/কেপ_ভার্ডি"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "অ্যাটলান্টিক/ফেরো"
+
+#: timezones.h:616
+#, fuzzy
+msgid "Atlantic/Faroe"
+msgstr "অ্যাটলান্টিক/ফেরো"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "অ্যাটলান্টিক/জান_মায়েন"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "অ্যাটলান্টিক/মাদিইরা"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "অ্যাটলান্টিক/রিকয়াভিক"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "অ্যাটলান্টিক/সাউথ_জর্জিয়া"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "অ্যাটলান্টিক/স্টেনলি"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "অ্যাটলান্টিক/সেন্ট_হেলেনা"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "অস্ট্রেলিয়া/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "অস্ট্রেলিয়া/অ্যাডিলেড"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+#, fuzzy
+msgid "South Australia"
+msgstr "অস্ট্রেলিয়া/ACT"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "অস্ট্রেলিয়া/ব্রিসবেন"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "অস্ট্রেলিয়া/ব্রোকেন_হিল"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "অস্ট্রেলিয়া/ক্যানবেরা"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "অস্ট্রেলিয়া/কারি"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "অস্ট্রেলিয়া/ডারউইন"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+#, fuzzy
+msgid "Australia/Eucla"
+msgstr "অস্ট্রেলিয়া/কুইন্সল্যান্ড"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+#, fuzzy
+msgid "Western Australia - Eucla area"
+msgstr "অস্ট্রেলিয়া/কুইন্সল্যান্ড"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "অস্ট্রেলিয়া/হোবার্ট"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "অস্ট্রেলিয়া/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "অস্ট্রেলিয়া/লিন্ডাম্যান"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "অস্ট্রেলিয়া/লর্ড_হাউই"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "অস্ট্রেলিয়া/মেলবোর্ন"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+#, fuzzy
+msgid "Victoria"
+msgstr "অস্ট্রেলিয়া/ভিক্টোরিয়া"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "অস্ট্রেলিয়া/উত্তর"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "অস্ট্রেলিয়া/নিউ সাইথ ওয়েলস"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "অস্ট্রেলিয়া/পার্থ"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "অস্ট্রেলিয়া/কুইন্সল্যান্ড"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "অস্ট্রেলিয়া/দক্ষিণ"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "অস্ট্রেলিয়া/সিডনি"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "অস্ট্রেলিয়া/তাসমানিয়া"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "অস্ট্রেলিয়া/ভিক্টোরিয়া"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "অস্ট্রেলিয়া/পশ্চিম"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "অস্ট্রেলিয়া/ইয়ানকোউইনা"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "ব্রাজিল/একর"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "ব্রাজিল/ডিনহোনহা"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "ব্রাজিল/পূর্ব"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "ব্রাজিল/পশ্চিম"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "কানাডা/আটলান্টিক"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "কানাডা/সেন্ট্রাল"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "কানাডা/পূর্ব"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "কানাডা/পূর্ব-সাসকাচুয়ান"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "কানাডা/মাউন্টেন"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "কানাডা/নিউফাউন্ডল্যান্ড"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "কানাডা/প্যাসিফিক"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "কানাডা/সাসকাচুয়ান"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "কানাডা/ইউকোন"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "চিলি/কন্টিনেন্টাল"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "চিলি/ইস্টারআইল্যান্ড"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "কিউবা"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "মিশর"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "আয়ার"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/গ্রিণউইচ"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/জুলু"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "ইউরোপ/আমস্টারডাম"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "ইউরোপ/এন্ডোরা"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "ইউরোপ/এথেন্স"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "ইউরোপ/বেলফাস্ট"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "ইউরোপ/বেলগ্রেড"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "ইউরোপ/বার্লিন"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "ইউরোপ/ব্রাতিসলাভা"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "ইউরোপ/ব্রাসেলস"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "ইউরোপ/বুখারেস্ট"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "ইউরোপ/বুডাপেস্ট"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "ইউরোপ/চিশিনাউ"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "ইউরোপ/কোপেনহেগেন"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "ইউরোপ/ডাবলিন"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "ইউরোপ/জিব্রালটার"
+
+#: timezones.h:744
+#, fuzzy
+msgid "Europe/Guernsey"
+msgstr "ইউরোপ/এথেন্স"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "ইউরোপ/হেলসিঙ্কি"
+
+#: timezones.h:746
+#, fuzzy
+msgid "Europe/Isle_of_Man"
+msgstr "ইউরোপ/ওসলো"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "ইউরোপ/ইস্তানবুল"
+
+#: timezones.h:748
+#, fuzzy
+msgid "Europe/Jersey"
+msgstr "ইউরোপ/প্যারিস"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "ইউরোপ/কালিনিনগ্রাড"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "ইউরোপ/কিভ"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "ইউরোপ/লিসবন"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "ইউরোপ/লুবলইয়ানা"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "ইউরোপ/লন্ডন"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "ইউরোপ/লুক্সেমবুর্গ"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "ইউরোপ/মাড্রিড"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "ইউরোপ/মল্টা"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "ইউরোপ/মারিহাম"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "ইউরোপ/মিনস্ক"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "ইউরোপ/মোনেকো"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "ইউরোপ/মস্কো"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "ইউরোপ/নিকোসিয়া"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "ইউরোপ/ওসলো"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "ইউরোপ/প্যারিস"
+
+#: timezones.h:774
+#, fuzzy
+msgid "Europe/Podgorica"
+msgstr "ইউরোপ/এন্ডোরা"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "ইউরোপ/প্রাগ"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "ইউরোপ/রিগা"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "ইউরোপ/রোম"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "ইউরোপ/সামারা"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "ইউরোপ/সান_মারিনো"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "ইউরোপ/সারায়েভো"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "ইউরোপ/সিম্ফিরোপেল"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "ইউরোপ/স্কপয়া"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "ইউরোপ/সোফিয়া"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "ইউরোপ/স্টকহোম"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "ইউরোপ/ট্যালিন"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "ইউরোপ/তিরানা"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "ইউরোপ/তিরাসপোল"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "ইউরোপ/উজগোরোদ"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "ইউরোপ/ভাদুজ"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "ইউরোপ/ভ্যাটিকেন"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "ইউরোপ/ভিয়েনা"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "ইউরোপ/ভিলনিয়াস"
+
+#: timezones.h:799
+#, fuzzy
+msgid "Europe/Volgograd"
+msgstr "ইউরোপ/বেলগ্রেড"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "ইউরোপ/ওয়ারস"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "ইউরোপ/জাগ্রেব"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "ইউরোপ/জাপোরোযেই"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "ইউরোপ/জুরিখ"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "কারখানা"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "গ্রেট ব্রিটেন"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "গ্রেট ব্রিটেন-আয়ার"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "গ্রিনউইচ"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "হং কং"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "আইসল্যান্ড"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "ভারত মহাসাগর/আন্তানানারিভো"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "ভারত মহাসাগর/চাগোস"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "ভারত মহাসাগর/ক্রিস্টমাস"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "ভারত মহাসাগর/কোকোস"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "ভারত মহাসাগর/কোমোরো"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "ভারত মহাসাগর/কারগুয়েলেন"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "ভারত মহাসাগর/মাহে"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "ভারত মহাসাগর/মালদিভ"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "ভারত মহাসাগর/মরিশাস"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "ভারত মহাসাগর/মেয়োতে"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "ভারত মহাসাগর/রিউনিয়ন"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "ইরান"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "ইজরায়েল"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "জামাইকা"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "জাপান"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "কয়াজালিইন"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "লিবিয়া"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "মেক্সিকো/বাহানোর্তে"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "মেক্সিকো/বাহাসুর"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "মেক্সিকো/সাধারণ"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "মধ্যপ্রাচ্য/রিয়াদ৮৭"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "মধ্যপ্রাচ্য/রিয়াদ৮৮"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "মধ্যপ্রাচ্য/রিয়াদ৮৯"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "নাভাজো"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "প্রশান্ত মহাসাগর/এপিয়া"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "প্রশান্ত মহাসাগর/অকল্যান্ড"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "প্রশান্ত মহাসাগর/চ্যাটহাম"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+#, fuzzy
+msgid "Chatham Islands"
+msgstr "চিলি/ইস্টারআইল্যান্ড"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "প্রশান্ত মহাসাগর/ট্রুক"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+#, fuzzy
+msgid "Pacific/Easter"
+msgstr "প্রশান্ত মহাসাগর/ইস্টার"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "প্রশান্ত মহাসাগর/এফাতে"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "প্রশান্ত মহাসাগর/এন্ডারবুরি"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "প্রশান্ত মহাসাগর/ফাকাওফো"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "প্রশান্ত মহাসাগর/ফিজি"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "প্রশান্ত মহাসাগর/ফুনাফুতি"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "প্রশান্ত মহাসাগর/গালাপাগোস"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "প্রশান্ত মহাসাগর/গ্যামবিয়ার"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "প্রশান্ত মহাসাগর/গুয়াডালকানাল"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "প্রশান্ত মহাসাগর/গুয়াম"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "প্রশান্ত মহাসাগর/হনোলুলু"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+#, fuzzy
+msgid "Hawaii"
+msgstr "যুক্তরাষ্ট্র/হাওয়াই"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "প্রশান্ত মহাসাগর/জনস্টন"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "প্রশান্ত মহাসাগর/কিরিবাস"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+# is this kiribati?
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "প্রশান্ত মহাসাগর/কোসরে"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+#, fuzzy
+msgid "Kosrae"
+msgstr "ইজরায়েল"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "প্রশান্ত মহাসাগর/কয়াজালিইন"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "প্রশান্ত মহাসাগর/মাজুরো"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "প্রশান্ত মহাসাগর/মারকিসাস"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+# not sure
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "প্রশান্ত মহাসাগর/মিডওয়ে"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "প্রশান্ত মহাসাগর/নাউরু"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "প্রশান্ত মহাসাগর/নিউ"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "প্রশান্ত মহাসাগর/নোরফোল্ক"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "প্রশান্ত মহাসাগর/নুমিয়া"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "প্রশান্ত মহাসাগর/পাগো_পাগো"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "প্রশান্ত মহাসাগর/পালাউ"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "প্রশান্ত মহাসাগর/পিটকেয়ার্ন"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "প্রশান্ত মহাসাগর/পোনাপে"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "প্রশান্ত মহাসাগর/পোনাপে"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "প্রশান্ত মহাসাগর/পোর্ট-মোর্সবি"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "প্রশান্ত মহাসাগর/রারোটোঙ্গা"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "প্রশান্ত মহাসাগর/সাইপান"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "প্রশান্ত মহাসাগর/সামোয়া"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "প্রশান্ত মহাসাগর/তাহিতি"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "প্রশান্ত মহাসাগর/তারাওয়া"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+#, fuzzy
+msgid "Gilbert Islands"
+msgstr "চিলি/ইস্টারআইল্যান্ড"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "প্রশান্ত মহাসাগর/টোঙ্গাটাপু"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "প্রশান্ত মহাসাগর/ট্রুক"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "প্রশান্ত মহাসাগর/ওয়েক"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "প্রশান্ত মহাসাগর/ওয়ালিস"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "প্রশান্ত মহাসাগর/ইয়াপ"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "পোল্যান্ড"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "পর্টুগাল"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "সিঙ্গাপুর"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "তুরস্ক"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "যুক্তরাষ্ট্র/আলাস্কা"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "যুক্তরাষ্ট্র/আলিউশিয়ান"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "যুক্তরাষ্ট্র/আরিজোনা"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "যুক্তরাষ্ট্র/সেন্ট্রাল"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "যুক্তরাষ্ট্র/ইস্টার্ন"
+
+# msgstr "যুক্তরাষ্ট্র/পূর্ববর্তী"
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "যুক্তরাষ্ট্র/পূর্ব-ইন্ডিয়ানা"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "যুক্তরাষ্ট্র/হাওয়াই"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "যুক্তরাষ্ট্র/ইন্ডিয়ানা-স্টার্ক"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "যুক্তরাষ্ট্র/মিশিগান"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "যুক্তরাষ্ট্র/মাউন্টেন"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "যুক্তরাষ্ট্র/প্যাসিফিক"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "যুক্তরাষ্ট্র/সামোয়া"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "জুলু"
+
+#, fuzzy
+#~ msgid "US/Pacific-New"
+#~ msgstr "যুক্তরাষ্ট্র/প্যাসিফিক"
+
+#~ msgid "SystemV/AST4"
+#~ msgstr "SystemV/AST4"
+
+#~ msgid "SystemV/AST4ADT"
+#~ msgstr "SystemV/AST4ADT"
+
+#~ msgid "SystemV/CST6"
+#~ msgstr "SystemV/CST6"
+
+#~ msgid "SystemV/CST6CDT"
+#~ msgstr "SystemV/CST6CDT"
+
+#~ msgid "SystemV/EST5"
+#~ msgstr "SystemV/EST5"
+
+#~ msgid "SystemV/EST5EDT"
+#~ msgstr "SystemV/EST5EDT"
+
+#~ msgid "SystemV/HST10"
+#~ msgstr "SystemV/HST10"
+
+#~ msgid "SystemV/MST7"
+#~ msgstr "SystemV/MST7"
+
+#~ msgid "SystemV/MST7MDT"
+#~ msgstr "SystemV/MST7MDT"
+
+#~ msgid "SystemV/PST8"
+#~ msgstr "SystemV/PST8"
+
+#~ msgid "SystemV/PST8PDT"
+#~ msgstr "SystemV/PST8PDT"
+
+#~ msgid "SystemV/YST9"
+#~ msgstr "SystemV/YST9"
+
+#~ msgid "SystemV/YST9YDT"
+#~ msgstr "SystemV/YST9YDT"
diff --git a/panels/datetime/po-timezones/bn_IN.po b/panels/datetime/po-timezones/bn_IN.po
new file mode 100644
index 0000000..fdb7cf7
--- /dev/null
+++ b/panels/datetime/po-timezones/bn_IN.po
@@ -0,0 +1,3259 @@
+# translation of system-config-date.master-timezones.po to Bengali INDIA
+# BANGLA TRANSLATION OF TIMEZONES.POT
+# Copyright (C) 2004 RedHat Inc.
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Runa Bhattahcarjee <runa@bengalinux.org>, 2004.
+# Runa Bhattacharjee <runab@redhat.com>, 2006, 2009, 2010.
+# Runa Bhattacharjee <runab@fedoraproject.org>, 2008.
+# runa b <runab@test.pnq.redhat.com>, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: system-config-date.master-timezones\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-12-06 16:58+0530\n"
+"Last-Translator: Runa Bhattacharjee <runab@redhat.com>\n"
+"Language-Team: Bengali India <anubad@lists.ankur.org.in>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: \n"
+"X-Generator: Lokalize 1.0\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"\n"
+"\n"
+"\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "আফ্রিকা/অবিজান"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "আফ্রিকা/আক্রা"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "আফ্রিকা/আডিস_আবাবা"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "আফ্রিকা/অ্যালজিয়ার্স"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "আফ্রিকা/আসমারা"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "আফ্রিকা/আসমেরা"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "আফ্রিকা/বামাকো"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "আফ্রিকা/বাঙ্গুই"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "আফ্রিকা/বানজুল"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "আফ্রিকা/বিসাউ"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "আফ্রিকা/ব্ল্যানটায়ার"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "আফ্রিকা/ব্রাজাভিল"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "আফ্রিকা/বুজুমবুরা"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "আফ্রিকা/কায়রো"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "আফ্রিকা/কাসাব্লাঙ্কা"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "আফ্রিকা/থেউটা"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "সিউটা ও মেলিলা"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "আফ্রিকা/কোনাক্রি"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "আফ্রিকা/ডাকার"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "আফ্রিকা/ডার_এস_সালাম"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "আফ্রিকা/জিবুতি"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "আফ্রিকা/ডুয়ালা"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "আফ্রিকা/এল_আউইন"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "আফ্রিকা/ফ্রিটাউন"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "আফ্রিকা/গ্যাবারোন"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "আফ্রিকা/হারারে"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "আফ্রিকা/জোহানেসবার্গ"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "আফ্রিকা/কাম্পালা"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "আফ্রিকা/খারতৌম"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "আফ্রিকা/কিগালি"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "আফ্রিকা/কিনশাসা"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "পশ্চিম গণতান্ত্রিক প্রজাতন্ত্র কঙ্গো"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "আফ্রিকা/লাগোস"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "আফ্রিকা/লিবারভিল"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "আফ্রিকা/লোমে"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "আফ্রিকা/লুয়ান্ডা"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "আফ্রিকা/লুবুম্বাশি"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "পূর্ব গণতান্ত্রিক প্রজাতন্ত্র কঙ্গো"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "আফ্রিকা/লুসাকা"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "আফ্রিকা/মালাবো"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "আফ্রিকা/মাপুতো"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "আফ্রিকা/মাসেরু"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "আফ্রিকা/আমবাবানে"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "আফ্রিকা/মোগাডিশু"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "আফ্রিকা/মোনরোভিয়া"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "আফ্রিকা/নায়রোবি"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "আফ্রিকা/আনজামেনা"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "আফ্রিকা/নিয়ামে"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "আফ্রিকা/নোয়াকশোট"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "আফ্রিকা/ওয়াগাডুগু"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "আফ্রিকা/পোর্টো-নোভো"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "আফ্রিকা/সাও_টোমে"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "আফ্রিকা/টিম্বাকটু"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "আফ্রিকা/ট্রিপোলি"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "আফ্রিকা/টিউনিস"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "আফ্রিকা/ভিন্টহুক"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "আমেরিকা/আদাক"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "আলুতিয়ান দ্বীপপুঞ্জ"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "আমেরিকা/অ্যাঙ্কোরেজ"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "আলাস্কা সময়"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "আমেরিকা/অ্যাঙ্গিলা"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "আমেরিকা/অ্যান্টিগা"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "আমেরিকা/আরাগুয়েনা"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "টোকান্টিন্স"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "আমেরিকা/আর্জেনটিনা/বুয়েনোস_আয়ারস"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "বুয়েনোস আয়ারস (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "আমেরিকা/আর্জেনটিনা/কাটামার্কা"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "কাটামার্কা (CT), ছুবুত (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "আমেরিকা/আর্জেনটিনা/কোমোডরিভাডাভিয়া"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "আমেরিকা/আর্জেনটিনা/কোর্ডোবা"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "অধিকাংশ স্থান (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "আমেরিকা/আর্জেনটিনা/জুজুই"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "জুজুই (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "আমেরিকা/আর্জেনটিনা/লা_রিওজা"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "লা রিওয়া (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "আমেরিকা/আর্জেনটিনা/মেন্ডোজা"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "মেন্ডোজা (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "আমেরিকা/আর্জেনটিনা/রিও_গেলিগোস"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "সান্টা ক্রুজ (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "আমেরিকা/আর্জেনটিনা/সল্টা"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "আমেরিকা/আর্জেনটিনা/সান_হুয়ান"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "সান হুয়ান (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "আমেরিকা/আর্জেনটিনা/সান_লুই"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "সান লুই (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "আমেরিকা/আর্জেনটিনা/টুকুমান"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "টুকুমান (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "আমেরিকা/আর্জেনটিনা/উশুয়াইয়া"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "টিয়েরা ডেল ফুয়েগো (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "আমেরিকা/আরুবা"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "আমেরিকা/অ্যাসানশিয়ান"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "আমেরিকা/আটিকোকান"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "ইস্টার্ন স্ট্যান্ডার্ড সময় - আটিকোকান, ওন্টারিও ও সাউথহ্যাম্পটন দ্বীপ, নুনাভুট"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "আমেরিকা/আটকা"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "আমেরিকা/বাহিয়া"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "বাহিয়া"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "আমেরিকা/বাহিয়া_বান্ডেরাস"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "মেক্সিকান সেন্ট্রাল সময় - বাহিয়া ডে বান্ডেরাস"
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "আমেরিকা/বারবাডোস"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "আমেরিকা/বেলেম"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "আমাপা, পূর্ব পারা"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "আমেরিকা/বেলিজে"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "আমেরিকা/ব্লাঙ্ক-সাবলোন"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "আতলান্তিক স্ট্যান্ডার্ড সময় - কিউবেক - লোয়ার নর্থ শোর"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "আমেরিকা/বোয়া_ভিস্টা"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "রোরাইমা"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "আমেরিকা/বোগোটা"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "আমেরিকা/বোয়স"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "মাউন্টেন সময় - দক্ষিণ আইডাহো ও পূর্ব ওরেগন"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "আমেরিকা/বুয়েনোস_আয়ারস"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "আমেরিকা/কেমব্রিজ_বে"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "মাউন্টেন সময় - পশ্চিত নুনাভুট"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "আমেরিকা/কাম্পো_গ্রান্ডে"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "মাটো গ্রোসো দো সুল"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "আমেরিকা/কেনকুন"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "সেন্ট্রাল সময় - কিন্টানা রু"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "আমেরিকা/কেরাকাস"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "আমেরিকা/কাটামার্কা"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "আমেরিকা/কেয়েন"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "আমেরিকা/কেমেন"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "আমেরিকা/শিকাগো"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "সেন্ট্রাল সময়"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "আমেরিকা/চিহুয়াহুয়া"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "মেক্সিক্যান মাউন্টেন সময় - চিহুয়াহুয়া (মার্কিন সীমান্ত থেকে দূরে)"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "আমেরিকা/কোরাল_হার্বার"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "আমেরিকা/কোর্ডোবা"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "আমেরিকা/কোস্টা_রিকা"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "আমেরিকা/কুইয়াবা"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "মাটো গ্রোসো"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "আমেরিকা/কুরাকাও"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "আমেরিকা/ডানমার্কশওয়ান"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "পূর্বী তট, স্কোর্সবাইসান্ডের উত্তর"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "আমেরিকা/ডসন"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "প্রশান্ত মহাসাগরীয় সময় -উত্তর ইউকোন"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "আমেরিকা/ডসন_ক্রিক"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid "Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr "মাউন্টেন স্ট্যান্ডার্ড সময় - ডসন ক্রিক ও ফোর্ট সেন্ট জন, ব্রিটিশ কলাম্বিয়া"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "আমেরিকা/ডেনভার"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "মাউন্টেন সময়"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "আমেরিকা/ডেট্রয়েট"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "পূর্ব সময় - মিচিগন - অধিকাংশ স্থান"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "আমেরিকা/ডোমিনিকা"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "আমেরিকা/এডমনটন"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "মাউন্টেন সময় - অ্যালবার্টা, পূর্ব ব্রিটিশ কলাম্বিয়া ও পশ্চিম সাসকাচুয়ান"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "আমেরিকা/ইরুনেপে"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "পঃ আমাজোনাস"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "আমেরিকা/এল_সালভাডোর"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "আমেরিকা/এনসেনাডা"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "আমেরিকা/ফোর্টালেজা"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "উঃপূঃ ব্রাজিল (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "আমেরিকা/ফোর্ট_ওয়েইন"
+
+# not appropriate imho
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "আমেরিকা/গ্লেস_বে"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+"আতলান্তিক সময় - নোভা স্কোশিয়া - ১৯৬৬-১৯৭১-র মধ্যে দিবালোক সংরক্ষণকারী সময় না "
+"ব্যবহারকারী স্থান"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "আমেরিকা/গডথাব"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "অধিকাংশ স্থান"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "আমেরিকা/গূজ_বে"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "আতলান্তিক সময় - ল্যাব্রেডর - অধিকাংশ স্থান"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "আমেরিকা/গ্র্যান্ড_টার্ক"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "আমেরিকা/গ্রেনাডা"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "আমেরিকা/গুয়াডেলুপ"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "আমেরিকা/গুয়াটেমালা"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "আমেরিকা/গায়াকুইল"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "মূল ভুখণ্ড"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "আমেরিকা/গায়ানা"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "আমেরিকা/হ্যালিফ্যাক্স"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "আতলান্তিক সময় - নোভা স্কোশিয়া (অধিকাংশ স্থান), PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "আমেরিকা/হাভানা"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "আমেরিকা/হার্মোসিলো"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "মাউন্টেন স্ট্যান্ডার্ড সময় - সোনোরা"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "আমেরিকা/ইন্ডিয়ানা/ইন্ডিয়ানাপোলিস"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "পূর্বীয় সময় - ইন্ডিয়ানা - অধিকাংশ স্থান"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "আমেরিকা/ইন্ডিয়ানা/নোক্স"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "সেন্ট্রাল সময় - ইন্ডিয়ানা - স্টার্ক কাউন্টি"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "আমেরিকা/ইন্ডিয়ানা/মারেঙ্গো"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "পূর্বীয় সময় - ইন্ডিয়ানা - ক্রফোর্ড কাউন্টি"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "আমেরিকা/ইন্ডিয়ানা/পিটার্সবার্গ"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "পূর্বীয় সময় - ইন্ডিয়ানা - পাইক কাউন্টি"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "আমেরিকা/ইন্ডিয়ানাপোলিস"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "আমেরিকা/ইন্ডিয়ানা/টেল_সিটি"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "সেন্ট্রাল সময় - ইন্ডিয়ানা - পেরি কাউন্টি"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "আমেরিকা/ইন্ডিয়ানা/ভিভে"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "পূর্বীয় সময় - ইন্ডিয়ানা - সুইৎজারল্যান্ড কাউন্টি"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "আমেরিকা/ইন্ডিয়ানা/ভিনসেন"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "পূর্বীয় সময় - ইন্ডিয়ানা - ডেভিস, ডুবোইস, নক্স ও মার্টিন কাউন্টি"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "আমেরিকা/ইন্ডিয়ানা/উইনামেক"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "পূর্বীয় সময় - ইন্ডিয়ানা - পুলাস্কি কাউন্টি"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "আমেরিকা/ইনুভিক"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "মাউন্টেন সময় - পশ্চিম উত্তরপশ্চিম প্রদেশ"
+
+# not sure
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "আমেরিকা/ইকালুইট"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "পূর্বীয় সময় - পূর্ব নুনাভুট - অধিকাংশ স্থান"
+
+# not sure
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "আমেরিকা/জামাইকা"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "আমেরিকা/জুজুই"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "আমেরিকা/জুনিউ"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "আলাস্কা সময় - আলাস্কা প্যান-হ্যান্ডেল"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "আমেরিকা/কেন্টাকি/লুইভিল"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "পূর্বীয় সময় - কেন্টাকি - লুইভিল অঞ্চল"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "আমেরিকা/কেন্টাকি/মোন্টিচেলো"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "পূর্বীয় সময় - কেন্টাকি - ওয়েইন কাউন্টি"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "আমেরিকা/নোক্স_ইন"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "আমেরিকা/লা_পাজ"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "আমেরিকা/লিমা"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "আমেরিকা/লস_অ্যাঞ্জেলস"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "প্রশান্ত মহাসাগরীয় সময়"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "আমেরিকা/লুইভিল"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "আমেরিকা/মাসিও"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "আলাগোয়াস, সার্গিপে"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "আমেরিকা/মানাগুয়া"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "আমেরিকা/মানাউস"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "পূঃ আমাজোনাস"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "আমেরিকা/মারিগট"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "আমেরিকা/মার্টিনিক"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "আমেরিকা/মাটামোরোস"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid "US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+"মার্কিন সেন্ট্রাল সময় - কোয়াহুইলা, ডুরাংগো, নুয়েভো লিওন, টাম্পাউলিপাস (মার্কিন "
+"সীমান্তের কাছে)"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "আমেরিকা/মাজাতলান"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "মাউন্টেন সময় - দঃ বাজা, নায়ারিত, সিনালোয়া"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "আমেরিকা/মেন্ডোজা"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "আমেরিকা/মেনোমিনি"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "সেন্ট্রাল সময় - মিচিগন - ডিকিনসন, গোগেবিক, আচইরন ও মেনোমিনি কাউন্টি"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "আমেরিকা/মেরিডা"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "সেন্ট্রাল সময় - ক্যাম্পেচে, ইউকাটান"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "আমেরিকা/মেক্সিকো_সিটি"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "সেন্ট্রাল সময় - অধিকাংশ স্থান"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "আমেরিকা/মিকেলন"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "আমেরিকা/মঙ্কটন"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "আতলান্তিক সময় -নিউ ব্রান্সউইক"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "আমেরিকা/মন্টেরি"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+"মেক্সিক্যান সেন্ট্রাল সময় - কোয়াহুইলা, ডুরাংগো, নুয়েভো লিওন, টাম্পাউলিপাস মার্কিন "
+"সীমান্তের দূরে"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "আমেরিকা/মন্টেভিডিও"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "আমেরিকা/মনট্রিল"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "পূর্বীয় সময় - কিউবেক - অধিকাংশ স্থান"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "আমেরিকা/মন্টসেরাত"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "আমেরিকা/নাসাউ"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "আমেরিকা/নিউ_ইয়োর্ক"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "পূর্বীয় সময়"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "আমেরিকা/নিপিগন"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid "Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+"পূর্বীয় সময় - ওন্টারিও ও কিউবেক - ১৯৬৭-১৯৭৩-র মধ্যে দিবালোক সংরক্ষণকারী সময় না "
+"ব্যবহারকারী স্থান"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "আমেরিকা/নোম"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "আলাস্কা সময় - পশ্চিম আলাস্কা"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "আমেরিকা/নোরোনহা"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "আতলান্তিক দ্বীপপুঞ্জ"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "আমেরিকা/নর্থ_ডাকোটা/সেন্টার"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "সেন্ট্রাল সময় - উত্তর ডাকোটা - অলিভার কাউন্টি"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "আমেরিকা/নর্থ_ডাকোটা/নিউ_সেলাম"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "সেন্ট্রাল সময় - উত্তর ডাকোটা - মর্টন কাউন্টি (ম্যান্ডান অঞ্চল ব্যাতীত)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "আমেরিকা/ওজিনাগা"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "মার্কিন মাউন্টেন সময় - চিহুয়াহুয়া মার্কিন সীমান্তের কাছে"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "আমেরিকা/পানামা"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "আমেরিকা/পাংনিরতুং"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "পূর্বীয় সময় - পাংগনিরটুংগ, নুনাভুট"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "আমেরিকা/পারামারিবো"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "আমেরিকা/ফিনিক্স"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "মাউন্টেন স্ট্যান্ডার্ড সময় - অ্যারিজোনা"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "আমেরিকা/পোর্ট_ও_প্রিন্স"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "আমেরিকা/পোর্তো_একর"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "আমেরিকা/পোর্ট_অফ_স্পেন"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "আমেরিকা/পোর্তো_ভেলহো"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "রোন্ডোনিয়া"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "আমেরিকা/পুয়ের্তো_রিকো"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "আমেরিকা/রেইনি_রিভার"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "সেন্ট্রাল সময় - রেইনি রিভার ও ফোর্ট ফ্রান্সেস, ওন্টারিও"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "আমেরিকা/রেঙ্কিন_ইনলেট"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "সেন্ট্রাল সময় - মধ্য নুনাভুট"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "আমেরিকা/রিসাইফে"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "পার্নেমবুকো"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "আমেরিকা/রেজিনা"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "সেন্ট্রাল স্ট্যান্ডার্ড সময় - সাস্কাচুয়ান - অধিকাংশ স্থান"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "আমেরিকা/রেসোলিউট"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "পূর্বীয় স্ট্যান্ডার্ড সময় - রেসোলিউট, নুনাভুট"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "আমেরিকা/রিও_ব্রাঙ্কো"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "একর"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "আমেরিকা/রোজারিও"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "আমেরিকা/সান্টা_ইসাবেল"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "মেক্সিক্যান প্রশান্ত মহাসাগরীয় সময় - বায়া ক্যালিফোর্নিয়া মার্কিন সীমান্তের দূরে"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "আমেরিকা/সান্টারেম"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "পঃ পারা"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "আমেরিকা/সান্টিয়াগো"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "আমেরিকা/সান্টো_ডোমিঙ্গো"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "আমেরিকা/সাও_পাওলো"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "দঃ ও দঃপূঃ ব্রাজিল (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "আমেরিকা/স্কোর্সবিসান্ড"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "স্কোর্সবাইসান্দ / ইটোকোর্টোরমিট"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "আমেরিকা/শিপরক"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "মাউন্টেন সময় - নাভাজো"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "আমেরিকা/সেইন্ট_বার্থেলেমি"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "আমেরিকা/সেন্ট_জনস"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "নিউফাউন্ডল্যান্ড সময়, দঃপূঃ ল্যাব্রেডর সহ"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "আমেরিকা/সেন্ট_কিটস"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "আমেরিকা/সেন্ট_লুসিয়া"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "আমেরিকা/সেন্ট_থোমাস"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "আমেরিকা/সেন্ট_ভিনসেন্ট"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "আমেরিকা/সুইফট_কারেন্ট"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "সেন্ট্রাল স্ট্যান্ডার্ড সময় - সাস্কাচুয়ান - মধ্যপশ্চিম"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "আমেরিকা/তেগুসিগালপা"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "আমেরিকা/থুল"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "থুলে / পিটুফিক"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "আমেরিকা/থান্ডার_বে"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "পূর্বীয় সময় - থান্ডার বে, ওন্টারিও"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "আমেরিকা/থেওয়ানা"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "মার্কিন প্রশান্ত মহাসাগীয় সময় - বায়া ক্যালিফোর্নিয়া মার্কিন সীমান্তের কাছে"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "আমেরিকা/টরোন্টো"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "পূর্বীয় সময় - ওন্টারিও - অধিকাংশ স্থান"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "আমেরিকা/টরটলা"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "আমেরিকা/ভ্যাংকুভার"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "প্রশান্ত মহাসাগীয় সময় - পশ্চিম ব্রিটিশ কলাম্বিয়া"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "আমেরিকা/ভার্জিন"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "আমেরিকা/ওয়াইটহর্স"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "প্রশান্ত মহাসাগীয় সময় - দক্ষিণ ইউকন"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "আমেরিকা/উইনিপেগ"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "সেন্ট্রাল সময় - মানিটোবা ও পশ্চিম ওন্টারিও"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "আমেরিকা/ইয়াকুতাত"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "আলাস্কা - আলাস্কা প্যানহ্যান্ডেল নেক"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "আমেরিকা/ইয়েলোনাইফ"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "মাউন্টেন সময় - মধ্য উত্তরপশ্চিম প্রদেশ"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "অ্যান্টার্কটিকা/ক্যাসি"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "কেসি স্টেশন, বেইলি উপদ্বীপ"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "অ্যান্টার্কটিকা/ড্যাভিস"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "ডেভিস স্টেশন, ভেস্টফোল্ড হিল্স"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "অ্যান্টার্কটিকা/দুমোন্ত দ্য উরভিল"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "দুমোন্ত দ্য উরভিল স্টেশন, টেরে অ্যাডেলি"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "অ্যান্টার্কটিকা/ম্যাকোয়েরি"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "ম্যাকোয়েরি দ্বীপের স্টেশন, ম্যাকোয়েরি দ্বীপ"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "অ্যান্টার্কটিকা/মসন"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "মোসন স্টেশন, হোল্ম বে"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "অ্যান্টার্কটিকা/ম্যাকমার্ডো"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "ম্যাকমার্ডো স্টেশন, রোস দ্বীপ"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "অ্যান্টার্কটিকা/পাল্মার"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "পাল্মার স্টেশন, অ্যান্ভার্স দ্বীপ"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "অ্যান্টার্কটিকা/রোথেরা"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "রোথেরা স্টেশন, অ্যাডেলেইড দ্বীপ"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "অ্যান্টার্কটিকা/দক্ষিণ_মেরু"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "অ্যামুন্ডসেন-স্কট স্টেশন, দক্ষিণ মেরু"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "অ্যান্টার্কটিকা/সিওয়া"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "সিওয়া স্টেশন, ই ওঙ্গুল দ্বীপ"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "অ্যান্টার্কটিকা/ভোস্টক"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "ভোস্টক স্টেশন, দঃ ম্যাগনেটিক মেরু"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "আর্কটিক/লংইয়ারবেন"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "এশিয়া/এডেন"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "এশিয়া/আলমাটি"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "এশিয়া/আম্মান"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "এশিয়া/আনাদির"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "মস্কো+০৮ - বেরিং সাগর"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "এশিয়া/আকতু"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "অতিরাউ (অতিরাউ, গুরয়েভ), মাংগিস্তাউ (মানকিস্তাউ)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "এশিয়া/আকতোবে"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "আখতোবে (আখতোবে)"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "এশিয়া/আশ‌গাবাত"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "এশিয়া/আশখাবাদ"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "এশিয়া/বাগদাদ"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "এশিয়া/বাহরেন"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "এশিয়া/বাকু"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "এশিয়া/ব্যাঙ্কক"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "এশিয়া/বেইরুট"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "এশিয়া/বিশকেক"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "এশিয়া/ব্রুনেই"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "এশিয়া/কলকাতা"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "এশিয়া/চৈবালছান"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "ডোরনোড, সুখবাতার"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "এশিয়া/চোংকিং"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "মধ্য চীন - সিচুয়ান, ইউনান, গুয়াংজি, সাংগজি, গিজু, প্রভৃতি"
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "এশিয়া/চুংকিং"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "এশিয়া/কোলোম্বো"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "এশিয়া/ঢাকা"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "এশিয়া/ডামাসকাস"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "এশিয়া/ঢাকা"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "এশিয়া/ডিলি"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "এশিয়া/দুবাই"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "এশিয়া/দুশানবে"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "এশিয়া/গাজা"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "এশিয়া/হার্বিন"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "হেইলোজিয়াং (মোহে ব্যতীত), জিলিন"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "এশিয়া/হো_চি_মিন"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "এশিয়া/হং _কং"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "এশিয়া/হোভড"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "বায়ান-ওলগিই, গোভি-অল্টাই, হোভড, উভস, জাভখান"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "এশিয়া/ইরকুটস"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "মস্কো+০৫ - লেক বৈকাল"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "এশিয়া/ইস্তানবুল"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "এশিয়া/জাকার্তা"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "জাভা ও সুমাত্রা"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "এশিয়া/জায়াপুরা"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "ইরিয়ান জায়া ও মোলুক্কাস"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "এশিয়া/জেরুসেলাম"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "এশিয়া/কাবুল"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "এশিয়া/কামচাটকা"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "মস্কো+০৮ - কামচাটকা"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "এশিয়া/করাচী"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "এশিয়া/কাশগার"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "পশ্চিম তিব্বত ও জিংজিয়াং"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "এশিয়া/কাটমান্ডু"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "এশিয়া/কাটমান্ডু"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "এশিয়া/কোলকাতা"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "এশিয়া/ক্রাসনোয়ার্স্ক"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "মস্কো+০৪ - ইয়েনিসেই নদী"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "এশিয়া/কুয়ালা_লাম্পুর"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "মালায়েশিয়া উপদ্বীপ"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "এশিয়া/কুচিং"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "সাবাক ও সারাওয়াক"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "এশিয়া/কুয়েত"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "এশিয়া/মাকাও"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "এশিয়া/মাকাও"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "এশিয়া/মাগাদান"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "মস্কো+০৮ - মাগাদান"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "এশিয়া/মাকাসসার"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "পূর্ব ও দক্ষিণ বোর্নিও, সেলেবেস, বালি, নুসা টেংগেরা, পশ্চিম তিমুর"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "এশিয়া/ম্যানিলা"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "এশিয়া/মাসকাট"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "এশিয়া/নিকোসিয়া"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "এশিয়া/নোভোকুজনেটক্স"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "মস্কো+০৩ - নোভোকুজনেটক্স"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "এশিয়া/নোভোসিবার্স্ক"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "মস্কো+০৩ - নোভোসিবার্স্ক"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "এশিয়া/ওমস্ক"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "মস্কো+০৩ - পশ্চিম সাইবেরিয়া"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "এশিয়া/ওরাল"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "পশ্চিম কাজাখস্তান"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "এশিয়া/নোম_ফেন"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "এশিয়া/পন্টিয়ানাক"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "পশ্চিম ও মধ্য বোর্নিও"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "এশিয়া/পিয়োংইয়াং"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "এশিয়া/কাতার"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "এশিয়া/কিজিলোর্দা"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "কিজিলোর্দা (কিজিলোর্দা, কিজিল-ওর্দা)"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "এশিয়া/ইয়াংগন"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "এশিয়া/রিয়াদ"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "এশিয়া/রিয়াদ৮৭"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "এশিয়া/রিয়াদ৮৮"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "এশিয়া/রিয়াদ৮৯"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "এশিয়া/সায়গন"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "এশিয়া/শাকালিন"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "মস্কো+০৭ - সাখালিন দ্বীপ"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "এশিয়া/সামারখান্দ"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "পশ্চিম উজবেকিস্তান"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "এশিয়া/সিওল"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "এশিয়া/সাংঘাই"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "পূর্ব চীন - বেইজিং, গুয়াংডন, সাংঘাই প্রভৃতি"
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "এশিয়া/সিঙ্গাপুর"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "এশিয়া/তাইপে"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "এশিয়া/তাসকেন্ত"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "পূর্ব উজবেকিস্তান"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "এশিয়া/তবিলিশি"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "এশিয়া/তেহেরান"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "এশিয়া/তেল_আভিভ"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "এশিয়া/থিম্বু"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "এশিয়া/থিম্পু"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "এশিয়া/টোকিও"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "এশিয়া/উজুং_পান্দাং"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "এশিয়া/উলানবাতোর"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "এশিয়া/উলান_বাতোর"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "এশিয়া/উরুমকি"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "অধিকাংশ তিব্বত ও জিংজিয়াং"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "এশিয়া/ভিয়েনতিয়েন"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "এশিয়া/ভ্লাডিভোস্টক"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "মস্কো+০৭ - আমুর নদী"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "এশিয়া/ইয়াকুটস"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "মস্কো+০৬ - লেনা নদী"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "এশিয়া/ইয়াকাতারিনবুর্গ"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "মস্কো+০২ - উরাল"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "এশিয়া/ইয়ারভান"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "আটলান্টিক/এজোরে"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "এজোরেস"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "আটলান্টিক/বারমুডা"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "আটলান্টিক/ক্যানারি"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "ক্যানারি দ্বীপপুঞ্জ"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "আটলান্টিক/কেপ_ভার্ডি"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "আটলান্টিক/ফেরো"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "আটলান্টিক/ফেরো"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "আটলান্টিক/জান_মায়েন"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "আটলান্টিক/মাদিইরা"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "মাদেইরা দ্বীপপুঞ্জ"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "আটলান্টিক/রিকয়াভিক"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "আটলান্টিক/সাউথ_জর্জিয়া"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "আটলান্টিক/স্টেনলি"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "আটলান্টিক/সেন্ট_হেলেনা"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "অস্ট্রেলিয়া/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "অস্ট্রেলিয়া/অ্যাডিলেড"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "দক্ষিণ অস্ট্রেলিয়া"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "অস্ট্রেলিয়া/ব্রিসবেন"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "কুইন্সল্যান্ড - অধিকাংশ স্থান"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "অস্ট্রেলিয়া/ব্রোকেন_হিল"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "নিউ সাউথ ওয়েল্স - ইয়ানকোউইনা"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "অস্ট্রেলিয়া/ক্যানবেরা"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "অস্ট্রেলিয়া/কারি"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "তাসমানিয়া - কিং দ্বীপ"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "অস্ট্রেলিয়া/ডারউইন"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "উত্তর অঞ্চল"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "অস্ট্রেলিয়া/ইউক্লা"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "পশ্চিম অস্ট্রেলিয়া - ইউক্লা অঞ্চল"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "অস্ট্রেলিয়া/হোবার্ট"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "তাসমেনিয়া - অধিকাংশ স্থান"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "অস্ট্রেলিয়া/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "অস্ট্রেলিয়া/লিন্ডাম্যান"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "কুইন্সল্যান্ড - হলিডে দ্বীপপুঞ্জ"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "অস্ট্রেলিয়া/লর্ড_হাউই"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "লর্ড হাওয়ি দ্বীপ"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "অস্ট্রেলিয়া/মেলবোর্ন"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "ভিক্টোরিয়া"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "অস্ট্রেলিয়া/উত্তর"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "অস্ট্রেলিয়া/নিউ সাইথ ওয়েলস"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "অস্ট্রেলিয়া/পার্থ"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "পশ্চিম অস্ট্রেলিয়া - অধিকাংশ স্থান"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "অস্ট্রেলিয়া/কুইন্সল্যান্ড"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "অস্ট্রেলিয়া/দক্ষিণ"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "অস্ট্রেলিয়া/সিডনি"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "নিউ সাউথ ওয়েলস - অধিকাংশ স্থান"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "অস্ট্রেলিয়া/তাসমানিয়া"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "অস্ট্রেলিয়া/ভিক্টোরিয়া"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "অস্ট্রেলিয়া/পশ্চিম"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "অস্ট্রেলিয়া/ইয়ানকোউইনা"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "ব্রাজিল/একর"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "ব্রাজিল/ডিনহোনহা"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "ব্রাজিল/পূর্ব"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "ব্রাজিল/পশ্চিম"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "কানাডা/আটলান্টিক"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "কানাডা/সেন্ট্রাল"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "কানাডা/পূর্ব"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "কানাডা/পূর্ব-সাসকাচুয়ান"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "কানাডা/মাউন্টেন"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "কানাডা/নিউফাউন্ডল্যান্ড"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "কানাডা/প্যাসিফিক"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "কানাডা/সাসকাচুয়ান"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "কানাডা/ইউকোন"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "চিলি/কন্টিনেন্টাল"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "চিলি/ইস্টারআইল্যান্ড"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "কিউবা"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "মিশর"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "আয়ার"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/গ্রিনউইচ"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/জুলু"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "ইউরোপ/আমস্টারডাম"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "ইউরোপ/এন্ডোরা"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "ইউরোপ/এথেন্স"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "ইউরোপ/বেলফাস্ট"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "ইউরোপ/বেলগ্রেড"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "ইউরোপ/বার্লিন"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "ইউরোপ/ব্রাতিসলাভা"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "ইউরোপ/ব্রাসেলস"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "ইউরোপ/বুখারেস্ট"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "ইউরোপ/বুডাপেস্ট"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "ইউরোপ/চিশিনাউ"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "ইউরোপ/কোপেনহেগেন"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "ইউরোপ/ডাবলিন"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "ইউরোপ/জিব্রালটার"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "ইউরোপ/গুয়ের্ন্সে"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "ইউরোপ/হেলসিঙ্কি"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "ইউরোপ/আইল_অফ_ম্যান"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "ইউরোপ/ইস্তানবুল"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "ইউরোপ/জার্সি"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "ইউরোপ/কালিনিনগ্রাড"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "মস্কো-০১ - কালিনগ্রাড"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "ইউরোপ/কিভ"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "ইউরোপ/লিসবন"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "ইউরোপ/লুবলইয়ানা"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "ইউরোপ/লন্ডন"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "ইউরোপ/লুক্সেমবুর্গ"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "ইউরোপ/মাদ্রিদ"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "ইউরোপ/মল্টা"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "ইউরোপ/মারিহাম"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "ইউরোপ/মিনস্ক"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "ইউরোপ/মোনেকো"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "ইউরোপ/মস্কো"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "মস্কো+০০ - পশ্চিম রাশিয়া"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "ইউরোপ/নিকোসিয়া"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "ইউরোপ/ওসলো"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "ইউরোপ/প্যারিস"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "ইউরোপ/পোডগোরিকা"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "ইউরোপ/প্রাগ"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "ইউরোপ/রিগা"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "ইউরোপ/রোম"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "ইউরোপ/সামারা"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "মস্কো - সামারা, উদমুর্শিয়া"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "ইউরোপ/সান_মারিনো"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "ইউরোপ/সারায়েভো"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "ইউরোপ/সিম্ফিরোপেল"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "মধ্য ক্রিমিয়া"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "ইউরোপ/স্কপয়া"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "ইউরোপ/সোফিয়া"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "ইউরোপ/স্টকহোম"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "ইউরোপ/ট্যালিন"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "ইউরোপ/তিরানা"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "ইউরোপ/তিরাসপোল"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "ইউরোপ/উজগোরোদ"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "রুথেনিয়া"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "ইউরোপ/ভাদুজ"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "ইউরোপ/ভ্যাটিকেন"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "ইউরোপ/ভিয়েনা"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "ইউরোপ/ভিলনিয়াস"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "ইউরোপ/ভোল্গোগ্রাড"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "মস্কো+০০ - ক্যাসপিয়ান সাগর"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "ইউরোপ/ওয়ারস"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "ইউরোপ/জাগ্রেব"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "ইউরোপ/জাপোরোযেই"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "জ্যাফোরিজিয়া, পূ লুগানস্ক / জ্যাফোরিজিয়া, পূ লুহানস্ক"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "ইউরোপ/জুরিখ"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "ফ্যাক্টরি"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "গ্রেট ব্রিটেন"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "গ্রেট ব্রিটেন-আয়ার"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "গ্রিনউইচ"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "হং কং"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "আইসল্যান্ড"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "ভারত মহাসাগর/আন্তানানারিভো"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "ভারত মহাসাগর/চাগোস"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "ভারত মহাসাগর/ক্রিস্টমাস"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "ভারত মহাসাগর/কোকোস"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "ভারত মহাসাগর/কোমোরো"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "ভারত মহাসাগর/কারগুয়েলেন"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "ভারত মহাসাগর/মাহে"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "ভারত মহাসাগর/মালদিভ"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "ভারত মহাসাগর/মরিশাস"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "ভারত মহাসাগর/মেয়োতে"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "ভারত মহাসাগর/রিউনিয়ন"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "ইরান"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "ইজরায়েল"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "জামাইকা"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "জাপান"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "কয়াজালিইন"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "লিবিয়া"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "মেক্সিকো/বাহানোর্তে"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "মেক্সিকো/বাহাসুর"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "মেক্সিকো/সাধারণ"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "মধ্যপ্রাচ্য/রিয়াদ৮৭"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "মধ্যপ্রাচ্য/রিয়াদ৮৮"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "মধ্যপ্রাচ্য/রিয়াদ৮৯"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "নাভাজো"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "প্রশান্ত_মহাসাগর/এপিয়া"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "প্রশান্ত_মহাসাগর/অকল্যান্ড"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "প্রশান্ত_মহাসাগর/চ্যাটহাম"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "চ্যাটহ্যাম দ্বীপপুঞ্জ"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "প্রশান্ত_মহাসাগর/চুউক"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "চুউক (ট্রুক) ও ইয়াপ"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "প্রশান্ত_মহাসাগর/ইস্টার"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "ইস্টার দ্বীপ ও সালা ই গোমেজ"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "প্রশান্ত_মহাসাগর/এফাতে"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "প্রশান্ত_মহাসাগর/এন্ডারবুরি"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "ফিনিক্স দ্বীপপুঞ্জ"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "প্রশান্ত_মহাসাগর/ফাকাওফো"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "প্রশান্ত_মহাসাগর/ফিজি"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "প্রশান্ত_মহাসাগর/ফুনাফুতি"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "প্রশান্ত_মহাসাগর/গালাপাগোস"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "গালাপাগোস দ্বীপপুঞ্জ"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "প্রশান্ত_মহাসাগর/গ্যামবিয়ার"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "গ্যাম্বিয়ার দ্বীপপুঞ্জ"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "প্রশান্ত_মহাসাগর/গুয়াডালকানাল"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "প্রশান্ত_মহাসাগর/গুয়াম"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "প্রশান্ত_মহাসাগর/হনোলুলু"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "হাওয়াই"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "প্রশান্ত_মহাসাগর/জনস্টন"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "জনস্টন অ্যাটোল"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "প্রশান্ত_মহাসাগর/কিরিবাস"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "লাইন দ্বীপপুঞ্জ"
+
+# is this kiribati?
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "প্রশান্ত_মহাসাগর/কোসরে"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "কোসরেই"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "প্রশান্ত_মহাসাগর/কয়াজালিইন"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "প্রশান্ত_মহাসাগর/মাজুরো"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "প্রশান্ত_মহাসাগর/মারকিসাস"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "মার্কুইসাস দ্বীপপুঞ্জ"
+
+# not sure
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "প্রশান্ত_মহাসাগর/মিডওয়ে"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "মিডওয়ে দ্বীপপুঞ্জ"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "প্রশান্ত_মহাসাগর/নাউরু"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "প্রশান্ত_মহাসাগর/নিউ"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "প্রশান্ত_মহাসাগর/নোরফোল্ক"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "প্রশান্ত_মহাসাগর/নুমিয়া"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "প্রশান্ত_মহাসাগর/পাগো_পাগো"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "প্রশান্ত_মহাসাগর/পালাউ"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "প্রশান্ত_মহাসাগর/পিটকেয়ার্ন"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "প্রশান্ত_মহাসাগর/পোনপেই"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr " পোনপেই (পোনাপে)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "প্রশান্ত_মহাসাগর/পোনাপে"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "প্রশান্ত_মহাসাগর/পোর্ট-মোর্সবি"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "প্রশান্ত_মহাসাগর/রারোটোঙ্গা"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "প্রশান্ত_মহাসাগর/সাইপান"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "প্রশান্ত_মহাসাগর/সামোয়া"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "প্রশান্ত_মহাসাগর/তাহিতি"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "সোসাইটি দ্বীপপুঞ্জ"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "প্রশান্ত_মহাসাগর/তারাওয়া"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "গিলবার্ট দ্বীপপুঞ্জ"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "প্রশান্ত_মহাসাগর/টোঙ্গাটাপু"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "প্রশান্ত_মহাসাগর/ট্রুক"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "প্রশান্ত_মহাসাগর/ওয়েক"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "ওয়েক দ্বীপ"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "প্রশান্ত_মহাসাগর/ওয়ালিস"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "প্রশান্ত_মহাসাগর/ইয়াপ"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "পোল্যান্ড"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "পর্তুগাল"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "সিঙ্গাপুর"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "তুরস্ক"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "যুক্তরাষ্ট্র/আলাস্কা"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "যুক্তরাষ্ট্র/আলিউশিয়ান"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "যুক্তরাষ্ট্র/আরিজোনা"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "যুক্তরাষ্ট্র/সেন্ট্রাল"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "যুক্তরাষ্ট্র/ইস্টার্ন"
+
+# msgstr "যুক্তরাষ্ট্র/পূর্ববর্তী"
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "যুক্তরাষ্ট্র/পূর্ব-ইন্ডিয়ানা"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "যুক্তরাষ্ট্র/হাওয়াই"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "যুক্তরাষ্ট্র/ইন্ডিয়ানা-স্টার্ক"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "যুক্তরাষ্ট্র/মিশিগান"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "যুক্তরাষ্ট্র/মাউন্টেন"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "যুক্তরাষ্ট্র/প্যাসিফিক"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "যুক্তরাষ্ট্র/সামোয়া"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "জুলু"
+
+
diff --git a/panels/datetime/po-timezones/bs.po b/panels/datetime/po-timezones/bs.po
new file mode 100644
index 0000000..5167b24
--- /dev/null
+++ b/panels/datetime/po-timezones/bs.po
@@ -0,0 +1,3283 @@
+# translation of bs.po to Bosnian
+# Adnan Hodzic <AbsintheSyringe@gmail.com>, 2007.
+# Translation of timezones to Croatian
+# Copyright (C) Croatian team
+# Translators: Dario Lah <>,Robert Sedak <robert.sedak@sk.tel.hr>,Vedran Vyroubal <vedran.vyroubal@inet.hr>,
+msgid ""
+msgstr ""
+"Project-Id-Version: bs\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2007-01-24 18:10+0100\n"
+"Last-Translator: Adnan Hodzic <AbsintheSyringe@gmail.com>\n"
+"Language-Team: Bosnian <lokal@linux.org.ba>\n"
+"Language: bs\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+"X-Poedit-Language: Bosnian\n"
+"X-Poedit-Country: BOSNIA\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Afrika/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Afrika/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Afrika/Adis_Ababa"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Afrika/Algiers"
+
+#: timezones.h:5
+#, fuzzy
+msgid "Africa/Asmara"
+msgstr "Afrika/Asmera"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Afrika/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Afrika/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Afrika/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Afrika/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Afrika/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Afrika/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Afrika/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Afrika/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Afrika/Kairo"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Afrika/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Afrika/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Afrika/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Afrika/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Afrika/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Afrika/Djibouti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Afrika/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Afrika/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Afrika/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Afrika/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Afrika/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Afrika/Johannesbur"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Afrika/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Afrika/Khartoum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Afrika/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Afrika/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Afrika/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Afrika/Liberville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Afrika/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Afrika/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Afrika/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Afrika/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Afrika/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Afrika/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Afrika/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Afrika/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Afrika/Mogadishu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Afrika/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Afrika/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Afrika/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Afrika/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Afrika/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Afrika/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Afrika/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Afrika/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Afrika/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Afrika/Tripoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Afrika/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Afrika/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Amerika/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+#, fuzzy
+msgid "Aleutian Islands"
+msgstr "Australija/Queensland"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Amerika/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+#, fuzzy
+msgid "Alaska Time"
+msgstr "SAD/Aljaska"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Amerika/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Amerika/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Amerika/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Amerika/Argentina/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Amerika/Argentina/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Amerika/Argentina/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Amerika/Argentina/Cordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Amerika/Argentina/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Amerika/Argentina/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Amerika/Argentina/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Amerika/Argentina/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+#, fuzzy
+msgid "America/Argentina/Salta"
+msgstr "Amerika/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Amerika/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+#, fuzzy
+msgid "America/Argentina/San_Luis"
+msgstr "Amerika/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Amerika/Argentina/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Amerika/Argentina/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Amerika/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Amerika/Asuncion"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Amerika/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Amerika/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Amerika/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "Amerika/Bahia"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Amerika/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Amerika/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Amerika/Belize"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "Amerika/Blanc-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Amerika/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Amerika/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Amerika/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Amerika/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Amerika/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "Amerika/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Amerika/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Amerika/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Amerika/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Amerika/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Amerika/Cayman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Amerika/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+#, fuzzy
+msgid "Central Time"
+msgstr "SAD/Središnje"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Amerika/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "Amerika/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Amerika/Cordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Amerika/Costa_Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Amerika/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Amerika/Curacao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Amerika/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Amerika/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Amerika/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Amerika/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+#, fuzzy
+msgid "Mountain Time"
+msgstr "SAD/Planine"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Amerika/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Amerika/Dominica"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Amerika/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Amerika/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Amerika/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Amerika/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Amerika/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Amerika/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Amerika/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Amerika/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Amerika/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Amerika/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Amerika/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Amerika/Guadaloupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Amerika/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Amerika/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Amerika/Guyana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Amerika/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Amerika/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Amerika/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Amerika/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Amerika/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Amerika/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "Amerika/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Amerika/Indianapolis"
+
+#: timezones.h:227
+#, fuzzy
+msgid "America/Indiana/Tell_City"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "Amerika/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+#, fuzzy
+msgid "America/Indiana/Winamac"
+msgstr "Amerika/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Amerika/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Amerika/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Amerika/Jamaica"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Amerika/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Amerika/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Amerika/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+#, fuzzy
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Amerika/Kentucky/Louisville"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Amerika/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Amerika/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Amerika/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Amerika/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Amerika/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+#, fuzzy
+msgid "Pacific Time"
+msgstr "Tihi_ocean/Niue"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Amerika/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Amerika/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Amerika/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Amerika/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+#, fuzzy
+msgid "America/Marigot"
+msgstr "Amerika/Maceio"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Amerika/Martinique"
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "Amerika/Manaus"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Amerika/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Amerika/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Amerika/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Amerika/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Amerika/Mexico_City"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Amerika/Miquelon"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "Amerika/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Amerika/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Amerika/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Amerika/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Amerika/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Amerika/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Amerika/New_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+#, fuzzy
+msgid "Eastern Time"
+msgstr "SAD/Istočno"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Amerika/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Amerika/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Amerika/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+#, fuzzy
+msgid "Atlantic islands"
+msgstr "Atlantik/Kanari"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Amerika/Sjeverna_Dakota/Center"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "Amerika/Sjeverna_Dakota/New_Salem"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "Amerika/Managua"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Amerika/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Amerika/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Amerika/Paramari"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Amerika/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Amerika/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Amerika/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Amerika/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Amerika/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Amerika/Puerto_Rico"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Amerika/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Amerika/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Amerika/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Amerika/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+#, fuzzy
+msgid "America/Resolute"
+msgstr "Amerika/Belem"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Amerika/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Amerika/Rosario"
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "Amerika/Santiago"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+#, fuzzy
+msgid "America/Santarem"
+msgstr "Amerika/Santiago"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Amerika/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Amerika/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Amerika/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Amerika/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Amerika/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+#, fuzzy
+msgid "America/St_Barthelemy"
+msgstr "Amerika/Belem"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Amerika/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Amerika/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Amerika/St_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Amerika/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Amerika/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Amerika/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Amerika/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Amerika/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Amerika/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Amerika/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "Amerika/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Amerika/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Amerika/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Amerika/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Amerika/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Amerika/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Amerika/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Amerika/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antarktika/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antarktika/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antarktika/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+#, fuzzy
+msgid "Antarctica/Macquarie"
+msgstr "Antarktika/McMurdo"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antarktika/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antarktika/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antarktika/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antarktika/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antarktika/South_Pole"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antarktika/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antarktika/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Arktik/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Azija/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Azija/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Azija/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Azija/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Azija/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Azija/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Azija/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Azija/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Azija/Bagdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Azija/Bahrain"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Azija/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Azija/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Azija/Bejrut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Azija/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Azija/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Azija/Kalkuta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Azija/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Azija/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Azija/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Azija/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Azija/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Azija/Damascus"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Azija/Dhaka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Azija/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Azija/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Azija/Dushanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Azija/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Azija/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+#, fuzzy
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Azija/Chongqing"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Azija/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Azija/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Azija/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Azija/Istanbul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Azija/Jakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Azija/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Azija/Jeruzalem"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Azija/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Azija/Kamchatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Azija/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Azija/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+#, fuzzy
+msgid "Asia/Kathmandu"
+msgstr "Azija/Katmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Azija/Katmandu"
+
+#: timezones.h:518
+#, fuzzy
+msgid "Asia/Kolkata"
+msgstr "Azija/Jakarta"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Azija/Krasnoyarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Azija/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Azija/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Azija/Kuvajt"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Azija/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Azija/Macau"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Azija/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Azija/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Azija/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Azija/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Azija/Nicosia"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "Azija/Irkutsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Azija/Novosibirsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Azija/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+#, fuzzy
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Azija/Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Azija/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Azija/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Azija/Phnom_Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Azija/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Azija/Pyongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Azija/Qatar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Azija/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Azija/Rangoon"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Azija/Riyadh"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Azija/Riyadh87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Azija/Riyadh88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Azija/Riyadh89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Azija/Saigon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Azija/Sakhalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Azija/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Azija/Seul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Azija/Shanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Azija/Singapore"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Azija/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Azija/Tashkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Azija/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Azija/Tehran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Azija/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Azija/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Azija/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Azija/Tokyo"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Azija/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Azija/Ulaanbaatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Azija/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Azija/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Azija/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Azija/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Azija/Yakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Azija/Yekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Azija/Yerevan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlantik/Azores"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlantik/Bermuda"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlantik/Kanari"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlantik/Cape_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlantik/Faeroe"
+
+#: timezones.h:616
+#, fuzzy
+msgid "Atlantic/Faroe"
+msgstr "Atlantik/Faeroe"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlantik/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlantik/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlantik/Reykjavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlantik/South_Georgia"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlantik/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlantik/Sv._Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Australija/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Australija/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+#, fuzzy
+msgid "South Australia"
+msgstr "Australija/ACT"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Australija/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Australija/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Australija/Canberra"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Australija/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Australija/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+#, fuzzy
+msgid "Australia/Eucla"
+msgstr "Australija/Queensland"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+#, fuzzy
+msgid "Western Australia - Eucla area"
+msgstr "Australija/Queensland"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Australija/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Australija/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Australija/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Australija/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Australija/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+#, fuzzy
+msgid "Victoria"
+msgstr "Australija/Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Australija/Sjever"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Australija/New South Wels"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Australija/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Australija/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Australija/Jug"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Australija/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Australija/Tasmania"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Australija/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Australija/Zapad"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Australija/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brazil/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brazil/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brazil/Istok"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brazil/Zapad"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Kanada/Atlantik"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Kanada/Središnje"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Kanada/Istočna"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Kanada/Istok-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Kanada/Planine"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Kanada/Newfoundland"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Kanada/Tihi_ocean"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Kanada/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Kanada/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Čile/Kontinentalno"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Čile/Istočni otoci"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Kuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Egipat"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Irska"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Ostalo/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Ostalo/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Ostalo/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Ostalo/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Ostalo/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Ostalo/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Ostalo/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Ostalo/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Ostalo/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Ostalo/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Ostalo/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Ostalo/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Ostalo/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Ostalo/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Ostalo/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Ostalo/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Ostalo/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Ostalo/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Ostalo/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Ostalo/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Ostalo/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Ostalo/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Ostalo/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Ostalo/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Ostalo/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Ostalo/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Ostalo/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Ostalo/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Ostalo/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Ostalo/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Ostalo/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Ostalo/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Ostalo/Univerzalno"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Ostalo/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Ostalo/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Europa/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Europa/Andora"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Europa/Atena"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Europa/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Europa/Beograd"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Europa/Berlin"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Europa/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Europa/Bruxelles"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Europa/Bukurešt"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Europa/Budimpešta"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Europa/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Europa/Kopenhagen"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Europa/Dublin"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Europa/Gibraltar"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Europa/Guernsey"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Europa/Helsinki"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Europa/Isle_of_Man"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Europa/Istanbul"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Europa/Jersey"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Europa/Kalinjingrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Europa/Kijev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Europa/Lisabon"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Europa/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Europa/London"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Europa/Luxemburg"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Europa/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Europa/Malta"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Europa/Mariehamn"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Europa/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Europa/Monaco"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Europa/Moskva"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Europa/Nikozija"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Europa/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Europa/Pariz"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Europa/Podgorica"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Europa/Prag"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Europa/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Europa/Rim"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Europa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Europa/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Europa/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Europa/Sevastopolj"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Europa/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Europa/Sofija"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Europa/Stockholm"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Europa/Tallinn"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Europa/Tirana"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Europa/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Europa/Užgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Europa/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Europa/Vatikan"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Europa/Beč"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Europa/Vilnius"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Europa/Volgograd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Europa/Varšava"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Europa/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Europa/Zaporožje"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Europa/Zurich"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Izvorno"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "VB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "VB-Irska"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hong_Kong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Island"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Indijski_ocean/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Indijski_ocean/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Indijski_ocean/Božićni_otoci"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Indijski_ocean/Kokosovi otoci"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Indijski_ocean/Komoro otoci"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Indijski_ocean/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Indijski_ocean/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Indijski_ocean/Maldivi"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Indijski_ocean/Mauricijus"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Indijski_ocean/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Indijski_ocean/Reunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Iran"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Izrael"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamajka"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Japan"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Libija"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Meksiko/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Meksiko/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Meksiko/General"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Srednji Istok/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Srednji Istok/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Srednji Istok/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Tihi_ocean/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Tihi_ocean/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Tihi_ocean/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+#, fuzzy
+msgid "Chatham Islands"
+msgstr "Čile/Istočni otoci"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "Tihi_ocean/Truk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+#, fuzzy
+msgid "Pacific/Easter"
+msgstr "Tihi_ocean/Easter"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Tihi_ocean/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Tihi_ocean/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Tihi_ocean/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Tihi_ocean/Fiji"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Tihi_ocean/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Tihi_ocean/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Tihi_ocean/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Tihi_ocean/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Tihi_ocean/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Tihi_ocean/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+#, fuzzy
+msgid "Hawaii"
+msgstr "SAD/Havaji"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Tihi_ocean/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Tihi_ocean/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Tihi_ocean/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+#, fuzzy
+msgid "Kosrae"
+msgstr "Izrael"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Tihi_ocean/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Tihi_ocean/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Tihi_ocean/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Tihi_ocean/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Tihi_ocean/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Tihi_ocean/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Tihi_ocean/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Tihi_ocean/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Tihi_ocean/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Tihi_ocean/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Tihi_ocean/Pitcairn"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "Tihi_ocean/Ponape"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Tihi_ocean/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Tihi_ocean/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Tihi_ocean/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Tihi_ocean/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Tihi_ocean/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Tihi_ocean/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Tihi_ocean/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+#, fuzzy
+msgid "Gilbert Islands"
+msgstr "Čile/Istočni otoci"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Tihi_ocean/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Tihi_ocean/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Tihi_ocean/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Tihi_ocean/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Tihi_ocean/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Poljska"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugal"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "NR Kina"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "Republika Kina"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "Republika Koreja"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapur"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Turska"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Univerzalno"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "SAD/Aljaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "SAD/Aleuti"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "SAD/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "SAD/Središnje"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "SAD/Istočno"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "SAD/Istok-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "SAD/Havaji"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "SAD/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "SAD/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "SAD/Planine"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "SAD/Tihi_ocean"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "SAD/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
+
+#~ msgid "US/Pacific-New"
+#~ msgstr "SAD/Tihi_ocean-Novo"
diff --git a/panels/datetime/po-timezones/ca.po b/panels/datetime/po-timezones/ca.po
new file mode 100644
index 0000000..bbd2221
--- /dev/null
+++ b/panels/datetime/po-timezones/ca.po
@@ -0,0 +1,3300 @@
+# Catalan translations for timezones package.
+# Copyright (C) 2004, 2006, 2007 Free Software Foundation Inc.
+# This file is distributed under the same license as the
+# system-config-date package.
+#
+# Robert Antoni Buj Gelonch <robert.buj@gmail.com>, 2010
+# Josep Puigdemont <josep.puigdemont@gmail.com>, 2004, 2006, 2007
+#
+# This file is translated according to the glossary and style guide of
+# Softcatalà. If you plan to modify this file, please read first the page
+# of the Catalan translation team for the Fedora project at:
+# http://www.softcatala.org/projectes/fedora/
+# and contact the previous translator
+#
+# Aquest fitxer s'ha de traduir d'acord amb el recull de termes i la guia
+# d'estil de Softcatalà. Si voleu modificar aquest fitxer, llegiu si
+# us plau la pàgina de catalanització del projecte Fedora a:
+# http://www.softcatala.org/projectes/fedora/
+# i contacteu l'anterior traductor/a.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-09-20 05:41+0100\n"
+"Last-Translator: Robert Antoni Buj Gelonch <robert.buj@gmail.com>\n"
+"Language-Team: Catalan <fedora@softcatala.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ca\n"
+"X-Poedit-Language: Catalan\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Àfrica/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Àfrica/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Àfrica/Addis_Ababa"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Àfrica/Algiers"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "Àfrica/Asmara"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Àfrica/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Àfrica/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Àfrica/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Àfrica/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Àfrica/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Àfrica/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Àfrica/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Àfrica/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Àfrica/El_Caire"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Àfrica/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Àfrica/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "Ceuta i Melilla"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Àfrica/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Àfrica/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Àfrica/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Àfrica/Djibouti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Àfrica/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Àfrica/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Àfrica/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Àfrica/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Àfrica/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Àfrica/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Àfrica/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Àfrica/Khartum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Àfrica/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Àfrica/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "Rep. Dem. del Congo de l'oest"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Àfrica/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Àfrica/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Àfrica/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Àfrica/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Àfrica/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "Rep. Dem. del Congo de l'est"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Àfrica/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Àfrica/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Àfrica/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Àfrica/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Àfrica/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Àfrica/Mogadishu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Àfrica/Monròvia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Àfrica/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Àfrica/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Àfrica/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Àfrica/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Àfrica/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Àfrica/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Àfrica/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Àfrica/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Àfrica/Trípoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Àfrica/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Àfrica/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Amèrica/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Illes Aleutianes"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Amèrica/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Horari d'Alaska"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Amèrica/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Amèrica/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Amèrica/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "Tocantins"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Amèrica/Argentina/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Buenos Aires (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Amèrica/Argentina/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "Catamarca (CT), Chubut (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Amèrica/Argentina/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Amèrica/Argentina/Còrdoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "la majoria dels llocs (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Amèrica/Argentina/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Jujuy (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Amèrica/Argentina/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "La Rioja (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Amèrica/Argentina/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "Mendoza (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Amèrica/Argentina/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "Santa Cruz (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "Amèrica/Argentina/Salta"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Amèrica/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "San Juan (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "Amèrica/Argentina/San_Luis"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "San Luis (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Amèrica/Argentina/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "Tucuman (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Amèrica/Argentina/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "Tierra del Fuego (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Amèrica/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Amèrica/Asuncion"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Amèrica/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Amèrica/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Amèrica/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "Amèrica/Bahia_Banderas"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Amèrica/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Amèrica/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Amèrica/Belize"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "Amèrica/Blanc-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Amèrica/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Amèrica/Bogotà"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Amèrica/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Amèrica/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Amèrica/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "Amèrica/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Amèrica/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Amèrica/Caraques"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Amèrica/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Amèrica/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Amèrica/Cayman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Amèrica/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "Horari cental"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Amèrica/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "Amèrica/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Amèrica/Còrdoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Amèrica/Costa_Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Amèrica/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Amèrica/Curaçao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Amèrica/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Amèrica/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Amèrica/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid "Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Amèrica/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+#, fuzzy
+msgid "Mountain Time"
+msgstr "US/Mountain"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Amèrica/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Amèrica/Dominica"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Amèrica/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Amèrica/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Amèrica/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Amèrica/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Amèrica/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "Brazil NE (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Amèrica/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Amèrica/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr "Horari de l'Atlàntic - Nova escòcia - llocs que no van observar l'horari d'estiu 1966-1971"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Amèrica/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195
+#: timezones.h:364
+#: timezones.h:453
+#: timezones.h:591
+#: timezones.h:754
+#: timezones.h:852
+#: timezones.h:894
+msgid "most locations"
+msgstr "la majoria dels llocs"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Amèrica/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "Horari de l'Atlàntic - Labrador - la majoria de llocs"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Amèrica/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Amèrica/Granada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Amèrica/Guadalupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Amèrica/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Amèrica/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205
+#: timezones.h:757
+#: timezones.h:763
+msgid "mainland"
+msgstr "continent"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Amèrica/Guaiana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Amèrica/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "Horari de l'Atlàntic - Nova Escòcia (la majoria de llocs), PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Amèrica/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Amèrica/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Amèrica/Indiana/Indianàpolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "Horari oriental - Indiana - la majoria de llocs"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Amèrica/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "Horari central - Indiana - Comptat d'Starke"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Amèrica/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "Horari oriental- Indiana - Comptat de Crawford"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "Amèrica/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "Horari oriental- Indiana - Comptat de Pike"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Amèrica/Indianàpolis"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "Amèrica/Indiana/Tell_City"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "Horari central - Indiana - Comptat de Perry"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Amèrica/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "Horari oriental - Indiana - Comptat de Suïssa"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "Amèrica/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "Horari oriental - Indiana - Comptats de Daviess, Dubois, Knox i Martin"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "Amèrica/Indiana/Winamac"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "Horari oriental- Indiana - Comptat de Pulaski"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Amèrica/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Amèrica/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "Horari oriental - Nunavut de l'est - la majoria de llocs"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Amèrica/Jamaica"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Amèrica/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Amèrica/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Amèrica/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Horari oriental - Kentucky - Zona de Louisville"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Amèrica/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "Horari oriental - Kentucky - Comptat de Wayne"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Amèrica/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Amèrica/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Amèrica/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Amèrica/Los_Àngeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "Horari del Pacífic"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Amèrica/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Amèrica/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Amèrica/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Amèrica/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "Amazones E"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "Amèrica/Marigot"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Amèrica/Martinica"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "Amèrica/Matamoros"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid "US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr "Horari central dels EEUU - Coahuila, Durango, Nuevo Leon, Tamaulipas pròxims al marge dels EEUU"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Amèrica/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Amèrica/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Amèrica/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "Horari central - Michigan - Comptats de Dickinson, Gogebic, Iron i Menominee"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Amèrica/Mèrida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "Horari central - Campeche, Yucatan"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Amèrica/Ciutat_de_Mèxic"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "Horari central - la majoria de llocs"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Amèrica/Miquelon"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "Amèrica/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "Horari de l'Atlàntic - Nova Brunsvic"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Amèrica/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid "Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from US border"
+msgstr "Horari central de Mèxic - Coahuila, Durango, Nuevo Leon, Tamaulipas fora del marge dels EEUU"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Amèrica/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Amèrica/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "Horari oriental - Quebec - la majoria de llocs"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Amèrica/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Amèrica/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Amèrica/Nova_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "Horari oriental"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Amèrica/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid "Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr "Horari oriental - Ontario i Quebec - llocs que no van observar l'horari d'estiu 1967-1973"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Amèrica/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "Horari d'Alaska - Alaska de l'oest"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Amèrica/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "Illes de l'Atlàntic"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Amèrica/Dakota_del_Nord/Center"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "Horari central - Dakota del nord - Comptat d'Oliver"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "Amèrica/Dakota_del_Nord/New_Salem"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "Horari central - Dakota del nord - Comptat de Morton (exceptuant la zona de Mandan)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "Amèrica/Ojinaga"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Amèrica/Panamà"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Amèrica/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Amèrica/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Amèrica/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Amèrica/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Amèrica/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Amèrica/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Amèrica/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "Rondonia"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Amèrica/Puerto_Rico"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Amèrica/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Amèrica/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "Horari central - Nunavut central"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Amèrica/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "Pernambuco"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Amèrica/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "Horari central estàndard - Saskatchewan - la majoria dels llocs"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "Amèrica/Resolute"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "Horari oriental estàndard - Resolute, Nunavut"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Amèrica/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Amèrica/Rosario"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "Amèrica/Santa_Isabel"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "Horari del Pacífic Mexicà - Baixa California fora del marge dels EEUU"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "Amèrica/Santarem"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Amèrica/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Amèrica/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Amèrica/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "Brasil S/SE (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Amèrica/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Amèrica/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "Amèrica/St_Barthelemy"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Amèrica/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Amèrica/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Amèrica/St_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Amèrica/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Amèrica/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Amèrica/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Amèrica/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Amèrica/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Amèrica/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Amèrica/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "Amèrica/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Amèrica/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Amèrica/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Amèrica/Virginia"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Amèrica/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Amèrica/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Amèrica/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Amèrica/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antàrtida/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antàrtida/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antàrtida/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "Antàrtida/Macquarie"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antàrtida/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antàrtida/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antàrtida/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antàrtida/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antàrtida/Pol_Sud"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antàrtida/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antàrtida/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Arctic/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Àsia/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Àsia/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Àsia/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Àsia/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Àsia/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Àsia/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Àsia/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Àsia/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Àsia/Bagdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Àsia/Bahrain"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Àsia/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Àsia/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Àsia/Beirut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Àsia/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Àsia/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Àsia/Calcuta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Àsia/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Àsia/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Àsia/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Àsia/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Àsia/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Àsia/Damasc"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Àsia/Dhaka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Àsia/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Àsia/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Àsia/Dushanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Àsia/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Àsia/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Àsia/Ho_Chi_Minh"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Àsia/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Àsia/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Àsia/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Moscou+05 - Llac Baikal"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Àsia/Estanbul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Àsia/Jakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "Java i Sumatra"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Àsia/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Àsia/Jerusalem"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Àsia/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Àsia/Kamchatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Àsia/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Àsia/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "Àsia/Katmandú"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Àsia/Katmandú"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "Àsia/Kolkata"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Àsia/Krasnoyarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Àsia/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Àsia/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Àsia/Kuwait"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Àsia/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Àsia/Macau"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Àsia/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "Moscou+08 - Magadan"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Àsia/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Àsia/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Àsia/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Àsia/Nicòsia"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "Àsia/Novokuznetsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Moscou+03 - Novosibirsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Àsia/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Moscou+03 - Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Àsia/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Àsia/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Àsia/Phnom_Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Àsia/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "Borneo oest i cental"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Àsia/Pyongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Àsia/Qatar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Àsia/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Àsia/Rangoon"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Àsia/Riyadh"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Àsia/Riyadh87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Àsia/Riyadh88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Àsia/Riyadh89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Àsia/Saigon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Àsia/Sakhalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Àsia/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "Uzbekistan de l'oest"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Àsia/Seul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Àsia/Shanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Àsia/Singapur"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Àsia/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Àsia/Tashkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "Uzbekistan de l'est"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Àsia/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Àsia/Teheran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Àsia/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Àsia/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Àsia/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Àsia/Tokyo"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Àsia/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Àsia/Ulaanbaatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Àsia/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Àsia/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "La major part del Tibet i Xinjiang"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Àsia/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Àsia/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Àsia/Yakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Àsia/Yekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Àsia/Yerevan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlàntic/Azores"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlàntic/Bermuda"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlàntic/Canàries"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "Illes Canàries"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlàntic/Cap_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlàntic/Faeroe"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "Atlàntic/Faroe"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlàntic/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlàntic/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlàntic/Reykjavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlàntic/South_Georgia"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlàntic/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlàntic/St_Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Austràlia/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Austràlia/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "Austràlia del sur"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Austràlia/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Austràlia/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Austràlia/Canberra"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Austràlia/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Austràlia/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "Austràlia/Eucla"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "Austràlia occidental - Zona d'Eucla"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Austràlia/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Austràlia/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Austràlia/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Austràlia/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Austràlia/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "Victòria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Austràlia/Nord"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Austràlia/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Austràlia/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Austràlia/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Austràlia/Sud"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Austràlia/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Austràlia/Tasmània"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Austràlia/Victòria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Austràlia/Oest"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Austràlia/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brasil/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brasil/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brasil/Est"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brasil/Oest"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Canadà/Atlàntic"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Canadà/Central"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Canadà/Oriental"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Canadà/Saskatchewan-Est"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Canadà/Mountain"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Canadà/Newfoundland"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Canadà/Pacífic"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Canadà/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Canadà/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Xile/Continental"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Xile/Illa_de_Pasqua"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Cuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Egipte"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Irlanda"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Europa/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Europa/Andorra"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Europa/Atenes"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Europa/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Europa/Belgrad"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Europa/Berlín"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Europa/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Europa/Brussel·les"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Europa/Bucarest"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Europa/Budapest"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Europa/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Europa/Copenhagen"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Europa/Dublín"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Europa/Gibraltar"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Europa/Guernsey"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Europa/Helsinki"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Europa/Illa_de_Man"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Europa/Estambul"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Europa/Jersey"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Europa/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Moscou-01 - Kaliningrad"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Europa/Kiev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Europa/Lisboa"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Europa/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Europa/Londres"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Europa/Luxemburg"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Europa/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Europa/Malta"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Europe/Mariehamn"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Europa/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Europa/Mònaco"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Europa/Moscou"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Europa/Nicòsia"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Europa/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Europa/París"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Europa/Podgorica"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Europa/Praga"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Europa/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Europa/Rome"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Europa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Moscou - Samara, Udmurtia"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Europa/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Europa/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Europa/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "Crimea central"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Europa/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Europa/Sofia"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Europa/Estocolm"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Europa/Tallin"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Europa/Tirane"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Europa/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Europa/Uzhgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Europa/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Europa/Vaticà"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Europa/Viena"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Europa/Vilnius"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Europa/Volgograd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Europa/Varsòvia"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Europa/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Europa/Zaporozhye"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Europa/Zúrich"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Fàbrica"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Irlanda"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Islàndia"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Índic/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Índic/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Índic/Christmas"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Índic/Cocos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Índic/Comoro"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Índic/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Índic/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Índic/Maldives"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Índic/Mauritius"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Índic/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Índic/Reunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Iran"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Israel"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamaica"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Japó"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835
+#: timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Líbia"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Mèxic/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Mèxic/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Mèxic/General"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Mideast/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Mideast/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Mideast/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Pacífic/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Pacífic/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Pacífic/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "Illes_Chatham"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "Pacífic/Chuuk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Pacífic/Pasqua"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Pacífic/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Pacífic/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Pacífic/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Pacífic/Fiji"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Pacífic/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Pacífic/Galàpagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Pacífic/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Pacífic/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Pacífic/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Pacífic/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "Hawaii"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Pacífic/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Pacífic/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Pacífic/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "Kosrae"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Pacífic/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Pacífic/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Pacífic/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Pacífic/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Pacífic/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Pacífic/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Pacífic/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Pacífic/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Pacífic/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Pacífic/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Pacífic/Pitcairn"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "Pacífic/Pohnpei"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Pacífic/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Pacífic/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Pacífic/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Pacífic/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Pacífic/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Pacífic/Tahití"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Pacífic/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "Illes de Gilbert"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Pacífic/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Pacífic/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Pacífic/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Pacífic/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Pacífic/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Polònia"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugal"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapur"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Turquia"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "EEUU/Alaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "EEUU/Aleutian"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "EEUU/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "EEUU/Central"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "EEUU/Oriental"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "EEUU/Indiana-Est"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "EEUU/Hawaii"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "EEUU/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "EEUU/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "EEUU/Mountain"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "EEUU/Pacífic"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "EEUU/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
+
+#~ msgid "US/Pacific-New"
+#~ msgstr "US/Pacífic-Nou"
+
+#~ msgid "SystemV/AST4"
+#~ msgstr "SystemV/AST4"
+
+#~ msgid "SystemV/AST4ADT"
+#~ msgstr "SystemV/AST4ADT"
+
+#~ msgid "SystemV/CST6"
+#~ msgstr "SystemV/CST6"
+
+#~ msgid "SystemV/CST6CDT"
+#~ msgstr "SystemV/CST6CDT"
+
+#~ msgid "SystemV/EST5"
+#~ msgstr "SystemV/EST5"
+
+#~ msgid "SystemV/EST5EDT"
+#~ msgstr "SystemV/EST5EDT"
+
+#~ msgid "SystemV/HST10"
+#~ msgstr "SystemV/HST10"
+
+#~ msgid "SystemV/MST7"
+#~ msgstr "SystemV/MST7"
+
+#~ msgid "SystemV/MST7MDT"
+#~ msgstr "SystemV/MST7MDT"
+
+#~ msgid "SystemV/PST8"
+#~ msgstr "SystemV/PST8"
+
+#~ msgid "SystemV/PST8PDT"
+#~ msgstr "SystemV/PST8PDT"
+
+#~ msgid "SystemV/YST9"
+#~ msgstr "SystemV/YST9"
+
+#~ msgid "SystemV/YST9YDT"
+#~ msgstr "SystemV/YST9YDT"
diff --git a/panels/datetime/po-timezones/cs.po b/panels/datetime/po-timezones/cs.po
new file mode 100644
index 0000000..0b42305
--- /dev/null
+++ b/panels/datetime/po-timezones/cs.po
@@ -0,0 +1,3227 @@
+# translation of timezones.tip.po to Czech
+#
+# Milan Kerslager <kerslage@linux.cz>, 2002, 2007, 2010.
+# Miloslav Trmac <mitr@volny.cz>, 2004.
+# Nikola Štohanzl <niko@srnet.cz>, 2006.
+# Adam Pribyl <pribyl@lowlevel.cz>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones.tip\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-04-20 16:04+0200\n"
+"PO-Revision-Date: 2010-08-22 10:45+0100\n"
+"Last-Translator: Milan Keršláger <milan.kerslager@pslib.cz>\n"
+"Language-Team: Czech <Czech <cs-users@lists.fedoraproject.org>>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Afrika/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Afrika/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Afrika/Addis_Abeba"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Afrika/Alžírsko"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "Afrika/Asmara"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Afrika/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Afrika/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Afrika/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Afrika/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Afrika/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Afrika/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Afrika/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Afrika/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Afrika/Cairo"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Afrika/Kasablanka"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Afrika/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "Ceuta & Melilla"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Afrika/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Afrika/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Afrika/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Afrika/Džibuti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Afrika/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Afrika/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Afrika/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Afrika/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Afrika/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Afrika/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Afrika/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Afrika/Chartúm"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Afrika/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Afrika/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "Záp. Dem. Rep. Kongo"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Afrika/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Afrika/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Afrika/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Afrika/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Afrika/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "Vých. Dem. Rep. Kongo"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Afrika/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Afrika/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Afrika/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Afrika/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Afrika/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Afrika/Mogadišo"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Afrika/Monrovie"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Afrika/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Afrika/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Afrika/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Afrika/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Afrika/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Afrika/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Afrika/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Afrika/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Afrika/Tripolis"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Afrika/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Afrika/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Amerika/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Aleutské ostrovy"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Amerika/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Aljašský čas"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Amerika/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Amerika/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Amerika/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "Tocantins"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Amerika/Argentina/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Buenos Aires (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Amerika/Argentina/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "Catamarca (CT), Chubut (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Amerika/Argentina/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Amerika/Argentina/Cordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "Většina umístění (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Amerika/Argentina/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Jujuy (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Amerika/Argentina/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "La Rioja (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Amerika/Argentina/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "Mendoza (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Amerika/Argentina/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "Santa Cruz (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "Amerika/Argentina/Salta"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Amerika/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "San Juan (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "Amerika/Argentina/San_Luis"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "San Luis (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Amerika/Argentina/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "Tucuman (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Amerika/Argentina/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "Tierra del Fuego (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Amerika/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Amerika/Asuncion"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Amerika/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "Východní standardní čas - Atikokan, Ontario a Southampton I, Nunavut"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Amerika/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Amerika/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "Bahía"
+
+#: timezones.h:117
+msgid "America/Barbados"
+msgstr "Amerika/Barbados"
+
+#: timezones.h:118
+msgid "America/Belem"
+msgstr "Amerika/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:120
+msgid "Amapa, E Para"
+msgstr "Amapa, E Para"
+
+#: timezones.h:121
+msgid "America/Belize"
+msgstr "Amerika/Belize"
+
+#: timezones.h:122
+msgid "America/Blanc-Sablon"
+msgstr "Amerika/Blanc-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:124
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "Atlantský standardní čas - Quebec - Lower North Shore"
+
+#: timezones.h:125
+msgid "America/Boa_Vista"
+msgstr "Amerika/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:127
+msgid "Roraima"
+msgstr "Roraima"
+
+#: timezones.h:128
+msgid "America/Bogota"
+msgstr "Amerika/Bogota"
+
+#: timezones.h:129
+msgid "America/Boise"
+msgstr "Amerika/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:131
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "Horský čas - jižní Idaho & východní Oregon"
+
+#: timezones.h:132
+msgid "America/Buenos_Aires"
+msgstr "Amerika/Buenos_Aires"
+
+#: timezones.h:133
+msgid "America/Cambridge_Bay"
+msgstr "Amerika/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:135
+msgid "Mountain Time - west Nunavut"
+msgstr "Horský čas - západní Nunavut"
+
+#: timezones.h:136
+msgid "America/Campo_Grande"
+msgstr "Amerika/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:138
+msgid "Mato Grosso do Sul"
+msgstr "Mato Grosso do Sul"
+
+#: timezones.h:139
+msgid "America/Cancun"
+msgstr "Amerika/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:141
+msgid "Central Time - Quintana Roo"
+msgstr "Centrální čas - Quintana Roo"
+
+#: timezones.h:142
+msgid "America/Caracas"
+msgstr "Amerika/Karakas"
+
+#: timezones.h:143
+msgid "America/Catamarca"
+msgstr "Amerika/Catamarca"
+
+#: timezones.h:144
+msgid "America/Cayenne"
+msgstr "Amerika/Cayenne"
+
+#: timezones.h:145
+msgid "America/Cayman"
+msgstr "Amerika/Cayman"
+
+#: timezones.h:146
+msgid "America/Chicago"
+msgstr "Amerika/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:148
+msgid "Central Time"
+msgstr "Centrální čas"
+
+#: timezones.h:149
+msgid "America/Chihuahua"
+msgstr "Amerika/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:151
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "Mexický horský čas - Chihuahua dále od US hranice"
+
+#: timezones.h:152
+msgid "America/Coral_Harbour"
+msgstr "Amerika/Coral_Harbour"
+
+#: timezones.h:153
+msgid "America/Cordoba"
+msgstr "Amerika/Kordóba"
+
+#: timezones.h:154
+msgid "America/Costa_Rica"
+msgstr "Amerika/Costa_Rica"
+
+#: timezones.h:155
+msgid "America/Cuiaba"
+msgstr "Amerika/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:157
+msgid "Mato Grosso"
+msgstr "Mato Grosso"
+
+#: timezones.h:158
+msgid "America/Curacao"
+msgstr "Amerika/Curacao"
+
+#: timezones.h:159
+msgid "America/Danmarkshavn"
+msgstr "Amerika/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:161
+msgid "east coast, north of Scoresbysund"
+msgstr "Východní záliv, sever Scoresbysundu"
+
+#: timezones.h:162
+msgid "America/Dawson"
+msgstr "Amerika/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:164
+msgid "Pacific Time - north Yukon"
+msgstr "Pacifický čas - severní Yukon"
+
+#: timezones.h:165
+msgid "America/Dawson_Creek"
+msgstr "Amerika/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:167
+msgid "Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr "Horský standardní čas - Dawson Creek & Fort Saint John, Britská Kolumbie"
+
+#: timezones.h:168
+msgid "America/Denver"
+msgstr "Amerika/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:170
+msgid "Mountain Time"
+msgstr "Horský čas"
+
+#: timezones.h:171
+msgid "America/Detroit"
+msgstr "Amerika/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:173
+msgid "Eastern Time - Michigan - most locations"
+msgstr "Východní čas - Michigan - většina míst"
+
+#: timezones.h:174
+msgid "America/Dominica"
+msgstr "Amerika/Dominica"
+
+#: timezones.h:175
+msgid "America/Edmonton"
+msgstr "Amerika/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:177
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "Horský čas - Alberta, východní Britská Kolumbie & západní Saskatchewan"
+
+#: timezones.h:178
+msgid "America/Eirunepe"
+msgstr "Amerika/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:180
+msgid "W Amazonas"
+msgstr "Západní Amazonie"
+
+#: timezones.h:181
+msgid "America/El_Salvador"
+msgstr "Amerika/El_Salvador"
+
+#: timezones.h:182
+msgid "America/Ensenada"
+msgstr "Amerika/Ensenada"
+
+#: timezones.h:183
+msgid "America/Fortaleza"
+msgstr "Amerika/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:185
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "Severovýchodní Brazílie (MA, PI, CE, RN, PB)"
+
+#: timezones.h:186
+msgid "America/Fort_Wayne"
+msgstr "Amerika/Fort_Wayne"
+
+#: timezones.h:187
+msgid "America/Glace_Bay"
+msgstr "Amerika/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:189
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr "Atlantský čas - Nové Skotsko - místa bez letního času 1966-1971"
+
+#: timezones.h:190
+msgid "America/Godthab"
+msgstr "Amerika/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:192
+#: timezones.h:361
+#: timezones.h:450
+#: timezones.h:588
+#: timezones.h:751
+#: timezones.h:849
+#: timezones.h:888
+msgid "most locations"
+msgstr "většina míst"
+
+#: timezones.h:193
+msgid "America/Goose_Bay"
+msgstr "Amerika/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:195
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "Atlantský čas - Labrador - většina míst"
+
+#: timezones.h:196
+msgid "America/Grand_Turk"
+msgstr "Amerika/Grand_Turk"
+
+#: timezones.h:197
+msgid "America/Grenada"
+msgstr "Amerika/Grenada"
+
+#: timezones.h:198
+msgid "America/Guadeloupe"
+msgstr "Amerika/Guadeloupe"
+
+#: timezones.h:199
+msgid "America/Guatemala"
+msgstr "Amerika/Guatemala"
+
+#: timezones.h:200
+msgid "America/Guayaquil"
+msgstr "Amerika/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:202
+#: timezones.h:754
+#: timezones.h:760
+msgid "mainland"
+msgstr "vnitrozemí"
+
+#: timezones.h:203
+msgid "America/Guyana"
+msgstr "Amerika/Guyana"
+
+#: timezones.h:204
+msgid "America/Halifax"
+msgstr "Amerika/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:206
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "Atlantský čas - Nové Skotsko (většina míst), PEI"
+
+#: timezones.h:207
+msgid "America/Havana"
+msgstr "Amerika/Havana"
+
+#: timezones.h:208
+msgid "America/Hermosillo"
+msgstr "Amerika/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:210
+msgid "Mountain Standard Time - Sonora"
+msgstr "Horský standardní čas - Sonora"
+
+#: timezones.h:211
+msgid "America/Indiana/Indianapolis"
+msgstr "Amerika/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:213
+msgid "Eastern Time - Indiana - most locations"
+msgstr "Východní čas - Indiana - většina míst"
+
+#: timezones.h:214
+msgid "America/Indiana/Knox"
+msgstr "Amerika/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:216
+msgid "Central Time - Indiana - Starke County"
+msgstr "Centrální čas - Indiana - Starke County"
+
+#: timezones.h:217
+msgid "America/Indiana/Marengo"
+msgstr "Amerika/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:219
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "Východní čas - Indiana - Crawford County"
+
+#: timezones.h:220
+msgid "America/Indiana/Petersburg"
+msgstr "Amerika/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "Východní čas - Indiana - Pike County"
+
+#: timezones.h:223
+msgid "America/Indianapolis"
+msgstr "Amerika/Indianapolis"
+
+#: timezones.h:224
+msgid "America/Indiana/Tell_City"
+msgstr "Amerika/Indiana/Tell_City"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:226
+msgid "Central Time - Indiana - Perry County"
+msgstr "Centrální čas - Indiana - Perry County"
+
+#: timezones.h:227
+msgid "America/Indiana/Vevay"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:229
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "Východní čas - Indiana - Switzerland County"
+
+#: timezones.h:230
+msgid "America/Indiana/Vincennes"
+msgstr "Amerika/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "Východní čas - Indiana - Daviess, Dubois, Knox & Martin Counties"
+
+#: timezones.h:233
+msgid "America/Indiana/Winamac"
+msgstr "Amerika/Indiana/Winamac"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "Východní čas - Indiana - Pulaski County"
+
+#: timezones.h:236
+msgid "America/Inuvik"
+msgstr "Amerika/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:238
+msgid "Mountain Time - west Northwest Territories"
+msgstr "Horský čas - západní Severozápadní teritoria"
+
+#: timezones.h:239
+msgid "America/Iqaluit"
+msgstr "Amerika/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:241
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "Východní čas - východní Nunavut - většina míst"
+
+#: timezones.h:242
+msgid "America/Jamaica"
+msgstr "Amerika/Jamaica"
+
+#: timezones.h:243
+msgid "America/Jujuy"
+msgstr "Amerika/Jujuy"
+
+#: timezones.h:244
+msgid "America/Juneau"
+msgstr "Amerika/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:246
+msgid "Alaska Time - Alaska panhandle"
+msgstr "Aljašský čas - Aljaška panhandle"
+
+#: timezones.h:247
+msgid "America/Kentucky/Louisville"
+msgstr "Amerika/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:249
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Východní čas - Kentucky - Louisville"
+
+#: timezones.h:250
+msgid "America/Kentucky/Monticello"
+msgstr "Amerika/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "Východní čas - Kentucky - Wayne County"
+
+#: timezones.h:253
+msgid "America/Knox_IN"
+msgstr "Amerika/Knox_IN"
+
+#: timezones.h:254
+msgid "America/La_Paz"
+msgstr "Amerika/La_Paz"
+
+#: timezones.h:255
+msgid "America/Lima"
+msgstr "Amerika/Lima"
+
+#: timezones.h:256
+msgid "America/Los_Angeles"
+msgstr "Amerika/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:258
+msgid "Pacific Time"
+msgstr "Pacifický čas"
+
+#: timezones.h:259
+msgid "America/Louisville"
+msgstr "Amerika/Louisville"
+
+#: timezones.h:260
+msgid "America/Maceio"
+msgstr "Amerika/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:262
+msgid "Alagoas, Sergipe"
+msgstr "Alagoas, Sergipe"
+
+#: timezones.h:263
+msgid "America/Managua"
+msgstr "Amerika/Managua"
+
+#: timezones.h:264
+msgid "America/Manaus"
+msgstr "Amerika/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:266
+msgid "E Amazonas"
+msgstr "Východní Amazonie"
+
+#: timezones.h:267
+msgid "America/Marigot"
+msgstr "Amerika/Marigot"
+
+#: timezones.h:268
+msgid "America/Martinique"
+msgstr "Amerika/Martinique"
+
+#: timezones.h:269
+msgid "America/Matamoros"
+msgstr "Amerika/Matamoros"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:271
+msgid "US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr "US centrální čas - Coahuila, Durango, Nuevo Leon, Tamaulipas u US hranice"
+
+#: timezones.h:272
+msgid "America/Mazatlan"
+msgstr "Amerika/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:274
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "Horský čas - S Baja, Nayarit, Sinaloa"
+
+#: timezones.h:275
+msgid "America/Mendoza"
+msgstr "Amerika/Mendoza"
+
+#: timezones.h:276
+msgid "America/Menominee"
+msgstr "Amerika/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:278
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "Centrální čas - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+
+#: timezones.h:279
+msgid "America/Merida"
+msgstr "Amerika/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:281
+msgid "Central Time - Campeche, Yucatan"
+msgstr "Centrální čas - Campeche, Yucatan"
+
+#: timezones.h:282
+msgid "America/Mexico_City"
+msgstr "Amerika/Mexico_City"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:284
+msgid "Central Time - most locations"
+msgstr "Centrální čas - většina míst"
+
+#: timezones.h:285
+msgid "America/Miquelon"
+msgstr "Amerika/Miquelon"
+
+#: timezones.h:286
+msgid "America/Moncton"
+msgstr "Amerika/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:288
+msgid "Atlantic Time - New Brunswick"
+msgstr "Atlantský čas - New Brunswick"
+
+#: timezones.h:289
+msgid "America/Monterrey"
+msgstr "Amerika/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:291
+msgid "Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from US border"
+msgstr "Mexický centrální čas - Coahuila, Durango, Nuevo Leon, Tamaulipas dále od US hranice"
+
+#: timezones.h:292
+msgid "America/Montevideo"
+msgstr "Amerika/Montevideo"
+
+#: timezones.h:293
+msgid "America/Montreal"
+msgstr "Amerika/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:295
+msgid "Eastern Time - Quebec - most locations"
+msgstr "Východní čas - Quebec - většina míst"
+
+#: timezones.h:296
+msgid "America/Montserrat"
+msgstr "Amerika/Montserrat"
+
+#: timezones.h:297
+msgid "America/Nassau"
+msgstr "Amerika/Nassau"
+
+#: timezones.h:298
+msgid "America/New_York"
+msgstr "Amerika/New_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:300
+msgid "Eastern Time"
+msgstr "Východní čas"
+
+#: timezones.h:301
+msgid "America/Nipigon"
+msgstr "Amerika/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:303
+msgid "Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr "Východní čas - Ontario & Quebec - místa bez letního času 1967-1973"
+
+#: timezones.h:304
+msgid "America/Nome"
+msgstr "Amerika/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:306
+msgid "Alaska Time - west Alaska"
+msgstr "Aljašský čas - západní Aljaška"
+
+#: timezones.h:307
+msgid "America/Noronha"
+msgstr "Amerika/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:309
+msgid "Atlantic islands"
+msgstr "Atlantské ostrovy"
+
+#: timezones.h:310
+msgid "America/North_Dakota/Center"
+msgstr "Amerika/Severní_Dakota/Střed"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:312
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "Centrální čas - Severní Dakota - Oliver County"
+
+#: timezones.h:313
+msgid "America/North_Dakota/New_Salem"
+msgstr "Amerika/Severní_Dakota/New_Salem"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:315
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "Centrální čas - Severní Dakota - Morton County (mimo oblast Mandan)"
+
+#: timezones.h:316
+msgid "America/Ojinaga"
+msgstr "Amerika/Ojinaga"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:318
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "US horský čas - Chihuahua blízko US hranice"
+
+#: timezones.h:319
+msgid "America/Panama"
+msgstr "Amerika/Panama"
+
+#: timezones.h:320
+msgid "America/Pangnirtung"
+msgstr "Amerika/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:322
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "Východní čas - Pangnirtung, Nunavut"
+
+#: timezones.h:323
+msgid "America/Paramaribo"
+msgstr "Amerika/Paramaribo"
+
+#: timezones.h:324
+msgid "America/Phoenix"
+msgstr "Amerika/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:326
+msgid "Mountain Standard Time - Arizona"
+msgstr "Horský standardní čas - Arizona"
+
+#: timezones.h:327
+msgid "America/Port-au-Prince"
+msgstr "Amerika/Port-au-Prince"
+
+#: timezones.h:328
+msgid "America/Porto_Acre"
+msgstr "Amerika/Porto_Acre"
+
+#: timezones.h:329
+msgid "America/Port_of_Spain"
+msgstr "Amerika/Port_of_Spain"
+
+#: timezones.h:330
+msgid "America/Porto_Velho"
+msgstr "Amerika/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:332
+msgid "Rondonia"
+msgstr "Rondônia"
+
+#: timezones.h:333
+msgid "America/Puerto_Rico"
+msgstr "Amerika/Portoriko"
+
+#: timezones.h:334
+msgid "America/Rainy_River"
+msgstr "Amerika/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:336
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "Centrální čas - Rainy River & Fort Frances, Ontario"
+
+#: timezones.h:337
+msgid "America/Rankin_Inlet"
+msgstr "Amerika/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:339
+msgid "Central Time - central Nunavut"
+msgstr "Centrální čas - centrální Nunavut"
+
+#: timezones.h:340
+msgid "America/Recife"
+msgstr "Amerika/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:342
+msgid "Pernambuco"
+msgstr "Pernambuco"
+
+#: timezones.h:343
+msgid "America/Regina"
+msgstr "Amerika/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:345
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "Centrální standardní čas - Saskatchewan - většina míst"
+
+#: timezones.h:346
+msgid "America/Resolute"
+msgstr "Amerika/Resolute"
+
+#. comment for time zone America/Resolute
+#: timezones.h:348
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "Východní standardní čas - Resolute, Nunavut"
+
+#: timezones.h:349
+msgid "America/Rio_Branco"
+msgstr "Amerika/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:351
+msgid "Acre"
+msgstr "Acre"
+
+#: timezones.h:352
+msgid "America/Rosario"
+msgstr "Amerika/Rosario"
+
+#: timezones.h:353
+msgid "America/Santa_Isabel"
+msgstr "Amerika/Santa Isabel"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:355
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "Mexický pacifický čas - Baja California dále od US hranice"
+
+#: timezones.h:356
+msgid "America/Santarem"
+msgstr "Amerika/Santarem"
+
+#. comment for time zone America/Santarem
+#: timezones.h:358
+msgid "W Para"
+msgstr "Západní Para"
+
+#: timezones.h:359
+msgid "America/Santiago"
+msgstr "Amerika/Santiago"
+
+#: timezones.h:362
+msgid "America/Santo_Domingo"
+msgstr "Amerika/Santo_Domingo"
+
+#: timezones.h:363
+msgid "America/Sao_Paulo"
+msgstr "Amerika/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:365
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "Jižní a jihovýchodní Brazílie (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:366
+msgid "America/Scoresbysund"
+msgstr "Amerika/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:368
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "Scoresbysund / Ittoqqortoormiit"
+
+#: timezones.h:369
+msgid "America/Shiprock"
+msgstr "Amerika/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:371
+msgid "Mountain Time - Navajo"
+msgstr "Horský čas - Navajo"
+
+#: timezones.h:372
+msgid "America/St_Barthelemy"
+msgstr "Amerika/St_Barthelemy"
+
+#: timezones.h:373
+msgid "America/St_Johns"
+msgstr "Amerika/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:375
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "Newfoundlandský čas, včetně jihovýchodního Labradoru"
+
+#: timezones.h:376
+msgid "America/St_Kitts"
+msgstr "Amerika/St_Kitts"
+
+#: timezones.h:377
+msgid "America/St_Lucia"
+msgstr "Amerika/St_Lucia"
+
+#: timezones.h:378
+msgid "America/St_Thomas"
+msgstr "Amerika/St_Thomas"
+
+#: timezones.h:379
+msgid "America/St_Vincent"
+msgstr "Amerika/St_Vincent"
+
+#: timezones.h:380
+msgid "America/Swift_Current"
+msgstr "Amerika/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:382
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "Centrální čas - Saskatchewan - středozápad"
+
+#: timezones.h:383
+msgid "America/Tegucigalpa"
+msgstr "Amerika/Tegucigalpa"
+
+#: timezones.h:384
+msgid "America/Thule"
+msgstr "Amerika/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:386
+msgid "Thule / Pituffik"
+msgstr "Thule / Pituffik"
+
+#: timezones.h:387
+msgid "America/Thunder_Bay"
+msgstr "Amerika/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:389
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "Východní čas - Thunder Bay, Ontario"
+
+#: timezones.h:390
+msgid "America/Tijuana"
+msgstr "Amerika/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:392
+msgid "US Pacific Time - Baja California near US border"
+msgstr "Mexický pacifický čas - Baja California blízko u US hranice"
+
+#: timezones.h:393
+msgid "America/Toronto"
+msgstr "Amerika/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:395
+msgid "Eastern Time - Ontario - most locations"
+msgstr "Východní čas - Ontario - většina míst"
+
+#: timezones.h:396
+msgid "America/Tortola"
+msgstr "Amerika/Tortola"
+
+#: timezones.h:397
+msgid "America/Vancouver"
+msgstr "Amerika/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:399
+msgid "Pacific Time - west British Columbia"
+msgstr "Pacifický čas - západní Britská Kolumbie"
+
+#: timezones.h:400
+msgid "America/Virgin"
+msgstr "Amerika/Virgin"
+
+#: timezones.h:401
+msgid "America/Whitehorse"
+msgstr "Amerika/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:403
+msgid "Pacific Time - south Yukon"
+msgstr "Pacifický čas - jižní Yukon"
+
+#: timezones.h:404
+msgid "America/Winnipeg"
+msgstr "Amerika/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:406
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "Centrální čas - Manitoba & západní Ontario"
+
+#: timezones.h:407
+msgid "America/Yakutat"
+msgstr "Amerika/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:409
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "Aljašský čas - Alaska panhandle neck"
+
+#: timezones.h:410
+msgid "America/Yellowknife"
+msgstr "Amerika/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:412
+msgid "Mountain Time - central Northwest Territories"
+msgstr "Horský čas - centrální Severozápadní teritoria"
+
+#: timezones.h:413
+msgid "Antarctica/Casey"
+msgstr "Antarktis/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:415
+msgid "Casey Station, Bailey Peninsula"
+msgstr "Casey Station, Bailey Peninsula"
+
+#: timezones.h:416
+msgid "Antarctica/Davis"
+msgstr "Antarktis/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:418
+msgid "Davis Station, Vestfold Hills"
+msgstr "Davis Station, Vestfold Hills"
+
+#: timezones.h:419
+msgid "Antarctica/DumontDUrville"
+msgstr "Antarktis/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:421
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "Dumont-d'Urville Station, Terre Adelie"
+
+#: timezones.h:422
+msgid "Antarctica/Macquarie"
+msgstr "Antarktida/Macquarie"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:424
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "Macquarie Island Station, Macquarie Island"
+
+#: timezones.h:425
+msgid "Antarctica/Mawson"
+msgstr "Antarktis/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:427
+msgid "Mawson Station, Holme Bay"
+msgstr "Mawson Station, Holme Bay"
+
+#: timezones.h:428
+msgid "Antarctica/McMurdo"
+msgstr "Antarktis/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:430
+msgid "McMurdo Station, Ross Island"
+msgstr "McMurdo Station, Ross Island"
+
+#: timezones.h:431
+msgid "Antarctica/Palmer"
+msgstr "Antarktis/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:433
+msgid "Palmer Station, Anvers Island"
+msgstr "Palmer Station, Anvers Island"
+
+#: timezones.h:434
+msgid "Antarctica/Rothera"
+msgstr "Antarktis/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:436
+msgid "Rothera Station, Adelaide Island"
+msgstr "Rothera Station, Adelaide Island"
+
+#: timezones.h:437
+msgid "Antarctica/South_Pole"
+msgstr "Antarktis/Jižní pól"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:439
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "Amundsen-Scott stanice, Jižní pól"
+
+#: timezones.h:440
+msgid "Antarctica/Syowa"
+msgstr "Antarktis/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:442
+msgid "Syowa Station, E Ongul I"
+msgstr "Syowa Station, E Ongul I"
+
+#: timezones.h:443
+msgid "Antarctica/Vostok"
+msgstr "Antarktis/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:445
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "Vostok Station, severní magnetický pól"
+
+#: timezones.h:446
+msgid "Arctic/Longyearbyen"
+msgstr "Arctic/Longyearbyen"
+
+#: timezones.h:447
+msgid "Asia/Aden"
+msgstr "Asie/Aden"
+
+#: timezones.h:448
+msgid "Asia/Almaty"
+msgstr "Asie/Almaty"
+
+#: timezones.h:451
+msgid "Asia/Amman"
+msgstr "Asie/Amman"
+
+#: timezones.h:452
+msgid "Asia/Anadyr"
+msgstr "Asie/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:454
+msgid "Moscow+08 - Bering Sea"
+msgstr "Moskva+08 - Beringovo moře"
+
+#: timezones.h:455
+msgid "Asia/Aqtau"
+msgstr "Asie/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:457
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+
+#: timezones.h:458
+msgid "Asia/Aqtobe"
+msgstr "Asie/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:460
+msgid "Aqtobe (Aktobe)"
+msgstr "Aqtobe (Aktobe)"
+
+#: timezones.h:461
+msgid "Asia/Ashgabat"
+msgstr "Asie/Ashgabat"
+
+#: timezones.h:462
+msgid "Asia/Ashkhabad"
+msgstr "Asie/Ashkhabad"
+
+#: timezones.h:463
+msgid "Asia/Baghdad"
+msgstr "Asie/Bagdád"
+
+#: timezones.h:464
+msgid "Asia/Bahrain"
+msgstr "Asie/Bahrain"
+
+#: timezones.h:465
+msgid "Asia/Baku"
+msgstr "Asie/Baku"
+
+#: timezones.h:466
+msgid "Asia/Bangkok"
+msgstr "Asie/Bangkok"
+
+#: timezones.h:467
+msgid "Asia/Beirut"
+msgstr "Asie/Bejrút"
+
+#: timezones.h:468
+msgid "Asia/Bishkek"
+msgstr "Asie/Bishkek"
+
+#: timezones.h:469
+msgid "Asia/Brunei"
+msgstr "Asie/Brunea"
+
+#: timezones.h:470
+msgid "Asia/Calcutta"
+msgstr "Asie/Kalkata"
+
+#: timezones.h:471
+msgid "Asia/Choibalsan"
+msgstr "Asie/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:473
+msgid "Dornod, Sukhbaatar"
+msgstr "Dornod, Sukhbaatar"
+
+#: timezones.h:474
+msgid "Asia/Chongqing"
+msgstr "Asie/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:476
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "Centrální Čína - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, atp."
+
+#: timezones.h:477
+msgid "Asia/Chungking"
+msgstr "Asie/Chungking"
+
+#: timezones.h:478
+msgid "Asia/Colombo"
+msgstr "Asie/Colombo"
+
+#: timezones.h:479
+msgid "Asia/Dacca"
+msgstr "Asie/Dacca"
+
+#: timezones.h:480
+msgid "Asia/Damascus"
+msgstr "Asie/Damašek"
+
+#: timezones.h:481
+msgid "Asia/Dhaka"
+msgstr "Asie/Dhaka"
+
+#: timezones.h:482
+msgid "Asia/Dili"
+msgstr "Asie/Dilí"
+
+#: timezones.h:483
+msgid "Asia/Dubai"
+msgstr "Asie/Dubai"
+
+#: timezones.h:484
+msgid "Asia/Dushanbe"
+msgstr "Asie/Dušanbe"
+
+#: timezones.h:485
+msgid "Asia/Gaza"
+msgstr "Asie/Gaza"
+
+#: timezones.h:486
+msgid "Asia/Harbin"
+msgstr "Asie/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:488
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "Heilongjiang (mimo Mohe), Jilin"
+
+#: timezones.h:489
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Asie/Ho-Či-Minovo Město"
+
+#: timezones.h:490
+msgid "Asia/Hong_Kong"
+msgstr "Asie/Hong_Kong"
+
+#: timezones.h:491
+msgid "Asia/Hovd"
+msgstr "Asie/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:493
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+
+#: timezones.h:494
+msgid "Asia/Irkutsk"
+msgstr "Asie/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:496
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Moscow+05 - jezero Bajkal"
+
+#: timezones.h:497
+msgid "Asia/Istanbul"
+msgstr "Asie/Istanbul"
+
+#: timezones.h:498
+msgid "Asia/Jakarta"
+msgstr "Asie/Jakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:500
+msgid "Java & Sumatra"
+msgstr "Jáva & Sumatra"
+
+#: timezones.h:501
+msgid "Asia/Jayapura"
+msgstr "Asie/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:503
+msgid "Irian Jaya & the Moluccas"
+msgstr "Irian Jaya & the Moluccas"
+
+#: timezones.h:504
+msgid "Asia/Jerusalem"
+msgstr "Asie/Jeruzalém"
+
+#: timezones.h:505
+msgid "Asia/Kabul"
+msgstr "Asie/Kábul"
+
+#: timezones.h:506
+msgid "Asia/Kamchatka"
+msgstr "Asie/Kamčatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:508
+msgid "Moscow+08 - Kamchatka"
+msgstr "Moscow+08 - Kamčatka"
+
+#: timezones.h:509
+msgid "Asia/Karachi"
+msgstr "Asie/Karáčí"
+
+#: timezones.h:510
+msgid "Asia/Kashgar"
+msgstr "Asie/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:512
+msgid "west Tibet & Xinjiang"
+msgstr "Západní Tibet & Xinjiang"
+
+#: timezones.h:513
+msgid "Asia/Kathmandu"
+msgstr "Asie/Káthmándú"
+
+#: timezones.h:514
+msgid "Asia/Katmandu"
+msgstr "Asie/Kátmándú"
+
+#: timezones.h:515
+msgid "Asia/Kolkata"
+msgstr "Asie/Kalkata"
+
+#: timezones.h:516
+msgid "Asia/Krasnoyarsk"
+msgstr "Asie/Krasnojarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:518
+msgid "Moscow+04 - Yenisei River"
+msgstr "Moscow+04 - řeka Jenisej"
+
+#: timezones.h:519
+msgid "Asia/Kuala_Lumpur"
+msgstr "Asie/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:521
+msgid "peninsular Malaysia"
+msgstr "Malajsie (peninsular)"
+
+#: timezones.h:522
+msgid "Asia/Kuching"
+msgstr "Asie/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:524
+msgid "Sabah & Sarawak"
+msgstr "Sabah & Sarawak"
+
+#: timezones.h:525
+msgid "Asia/Kuwait"
+msgstr "Asie/Kuvait"
+
+#: timezones.h:526
+msgid "Asia/Macao"
+msgstr "Asie/Makao"
+
+#: timezones.h:527
+msgid "Asia/Macau"
+msgstr "Asie/Macao"
+
+#: timezones.h:528
+msgid "Asia/Magadan"
+msgstr "Asie/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:530
+msgid "Moscow+08 - Magadan"
+msgstr "Moskva+08 - Magadan"
+
+#: timezones.h:531
+msgid "Asia/Makassar"
+msgstr "Asie/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:533
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "Východní & jižní Borneo, Celebes, Bali, Nusa Tengarra, západní Timor"
+
+#: timezones.h:534
+msgid "Asia/Manila"
+msgstr "Asie/Manila"
+
+#: timezones.h:535
+msgid "Asia/Muscat"
+msgstr "Asie/Muscat"
+
+#: timezones.h:536
+msgid "Asia/Nicosia"
+msgstr "Asie/Nikósie"
+
+#: timezones.h:537
+msgid "Asia/Novokuznetsk"
+msgstr "Asie/Novokuznětsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:539
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Moskva+03 - Novokuznětsk"
+
+#: timezones.h:540
+msgid "Asia/Novosibirsk"
+msgstr "Asie/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:542
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Moskva+03 - Novosibirsk"
+
+#: timezones.h:543
+msgid "Asia/Omsk"
+msgstr "Asie/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:545
+msgid "Moscow+03 - west Siberia"
+msgstr "Moskva+03 - západní Sibiř"
+
+#: timezones.h:546
+msgid "Asia/Oral"
+msgstr "Asie/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:548
+msgid "West Kazakhstan"
+msgstr "Západní Kazachstán"
+
+#: timezones.h:549
+msgid "Asia/Phnom_Penh"
+msgstr "Asie/Phnom_Penh"
+
+#: timezones.h:550
+msgid "Asia/Pontianak"
+msgstr "Asie/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:552
+msgid "west & central Borneo"
+msgstr "Západní & centrální Borneo"
+
+#: timezones.h:553
+msgid "Asia/Pyongyang"
+msgstr "Asie/Pchjongjang"
+
+#: timezones.h:554
+msgid "Asia/Qatar"
+msgstr "Asie/Qatar"
+
+#: timezones.h:555
+msgid "Asia/Qyzylorda"
+msgstr "Asie/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:557
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+
+#: timezones.h:558
+msgid "Asia/Rangoon"
+msgstr "Asie/Rangůn"
+
+#: timezones.h:559
+msgid "Asia/Riyadh"
+msgstr "Asie/Rijád"
+
+#: timezones.h:560
+msgid "Asia/Riyadh87"
+msgstr "Asie/Rijád87"
+
+#: timezones.h:561
+msgid "Asia/Riyadh88"
+msgstr "Asie/Rijád88"
+
+#: timezones.h:562
+msgid "Asia/Riyadh89"
+msgstr "Asie/Rijád89"
+
+#: timezones.h:563
+msgid "Asia/Saigon"
+msgstr "Asie/Saigon"
+
+#: timezones.h:564
+msgid "Asia/Sakhalin"
+msgstr "Asie/Sachalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:566
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "Moskva+07 - ostrov Šakalin"
+
+#: timezones.h:567
+msgid "Asia/Samarkand"
+msgstr "Asie/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:569
+msgid "west Uzbekistan"
+msgstr "Západní Uzbekistán"
+
+#: timezones.h:570
+msgid "Asia/Seoul"
+msgstr "Asie/Soul"
+
+#: timezones.h:571
+msgid "Asia/Shanghai"
+msgstr "Asie/Šanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:573
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "Východní Čína - Peking, Guangdong, Šanghaj atp."
+
+#: timezones.h:574
+msgid "Asia/Singapore"
+msgstr "Asie/Singapore"
+
+#: timezones.h:575
+msgid "Asia/Taipei"
+msgstr "Asie/Taipei"
+
+#: timezones.h:576
+msgid "Asia/Tashkent"
+msgstr "Asie/Taškent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:578
+msgid "east Uzbekistan"
+msgstr "Východní Uzbekistán"
+
+#: timezones.h:579
+msgid "Asia/Tbilisi"
+msgstr "Asie/Tbilisi"
+
+#: timezones.h:580
+msgid "Asia/Tehran"
+msgstr "Asie/Teherán"
+
+#: timezones.h:581
+msgid "Asia/Tel_Aviv"
+msgstr "Asie/Tel_Aviv"
+
+#: timezones.h:582
+msgid "Asia/Thimbu"
+msgstr "Asie/Thimbu"
+
+#: timezones.h:583
+msgid "Asia/Thimphu"
+msgstr "Asie/Thimphu"
+
+#: timezones.h:584
+msgid "Asia/Tokyo"
+msgstr "Asie/Tokio"
+
+#: timezones.h:585
+msgid "Asia/Ujung_Pandang"
+msgstr "Asie/Ujung_Pandang"
+
+#: timezones.h:586
+msgid "Asia/Ulaanbaatar"
+msgstr "Asie/Ulaanbaatar"
+
+#: timezones.h:589
+msgid "Asia/Ulan_Bator"
+msgstr "Asie/Ulan_Bator"
+
+#: timezones.h:590
+msgid "Asia/Urumqi"
+msgstr "Asie/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:592
+msgid "most of Tibet & Xinjiang"
+msgstr "Většina Tibetu & Xinjiang"
+
+#: timezones.h:593
+msgid "Asia/Vientiane"
+msgstr "Asie/Vientiane"
+
+#: timezones.h:594
+msgid "Asia/Vladivostok"
+msgstr "Asie/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:596
+msgid "Moscow+07 - Amur River"
+msgstr "Moskva+07 - řeka Amur"
+
+#: timezones.h:597
+msgid "Asia/Yakutsk"
+msgstr "Asie/Jakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:599
+msgid "Moscow+06 - Lena River"
+msgstr "Moskva+06 - řeka Lena"
+
+#: timezones.h:600
+msgid "Asia/Yekaterinburg"
+msgstr "Asie/Jekatěrinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:602
+msgid "Moscow+02 - Urals"
+msgstr "Moskva+02 - Ural"
+
+#: timezones.h:603
+msgid "Asia/Yerevan"
+msgstr "Asie/Jerevan"
+
+#: timezones.h:604
+msgid "Atlantic/Azores"
+msgstr "Atlantik/Azory"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:606
+msgid "Azores"
+msgstr "Azory"
+
+#: timezones.h:607
+msgid "Atlantic/Bermuda"
+msgstr "Atlantik/Bermudy"
+
+#: timezones.h:608
+msgid "Atlantic/Canary"
+msgstr "Atlantik/Kanárské_ostrovy"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:610
+msgid "Canary Islands"
+msgstr "Kanárské ostrovy"
+
+#: timezones.h:611
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlantik/Capeverdské_ostrovy"
+
+#: timezones.h:612
+msgid "Atlantic/Faeroe"
+msgstr "Atlantik/Faerské_ostrovy"
+
+#: timezones.h:613
+msgid "Atlantic/Faroe"
+msgstr "Atlantik/Faroe"
+
+#: timezones.h:614
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlantik/Jan_Mayen"
+
+#: timezones.h:615
+msgid "Atlantic/Madeira"
+msgstr "Atlantik/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:617
+msgid "Madeira Islands"
+msgstr "Madeira (ostrovy)"
+
+#: timezones.h:618
+msgid "Atlantic/Reykjavik"
+msgstr "Atlantik/Rejkjavík"
+
+#: timezones.h:619
+msgid "Atlantic/South_Georgia"
+msgstr "Atlantik/South_Georgia"
+
+#: timezones.h:620
+msgid "Atlantic/Stanley"
+msgstr "Atlantik/Stanley"
+
+#: timezones.h:621
+msgid "Atlantic/St_Helena"
+msgstr "Atlantik/Svatá_Helena"
+
+#: timezones.h:622
+msgid "Australia/ACT"
+msgstr "Austrálie/ACT"
+
+#: timezones.h:623
+msgid "Australia/Adelaide"
+msgstr "Austrálie/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:625
+msgid "South Australia"
+msgstr "Jižní Austrálie"
+
+#: timezones.h:626
+msgid "Australia/Brisbane"
+msgstr "Austrálie/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:628
+msgid "Queensland - most locations"
+msgstr "Queensland - většina míst"
+
+#: timezones.h:629
+msgid "Australia/Broken_Hill"
+msgstr "Austrálie/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:631
+msgid "New South Wales - Yancowinna"
+msgstr "Nový Jižní Wales - Yancowinna"
+
+#: timezones.h:632
+msgid "Australia/Canberra"
+msgstr "Austrálie/Canberra"
+
+#: timezones.h:633
+msgid "Australia/Currie"
+msgstr "Austrálie/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:635
+msgid "Tasmania - King Island"
+msgstr "Tasmánie - King Island"
+
+#: timezones.h:636
+msgid "Australia/Darwin"
+msgstr "Austrálie/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:638
+msgid "Northern Territory"
+msgstr "Severní teritorium"
+
+#: timezones.h:639
+msgid "Australia/Eucla"
+msgstr "Austrálie/Eucla"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:641
+msgid "Western Australia - Eucla area"
+msgstr "Západní Austrálie - oblast Eucla"
+
+#: timezones.h:642
+msgid "Australia/Hobart"
+msgstr "Austrálie/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:644
+msgid "Tasmania - most locations"
+msgstr "Tasmánie - většina míst"
+
+#: timezones.h:645
+msgid "Australia/LHI"
+msgstr "Austrálie/LHI"
+
+#: timezones.h:646
+msgid "Australia/Lindeman"
+msgstr "Austrálie/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:648
+msgid "Queensland - Holiday Islands"
+msgstr "Queensland - Holiday Islands"
+
+#: timezones.h:649
+msgid "Australia/Lord_Howe"
+msgstr "Austrálie/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:651
+msgid "Lord Howe Island"
+msgstr "Lord Howe Island"
+
+#: timezones.h:652
+msgid "Australia/Melbourne"
+msgstr "Austrálie/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:654
+msgid "Victoria"
+msgstr "Victorie"
+
+#: timezones.h:655
+msgid "Australia/North"
+msgstr "Austrálie/Sever"
+
+#: timezones.h:656
+msgid "Australia/NSW"
+msgstr "Austrálie/NSW"
+
+#: timezones.h:657
+msgid "Australia/Perth"
+msgstr "Austrálie/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:659
+msgid "Western Australia - most locations"
+msgstr "Západní Austrálie - většina míst"
+
+#: timezones.h:660
+msgid "Australia/Queensland"
+msgstr "Austrálie/Queensland"
+
+#: timezones.h:661
+msgid "Australia/South"
+msgstr "Austrálie/Jih"
+
+#: timezones.h:662
+msgid "Australia/Sydney"
+msgstr "Austrálie/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:664
+msgid "New South Wales - most locations"
+msgstr "Nový Jižní Wales - většina míst"
+
+#: timezones.h:665
+msgid "Australia/Tasmania"
+msgstr "Austrálie/Tasmania"
+
+#: timezones.h:666
+msgid "Australia/Victoria"
+msgstr "Austrálie/Victoria"
+
+#: timezones.h:667
+msgid "Australia/West"
+msgstr "Austrálie/Západ"
+
+#: timezones.h:668
+msgid "Australia/Yancowinna"
+msgstr "Austrálie/Yancowinna"
+
+#: timezones.h:669
+msgid "Brazil/Acre"
+msgstr "Brazílie/Acre"
+
+#: timezones.h:670
+msgid "Brazil/DeNoronha"
+msgstr "Brazílie/DeNoronha"
+
+#: timezones.h:671
+msgid "Brazil/East"
+msgstr "Brazílie/Východ"
+
+#: timezones.h:672
+msgid "Brazil/West"
+msgstr "Brazílie/Západ"
+
+#: timezones.h:673
+msgid "Canada/Atlantic"
+msgstr "Kanada/Atlantik"
+
+#: timezones.h:674
+msgid "Canada/Central"
+msgstr "Kanada/Centralní"
+
+#: timezones.h:675
+msgid "Canada/Eastern"
+msgstr "Kanada/Východní"
+
+#: timezones.h:676
+msgid "Canada/East-Saskatchewan"
+msgstr "Kanada/Východní-Saskatchewan"
+
+#: timezones.h:677
+msgid "Canada/Mountain"
+msgstr "Kanada/Mountain"
+
+#: timezones.h:678
+msgid "Canada/Newfoundland"
+msgstr "Kanada/Newfoundland"
+
+#: timezones.h:679
+msgid "Canada/Pacific"
+msgstr "Kanada/Pacifik"
+
+#: timezones.h:680
+msgid "Canada/Saskatchewan"
+msgstr "Kanada/Saskatchewan"
+
+#: timezones.h:681
+msgid "Canada/Yukon"
+msgstr "Kanada/Jukon"
+
+#: timezones.h:682
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:683
+msgid "Chile/Continental"
+msgstr "Chile/Continental"
+
+#: timezones.h:684
+msgid "Chile/EasterIsland"
+msgstr "Chile/EasterIsland"
+
+#: timezones.h:685
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:686
+msgid "Cuba"
+msgstr "Kuba"
+
+#: timezones.h:687
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:688
+msgid "Egypt"
+msgstr "Egypt"
+
+#: timezones.h:689
+msgid "Eire"
+msgstr "Eire"
+
+#: timezones.h:690
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:691
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:692
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:693
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:694
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:695
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:696
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:697
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:698
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:699
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:700
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:701
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:702
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:703
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:704
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:705
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:706
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:707
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:708
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:709
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:710
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:711
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:712
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:713
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:714
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:715
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:716
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:717
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:718
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:719
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:720
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:721
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:722
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#: timezones.h:723
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:724
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:725
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:726
+msgid "Etc/Zulu"
+msgstr "Etc/Zulu"
+
+#: timezones.h:727
+msgid "Europe/Amsterdam"
+msgstr "Evropa/Amsterodam"
+
+#: timezones.h:728
+msgid "Europe/Andorra"
+msgstr "Evropa/Andora"
+
+#: timezones.h:729
+msgid "Europe/Athens"
+msgstr "Evropa/Athény"
+
+#: timezones.h:730
+msgid "Europe/Belfast"
+msgstr "Evropa/Belfast"
+
+#: timezones.h:731
+msgid "Europe/Belgrade"
+msgstr "Evropa/Bělehrad"
+
+#: timezones.h:732
+msgid "Europe/Berlin"
+msgstr "Evropa/Berlín"
+
+#: timezones.h:733
+msgid "Europe/Bratislava"
+msgstr "Evropa/Bratislava"
+
+#: timezones.h:734
+msgid "Europe/Brussels"
+msgstr "Evropa/Brusel"
+
+#: timezones.h:735
+msgid "Europe/Bucharest"
+msgstr "Evropa/Bukurešť"
+
+#: timezones.h:736
+msgid "Europe/Budapest"
+msgstr "Evropa/Budapešť"
+
+#: timezones.h:737
+msgid "Europe/Chisinau"
+msgstr "Evropa/Chisinau"
+
+#: timezones.h:738
+msgid "Europe/Copenhagen"
+msgstr "Evropa/Kodaň"
+
+#: timezones.h:739
+msgid "Europe/Dublin"
+msgstr "Evropa/Dublin"
+
+#: timezones.h:740
+msgid "Europe/Gibraltar"
+msgstr "Evropa/Gibraltar"
+
+#: timezones.h:741
+msgid "Europe/Guernsey"
+msgstr "Evropa/Guernsey"
+
+#: timezones.h:742
+msgid "Europe/Helsinki"
+msgstr "Evropa/Helsinky"
+
+#: timezones.h:743
+msgid "Europe/Isle_of_Man"
+msgstr "Evropa/Isle_of_Man"
+
+#: timezones.h:744
+msgid "Europe/Istanbul"
+msgstr "Evropa/Istanbul"
+
+#: timezones.h:745
+msgid "Europe/Jersey"
+msgstr "Evropa/Jersey"
+
+#: timezones.h:746
+msgid "Europe/Kaliningrad"
+msgstr "Evropa/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:748
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Moskva-01 - Kaliningrad"
+
+#: timezones.h:749
+msgid "Europe/Kiev"
+msgstr "Evropa/Kijev"
+
+#: timezones.h:752
+msgid "Europe/Lisbon"
+msgstr "Evropa/Lisabon"
+
+#: timezones.h:755
+msgid "Europe/Ljubljana"
+msgstr "Evropa/Ljubljana"
+
+#: timezones.h:756
+msgid "Europe/London"
+msgstr "Evropa/Londýn"
+
+#: timezones.h:757
+msgid "Europe/Luxembourg"
+msgstr "Evropa/Lucembursko"
+
+#: timezones.h:758
+msgid "Europe/Madrid"
+msgstr "Evropa/Madrid"
+
+#: timezones.h:761
+msgid "Europe/Malta"
+msgstr "Evropa/Malta"
+
+#: timezones.h:762
+msgid "Europe/Mariehamn"
+msgstr "Evropa/Mariehamn"
+
+#: timezones.h:763
+msgid "Europe/Minsk"
+msgstr "Evropa/Minsk"
+
+#: timezones.h:764
+msgid "Europe/Monaco"
+msgstr "Evropa/Monako"
+
+#: timezones.h:765
+msgid "Europe/Moscow"
+msgstr "Evropa/Moskva"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:767
+msgid "Moscow+00 - west Russia"
+msgstr "Moskva+00 - západní Rusko"
+
+#: timezones.h:768
+msgid "Europe/Nicosia"
+msgstr "Evropa/Nicosia"
+
+#: timezones.h:769
+msgid "Europe/Oslo"
+msgstr "Evropa/Oslo"
+
+#: timezones.h:770
+msgid "Europe/Paris"
+msgstr "Evropa/Paříž"
+
+#: timezones.h:771
+msgid "Europe/Podgorica"
+msgstr "Evropa/Podgorica"
+
+#: timezones.h:772
+msgid "Europe/Prague"
+msgstr "Evropa/Praha"
+
+#: timezones.h:773
+msgid "Europe/Riga"
+msgstr "Evropa/Riga"
+
+#: timezones.h:774
+msgid "Europe/Rome"
+msgstr "Evropa/Řím"
+
+#: timezones.h:775
+msgid "Europe/Samara"
+msgstr "Evropa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:777
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Moskva - Samara, Udmurtia"
+
+#: timezones.h:778
+msgid "Europe/San_Marino"
+msgstr "Evropa/San_Marino"
+
+#: timezones.h:779
+msgid "Europe/Sarajevo"
+msgstr "Evropa/Sarajevo"
+
+#: timezones.h:780
+msgid "Europe/Simferopol"
+msgstr "Evropa/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:782
+msgid "central Crimea"
+msgstr "Krym (centrální)"
+
+#: timezones.h:783
+msgid "Europe/Skopje"
+msgstr "Evropa/Skopje"
+
+#: timezones.h:784
+msgid "Europe/Sofia"
+msgstr "Evropa/Sofie"
+
+#: timezones.h:785
+msgid "Europe/Stockholm"
+msgstr "Evropa/Stockholm"
+
+#: timezones.h:786
+msgid "Europe/Tallinn"
+msgstr "Evropa/Talin"
+
+#: timezones.h:787
+msgid "Europe/Tirane"
+msgstr "Evropa/Tirana"
+
+#: timezones.h:788
+msgid "Europe/Tiraspol"
+msgstr "Evropa/Tiraspol"
+
+#: timezones.h:789
+msgid "Europe/Uzhgorod"
+msgstr "Evropa/Užhorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:791
+msgid "Ruthenia"
+msgstr "Bělorusko"
+
+#: timezones.h:792
+msgid "Europe/Vaduz"
+msgstr "Evropa/Vaduz"
+
+#: timezones.h:793
+msgid "Europe/Vatican"
+msgstr "Evropa/Vatikán"
+
+#: timezones.h:794
+msgid "Europe/Vienna"
+msgstr "Evropa/Vídeň"
+
+#: timezones.h:795
+msgid "Europe/Vilnius"
+msgstr "Evropa/Vilnius"
+
+#: timezones.h:796
+msgid "Europe/Volgograd"
+msgstr "Evropa/Volgograd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:798
+msgid "Moscow+00 - Caspian Sea"
+msgstr "Moskva+00 - Kaspické moře"
+
+#: timezones.h:799
+msgid "Europe/Warsaw"
+msgstr "Evropa/Varšava"
+
+#: timezones.h:800
+msgid "Europe/Zagreb"
+msgstr "Evropa/Záhřeb"
+
+#: timezones.h:801
+msgid "Europe/Zaporozhye"
+msgstr "Evropa/Zaporozhye"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:803
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "Záporoží, E Lugansk / Zaporizhia, E Luhansk"
+
+#: timezones.h:804
+msgid "Europe/Zurich"
+msgstr "Evropa/Curich"
+
+#: timezones.h:805
+msgid "Factory"
+msgstr "Tovární"
+
+#: timezones.h:806
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:807
+msgid "GB-Eire"
+msgstr "GB-Eire"
+
+#: timezones.h:808
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:809
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:810
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:811
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:812
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:813
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#: timezones.h:814
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:815
+msgid "Iceland"
+msgstr "Island"
+
+#: timezones.h:816
+msgid "Indian/Antananarivo"
+msgstr "Indie/Antananarivo"
+
+#: timezones.h:817
+msgid "Indian/Chagos"
+msgstr "Indie/Chagos"
+
+#: timezones.h:818
+msgid "Indian/Christmas"
+msgstr "Indie/Christmas"
+
+#: timezones.h:819
+msgid "Indian/Cocos"
+msgstr "Indie/Cocos"
+
+#: timezones.h:820
+msgid "Indian/Comoro"
+msgstr "Indie/Comoro"
+
+#: timezones.h:821
+msgid "Indian/Kerguelen"
+msgstr "Indie/Kerguelen"
+
+#: timezones.h:822
+msgid "Indian/Mahe"
+msgstr "Indie/Mahe"
+
+#: timezones.h:823
+msgid "Indian/Maldives"
+msgstr "Indie/Maldives"
+
+#: timezones.h:824
+msgid "Indian/Mauritius"
+msgstr "Indie/Mauritius"
+
+#: timezones.h:825
+msgid "Indian/Mayotte"
+msgstr "Indie/Mayotte"
+
+#: timezones.h:826
+msgid "Indian/Reunion"
+msgstr "Indie/Reunion"
+
+#: timezones.h:827
+msgid "Iran"
+msgstr "Írán"
+
+#: timezones.h:828
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:829
+msgid "Israel"
+msgstr "Izrael"
+
+#: timezones.h:830
+msgid "Jamaica"
+msgstr "Jamajka"
+
+#: timezones.h:831
+msgid "Japan"
+msgstr "Japonsko"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:832
+#: timezones.h:885
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:833
+msgid "Libya"
+msgstr "Libye"
+
+#: timezones.h:834
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:835
+msgid "Mexico/BajaNorte"
+msgstr "Mexiko/BajaNorte"
+
+#: timezones.h:836
+msgid "Mexico/BajaSur"
+msgstr "Mexiko/BajaSur"
+
+#: timezones.h:837
+msgid "Mexico/General"
+msgstr "Mexiko/General"
+
+#: timezones.h:838
+msgid "Mideast/Riyadh87"
+msgstr "Střední_východ/Rijád87"
+
+#: timezones.h:839
+msgid "Mideast/Riyadh88"
+msgstr "Střední_východ/Rijád88"
+
+#: timezones.h:840
+msgid "Mideast/Riyadh89"
+msgstr "Střední_východ/Rijád89"
+
+#: timezones.h:841
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:842
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:843
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:844
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:845
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:846
+msgid "Pacific/Apia"
+msgstr "Pacifik/Apia"
+
+#: timezones.h:847
+msgid "Pacific/Auckland"
+msgstr "Pacifik/Auckland"
+
+#: timezones.h:850
+msgid "Pacific/Chatham"
+msgstr "Pacifik/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:852
+msgid "Chatham Islands"
+msgstr "Chathamské ostrovy"
+
+#: timezones.h:853
+msgid "Pacific/Easter"
+msgstr "Pacifik/Velikonoční"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:855
+msgid "Easter Island & Sala y Gomez"
+msgstr "Východní ostrovy & Sala y Gomez"
+
+#: timezones.h:856
+msgid "Pacific/Efate"
+msgstr "Pacifik/Efate"
+
+#: timezones.h:857
+msgid "Pacific/Enderbury"
+msgstr "Pacifik/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:859
+msgid "Phoenix Islands"
+msgstr "Phoenix Islands"
+
+#: timezones.h:860
+msgid "Pacific/Fakaofo"
+msgstr "Pacifik/Fakaofo"
+
+#: timezones.h:861
+msgid "Pacific/Fiji"
+msgstr "Pacifik/Fidži"
+
+#: timezones.h:862
+msgid "Pacific/Funafuti"
+msgstr "Pacifik/Funafuti"
+
+#: timezones.h:863
+msgid "Pacific/Galapagos"
+msgstr "Pacifik/Galapágy"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:865
+msgid "Galapagos Islands"
+msgstr "Galapágy (ostrovy)"
+
+#: timezones.h:866
+msgid "Pacific/Gambier"
+msgstr "Pacifik/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:868
+msgid "Gambier Islands"
+msgstr "Gambier Islands"
+
+#: timezones.h:869
+msgid "Pacific/Guadalcanal"
+msgstr "Pacifik/Guadalcanal"
+
+#: timezones.h:870
+msgid "Pacific/Guam"
+msgstr "Pacifik/Guam"
+
+#: timezones.h:871
+msgid "Pacific/Honolulu"
+msgstr "Pacifik/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:873
+msgid "Hawaii"
+msgstr "Havaj"
+
+#: timezones.h:874
+msgid "Pacific/Johnston"
+msgstr "Pacifik/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:876
+msgid "Johnston Atoll"
+msgstr "Johnston Atoll"
+
+#: timezones.h:877
+msgid "Pacific/Kiritimati"
+msgstr "Pacifik/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:879
+msgid "Line Islands"
+msgstr "Line Islands"
+
+#: timezones.h:880
+msgid "Pacific/Kosrae"
+msgstr "Pacifik/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:882
+msgid "Kosrae"
+msgstr "Kosrae"
+
+#: timezones.h:883
+msgid "Pacific/Kwajalein"
+msgstr "Pacifik/Kwajalein"
+
+#: timezones.h:886
+msgid "Pacific/Majuro"
+msgstr "Pacifik/Majuro"
+
+#: timezones.h:889
+msgid "Pacific/Marquesas"
+msgstr "Pacifik/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:891
+msgid "Marquesas Islands"
+msgstr "Markézské ostrovy"
+
+#: timezones.h:892
+msgid "Pacific/Midway"
+msgstr "Pacifik/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:894
+msgid "Midway Islands"
+msgstr "Midway (ostrovy)"
+
+#: timezones.h:895
+msgid "Pacific/Nauru"
+msgstr "Pacifik/Nauru"
+
+#: timezones.h:896
+msgid "Pacific/Niue"
+msgstr "Pacifik/Niue"
+
+#: timezones.h:897
+msgid "Pacific/Norfolk"
+msgstr "Pacifik/Norfolk"
+
+#: timezones.h:898
+msgid "Pacific/Noumea"
+msgstr "Pacifik/Noumea"
+
+#: timezones.h:899
+msgid "Pacific/Pago_Pago"
+msgstr "Pacifik/Pago_Pago"
+
+#: timezones.h:900
+msgid "Pacific/Palau"
+msgstr "Pacifik/Palau"
+
+#: timezones.h:901
+msgid "Pacific/Pitcairn"
+msgstr "Pacifik/Pitcairn"
+
+#: timezones.h:902
+msgid "Pacific/Ponape"
+msgstr "Pacifik/Ponape"
+
+#. comment for time zone Pacific/Ponape
+#: timezones.h:904
+msgid "Ponape (Pohnpei)"
+msgstr "Ponape (Pohnpei)"
+
+#: timezones.h:905
+msgid "Pacific/Port_Moresby"
+msgstr "Pacifik/Port_Moresby"
+
+#: timezones.h:906
+msgid "Pacific/Rarotonga"
+msgstr "Pacifik/Rarotonga"
+
+#: timezones.h:907
+msgid "Pacific/Saipan"
+msgstr "Pacifik/Saipan"
+
+#: timezones.h:908
+msgid "Pacific/Samoa"
+msgstr "Pacifik/Samoa"
+
+#: timezones.h:909
+msgid "Pacific/Tahiti"
+msgstr "Pacifik/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:911
+msgid "Society Islands"
+msgstr "Společenské ostrovy"
+
+#: timezones.h:912
+msgid "Pacific/Tarawa"
+msgstr "Pacifik/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:914
+msgid "Gilbert Islands"
+msgstr "Gilbertovy ostrovy"
+
+#: timezones.h:915
+msgid "Pacific/Tongatapu"
+msgstr "Pacifik/Tongatapu"
+
+#: timezones.h:916
+msgid "Pacific/Truk"
+msgstr "Pacifik/Truk"
+
+#. comment for time zone Pacific/Truk
+#: timezones.h:918
+msgid "Truk (Chuuk) and Yap"
+msgstr "Truk (Chuuk) a Yap"
+
+#: timezones.h:919
+msgid "Pacific/Wake"
+msgstr "Pacifik/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:921
+msgid "Wake Island"
+msgstr "Wake Island"
+
+#: timezones.h:922
+msgid "Pacific/Wallis"
+msgstr "Pacifik/Wallis"
+
+#: timezones.h:923
+msgid "Pacific/Yap"
+msgstr "Pacifik/Yap"
+
+#: timezones.h:924
+msgid "Poland"
+msgstr "Polsko"
+
+#: timezones.h:925
+msgid "Portugal"
+msgstr "Portugalsko"
+
+#: timezones.h:926
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:927
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:928
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:929
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:930
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:931
+msgid "Singapore"
+msgstr "Singapore"
+
+#: timezones.h:932
+msgid "Turkey"
+msgstr "Turecko"
+
+#: timezones.h:933
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:934
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:935
+msgid "US/Alaska"
+msgstr "US/Aljaška"
+
+#: timezones.h:936
+msgid "US/Aleutian"
+msgstr "US/Aleutian"
+
+#: timezones.h:937
+msgid "US/Arizona"
+msgstr "US/Arizona"
+
+#: timezones.h:938
+msgid "US/Central"
+msgstr "US/Centrální"
+
+#: timezones.h:939
+msgid "US/Eastern"
+msgstr "US/Východní"
+
+#: timezones.h:940
+msgid "US/East-Indiana"
+msgstr "US/Východní-Indiana"
+
+#: timezones.h:941
+msgid "US/Hawaii"
+msgstr "US/Hawaj"
+
+#: timezones.h:942
+msgid "US/Indiana-Starke"
+msgstr "US/Indiana-Starke"
+
+#: timezones.h:943
+msgid "US/Michigan"
+msgstr "US/Michigan"
+
+#: timezones.h:944
+msgid "US/Mountain"
+msgstr "US/Mountain"
+
+#: timezones.h:945
+msgid "US/Pacific"
+msgstr "US/Pacifik"
+
+#: timezones.h:946
+msgid "US/Samoa"
+msgstr "US/Samoa"
+
+#: timezones.h:947
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:948
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:949
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:950
+msgid "Zulu"
+msgstr "Zulu"
+
diff --git a/panels/datetime/po-timezones/cy.po b/panels/datetime/po-timezones/cy.po
new file mode 100644
index 0000000..052ced2
--- /dev/null
+++ b/panels/datetime/po-timezones/cy.po
@@ -0,0 +1,3333 @@
+# translation of timezones.pot to Cymraeg
+# This file is distributed under the same license as the
+# system-config-date package.
+# Copyright (C) 2004 Alan Cox
+# Translation by Owain Green <owaing@oceanfree.net>, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones.cy\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2004-02-24 12:32+0000\n"
+"Last-Translator: Owain Green <owaing@oceanfree.net>\n"
+"Language-Team: Cymraeg <Cy@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.0.2\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Affrica/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Affrica/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Affrica/Addis_Ababa"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Affrica/Algiers"
+
+#: timezones.h:5
+#, fuzzy
+msgid "Africa/Asmara"
+msgstr "Affrica/Asmera"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Affrica/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Affrica/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Affrica/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Affrica/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Affrica/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Affrica/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Affrica/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Affrica/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Affrica/Cairo"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Affrica/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Affrica/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Affrica/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Affrica/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Affrica/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Affrica/Djibouti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Affrica/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Affrica/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Affrica/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Affrica/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Affrica/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Affrica/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Affrica/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Affrica/Khartoum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Affrica/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Affrica/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Affrica/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Affrica/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Affrica/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Affrica/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Affrica/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Affrica/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Affrica/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Affrica/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Affrica/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Affrica/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Affrica/Mogadishu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Affrica/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Affrica/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Affrica/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Affrica/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Affrica/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Affrica/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Affrica/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Affrica/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Affrica/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Affrica/Tripoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Affrica/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Affrica/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "America/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+#, fuzzy
+msgid "Aleutian Islands"
+msgstr "Awstralia/Queensland"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "America/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+#, fuzzy
+msgid "Alaska Time"
+msgstr "UD/Alasca"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "America/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "America/Antigwa"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "America/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "America/Ariannin/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "America/Ariannin/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "America/Ariannin/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "America/Ariannin/Cordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "America/Ariannin/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "America/Ariannin/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "America/Ariannin/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "America/Ariannin/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+#, fuzzy
+msgid "America/Argentina/Salta"
+msgstr "America/Ariannin/San_Juan"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "America/Ariannin/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+#, fuzzy
+msgid "America/Argentina/San_Luis"
+msgstr "America/Ariannin/San_Juan"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "America/Ariannin/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "America/Ariannin/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "America/Arwba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "America/Asuncion"
+
+#: timezones.h:110
+#, fuzzy
+msgid "America/Atikokan"
+msgstr "America/Atka"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "America/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "America/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "America/Bahia"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "America/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "America/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "America/Belîs"
+
+#: timezones.h:125
+#, fuzzy
+msgid "America/Blanc-Sablon"
+msgstr "America/Cancwn"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "America/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "America/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "America/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "America/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "America/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "America/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "America/Cancwn"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "America/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "America/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "America/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "America/Cayman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "America/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+#, fuzzy
+msgid "Central Time"
+msgstr "UD/Canolbarth"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "America/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "America/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "America/Cordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "America/Costa_Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "America/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "America/Curacao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "America/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "America/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "America/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "America/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+#, fuzzy
+msgid "Mountain Time"
+msgstr "UD/Mynyddoedd"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "America/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "America/Dominica"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "America/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "America/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "America/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "America/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "America/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "America/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "America/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "America/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "America/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "America/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "America/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "America/Gwadelwp"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "America/Gwatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "America/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "America/Giana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "America/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "America/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "America/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "America/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "America/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "America/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+#, fuzzy
+msgid "America/Indiana/Petersburg"
+msgstr "America/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "America/Indianapolis"
+
+#: timezones.h:227
+#, fuzzy
+msgid "America/Indiana/Tell_City"
+msgstr "America/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "America/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+#, fuzzy
+msgid "America/Indiana/Vincennes"
+msgstr "America/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+#, fuzzy
+msgid "America/Indiana/Winamac"
+msgstr "America/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "America/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "America/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "America/Jamaica"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "America/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "America/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "America/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+#, fuzzy
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "America/Kentucky/Louisville"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "America/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "America/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "America/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "America/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "America/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+#, fuzzy
+msgid "Pacific Time"
+msgstr "Môr_tawel/Niue"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "America/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "America/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "America/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "America/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+#, fuzzy
+msgid "America/Marigot"
+msgstr "America/Maceio"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "America/Martinique"
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "America/Manaus"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "America/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "America/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "America/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "America/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "America/Dinas_Mecsico"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "America/Miquelon"
+
+#: timezones.h:289
+#, fuzzy
+msgid "America/Moncton"
+msgstr "America/Edmonton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "America/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "America/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "America/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "America/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "America/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "America/Efrog_Newydd"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+#, fuzzy
+msgid "Eastern Time"
+msgstr "UD/Dwyreiniol"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "America/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "America/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "America/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+#, fuzzy
+msgid "Atlantic islands"
+msgstr "Yr_Iwerydd/Ynysoedd_Dedwydd"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "America/Gogledd_Dakota/Center"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+#, fuzzy
+msgid "America/North_Dakota/New_Salem"
+msgstr "America/Gogledd_Dakota/Center"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "America/Managua"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "America/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "America/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "America/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "America/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "America/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "America/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "America/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "America/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "America/Puerto_Rico"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "America/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "America/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "America/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "America/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+#, fuzzy
+msgid "America/Resolute"
+msgstr "America/Belem"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "America/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "America/Rosario"
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "America/Santiago"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+#, fuzzy
+msgid "America/Santarem"
+msgstr "America/Santiago"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "America/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "America/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "America/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "America/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "America/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+#, fuzzy
+msgid "America/St_Barthelemy"
+msgstr "America/Belem"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "America/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "America/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "America/St_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "America/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "America/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "America/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "America/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "America/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "America/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "America/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "America/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "America/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "America/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "America/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "America/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "America/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "America/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "America/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antarctica/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antarctica/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antarctica/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+#, fuzzy
+msgid "Antarctica/Macquarie"
+msgstr "Antarctica/McMurdo"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antarctica/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antarctica/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antarctica/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antarctica/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antarctica/Pegwn_y_De"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antarctica/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antarctica/Fostoc"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Arctic/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Asia/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Asia/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Asia/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Asia/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Asia/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Asia/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Asia/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Asia/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Asia/Baghdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Asia/Bahrain"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Asia/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Asia/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Asia/Beirut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Asia/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Asia/Brwnei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Asia/Calcutta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Asia/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Asia/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Asia/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Asia/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Asia/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Asia/Damascus"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Asia/Dhaka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Asia/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Asia/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Asia/Dushanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Asia/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Asia/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+#, fuzzy
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Asia/Chongqing"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Asia/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Asia/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Asia/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Asia/Istanbul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Asia/Jakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Asia/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Asia/Jerwsalem"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Asia/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Asia/Kamchatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Asia/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Asia/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+#, fuzzy
+msgid "Asia/Kathmandu"
+msgstr "Asia/Katmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Asia/Katmandu"
+
+#: timezones.h:518
+#, fuzzy
+msgid "Asia/Kolkata"
+msgstr "Asia/Jakarta"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Asia/Krasnoyarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Asia/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Asia/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Asia/Coweit"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Asia/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Asia/Macau"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Asia/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Asia/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Asia/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Asia/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Asia/Nicosia"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "Asia/Irkutsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Asia/Nofosibirsc"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Asia/Nofosibirsc"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+#, fuzzy
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Asia/Nofosibirsc"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Asia/Omsc"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Asia/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Asia/Phnom_Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Asia/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Asia/Pyongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Asia/Qatar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Asia/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Asia/Rangoon"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Asia/Riyadh"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Asia/Riyadh87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Asia/Riyadh88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Asia/Riyadh89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Asia/Saigon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Asia/Sachalîn"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Asia/Samarcand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Asia/Seoul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Asia/Sianghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Asia/Singapôr"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Asia/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Asia/Tashkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Asia/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Asia/Tehran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Asia/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Asia/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Asia/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Asia/Tokyo"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Asia/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Asia/Ulaanbaatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Asia/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Asia/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Asia/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Asia/Fladifostoc"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Asia/Yacwtsc"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Asia/Yecaterinbwrg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Asia/Ierefan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Yr_Iwerydd/Azores"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Yr_Iwerydd/Bermwda"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Yr_Iwerydd/Ynysoedd_Dedwydd"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Yr_Iwerydd/Cape_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Yr_Iwerydd/Ffaröe"
+
+#: timezones.h:616
+#, fuzzy
+msgid "Atlantic/Faroe"
+msgstr "Yr_Iwerydd/Ffaröe"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Yr_Iwerydd/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Yr_Iwerydd/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Yr_Iwerydd/Reykjavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Yr_Iwerydd/De_Georgia"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Yr_Iwerydd/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Yr_Iwerydd/St_Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Awstralia/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Awstralia/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+#, fuzzy
+msgid "South Australia"
+msgstr "Awstralia/ACT"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Awstralia/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Awstralia/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Awstralia/Canberra"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Awstralia/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Awstralia/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+#, fuzzy
+msgid "Australia/Eucla"
+msgstr "Awstralia/Queensland"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+#, fuzzy
+msgid "Western Australia - Eucla area"
+msgstr "Awstralia/Queensland"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Awstralia/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Awstralia/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Awstralia/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Awstralia/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Awstralia/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+#, fuzzy
+msgid "Victoria"
+msgstr "Awstralia/Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Awstralia/Gogledd"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Awstralia/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Awstralia/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Awstralia/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Awstralia/De"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Awstralia/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Awstralia/Tasmania"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Awstralia/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Awstralia/Gorllewin"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Awstralia/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brasil/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brasil/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brasil/Dwyrain"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brasil/Gorllewin"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Canada/Iwerydd"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Canada/Canolbarth"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Canada/Dwyreiniol"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Canada/Dwyrain-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Canada/Mynyddoedd"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Canada/Y_Tir_Newydd"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Canada/Môr_Tawel"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Canada/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Canada/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Chile/Cyfandirol"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Chile/Ynys_y_Pasg"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Ciwba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Yr Aifft"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Iwerddon"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Ayb/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Ayb/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Ayb/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Ayb/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Ayb/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Ayb/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Ayb/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Ayb/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Ayb/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Ayb/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Ayb/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Ayb/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Ayb/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Ayb/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Ayb/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Ayb/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Ayb/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Ayb/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Ayb/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Ayb/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Ayb/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Ayb/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Ayb/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Ayb/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Ayb/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Ayb/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Ayb/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Ayb/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Ayb/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Ayb/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Ayb/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Ayb/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Ayb/Byd-eang"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Ayb/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Ayb/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Ewrop/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Ewrop/Andorra"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Ewrop/Athen"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Ewrop/Belffast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Ewrop/Belgrade"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Ewrop/Berlin"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Ewrop/Bratislafa"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Ewrop/Brwsel"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Ewrop/Bwcarest"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Ewrop/Bwdapest"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Ewrop/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Ewrop/Copenhagen"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Ewrop/Dulyn"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Ewrop/Gibraltar"
+
+#: timezones.h:744
+#, fuzzy
+msgid "Europe/Guernsey"
+msgstr "Ewrop/Athen"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Ewrop/Helsinci"
+
+#: timezones.h:746
+#, fuzzy
+msgid "Europe/Isle_of_Man"
+msgstr "Ewrop/Oslo"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Ewrop/Istanbwl"
+
+#: timezones.h:748
+#, fuzzy
+msgid "Europe/Jersey"
+msgstr "Ewrop/Paris"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Ewrop/Caliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Ewrop/Cïef"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Ewrop/Lisbon"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Ewrop/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Ewrop/Llundain"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Ewrop/Lwcsembwrg"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Ewrop/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Ewrop/Malta"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Ewrop/Mariehamn"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Ewrop/Minsc"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Ewrop/Monaco"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Ewrop/Mosgo"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Ewrop/Nicosia"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Ewrop/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Ewrop/Paris"
+
+#: timezones.h:774
+#, fuzzy
+msgid "Europe/Podgorica"
+msgstr "Ewrop/Andorra"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Ewrop/Prâg"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Ewrop/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Ewrop/Rhufain"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Ewrop/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Ewrop/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Ewrop/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Ewrop/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Ewrop/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Ewrop/Soffia"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Ewrop/Stockholm"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Ewrop/Tallinn"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Ewrop/Tirane"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Ewrop/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Ewrop/Uzhgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Ewrop/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Ewrop/Y Fatican"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Ewrop/Fienna"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Ewrop/Filniws"
+
+#: timezones.h:799
+#, fuzzy
+msgid "Europe/Volgograd"
+msgstr "Ewrop/Belgrade"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Ewrop/Warsaw"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Ewrop/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Ewrop/Zaporozhye"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Ewrop/Zurich"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Ffatri"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Eire"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Ynys yr Iâ"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Cefnfor_yr_India/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Cefnfor_yr_India/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Cefnfor_yr_India/Ynys_y_Nadolig"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Cefnfor_yr_India/Cocos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Cefnfor_yr_India/Comoro"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Cefnfor_yr_India/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Cefnfor_yr_India/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Cefnfor_yr_India/Maldîfau"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Cefnfor_yr_India/Mawrisiws"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Cefnfor_yr_India/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Cefnfor_yr_India/Reunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Iran"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Israel"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamaica"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Siapan"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Libya"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Mecsico/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Mecsico/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Mecsico/Cyffredinol"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Dwyrain_canol/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Dwyrain_canol/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Dwyrain_canol/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Môr_tawel/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Môr_tawel/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Môr_tawel/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+#, fuzzy
+msgid "Chatham Islands"
+msgstr "Chile/Ynys_y_Pasg"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "Môr_tawel/Truk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+#, fuzzy
+msgid "Pacific/Easter"
+msgstr "Môr_tawel/Dwyrainer"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Môr_tawel/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Môr_tawel/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Môr_tawel/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Môr_tawel/Fiji"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Môr_tawel/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Môr_tawel/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Môr_tawel/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Môr_tawel/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Môr_tawel/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Môr_tawel/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+#, fuzzy
+msgid "Hawaii"
+msgstr "UD/Hawaii"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Môr_tawel/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Môr_tawel/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Môr_tawel/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+#, fuzzy
+msgid "Kosrae"
+msgstr "Israel"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Môr_tawel/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Môr_tawel/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Môr_tawel/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Môr_tawel/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Môr_tawel/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Môr_tawel/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Môr_tawel/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Môr_tawel/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Môr_tawel/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Môr_tawel/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Môr_tawel/Pitcairn"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "Môr_tawel/Ponape"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Môr_tawel/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Môr_tawel/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Môr_tawel/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Môr_tawel/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Môr_tawel/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Môr_tawel/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Môr_tawel/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+#, fuzzy
+msgid "Gilbert Islands"
+msgstr "Chile/Ynys_y_Pasg"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Môr_tawel/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Môr_tawel/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Môr_tawel/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Môr_tawel/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Môr_tawel/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Gwlad_Pwyl"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portwgal"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapore"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Twrci"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Byd-eang"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "UD/Alasca"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "UD/Alewtaidd"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "UD/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "UD/Canolbarth"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "UD/Dwyreiniol"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "UD/Dwyrain-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "UD/Hawaii"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "UD/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "UD/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "UD/Mynyddoedd"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "UD/Môr_Tawel"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "UD/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
+
+#, fuzzy
+#~ msgid "US/Pacific-New"
+#~ msgstr "UD/Môr_Tawel"
+
+#~ msgid "SystemV/AST4"
+#~ msgstr "SystemV/AST4"
+
+#~ msgid "SystemV/AST4ADT"
+#~ msgstr "SystemV/AST4ADT"
+
+#~ msgid "SystemV/CST6"
+#~ msgstr "SystemV/CST6"
+
+#~ msgid "SystemV/CST6CDT"
+#~ msgstr "SystemV/CST6CDT"
+
+#~ msgid "SystemV/EST5"
+#~ msgstr "SystemV/EST5"
+
+#~ msgid "SystemV/EST5EDT"
+#~ msgstr "SystemV/EST5EDT"
+
+#~ msgid "SystemV/HST10"
+#~ msgstr "SystemV/HST10"
+
+#~ msgid "SystemV/MST7"
+#~ msgstr "SystemV/MST7"
+
+#~ msgid "SystemV/MST7MDT"
+#~ msgstr "SystemV/MST7MDT"
+
+#~ msgid "SystemV/PST8"
+#~ msgstr "SystemV/PST8"
+
+#~ msgid "SystemV/PST8PDT"
+#~ msgstr "SystemV/PST8PDT"
+
+#~ msgid "SystemV/YST9"
+#~ msgstr "SystemV/YST9"
+
+#~ msgid "SystemV/YST9YDT"
+#~ msgstr "SystemV/YST9YDT"
diff --git a/panels/datetime/po-timezones/da.po b/panels/datetime/po-timezones/da.po
new file mode 100644
index 0000000..fda5574
--- /dev/null
+++ b/panels/datetime/po-timezones/da.po
@@ -0,0 +1,3250 @@
+# Danish translation of system-config-date
+# Claus Hindsgaul <claus_h@image.dk>, 2001.
+# Keld Simonsen <keld@dkuug.dk>, 2002.
+# Keld Simonsen <keld@rap.dk>, 2006, 2007.
+# Kris Thomsen <lakristho@gmail.com>, 2009, 2010.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: system-config-date\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-04-27 17:56+0200\n"
+"Last-Translator: Kris Thomsen <lakristho@gmail.com>\n"
+"Language-Team: Danish <dansk@dansk-gruppen.dk>\n"
+"Language: da\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Afrika/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Afrika/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Afrika/Addis_Ababa"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Afrika/Algier"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "Afrika/Asmara"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Afrika/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Afrika/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Afrika/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Afrika/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Afrika/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Afrika/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Afrika/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Afrika/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Afrika/Kairo"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Afrika/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Afrika/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "Ceuta & Melilla"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Afrika/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Afrika/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Afrika/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Afrika/Djibouti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Afrika/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Afrika/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Afrika/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Afrika/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Afrika/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Afrika/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Afrika/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Afrika/Khartoum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Afrika/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Afrika/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "vest Demokratiske republik Congo"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Afrika/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Afrika/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Afrika/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Afrika/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Afrika/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "øst Demokratiske republik Congo"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Afrika/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Afrika/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Afrika/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Afrika/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Afrika/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Afrika/Mogadishu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Afrika/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Afrika/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Afrika/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Afrika/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Afrika/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Afrika/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Afrika/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Afrika/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Afrika/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Afrika/Tripoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Afrika/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Afrika/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Amerika/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Aleutian Øer"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Amerika/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Alaska-tid"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Amerika/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Amerika/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Amerika/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "Tocantins"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Amerika/Argentina/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Buenos Aires (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Amerika/Argentina/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "Catamarca (CT), Chubut (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Amerika/Argentina/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Amerika/Argentina/Cordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "fleste placeringer (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Amerika/Argentina/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Jujuy (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Amerika/Argentina/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "La Rioja (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Amerika/Argentina/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "Mendoza (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Amerika/Argentina/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "Santa Cruz (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "Amerika/Argentina/Salta"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Amerika/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "San Juan (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "Amerika/Argentina/San_Luis"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "San Luis (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Amerika/Argentina/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "Tucuman (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Amerika/Argentina/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "Tierra del Fuego (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Amerika/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Amerika/Asuncion"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Amerika/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "Øststandardtid - Atikokan, Ontario og Southampton I, Nunavut"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Amerika/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Amerika/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "Bahia"
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "Amerika/Bahia"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Amerika/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Amerika/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "Amapa, E Para"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Amerika/Belize"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "Amerika/Blanc-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "Atlantisk standardtid - Quebec - Nedre Nord Shore"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Amerika/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "Roraima"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Amerika/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Amerika/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "Bjergtid - syd Idaho & øst Oregon"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Amerika/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Amerika/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "Bjergtid - vest Nunavut"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "Amerika/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "Mato Grosso do Sul"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Amerika/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "Centraltid - Quintana Roo"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Amerika/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Amerika/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Amerika/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Amerika/Cayman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Amerika/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "Central-tid"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Amerika/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "Mexikansk bjertid - Chihuahua væk fra US-grænse"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "Amerika/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Amerika/Cordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Amerika/Costa_Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Amerika/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "Mato Grosso"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Amerika/Curacao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Amerika/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "østkyst, nord for Scoresbysund"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Amerika/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "Stillehavstid - nord Yukon"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Amerika/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr "Bjerg-standardtid - Dawson Creek & Fort Saint John, Britisk Columbia"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Amerika/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "Bjergtid"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Amerika/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "Østtid - Michigan - fleste placeringer"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Amerika/Dominica"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Amerika/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "Bjergtid - Alberta, øst Britisk Columbia & vest Saskatchewan"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Amerika/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "W Amazonas"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Amerika/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Amerika/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Amerika/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "NE Brazilien (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Amerika/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Amerika/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+"Atlanterhavstid - Nova Scotia - steder, som ikke observerede DST 1966-1971"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Amerika/Godthåb"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "fleste placeringer"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Amerika/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "Atlanterhavstid - Labrador - fleste placeringer"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Amerika/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Amerika/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Amerika/Guadeloupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Amerika/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Amerika/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "hovedland"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Amerika/Guyana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Amerika/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "Atlanterhavstid - Nova Scotia (fleste steder), PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Amerika/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Amerika/Hermosillio"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "Bjergstandardtid - Sonora"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Amerika/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "Østtid - Indiana - fleste placeringer"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Amerika/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "Centraltid - Indiana - Starke County"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Amerika/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "Østtid - Indiana - Crawford County"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "Amerika/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "Østtid - Indiana - Pike County"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Amerika/Indianapolis"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "Amerika/Indiana/Tell_City"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "Centraltid - Indiana - Perry County"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "Østtid - Indiana - Switzerland County"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "Amerika/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "Østtid - Indiana - Daviess, Dubois, Knox & Martin Counties"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "Amerika/Indiana/Winamac"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "Østtid - Indiana - Pulaski County"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Amerika/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "Bjergtid - vest Nordvest Territorier"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Amerika/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "Østtid - øst Nunavut - fleste placeringer"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Amerika/Jamaica"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Amerika/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Amerika/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "Alaska-tid - Alaska panhandle"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Amerika/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Østtid - Kentucky - Louisville-området"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Amerika/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "Østtid - Kentucky - Wayne County"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Amerika/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Amerika/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Amerika/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Amerika/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "Stillehavstid"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Amerika/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Amerika/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "Alagoas, Sergipe"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Amerika/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Amerika/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "E Amazonas"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "Amerika/Marigot"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Amerika/Martinique"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "Amerika/Matamoros"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+"US Centraltid - Coahuila, Durango, Nuevo Leon, Tamaulipas nær US-grænse"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Amerika/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "Bjergtid - S Baja, Nayarit, Sinaloa"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Amerika/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Amerika/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "Centraltid - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Amerika/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "Centraltid - Campeche, Yucatan"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Amerika/Mexico_By"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "Centraltid - fleste placeringer"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Amerika/Miquelon"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "Amerika/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "Atlanterhavstid - New Brunswick"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Amerika/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+"Mexikansk centraltid - Coahuila, Durango, Nuevo Leon, Tamaulipas væk fra US-"
+"grænse"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Amerika/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Amerika/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "Østtid - Quebec - fleste placeringer"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Amerika/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Amerika/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Amerika/New_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "Østtid"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Amerika/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr "Østtid - Ontario & Quebec - steder som ikke observerer DST 1967-1973"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Amerika/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "Alaska-tid - vest Alaska"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Amerika/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "Atlanterhavsøer"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Amerika/North_Dakota/Center"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "Centraltid - Nord Dakota - Oliver County"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "Amerika/North_Dakota/New_Salem"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "Centraltid - Nord Dakota - Morton County (undtagen Mandan-området)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "Amerika/Ojinaga"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "US bjertid - Chihuahua nær US-grænse"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Amerika/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Amerika/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "Østtid - Pangnirtung, Nunavut"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Amerika/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Amerika/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "Bjergstandardtid - Arizona"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Amerika/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Amerika/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Amerika/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Amerika/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "Rondonia"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Amerika/Puerto_Rico"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Amerika/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "Centraltid - Rainy River & Fort Frances, Ontario"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Amerika/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "Centraltid - centrak Nunavut"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Amerika/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "Pernambuco"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Amerika/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "Centralstandardtid - Saskatchewan - fleste placeringer"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "Amerika/Resolute"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "Øststandardtid - Resolute, Nunavut"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Amerika/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "Acre"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Amerika/Rosario"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "Amerika/Santa_Isabel"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "Mexikansk stillehavstid - Baja Californien væk fra US-grænse"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "Amerika/Santarem"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "W Para"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Amerika/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Amerika/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Amerika/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "S & SE Brazilien (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Amerika/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "Scoresbysund / Ittoqqortoormiit"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Amerika/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "Bjertid - Navajo"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "Amerika/St_Barthelemy"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Amerika/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "Newfoundlandtid, inkluderer SE Labrador"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Amerika/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Amerika/St_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Amerika/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Amerika/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Amerika/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "Centralstandardtid - Saskatchewan - midt-vest"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Amerika/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Amerika/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "Thule / Pituffik"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Amerika/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "Østtid - Thunder Bay, Ontario"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Amerika/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "US stillehavstid - Baja Californien nær US-grænse"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "Amerika/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "Østtid - Ontario - fleste placeringer"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Amerika/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Amerika/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "Stillehavstid - Vest Britisk Columbia"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Amerika/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Amerika/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "Stillehavstid - Syd Yukon"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Amerika/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "Centraltid - Manitoba & vest Ontario"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Amerika/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "Alaska-tid - Alaska panhandle neck"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Amerika/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "Bjergtid central-nord-vest territorierne"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antarktis/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "Casey Station, Bailey Peninsula"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antarktis/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "Davis Station, Vestfold Hills"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antarktis/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "Dumont-d'Urville Station, Terre Adelie"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "Antarktis/Macquarie"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "Macquarie Island Station, Macquarie Island"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antarktis/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "Mawson Station, Holme Bay"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antarktis/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "McMurdo Station, Ross Island"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antarktis/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "Palmer Station, Anvers Island"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antarktis/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "Rothera Station, Adelaide Island"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antarktis/South_Pole"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "Amundsen-Scott Station, South Pole"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antarktis/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "Syowa Station, E Ongul I"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antarktis/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "Vostok Station, S Magnetic Pole"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Arktis/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Asien/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Asien/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Asien/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Asien/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "Moskva+08 - Bering Sea"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Asien/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Asien/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "Aqtobe (Aktobe)"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Asien/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Asien/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Asien/Baghdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Asien/Bahrain"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Asien/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Asien/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Asien/Beirut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Asien/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Asien/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Asien/Calcutta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Asien/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "Dornod, Sukhbaatar"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Asien/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "Central Kina - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Asien/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Asien/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Asien/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Asien/Damaskus"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Asien/Daka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Asien/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Asien/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Asien/Dushanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Asien/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Asien/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "Heilongjiang (undtagen Mohe), Jilin"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Asien/Ho_Chi_Minh"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Asien/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Asien/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Asien/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Moskva+05 - Lake Baikal"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Asien/Istanbul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Asien/Jakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "Java & Sumatra"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Asien/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "Irian Jaya & the Moluccas"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Asien/Jerusalem"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Asien/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Asien/Kamchatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "Moskva+08 - Kamchatka"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Asien/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Asien/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "Vest Tibet & Xinjiang"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "Asien/Katmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Asien/Katmandu"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "Asien/Kolkata"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Asien/Krasnoyarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "Moskva+04 - Yenisei River"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Asien/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "peninsular Malaysia"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Asien/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "Sabah & Sarawak"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Asien/Kuwait"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Asien/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Asien/Macau"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Asien/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "Moskva+08 - Magadan"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Asien/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "Øst- & Syd-borneo, Celebes, Bali, Nusa Tengarra, Vesttimor"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Asien/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Asien/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Asien/Nicosia"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "Asien/Novokuznetsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Moskva+03 - Novokuznetsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Asien/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Moskva+03 - Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Asien/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "Moskva+03 - Vestsiberien"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Asien/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "Vestkazakhstan"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Asien/Phnom_Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Asien/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "Vest- & Central-borneo"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Asien/Pyongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Asien/Qatar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Asien/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Asien/Rangoon"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Asien/Riyadh"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Asien/Riyadh87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Asien/Riyadh88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Asien/Riyadh89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Asien/Saigon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Asien/Sakhalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "Moskva+07 - Sakhalin Øen"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Asien/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "Vestuzbekistan"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Asien/Seoul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Asien/Shanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "Østkina - Beijing, Guangdong, Shanghai osv."
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Asien/Singapore"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Asien/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Asien/Tashkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "Østuzbekistan"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Asien/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Asien/Teheran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Asien/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Asien/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Asien/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Asien/Tokyo"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Asien/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Asien/Ulaanbaatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Asien/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Asien/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "meste af Tibet & Xinjiang"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Asien/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Asien/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "Moskva+07 - Amur River"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Asien/Yakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "Moskva+06 - Lena River"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Asien/Jekaterineburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "Moskva+02 - Urals"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Asien/Jerevan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlanterhav/Azores"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "Azores"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlanterhav/Bermuda"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlanterhav/Kanariske Øer"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "De Kanariske Øer"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlanterhav/Cape_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlanterhav/Færøerne"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "Atlanterhav/Faroe"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlanterhav/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlanterhav/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "Madeira Øerne"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlanterhav/Reykjavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlanterhav/South_Georgia"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlanterhav/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlanterhav/St_Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Australien/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Australien/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "Sydaustralien"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Australien/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "Queensland - fleste steder"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Australien/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "Nye Syd Wales - Yancowinna"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Australien/Canberra"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Australien/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "Tasmanien - King Øen"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Australien/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "Nordterritoriet"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "Australien/Eucla"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "Vestaustralien - Eucla-området"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Australien/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "Tasmanien - fleste steder"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Australien/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Australien/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "Queensland - Holiday Øerne"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Australien/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "Lord Howe Øen"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Australien/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Australien/North"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Australien/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Australien/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "Vestaustralien - fleste steder"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Australien/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Australien/South"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Australien/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "Nye Syd Wales - fleste steder"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Australien/Tasmania"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Australien/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Australien/West"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Australien/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brasilien/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brasilien/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brasilien/Øst"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brasilien/Vest"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Canada/Atlanterhav"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Canada/Central"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Canada/Øst"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Canada/Øst-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Canada/Mountain"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Canada/Newfoundland"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Canada/Stillehav"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Canada/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Canada/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Chile/Kontinental"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Chile/EasterIsland"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Cuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Ægypten"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Irland"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universel"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Europa/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Europa/Andorra"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Europa/Athen"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Europa/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Europa/Beograd"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Europa/Berlin"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Europa/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Europa/Bryssel"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Europa/Bukarest"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Europa/Budapest"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Europa/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Europa/København"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Europa/Dublin"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Europa/Gibraltar"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Europa/Guernsey"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Europa/Helsinki"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Europa/Isle_of_Man"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Europa/Istanbul"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Europa/Jersey"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Europa/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Moskva-01 - Kaliningrad"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Europa/Kiev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Europa/Lissabon"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Europa/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Europa/London"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Europa/Luxembourg"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Europa/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Europa/Malta"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Europa/Mariehamn"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Europa/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Europa/Monaco"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Europa/Moskva"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "Moskva+00 - Vestrusland"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Europa/Nicosia"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Europa/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Europa/Paris"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Europa/Podgorica"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Europa/Prag"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Europa/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Europa/Rom"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Europa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Moskva - Samara, Udmurtia"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Europa/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Europa/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Europa/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "Central Crimea"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Europa/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Europa/Sofia"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Europa/Stockholm"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Europa/Tallin"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Europa/Tirana"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Europa/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Europa/Uzhgrod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "Ruthenia"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Europa/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Europa/Vatikanet"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Europa/Wien"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Europa/Vilnius"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Europa/Volgograd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "Moskva+00 - Kaspiskehav"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Europa/Warsawa"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Europa/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Europa/Zaporozhye"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Europa/Zürich"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Fabrik"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Irland"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Island"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "IndiskOcean/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "IndiskOcean/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "IndiskOcean/Christmas"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "IndiskOcean/Cocos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "IndiskOcean/Comoro"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "IndiskOcean/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "IndiskOcean/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "IndiskOcean/Maldiverne"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "IndiskOcean/Mauritius"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "IndiskOcean/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "IndiskOcean/Reunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Iran"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Israel"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamaica"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Japan"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Libyen"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Mexico/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Mexico/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Mexico/Generel"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Mellemøsten/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Mellemøsten/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Mellemøsten/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Stillehav/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Stillehav/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Stillehav/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "Chathamøerne"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "Stillehav/Truk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+#, fuzzy
+msgid "Chuuk (Truk) and Yap"
+msgstr "Truk (Chuuk) og Yap"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Stillehavet/Easter"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "Easter Øen & Sala y Gomez"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Stillehav/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Stillehav/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "Phoenix Øerne"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Stillehav/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Stillehav/Fiji"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Stillehav/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Stillehav/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "Galapagos Øerne"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Stillehav/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "Gambier Øerne"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Stillehav/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Stillehav/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Stillehav/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "Hawaii"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Stillehav/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "Johnston Atoll"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Stillehav/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "Line Øerne"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Stillehav/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "Kosrae"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Stillehav/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Stillehav/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Stillehav/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "Marquesas Øerne"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Stillehav/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "Midway Øerne"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Stillehav/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Stillehav/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Stillehav/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Stillehav/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Stillehav/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Stillehav/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Stillehav/Pitcairn"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "Stillehav/Ponape"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+#, fuzzy
+msgid "Pohnpei (Ponape)"
+msgstr "Ponape (Pohnpei)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Stillehav/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Stillehav/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Stillehav/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Stillehav/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Stillehav/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Stillehav/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "Society Øerne"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Stillehav/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "Gilbertøerne"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Stillehav/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Stillehav/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Stillehav/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "Wake Øen"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Stillehav/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Stillehav/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Polen"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugal"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapore"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Tyrkiet"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universel"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "USA/Alaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "USA/Aleutian"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "USA/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "USA/Central"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "USA/Eastern"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "USA/East-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "USA/Hawaii"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "USA/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "USA/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "USA/Mountain"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "USA/Pacific"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "USA/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
+
+#~ msgid "US/Pacific-New"
+#~ msgstr "US/Pacific-New"
diff --git a/panels/datetime/po-timezones/de.po b/panels/datetime/po-timezones/de.po
new file mode 100644
index 0000000..3ae86bc
--- /dev/null
+++ b/panels/datetime/po-timezones/de.po
@@ -0,0 +1,3722 @@
+# translation of system-config-date.master-timezones.po to
+# translation of system-config-date.master-timezones.de.po to
+# Ferman translation of system-config-date.timezones
+# Copyright (C) 2004 Red Hat, Inc.
+# This file is distributed under the same license as the system-config-date package.
+#
+#
+# Automatically generated, 2004.
+# Jens Maucher <jensm@fedoraproject.org>, 2009.
+# Nils Philippsen <nils@redhat.com>, 2009, 2010.
+# Fabian Affolter <fab@fedoraproject.org>, 2008, 2009.
+# Hedda Peters <hpeters@redhat.com>, 2009.
+# sknirT omiT <moc.tahder@sknirtt>, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: system-config-date.master-timezones\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-08-16 14:09+0100\n"
+"Last-Translator: Nils Philippsen <nils@redhat.com>\n"
+"Language-Team: \n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: German\n"
+"X-Generator: vim\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Afrika/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Afrika/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Afrika/Addis_Abeba"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Afrika/Algier"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "Afrika/Asmera"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Afrika/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Afrika/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Afrika/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Afrika/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Afrika/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Afrika/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Afrika/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Afrika/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Afrika/Kairo"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Afrika/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Afrika/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "Ceuta & Melilla"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Afrika/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Afrika/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Afrika/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Afrika/Dschibuti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Afrika/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Afrika/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Afrika/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Afrika/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Afrika/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Afrika/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Afrika/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Afrika/Khartum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Afrika/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Afrika/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "Westl. Dem. Rep. Kongo"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Afrika/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Afrika/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Afrika/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Afrika/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Afrika/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "Östl. Dem. Rep. Kongo"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Afrika/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Afrika/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Afrika/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Afrika/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Afrika/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Afrika/Mogadischu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Afrika/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Afrika/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Afrika/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Afrika/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Afrika/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Afrika/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Afrika/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Afrika/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Afrika/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Afrika/Tripolis"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Afrika/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Afrika/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Amerika/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Aleuten Inseln"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Amerika/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Alaska-Zeit"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Amerika/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Amerika/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Amerika/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "Tocantins"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Amerika/Argentinien/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Buenos Aires (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Amerika/Argentinien/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "Catamarca (CT), Chubut (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Amerika/Argentinien/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Amerika/Argentinien/Cordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "fast alle Orte (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Amerika/Argentinien/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Jujuy (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Amerika/Argentinien/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "La Rioja (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Amerika/Argentinien/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "Mendoza (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Amerika/Argentinien/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "Santa Cruz (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "Amerika/Argentinien/Salta"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Amerika/Argentinien/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "San Juan (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "Amerika/Argentinien/San_Luis"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "San Luis (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Amerika/Argentinien/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "Tucuman (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Amerika/Argentinien/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "Feuerland (Tierra del Fuego, TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Amerika/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Amerika/Asuncion"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Amerika/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "Eastern Standard Time - Atikokan, Ontario und Southampton Insel, Nunavut"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Amerika/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Amerika/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "Bahia"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "Amerika/Bahia_Banderas"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "Mexican Central Time - Bahia de Banderas"
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Amerika/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Amerika/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "Amapa, E Para"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Amerika/Belize"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "Amerika/Blanc-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "Atlantic Standard Time - Quebec - Untere Nordküste"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Amerika/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "Roraima"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Amerika/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Amerika/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "Mountain Time - Süd-Idaho & Ost-Oregon"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Amerika/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Amerika/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "Mountain Time - West-Nunavut"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "Amerika/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "Mato Grosso do Sul"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Amerika/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "Central Time - Quintana Roo"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Amerika/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Amerika/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Amerika/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Amerika/Cayman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Amerika/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "Central Time"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Amerika/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "Mexican Mountain Time - Chihuahua fern der US-Grenze"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "Amerika/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Amerika/Cordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Amerika/Costa_Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Amerika/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "Mato Grosso"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Amerika/Curacao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Amerika/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "Ostküste, im Norden von Scoresbysund"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Amerika/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "Pacific Time - Nord Yukon"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Amerika/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid "Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr "Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Amerika/Denver"
+
+#
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "Mountain Time"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Amerika/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "Eastern Time - Michigan - fast alle Orte"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Amerika/Dominica"
+
+#
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Amerika/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "Mountain Time - Alberta, östl. British-Columbia & westl. Saskatchewan"
+
+#
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Amerika/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "Westl. Amazonas"
+
+#
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Amerika/El_Salvador"
+
+#
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Amerika/Ensenada"
+
+#
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Amerika/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "Nordöstl. Brasilien (MA, PI, CE, RN, PB)"
+
+#
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Amerika/Fort_Wayne"
+
+#
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Amerika/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr "Atlantic Time - Nova Scotia - Orte, die der DST (Sommerzeit) 1966-1971 nicht folgten"
+
+#
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Amerika/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195
+#: timezones.h:364
+#: timezones.h:453
+#: timezones.h:591
+#: timezones.h:754
+#: timezones.h:852
+#: timezones.h:894
+msgid "most locations"
+msgstr "fast alle Orte"
+
+#
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Amerika/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "Atlantic Time - Labrador - fast alle Orte"
+
+#
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Amerika/Grand_Turk"
+
+#
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Amerika/Grenada"
+
+#
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Amerika/Guadeloupe"
+
+#
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Amerika/Guatemala"
+
+#
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Amerika/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205
+#: timezones.h:757
+#: timezones.h:763
+msgid "mainland"
+msgstr "Festland"
+
+#
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Amerika/Guyana"
+
+#
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Amerika/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "Atlantic Time - Nova Scotia (fast alle Orte), PEI"
+
+#
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Amerika/Havanna"
+
+#
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Amerika/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "Mountain Standard Time - Sonora"
+
+#
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Amerika/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "Eastern Time - Indiana - fast alle Orte"
+
+#
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Amerika/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "Central Time - Indiana - Starke County"
+
+#
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Amerika/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "Eastern Time - Indiana - Crawford County"
+
+#
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "Amerika/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "Eastern Time - Indiana - Pike County"
+
+#
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Amerika/Indianapolis"
+
+#
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "Amerika/Indiana/Tell_City"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "Central Time - Indiana - Perry County"
+
+#
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "Eastern Time - Indiana - Switzerland County"
+
+#
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "Amerika/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+
+#
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "Amerika/Indiana/Winamac"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "Eastern Time - Indiana - Pulaski County"
+
+#
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Amerika/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "Mountain Time - westliche Northwest Territories"
+
+#
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Amerika/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "Eastern Time - Ost-Nunavut - fast alle Orte"
+
+#
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Amerika/Jamaika"
+
+#
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Amerika/Jujuy"
+
+#
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Amerika/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "Alaska Time - Alaska Panhandle"
+
+#
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Amerika/Kentucky/Louisville"
+
+#
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Amerika/Kentucky/Louisville"
+
+#
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Amerika/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "Eastern Time - Kentucky - Wayne County"
+
+#
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Amerika/Knox_IN"
+
+#
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Amerika/La_Paz"
+
+#
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Amerika/Lima"
+
+#
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Amerika/Los_Angeles"
+
+#
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "Pacific Time"
+
+#
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Amerika/Louisville"
+
+#
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Amerika/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "Alagoas"
+
+#
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Amerika/Managua"
+
+#
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Amerika/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "Östl. Amazonas"
+
+#
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "Amerika/Marigot"
+
+#
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Amerika/Martinique"
+
+#
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "Amerika/Matamoros"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid "US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr "US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas nahe der US-Grenze"
+
+#
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Amerika/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "Mountain Time - Südl. Baja, Nayarit, Sinaloa"
+
+#
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Amerika/Mendoza"
+
+#
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Amerika/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+
+#
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Amerika/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "Central Time - Campeche, Yucatan"
+
+#
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Amerika/Mexiko_Stadt"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "Central Time - fast alle Orte"
+
+#
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Amerika/Miquelon"
+
+#
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "Amerika/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "Atlantic Time - New Brunswick"
+
+#
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Amerika/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid "Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from US border"
+msgstr "Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas fern der US-Grenze"
+
+#
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Amerika/Montevideo"
+
+#
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Amerika/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "Eastern Time - Quebec - fast alle Orte"
+
+#
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Amerika/Montserrat"
+
+#
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Amerika/Nassau"
+
+#
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Amerika/New_York"
+
+#
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "Eastern Time"
+
+#
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Amerika/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid "Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr "Eastern Time - Ontario & Quebec - Orte, die der DST (Sommerzeit) 1967-1973 nicht folgten"
+
+#
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Amerika/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "Alaska Time - West-Alaska"
+
+#
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Amerika/Noronha"
+
+#
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "Atlantische Inseln"
+
+#
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Amerika/North_Dakota/Zentrum"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "Central Time - North Dakota - Oliver County"
+
+#
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "Amerika/North_Dakota/New_Salem"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "Central Time - North Dakota - Morton County (außer Mandan-Region)"
+
+#
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "Amerika/Ojinaga"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "US Mountain Time - Chihuahua nahe der US-Grenze"
+
+#
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Amerika/Panama"
+
+#
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Amerika/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "Eastern Time - Pangnirtung, Nunavut"
+
+#
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Amerika/Paramaribo"
+
+#
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Amerika/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "Mountain Standard Time - Arizona"
+
+#
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Amerika/Port-au-Prince"
+
+#
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Amerika/Porto_Acre"
+
+#
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Amerika/Port_of_Spain"
+
+#
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Amerika/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "Rondonia"
+
+#
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Amerika/Puerto_Rico"
+
+#
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Amerika/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "Central Time - Rainy River & Fort Frances, Ontario"
+
+#
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Amerika/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "Central Time - Zentral-Nunavut"
+
+#
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Amerika/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "Pernambuco"
+
+#
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Amerika/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "Central Standard Time - Saskatchewan - fast alle Orte"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "Amerika/Resolute"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "Eastern Standard Time - Resolute, Nunavut"
+
+#
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Amerika/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "Acre"
+
+#
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Amerika/Rosario"
+
+#
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "Amerika/Santa_Isabel"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "Mexican Pacific Time - Baja California fern der US-Grenze"
+
+#
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "Amerika/Santarem"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "Westl. Para"
+
+#
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Amerika/Santiago"
+
+#
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Amerika/Santo_Domingo"
+
+#
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Amerika/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "Südl. & Südöstl. Brasilien (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Amerika/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "Scoresbysund / Ittoqqortoormiit"
+
+#
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Amerika/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "Mountain Time - Navajo"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "Amerika/St_Barthelemy"
+
+#
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Amerika/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "Newfoundland Time, einschließlich südöstl. Labrador"
+
+#
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Amerika/St_Kitts"
+
+#
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Amerika/St_Lucia"
+
+#
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Amerika/St_Thomas"
+
+#
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Amerika/St_Vincent"
+
+#
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Amerika/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "Central Standard Time - Saskatchewan - Mittlerer Westen"
+
+#
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Amerika/Tegucigalpa"
+
+#
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Amerika/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "Thule / Pituffik"
+
+#
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Amerika/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "Eastern Time - Thunder Bay, Ontario"
+
+#
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Amerika/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "US Pacific Time - Baja California nahe der US-Grenze"
+
+#
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "Amerika/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "Eastern Time - Ontario - fast alle Orte"
+
+#
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Amerika/Tortola"
+
+#
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Amerika/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "Pacific Time - Westliches British Columbia"
+
+#
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Amerika/Virgin"
+
+#
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Amerika/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "Pacific Time - Süd-Yukon"
+
+#
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Amerika/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "Central Time - Manitoba & West-Ontario"
+
+#
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Amerika/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "Alaska Time - Alaska Panhandle"
+
+#
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Amerika/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "Mountain Time - zentrale Northwest Territories"
+
+#
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antarktis/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "Casey Station, Bailey Peninsula"
+
+#
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antarktis/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "Davis Station, Vestfold Hills"
+
+#
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antarktis/Dumont d'Urville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "Dumont-d'Urville Station, Terre Adelie"
+
+#
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "Antarktis/Macquarie"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "Macquarie-Insel Station, Macquarie-Insel"
+
+#
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antarktis/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "Mawson Station, Holme Bay"
+
+#
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antarktis/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "McMurdo Station, Ross Island"
+
+#
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antarktis/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "Palmer Station, Anvers Island"
+
+#
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antarktis/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "Rothera Station, Adelaide Island"
+
+#
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antarktis/Südpol"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "Amundsen-Scott Station, South Pole"
+
+#
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antarktis/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "Syowa Station, östl. Ongul Insel"
+
+#
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antarktis/Wostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "Vostok Station, magnetischer Südpol"
+
+#
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Arktis/Longyearbyen"
+
+#
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Asien/Aden"
+
+#
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Asien/Almaty"
+
+#
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Asien/Amman"
+
+#
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Asien/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "Moskau+08 - Beringsee"
+
+#
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Asien/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+
+#
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Asien/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "Aqtobe (Aktobe)"
+
+#
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Asien/Ashgabat"
+
+#
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Asien/Ashkhabad"
+
+#
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Asien/Bagdad"
+
+#
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Asien/Bahrain"
+
+#
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Asien/Baku"
+
+#
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Asien/Bangkok"
+
+#
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Asien/Beirut"
+
+#
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Asien/Bishkek"
+
+#
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Asien/Brunei"
+
+#
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Asien/Kalkutta"
+
+#
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Asien/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "Dornod, Sukhbaatar"
+
+#
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Asien/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "Zentral-China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, usw."
+
+#
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Asien/Chungking"
+
+#
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Asien/Colombo"
+
+#
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Asien/Dacca"
+
+#
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Asien/Damaskus"
+
+#
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Asien/Dhaka"
+
+#
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Asien/Dili"
+
+#
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Asien/Dubai"
+
+#
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Asien/Duschanbe"
+
+#
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Asien/Gaza"
+
+#
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Asien/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "Heilongjiang (außer Mohe), Jilin"
+
+#
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Asien/Ho_Chi_Minh_Stadt"
+
+#
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Asien/Hong_Kong"
+
+#
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Asien/Chowd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "Bajan-Ölgii, Gobi-Altai, Chowd, Uws, Zawchan"
+
+#
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Asien/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Moskau+05 - Baikal-See"
+
+#
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Asien/Istanbul"
+
+#
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Asien/Jakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "Java & Sumatra"
+
+#
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Asien/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "Irian Jaya & die Molukken"
+
+#
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Asien/Jerusalem"
+
+#
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Asien/Kabul"
+
+#
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Asien/Kamtschatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "Moskau+08 - Kamtschatka"
+
+#
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Asien/Karachi"
+
+#
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Asien/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "West-Tibet & Xinjiang"
+
+#
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "Asien/Kathmandu"
+
+#
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Asien/Katmandu"
+
+#
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "Asien/Kalkutta"
+
+#
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Asien/Krasnojarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "Moskau+04 - Jenissei Fluss"
+
+#
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Asien/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "Halbinsel Malaysia"
+
+#
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Asien/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "Sabah & Sarawak"
+
+#
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Asien/Kuwait"
+
+#
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Asien/Macao"
+
+#
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Asien/Macau"
+
+#
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Asien/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "Moskau+08 - Magadan"
+
+#
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Asien/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "Ost- & Süd-Borneo, Sulawesi, Bali, Kleine Sunda-Inseln, West-Timor"
+
+#
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Asien/Manila"
+
+#
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Asien/Maskat"
+
+#
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Asien/Nikosia"
+
+#
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "Asien/Nowokusnezk"
+
+#
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Moskau+03 - Nowokusnezk"
+
+#
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Asien/Nowosibirsk"
+
+#
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Moskau+03 - Nowosibirsk"
+
+#
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Asien/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "Moskau+03 - Westl. Sibirien"
+
+#
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Asien/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "Westl. Kasachstan"
+
+#
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Asien/Phnom_Penh"
+
+#
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Asien/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "West- & Zentral-Borneo"
+
+#
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Asien/Pjöngjang"
+
+#
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Asien/Katar"
+
+#
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Asien/Qysylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "Qysylorda (Kysyl-Orda, Ksyl-Orda)"
+
+#
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Asien/Rangun"
+
+#
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Asien/Riad"
+
+#
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Asien/Riad87"
+
+#
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Asien/Riad88"
+
+#
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Asien/Riad89"
+
+#
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Asien/Saigon"
+
+#
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Asien/Sachalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "Moskau+07 - Sachalin Inseln"
+
+#
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Asien/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "Westliches Usbekistan"
+
+#
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Asien/Seoul"
+
+#
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Asien/Shanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "Östl. China - Peking, Guangdong, Shanghai, etc."
+
+#
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Asien/Singapur"
+
+#
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Asien/Taipei"
+
+#
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Asien/Taschkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "Östl. Usbekistan"
+
+#
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Asien/Tiflis"
+
+#
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Asien/Teheran"
+
+#
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Asien/Tel_Aviv"
+
+#
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Asien/Thimbu"
+
+#
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Asien/Thimphu"
+
+#
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Asien/Tokio"
+
+#
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Asien/Ujung_Pandang"
+
+#
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Asien/Ulaanbaatar"
+
+#
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Asien/Ulan_Bator"
+
+#
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Asien/Ürümqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "Große Teile von Tibet & Xinjiang"
+
+#
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Asien/Vientiane"
+
+#
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Asien/Wladiwostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "Moskau+07 - Amur Fluss"
+
+#
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Asien/Jakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "Moskau+06 - Lena Fluss"
+
+#
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Asien/Jekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "Moskau+02 - Ural"
+
+#
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Asien/Eriwan"
+
+#
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlantik/Azoren"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "Azoren"
+
+#
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlantik/Bermuda"
+
+#
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlantik/Kanaren"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "Kanarische Inseln"
+
+#
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlantik/Kap_Verde"
+
+#
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlantik/Färöer"
+
+#
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "Atlantik/Färöer"
+
+#
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlantik/Jan_Mayen"
+
+#
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlantik/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "Madeira Inseln"
+
+#
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlantik/Reykjavik"
+
+#
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlantik/Südgeorgien"
+
+#
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlantik/Stanley"
+
+#
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlantik/St._Helena"
+
+#
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Australien/ACT"
+
+#
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Australien/Adelaide"
+
+#
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "Südaustralien"
+
+#
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Australien/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "Queensland - fast alle Orte"
+
+#
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Australien/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "Neusüdwales - Yancowinna"
+
+#
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Australien/Canberra"
+
+#
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Australien/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "Tasmanien - King Island"
+
+#
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Australien/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "Nordterritorium"
+
+#
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "Australien/Eucla"
+
+#
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "Westaustralien - Eucla-Gebiet"
+
+#
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Australien/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "Tasmanien - fast alle Orte"
+
+#
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Australien/LHI"
+
+#
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Australien/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "Queensland - Holiday Islands"
+
+#
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Australien/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "Lord-Howe-Insel"
+
+#
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Australien/Melbourne"
+
+#
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "Viktoria"
+
+#
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Australien/Nord"
+
+#
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Australien/NSW"
+
+#
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Australien/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "Westaustralien - fast alle Orte"
+
+#
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Australien/Queensland"
+
+#
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Australien/Süd"
+
+#
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Australien/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "Neusüdwales - fast alle Orte"
+
+#
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Australien/Tasmanien"
+
+#
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Australien/Viktoria"
+
+#
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Australien/West"
+
+#
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Australien/Yancowinna"
+
+#
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brasilien/Acre"
+
+#
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brasilien/DeNoronha"
+
+#
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brasilien/Ost"
+
+#
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brasilien/West"
+
+#
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Kanada/Atlantik"
+
+#
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Kanada/Zentral"
+
+#
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Kanada/Ost"
+
+#
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Kanada/Ost-Saskatchewan"
+
+#
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Kanada/Mountain"
+
+#
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Kanada/Neufundland"
+
+#
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Kanada/Pazifik"
+
+#
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Kanada/Saskatchewan"
+
+#
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Kanada/Yukon"
+
+#
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Chile/Kontinental"
+
+#
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Chile/Osterinsel"
+
+#
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Kuba"
+
+#
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Ägypten"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Irland"
+
+#
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulu"
+
+#
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Europa/Amsterdam"
+
+#
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Europa/Andorra"
+
+#
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Europa/Athen"
+
+#
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Europa/Belfast"
+
+#
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Europa/Belgrad"
+
+#
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Europa/Berlin"
+
+#
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Europa/Bratislava"
+
+#
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Europa/Brüssel"
+
+#
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Europa/Bukarest"
+
+#
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Europa/Budapest"
+
+#
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Europa/Chişinău"
+
+#
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Europa/Kopenhagen"
+
+#
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Europa/Dublin"
+
+#
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Europa/Gibraltar"
+
+#
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Europa/Guernsey"
+
+#
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Europa/Helsinki"
+
+#
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Europa/Isle_of_Man"
+
+#
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Europa/Istanbul"
+
+#
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Europa/Jersey"
+
+#
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Europa/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Moskau-01 - Kaliningrad"
+
+#
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Europa/Kiew"
+
+#
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Europa/Lissabon"
+
+#
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Europa/Ljubljana"
+
+#
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Europa/London"
+
+#
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Europa/Luxemburg"
+
+#
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Europa/Madrid"
+
+#
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Europa/Malta"
+
+#
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Europa/Mariehamn"
+
+#
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Europa/Minsk"
+
+#
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Europa/Monaco"
+
+#
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Europa/Moskau"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "Moskau+00 - Westliches Russland"
+
+#
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Europa/Nikosia"
+
+#
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Europa/Oslo"
+
+#
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Europa/Paris"
+
+#
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Europa/Podgorica"
+
+#
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Europa/Prag"
+
+#
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Europa/Riga"
+
+#
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Europa/Rom"
+
+#
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Europa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Moskau - Samara, Udmurtia"
+
+#
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Europa/San_Marino"
+
+#
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Europa/Sarajevo"
+
+#
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Europa/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "Zentral-Crimea"
+
+#
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Europa/Skopje"
+
+#
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Europa/Sofia"
+
+#
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Europa/Stockholm"
+
+#
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Europa/Tallinn"
+
+#
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Europa/Tirana"
+
+#
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Europa/Tiraspol"
+
+#
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Europa/Uschhorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "Ruthenien"
+
+#
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Europa/Vaduz"
+
+#
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Europa/Vatikan"
+
+#
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Europa/Wien"
+
+#
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Europa/Vilnius"
+
+#
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Europa/Wolgograd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "Moskau+00 - Kaspisches Meer"
+
+#
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Europa/Warschau"
+
+#
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Europa/Zagreb"
+
+#
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Europa/Saporischschja"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "Saporoschje, östl. Lugansk / Saporischschja, östl. Luhansk"
+
+#
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Europa/Zürich"
+
+#
+#: timezones.h:808
+msgid "Factory"
+msgstr "Factory"
+
+#
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Irland"
+
+#
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Island"
+
+#
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Indischer Ozean/Antananarivo"
+
+#
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Indischer Ozean/Chagos"
+
+#
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Indischer Ozean/Weihnachtsinseln"
+
+#
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Indischer Ozean/Kokosinseln"
+
+#
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Indischer Ozean/Komoren"
+
+#
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Indischer Ozean/Kerguelen"
+
+#
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Indischer Ozean/Mahe"
+
+#
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Indischer Ozean/Malediven"
+
+#
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Indischer Ozean/Mauritius"
+
+#
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Indischer Ozean/Mayotte"
+
+#
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Indischer Ozean/Réunion"
+
+#
+#: timezones.h:830
+msgid "Iran"
+msgstr "Iran"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#
+#: timezones.h:832
+msgid "Israel"
+msgstr "Israel"
+
+#
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamaika"
+
+#
+#: timezones.h:834
+msgid "Japan"
+msgstr "Japan"
+
+#
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835
+#: timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Libyen"
+
+#
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Mexiko/BajaNorte"
+
+#
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Mexiko/BajaSur"
+
+#
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Mexiko/General"
+
+#
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Mittlerer Osten/Riad87"
+
+#
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Mittlerer Osten/Riad88"
+
+#
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Mittlerer Osten/Riad89"
+
+#
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Pazifik/Apia"
+
+#
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Pazifik/Auckland"
+
+#
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Pazifik/Chatham"
+
+#
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "Chatham Inseln"
+
+#
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "Pazifik/Chuuk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "Chuuk (Truk) und Yap"
+
+#
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Pazifik/Osterinsel"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "Osterinseln & Sala y Gomez"
+
+#
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Pazifik/Efate"
+
+#
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Pazifik/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "Phoenixinseln"
+
+#
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Pazifik/Fakaofo"
+
+#
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Pazifik/Fidschi"
+
+#
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Pazifik/Funafuti"
+
+#
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Pazifik/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "Galapagos-Inseln"
+
+#
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Pazifik/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "Gambier Inseln"
+
+#
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Pazifik/Guadalcanal"
+
+#
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Pazifik/Guam"
+
+#
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Pazifik/Honolulu"
+
+#
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "Hawaii"
+
+#
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Pazifik/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "Johnston-Atoll"
+
+#
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Pazifik/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "Line-Inseln"
+
+#
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Pazifik/Kosrae"
+
+#
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "Kosrae"
+
+#
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Pazifik/Kwajalein"
+
+#
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Pazifik/Majuro"
+
+#
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Pazifik/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "Marquesas-Inseln"
+
+#
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Pazifik/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "Midway-Inseln"
+
+#
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Pazifik/Nauru"
+
+#
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Pazifik/Niue"
+
+#
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Pazifik/Norfolk"
+
+#
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Pazifik/Noumea"
+
+#
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Pazifik/Pago_Pago"
+
+#
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Pazifik/Palau"
+
+#
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Pazifik/Pitcairn"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "Pazifik/Pohnpei"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "Pohnpei (Ponape)"
+
+#
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Pazifik/Ponape"
+
+#
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Pazifik/Port_Moresby"
+
+#
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Pazifik/Rarotonga"
+
+#
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Pazifik/Saipan"
+
+#
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Pazifik/Samoa"
+
+#
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Pazifik/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "Gesellschaftsinseln"
+
+#
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Pazifik/Tarawa"
+
+#
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "Gilbert-Inseln"
+
+#
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Pazifik/Tongatapu"
+
+#
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Pazifik/Truk"
+
+#
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Pazifik/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "Wake Island"
+
+#
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Pazifik/Wallis"
+
+#
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Pazifik/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Polen"
+
+#
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugal"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapur"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Türkei"
+
+#
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "US/Alaska"
+
+#
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "US/Aleutian"
+
+#
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "US/Arizona"
+
+#
+#: timezones.h:943
+msgid "US/Central"
+msgstr "US/Central"
+
+#
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "US/Eastern"
+
+#
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "US/Ost-Indiana"
+
+#
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "US/Hawaii"
+
+#
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "US/Indiana-Starke"
+
+#
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "US/Michigan"
+
+#
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "US/Mountain"
+
+#
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "US/Pacific"
+
+#
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "US/Samoa"
+
+#
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
+
diff --git a/panels/datetime/po-timezones/el.po b/panels/datetime/po-timezones/el.po
new file mode 100644
index 0000000..cc01e1e
--- /dev/null
+++ b/panels/datetime/po-timezones/el.po
@@ -0,0 +1,3272 @@
+# translation of el.po to Greek
+# Timezones Greek Translation.
+# Copyright (C) 2003 Nikos Charonitakis
+# This file is distributed under the same license as the redhat-config-date/timezones package.
+#
+#
+# Nikos Charonitakis <charosn@her.forthnet.gr>, 2003, 2004, 2006.
+# Dimitrios Michelinakis <dimitris@michelinakis.gr>, 2006.
+# Dimitris Glezos <dimitris@glezos.com>, 2007.
+# Thalia Papoutsaki <saliyath@gmail.com>, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: el\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-03-13 17:14+0200\n"
+"Last-Translator: thalia papoutsaki <saliyath@gmail.com>\n"
+"Language-Team: Greek <fedora-trans-el@redhat.com>\n"
+"Language: el\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Αφρική/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Αφρική/Άκκρα"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Αφρική/Αντίς_Αμπέμπα"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Αφρική/Αλγέρι"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "Αφρική/Asmera"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Αφρική/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Αφρική/Μπαμάκο"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Αφρική/Μπανγκούι"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Αφρική/Μπανζούλ"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Αφρική/Μπισσάου"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Αφρική/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Αφρική/Μπραζαβίλ"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Αφρική/Μπουζουμπούρα"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Αφρική/Κάιρο"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Αφρική/Καζαμπλάνκα"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Αφρική/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "Ceuta & Melilla"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Αφρική/Κόνακρι"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Αφρική/Ντακάρ"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Αφρική/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Αφρική/Τζιμπουτί"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Αφρική/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Αφρική/Ελ_Αϊούν"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Αφρική/Φρίταουν"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Αφρική/Γκαμπορόν"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Αφρική/Χαράρε"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Αφρική/Γιοχάνεσμπουργκ"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Αφρική/Καμπάλα"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Αφρική/Χαρτούμ"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Αφρική/Κιγκάλι"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Αφρική/Κινσάσα"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "Δυτική Λαϊκή Δημοκρατία του Κονγκό"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Αφρική/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Αφρική/Λιμπρεβίλ"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Αφρική/Λομέ"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Αφρική/Λουάντα"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Αφρική/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "Ανατολική Λαϊκή Δημοκρατία του Κονγκό"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Αφρική/Λουσάκα"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Αφρική/Μαλάμπο"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Αφρική/Μαπούτο"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Αφρική/Μασερού"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Αφρική/Μπαμπάνε"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Αφρική/Μογκαντίσου"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Αφρική/Μονρόβια"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Αφρική/Ναϊρόμπι"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Αφρική/Τζαμένα"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Αφρική/Νιαμέι"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Αφρική/Νουαξότ"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Αφρική/Ουαγκαντούγκου"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Αφρική/Πόρτο Νόβο"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Αφρική/Σάο_Τομέ"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Αφρική/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Αφρική/Τρίπολη"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Αφρική/Τύνιδα"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Αφρική/Γουίντχουκ"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Αμερική/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Νησιά Aleutian "
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Αμερική/Άνκορατζ"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Ώρα Αλάσκας"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Αμερική/Ανγκουίλα"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Αμερική/Αντίγκουα"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Αμερική/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "Τοκαντίνς"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Αμερική/Αργεντινή/Μπουένος_Άιρες"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Μπουένος Άιρες (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Αμερική/Αργεντινή/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "Catamarca (CT), Chubut (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Αμερική/Αργεντινή/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Αμερική/Αργεντινή/Cordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "περισσότερες περιοχές (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Αμερική/Αργεντινή/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Jujuy (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Αμερική/Αργεντινή/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "Λα Ριόχα (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Αμερική/Αργεντινή/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "Μεντόζα (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Αμερική/Αργεντινή/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "Σάντα Κρουζ (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "Αμερική/Αργεντινή/Salta"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Αμερική/Αργεντινή/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "Σαν Χουάν (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "Αμερική/Αργεντινή/San_Luis"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "Σαν Λιούις (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Αμερική/Αργεντινή/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "Τουκουμαν (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Αμερική/Αργεντινή/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "Τιέρα ντελ Φουέγο (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Αμερική/Αρούμπα"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Αμερική/Ασουνσιόν"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Αμερική/Ατικόκαν"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "Ηπα/Ανατολική Ακτή - Atikokan, Οντάριο και Σαουθάμπτον I, Nunavut"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Αμερική/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Αμερική/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "Μπάχια "
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "Αμερική/Bahia"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Αμερική/Μπαρμπάντος"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Αμερική/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "Amapa, E Para"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Αμερική/Μπελίζε"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "Αμερική/Blanc-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "Καναδάς/Ατλαντικός - Κεμπέκ- Lower North Shore"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Αμερική/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "Roraima"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Αμερική/Μπογκοτά"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Αμερική/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "ΗΠΑ/Mountain - νότιο Idaho & ανατολικό Oregon"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Αμερική/Μπουένος_Άιρες"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Αμερική/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "ΗΠΑ/Mountain - δυτικό Nunavut"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "Αμερική/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "Μάτο Γκρόσσο Ντο Σουλ"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Αμερική/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "ΗΠΑ/Κεντρική - Κουιντάνα Ρου"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Αμερική/Καράκας"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Αμερική/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Αμερική/Καγιέν"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Αμερική/Κάυμαν"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Αμερική/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "ΗΠΑ/Κεντρική"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Αμερική/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+#, fuzzy
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "ΗΠΑ/Mountain - Chihuahua"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "Αμερική/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Αμερική/Cordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Αμερική/Κόστα_Ρίκα"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Αμερική/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "Μάτο Γκρόσσο"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Αμερική/Κουρακάο"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Αμερική/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "ανατολική ακτή, βόρεια του Scoresbysund"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Αμερική/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "Ειρηνικός - βόρειο Yukon"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Αμερική/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr "ΗΠΑ/Mountain - Dawson Creek & Fort Saint John, Βρετανική Κολομβία"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Αμερική/Ντένβερ"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "ΗΠΑ/Mountain"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Αμερική/Ντιτρόιτ"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "ΗΠΑ/Ανατολική ακτή - Μίσιγκαν - περισσότερες περιοχές"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Αμερική/Ντομίνικα"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Αμερική/Έντμοντον"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+"ΗΠΑ/Mountain - Alberta, ανατολική Βρετανική Κολομβία & δυτικό Saskatchewan"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Αμερική/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "Δ. Αμαζόνιος"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Αμερική/Ελ_Σαλβαδόρ"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Αμερική/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Αμερική/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "ΒΑ Βραζιλία (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Αμερική/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Αμερική/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+"´Ωρα Ατλαντικού - Nova Scotia - περιοχές που δεν τηρούν το DST 1966-1971"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Αμερική/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "περισσότερες περιοχές"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Αμερική/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "´Ωρα Ατλαντικού - Λαμπραντόρ - περισσότερες περιοχές"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Αμερική/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Αμερική/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Αμερική/Γουαδελούπη"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Αμερική/Γουατεμάλα"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Αμερική/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "ηπειρωτική περιοχή"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Αμερική/Γουιάνα"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Αμερική/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "´Ωρα Ατλαντικού - Nova Scotia (περισσότερες περιοχές), PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Αμερική/Αβάνα"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Αμερική/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "ΗΠΑ/Mountain - Sonora"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Αμερική/Ιντιάνα/Ιντιανάπολις"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "ΗΠΑ/Ανατολική ακτή - Ιντιάνα - περισσότερες περιοχές"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Αμερική/Ιντιάνα/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "ΗΠΑ/Κεντρική - Ιντιάνα - Starke County"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Αμερική/Ιντιάνα/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "ΗΠΑ/Ανατολική ακτή - Ιντιάνα - Crawford County"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "Αμερική/Ιντιάνα/Πετρούπολη"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "ΗΠΑ/Ανατολική ακτή - Ιντιάνα - Pike County"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Αμερική/Ιντιανάπολις"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "Αμερική/Ιντιάνα/Vevay"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "ΗΠΑ/Κεντρική - Ιντιάνα - Perry County"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Αμερική/Ιντιάνα/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "ΗΠΑ/Ανατολική ακτή - Ιντιάνα - Switzerland County"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "Αμερική/Ιντιάνα/Vincennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "ΗΠΑ/Ανατολική ακτή - Ιντιάνα - Daviess, Dubois, Knox & Martin Counties"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "Αμερική/Ινδιάνα/Winamac"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "ΗΠΑ/Ανατολική ακτή - Ιντιάνα - Pulaski County"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Αμερική/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "ΗΠΑ/Mountain - west Northwest Territories"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Αμερική/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "ΗΠΑ/Ανατολική ακτή - Ανατολικό Nunavut - περισσότερες περιοχές"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Αμερική/Τζαμάικα"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Αμερική/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Αμερική/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "Ώρα Αλάσκας - Alaska panhandle"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Αμερική/Κεντάκι/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "ΗΠΑ/Ανατολική Ακτή - Κεντάκι - περιοχή Louisville"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Αμερική/Κεντάκι/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "ΗΠΑ/Ανατολική ακτή - Κεντάκι - Wayne County"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Αμερική/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Αμερική/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Αμερική/Λίμα"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Αμερική/Λος_Άντζελες"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "ΗΠΑ/Ειρηνικός"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Αμερική/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Αμερική/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "Alagoas, Sergipe"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Αμερική/Μανάγκουα"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Αμερική/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "Α Αμαζόνιος"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "Αμερική/Μάριγκοτ"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Αμερική/Μαρτινίκα"
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "Αμερική/Manaus"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+#, fuzzy
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr "ΗΠΑ/Κεντρική - Coahuila, Durango, Nuevo Leon, Tamaulipas"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Αμερική/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "ΗΠΑ/Mountain -S Baja, Nayarit, Sinaloa"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Αμερική/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Αμερική/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+"ΗΠΑ/Κεντρική - Μίσιγκαν - Ντίκινσον, Gogebic, Iron & Menominee Counties"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Αμερική/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "ΗΠΑ/Κεντρική - Campeche, Yucatan"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Αμερική/Μεξικό"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "ΗΠΑ/Κεντρική - περισσότερες περιοχές"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Αμερική/Μικελόν"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "Αμερική/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "´Ωρα Ατλαντικού - Νέο Brunswick"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Αμερική/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+#, fuzzy
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr "ΗΠΑ/Κεντρική - Coahuila, Durango, Nuevo Leon, Tamaulipas"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Αμερική/Μοντεβιδέο"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Αμερική/Μόντρεαλ"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "ΗΠΑ/Ανατολική ακτή - Κεμπέκ - περισσότερες περιοχές"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Αμερική/Μοντσεράτ"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Αμερική/Νασσάου"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Αμερική/Νέα Υόρκη"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "ΗΠΑ/Ανατολική ακτή"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Αμερική/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+"ΗΠΑ/Ανατολική ακτή - Οντάριο & Κεμπέκ - περιοχές που δεν τηρούν το DST "
+"1967-1973"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Αμερική/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "Ώρα Αλάσκας - δυτική Αλάσκα"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Αμερική/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "Νησιά Ατλαντικού"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Αμερική/Βόρεια_Ντακότα/Κέντρο"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "ΗΠΑ/Κεντρική - Βόρεια Ντακότα - Oliver County"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "Αμερική/Βόρεια_Ντακότα/Νέο_Σάλεμ"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "ΗΠΑ/Κεντρική - Βόρεια Ντακότα - Morton County (εκτός περιοχής Mandan)"
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "Αμερική/Μανάγκουα"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+#, fuzzy
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "ΗΠΑ/Mountain - Chihuahua"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Αμερική/Παναμάς"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Αμερική/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "ΗΠΑ/Ανατολική ακτή - Pangnirtung, Nunavut"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Αμερική/Παραμαρίμπο"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Αμερική/Φοίνιξ"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "ΗΠΑ/Mountain - Αριζόνα"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Αμερική/Πορτ-ο-Πρενς"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Αμερική/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Αμερική/Πορτ_οφ_Σπέιν"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Αμερική/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "Ροντονία"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Αμερική/Πουέρτο Ρίκο"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Αμερική/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "ΗΠΑ/Κεντρική - Rainy River & Fort Frances, Οντάριο"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Αμερική/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "ΗΠΑ/Κεντρική - κεντρική Nunavut"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Αμερική/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "Περναμπούκο"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Αμερική/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "ΗΠΑ/Κεντρική - - Saskatchewan - περισσότερες περιοχές"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "Αμερική/Resolute"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "ΗΠΑ/Ανατολική - Resolute, Nunavut"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Αμερική/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "Ακρ"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Αμερική/Rosario"
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "Αμερική/Santarem"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "Αμερική/Santarem"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "Δ. Para"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Αμερική/Σαντιάγκο"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Αμερική/Άγιος_Δομίνικος"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Αμερική/Σάο_Πάολο"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "Β. και ΒΑ Βραζιλία (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Αμερική/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "Scoresbysund / Ittoqqortoormiit"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Αμερική/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "ΗΠΑ/Mountain - Ναβάχο"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "Αμερική/Άγιος Βαρθολομαιος (Σεν Μπαρτς)"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Αμερική/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "Newfoundland Time, including SE Labrador"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Αμερική/Αγίου_Χριστόφορου_(Κιτς)"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Αμερική/Αγία_Λουκία"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Αμερική/Άγιος_Θωμάς"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Αμερική/Άγιος_Βικέντιος"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Αμερική/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "ΗΠΑ/Κεντρική - Saskatchewan - midwest"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Αμερική/Τεγκουσιγκάλπα"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Αμερική/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "Thule / Pituffik"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Αμερική/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "ΗΠΑ/Ανατολική ακτή - Thunder Bay, Οντάριο"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Αμερική/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "Αμερική/Τορόντο"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "ΗΠΑ/Ανατολική ακτή - Οντάριο - περισσότερες περιοχές"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Αμερική/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Αμερική/Βανκούβερ"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "ΗΠΑ/Ειρηνικός - Δυτική Κολομβία"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Αμερική/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Αμερική/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "ΗΠΑ/Κεντρική - νότια Yukon"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Αμερική/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "ΗΠΑ/Κεντρική - Manitoba & δυτικό Οντάριο"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Αμερική/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "Ώρα Αλάσκας - Alaska panhandle neck"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Αμερική/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "ΗΠΑ/Mountain - central Northwest Territories"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Ανταρκτική/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "Casey Station, Bailey Peninsula"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Ανταρκτική/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "Davis Station, Vestfold Hills"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Ανταρκτική/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "Dumont-d'Urville Station, Terre Adelie"
+
+#: timezones.h:425
+#, fuzzy
+msgid "Antarctica/Macquarie"
+msgstr "Ανταρκτική/McMurdo"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+#, fuzzy
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "McMurdo Station, Ross Island"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Ανταρκτική/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "Mawson Station, Holme Bay"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Ανταρκτική/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "McMurdo Station, Ross Island"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Ανταρκτική/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "Palmer Station, Anvers Island"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Ανταρκτική/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "Rothera Station, Adelaide Island"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Ανταρκτική/Νότιος_Πόλος"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "Amundsen-Scott Station, South Pole"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Ανταρκτική/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "Syowa Station, E Ongul I"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Ανταρκτική/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "Vostok Station, S Magnetic Pole"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Αρκτική/Λόνγκγεαρμπγεν"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Ασία/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Ασία/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Ασία/Αμμάν"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Ασία/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+#, fuzzy
+msgid "Moscow+08 - Bering Sea"
+msgstr "Μόσχα+10 - Θάλασσα Μπέρινγκ"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Ασία/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Ασία/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "Aqtobe (Aktobe)"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Ασία/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Ασία/Ασγκαμπάτ"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Ασία/Βαγδάτη"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Ασία/Μπαχρέιν"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Ασία/Μπακού"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Ασία/Μπανγκόκ"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Ασία/Βηρυτός"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Ασία/Μπισκέκ"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Ασία/Μπρουνέι"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Ασία/Καλκούτα"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Ασία/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "Dornod, Sukhbaatar"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Ασία/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "κεντρική Κίνα - Σιτσουάν, Γιουνάν, Γκουανξί, Σαανχί, ΓΚουίζου, κλπ. "
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Ασία/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Ασία/Κολόμπο"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Ασία/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Ασία/Δαμασκός"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Ασία/Ντάκα"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Ασία/Ντίλι"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Ασία/Ντουμπάι"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Ασία/Ντουσάνμπε"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Ασία/Γάζα"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Ασία/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "Heilongjiang (εκτός Mohe), Jilin"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Ασία/Χο Τσι Μινχ"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Ασία/Χονγκ_Κογκ"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Ασία/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Ασία/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Μόσχα+05 - Λίμνη Βα"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Ασία/Istanbul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Ασία/Τζακάρτα"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "Ιάβα και Σουμάτρα"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Ασία/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "Irian Jaya και Moluccas"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Ασία/Ιερουσαλήμ"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Ασία/Καμπούλ"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Ασία/Kamchatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+#, fuzzy
+msgid "Moscow+08 - Kamchatka"
+msgstr "Μόσχα+09 - Καμτσάτκα"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Ασία/Καράτσι"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Ασία/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "Δυτικό ΘΙβέτ και Xinjiang"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "Ασία/Κατμαντού"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Ασία/Κατμαντού"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "Ασία/Kolkata"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Ασία/Krasnoyarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "Μόσχα+04 - Ποταμός Γεινισέϊ"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Ασία/Κουάλα_Λουμπούρ"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "Πενινσούλα Μαλαισία"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Ασία/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "Sabah και Sarawak"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Ασία/Κουβέιτ"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Ασία/Μακάο"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Ασία/Macau"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Ασία/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "Μόσχα+08 - Μαγαδάν"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Ασία/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+"ανατολικό & νότιο Μπόρνεο, Σέλεμπες, Μπαλί, Νούσα Τενάγκρα, δυτικό Τιμόρ"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Ασία/Μανίλα"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Ασία/Μουσκάτ"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Ασία/Λευκωσία"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "Ασία/Irkutsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Μόσχα+03 - Novosibirsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Ασία/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Μόσχα+03 - Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Ασία/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "Μόσχα+03 - δυτική Σιβηρία "
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Ασία/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "Δυτικό Καζακστάν"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Ασία/Πνομ_Πενχ"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Ασία/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "δυτικό & κεντρικό Μπόρνεο"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Ασία/Πιονγιάνγκ"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Ασία/Κατάρ"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Ασία/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Ασία/Rangoon"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Ασία/Ριάντ"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Ασία/Ριάντ87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Ασία/Ριάντ88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Ασία/Ριάντ89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Ασία/Σαϊγκόν"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Ασία/Sakhalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "Μόσχα+07 - νήσος Sakhalin"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Ασία/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "δυτικό Ουζμπεκιστάν "
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Ασία/Σεούλ"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Ασία/Σαγκάη"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "ανατολική Κίνα - Πεκίνο, Γκουαντόνγκ, Σαγκάη, κτλ. "
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Ασία/Σινγκαπούρη"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Ασία/Ταϊπέι"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Ασία/Τασκένδη"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "ανατολικό ουζμπεκιστάν"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Ασία/Τιφλίδα"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Ασία/Τεχεράνη"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Ασία/Τελ_Αβίβ"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Ασία/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Ασία/Θιμπού"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Ασία/Τόκιο"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Ασία/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Ασία/Ulaanbaatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Ασία/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Ασία/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "περισσότερα από Θιβέτ & Xinjiang"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Ασία/Βιεντιάν"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Ασία/Βλαδιβοστόκ"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "Μόσχα+07 - Αμουρ ποταμός"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Ασία/Yakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "Μόσχα+06 - Λένας Ποταμός "
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Ασία/Yekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "Μόσχα+02 - Ουράλης"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Ασία/Ερεβάν"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Ατλαντικός/Αζόρες"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "Αζόρες"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Ατλαντικός/Βερμούδες"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Ατλαντικός/Κανάριοι_Νήσοι"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "Κανάρια Νησιά"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Ατλαντικός/Πράσινο_Ακρωτήριο"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Ατλαντικός/Φερόες"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "Ατλαντικός/Φερόες Νήσοι"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Ατλαντικός/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Ατλαντικός/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "Νησιά Μαδέρας"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Ατλαντικός/Ρέικιαβικ"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Ατλαντικός/Νότια_Γεωργία"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Ατλαντικός/Στάνλεϊ"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Ατλαντικός/Αγία_Ελένη"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Αυστραλία/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Αυστραλία/Αδελαΐδα"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "Νότια Αυστραλία"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Αυστραλία/Μπρίσμπεϊν"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "Κουίνσλαντ - περισσότερες περιοχές"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Αυστραλία/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "Νέα Νότια Ουαλία - Yancowinna"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Αυστραλία/Canberra"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Αυστραλία/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "Τασμανία - Νήσος Κίνγκ"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Αυστραλία/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "Northern Territory"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "Αυστραλία/Eucla"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "Δυτική Αυστραλία - περιοχή Eucla "
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Αυστραλία/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "Ταζμανία - περισσότερες περιοχές"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Αυστραλία/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Αυστραλία/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "Κουίνσλαντ - Holiday Islands"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Αυστραλία/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "Νήσος Λόρντ Χάουι"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Αυστραλία/Μελβούρνη"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Αυστραλία/Βόρεια"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Αυστραλία/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Αυστραλία/Πέρθ"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "Δυτική Αυστραλία - περισσότερες περιοχές"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Αυστραλία/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Αυστραλία/Νότια"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Αυστραλία/Σίδνεϊ"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "Νέα Νότια Ουαλία - περισσότερες περιοχές"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Αυστραλία/Tasmania"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Αυστραλία/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Αυστραλία/Δυτική"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Αυστραλία/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Βραζιλία/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Βραζιλία/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Βραζιλία/Ανατολική"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Βραζιλία/Δυτική"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Καναδάς/Ατλαντικός"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Καναδάς/Κεντρικός"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Καναδάς/Ανατολικός"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Καναδάς/East-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Καναδάς/Mountain"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Καναδάς/Newfoundland"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Καναδάς/Pacific"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Καναδάς/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Καναδάς/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Χιλή/Continental"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Χιλή/EasterIsland"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Κούβα"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Αίγυπτος"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Εΐρε"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Ζουλού"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Ευρώπη/Άμστερνταμ"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Ευρώπη/Ανδόρα"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Ευρώπη/Αθήνα"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Ευρώπη/Μπέλφαστ"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Ευρώπη/Βελιγράδι"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Ευρώπη/Βερολίνο"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Ευρώπη/Μπρατισλάβα"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Ευρώπη/Βρυξέλες"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Ευρώπη/Βουκουρέστι"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Ευρώπη/Βουδαπέστη"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Ευρώπη/Κισινάου"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Ευρώπη/Κοπενχάγη"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Ευρώπη/Δουβλίνο"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Ευρώπη/Γιβραλτάρ"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Ευρώπη/Γκουέρσνευ"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Ευρώπη/Ελνσίνκι"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Ευρώπη/Νήσος_Μαν"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Ευρώπη/Κωνσταντινούπολη"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Ευρώπη/Τζέρσεϊ"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Ευρώπη/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Μόσχα-01 - Καλινγκραντ"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Ευρώπη/Κίεβο"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Ευρώπη/Λισαβώνα"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Ευρώπη/Λιουμπλιάνα"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Ευρώπη/Λονδίνο"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Ευρώπη/Λουξεμβούργο"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Ευρώπη/Μαδρίτη"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Ευρώπη/Μάλτα"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Ευρώπη/Mariehamn"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Ευρώπη/Μίνσκ"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Ευρώπη/Μονακό"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Ευρώπη/Μόσχα"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "Μόσχα+00 - δυτική Ρωσία"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Ευρώπη/Λευκωσία"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Ευρώπη/Όσλο"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Ευρώπη/Παρίσι"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Ευρώπη/Podgorica"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Ευρώπη/Πράγα"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Ευρώπη/Ρήγα"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Ευρώπη/Ρώμη"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Ευρώπη/Σαμάρα"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+#, fuzzy
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Μόσχα+00 - Σαμάρα, Ουντμουρτία "
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Ευρώπη/Άγιος_Μαρίνος"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Ευρώπη/Σεράγεβο"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Ευρώπη/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "κεντρική Κριμέα"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Ευρώπη/Σκόπια"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Ευρώπη/Σόφια"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Ευρώπη/Στοκχόλμη"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Ευρώπη/Ταλίν"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Ευρώπη/Τίρανα"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Ευρώπη/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Ευρώπη/Uzhgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "Ruthenia"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Ευρώπη/Βαντούζ"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Ευρώπη/Βατικανό"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Ευρώπη/Βιέννη"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Ευρώπη/Βίλνα"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Ευρώπη/Volgograd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "Μόσχα+00 - Κασπία θάλασσα "
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Ευρώπη/Βαρσοβία"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Ευρώπη/Ζάγκρεπ"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Ευρώπη/Zaporozhye"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Ευρώπη/Ζυρίχη"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Εργοστάσιο"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Eire"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Γκρήνουιτς"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Χονγκ Κονγκ"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Ισλανδία"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Ινδικός/Ανταναναρίβο"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Ινδικός/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Ινδικός/Christmas"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Ινδικός/Κόκος"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Ινδικός/Comoro"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Ινδικός/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Ινδικός/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Ινδικός/Μαλδίβες"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Ινδικός/Μαυρίκιος"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Ινδικός/Μαγιότ"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Ινδικός/Ρεϋνιόν"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Ιράν"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Ισραήλ"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Τζαμάικα"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Ιαπωνία"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Λιβύη"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Μεξικό/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Μεξικό/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Μεξικό/Γενικά"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Μέση ανατολή/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Μέση ανατολή/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Μέση ανατολή/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Ναβάχο"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Ειρηνικός/Άπια"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Ειρηνικός/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Ειρηνικός/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "Νησιά Chatham "
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "Ειρηνικός/Truk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+#, fuzzy
+msgid "Chuuk (Truk) and Yap"
+msgstr "Truk (Chuuk) και Yap"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Ειρηνικός/Νησιά του Πάσχα"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "Νησί Πάσχα & Σάλα ι Γκομέζ"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Ειρηνικός/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Ειρηνικός/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "Νησιά Φοίνικα"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Ειρηνικός/Φακαόφο"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Ειρηνικός/Φίτζι"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Ειρηνικός/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Ειρηνικός/Γκαλαπάγκος"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "Νησιά Γκαλαπάγκος"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Ειρηνικός/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "Νησιά Γκαπιέρ "
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Ειρηνικός/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Ειρηνικός/Γκουάμ"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Ειρηνικός/Χονολουλού"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "Χαβάη"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Ειρηνικός/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "Johnston Atoll"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Ειρηνικός/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "Νησιά Λάιν"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Ειρηνικός/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "Kosrae"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Ειρηνικός/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Ειρηνικός/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Ειρηνικός/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "Νησιά Μαρκέσας "
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Ειρηνικός/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "Νησιά Μίντγουέϊ"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Ειρηνικός/Ναουρού"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Ειρηνικός/Νιούε"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Ειρηνικός/Νόρφοκ"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Ειρηνικός/Νουμέα"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Ειρηνικός/Πάγκο_Πάγκο"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Ειρηνικός/Παλάου"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Ειρηνικός/Πίτκαιρν"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "Ειρηνικός/Ponape"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+#, fuzzy
+msgid "Pohnpei (Ponape)"
+msgstr "Ponape (Pohnpei)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Ειρηνικός/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Ειρηνικός/Πορτ_Μόρεσμπι"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Ειρηνικός/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Ειρηνικός/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Ειρηνικός/Σαμόα"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Ειρηνικός/Ταϊτή"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "Νησιά Society"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Ειρηνικός/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "Νησιά Γκίλμπερτ"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Ειρηνικός/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Ειρηνικός/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Ειρηνικός/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "Νησί Γουέικ "
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Ειρηνικός/Βαλίς"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Ειρηνικός/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Πολωνία"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Πορτογαλία"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Σινγκαπούρη"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Τουρκία"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "ΗΠΑ/Αλάσκα"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "ΗΠΑ/Aleutian"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "ΗΠΑ/Αριζόνα"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "ΗΠΑ/Κεντρική"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "ΗΠΑ/Ανατολική"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "ΗΠΑ/East-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "ΗΠΑ/Χαβάη"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "ΗΠΑ/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "ΗΠΑ/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "ΗΠΑ/Mountain"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "ΗΠΑ/Ειρηνικός"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "ΗΠΑ/Σαμόα"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Ζουλού"
+
+#~ msgid "US/Pacific-New"
+#~ msgstr "ΗΠΑ/Ειρηνικός-Νέος"
diff --git a/panels/datetime/po-timezones/en_GB.po b/panels/datetime/po-timezones/en_GB.po
new file mode 100644
index 0000000..b0a2fef
--- /dev/null
+++ b/panels/datetime/po-timezones/en_GB.po
@@ -0,0 +1,3262 @@
+# English (British) translation.
+# Copyright (C) 2010 system-config-date's COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# Abigail Brady <morwen@evilmagic.org>, Bastien Nocera <hadess@hadess.net>, 2010.
+# Bruce Cowan <bcowan@fastmail.co.uk>, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-02-28 20:20+0100\n"
+"Last-Translator: Bruce Cowan <bcowan@fastmail.co.uk>\n"
+"Language-Team: British English <en@li.org>\n"
+"Language: en_GB\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Virtaal 0.5.2\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Africa/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Africa/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Africa/Addis_Ababa"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Africa/Algiers"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "Africa/Asmara"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Africa/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Africa/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Africa/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Africa/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Africa/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Africa/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Africa/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Africa/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Africa/Cairo"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Africa/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Africa/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "Ceuta & Melilla"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Africa/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Africa/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Africa/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Africa/Djibouti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Africa/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Africa/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Africa/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Africa/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Africa/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Africa/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Africa/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Africa/Khartoum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Africa/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Africa/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "west Dem. Rep. of Congo"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Africa/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Africa/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Africa/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Africa/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Africa/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "east Dem. Rep. of Congo"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Africa/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Africa/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Africa/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Africa/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Africa/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Africa/Mogadishu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Africa/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Africa/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Africa/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Africa/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Africa/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Africa/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Africa/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Africa/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Africa/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Africa/Tripoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Africa/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Africa/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "America/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Aleutian Islands"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "America/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Alaska Time"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "America/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "America/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "America/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "Tocantins"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "America/Argentina/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Buenos Aires (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "America/Argentina/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "Catamarca (CT), Chubut (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "America/Argentina/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "America/Argentina/Cordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "America/Argentina/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Jujuy (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "America/Argentina/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "La Rioja (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "America/Argentina/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "Mendoza (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "America/Argentina/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "Santa Cruz (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "America/Argentina/Salta"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "America/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "San Juan (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "America/Argentina/San_Luis"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "San Luis (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "America/Argentina/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "Tucuman (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "America/Argentina/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "Tierra del Fuego (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "America/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "America/Asuncion"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "America/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "America/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "America/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "Bahia"
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "America/Bahia"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "America/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "America/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "Amapa, E Para"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "America/Belize"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "America/Blanc-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "Atlantic Standard Time - Quebec - Lower North Shore"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "America/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "Roraima"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "America/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "America/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "Mountain Time - south Idaho & east Oregon"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "America/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "America/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "Mountain Time - west Nunavut"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "America/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "Mato Grosso do Sul"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "America/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "Central Time - Quintana Roo"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "America/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "America/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "America/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "America/Cayman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "America/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "Central Time"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "America/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+#, fuzzy
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "Mountain Time - Chihuahua"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "America/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "America/Cordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "America/Costa_Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "America/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "Mato Grosso"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "America/Curacao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "America/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "east coast, north of Scoresbysund"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "America/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "Pacific Time - north Yukon"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "America/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "America/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "Mountain Time"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "America/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "Eastern Time - Michigan - most locations"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "America/Dominica"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "America/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "America/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "W Amazonas"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "America/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "America/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "America/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "NE Brazil (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "America/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "America/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+"Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "America/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "most locations"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "America/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "Atlantic Time - Labrador - most locations"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "America/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "America/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "America/Guadeloupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "America/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "America/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "mainland"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "America/Guyana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "America/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "Atlantic Time - Nova Scotia (most places), PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "America/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "America/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "Mountain Standard Time - Sonora"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "America/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "Eastern Time - Indiana - most locations"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "America/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "Central Time - Indiana - Starke County"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "America/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "Eastern Time - Indiana - Crawford County"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "America/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "Eastern Time - Indiana - Pike County"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "America/Indianapolis"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "America/Indiana/Tell_City"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "Central Time - Indiana - Perry County"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "America/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "Eastern Time - Indiana - Switzerland County"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "America/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "America/Indiana/Winamac"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "Eastern Time - Indiana - Pulaski County"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "America/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "Mountain Time - west Northwest Territories"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "America/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "Eastern Time - east Nunavut - most locations"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "America/Jamaica"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "America/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "America/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "Alaska Time - Alaska panhandle"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "America/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Eastern Time - Kentucky - Louisville area"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "America/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "Eastern Time - Kentucky - Wayne County"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "America/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "America/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "America/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "America/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "Pacific Time"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "America/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "America/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "Alagoas, Sergipe"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "America/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "America/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "E Amazonas"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "America/Marigot"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "America/Martinique"
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "America/Manaus"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+#, fuzzy
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr "Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "America/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "Mountain Time - S Baja, Nayarit, Sinaloa"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "America/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "America/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+"Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "America/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "Central Time - Campeche, Yucatan"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "America/Mexico_City"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "Central Time - most locations"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "America/Miquelon"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "America/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "Atlantic Time - New Brunswick"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "America/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+#, fuzzy
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr "Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "America/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "America/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "Eastern Time - Quebec - most locations"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "America/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "America/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "America/New_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "Eastern Time"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "America/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "America/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "Alaska Time - west Alaska"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "America/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "Atlantic islands"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "America/North_Dakota/Centre"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "Central Time - North Dakota - Oliver County"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "America/North_Dakota/New_Salem"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "Central Time - North Dakota - Morton County (except Mandan area)"
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "America/Managua"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+#, fuzzy
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "Mountain Time - Chihuahua"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "America/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "America/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "Eastern Time - Pangnirtung, Nunavut"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "America/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "America/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "Mountain Standard Time - Arizona"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "America/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "America/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "America/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "America/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "Rondonia"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "America/Puerto_Rico"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "America/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "Central Time - Rainy River & Fort Frances, Ontario"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "America/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "Central Time - central Nunavut"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "America/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "Pernambuco"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "America/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "Central Standard Time - Saskatchewan - most locations"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "America/Resolute"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "Eastern Standard Time - Resolute, Nunavut"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "America/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "Acre"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "America/Rosario"
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "America/Santarem"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "America/Santarem"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "W Para"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "America/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "America/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "America/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "America/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "Scoresbysund / Ittoqqortoormiit"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "America/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "Mountain Time - Navajo"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "America/St_Barthelemy"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "America/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "Newfoundland Time, including SE Labrador"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "America/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "America/St_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "America/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "America/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "America/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "Central Standard Time - Saskatchewan - midwest"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "America/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "America/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "Thule / Pituffik"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "America/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "Eastern Time - Thunder Bay, Ontario"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "America/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "America/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "Eastern Time - Ontario - most locations"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "America/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "America/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "Pacific Time - west British Columbia"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "America/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "America/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "Pacific Time - south Yukon"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "America/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "Central Time - Manitoba & west Ontario"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "America/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "Alaska Time - Alaska panhandle neck"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "America/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "Mountain Time - central Northwest Territories"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antarctica/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "Casey Station, Bailey Peninsula"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antarctica/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "Davis Station, Vestfold Hills"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antarctica/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "Dumont-d'Urville Station, Terre Adelie"
+
+#: timezones.h:425
+#, fuzzy
+msgid "Antarctica/Macquarie"
+msgstr "Antarctica/McMurdo"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+#, fuzzy
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "McMurdo Station, Ross Island"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antarctica/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "Mawson Station, Holme Bay"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antarctica/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "McMurdo Station, Ross Island"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antarctica/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "Palmer Station, Anvers Island"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antarctica/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "Rothera Station, Adelaide Island"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antarctica/South_Pole"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "Amundsen-Scott Station, South Pole"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antarctica/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "Syowa Station, E Ongul I"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antarctica/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "Vostok Station, S Magnetic Pole"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Arctic/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Asia/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Asia/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Asia/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Asia/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+#, fuzzy
+msgid "Moscow+08 - Bering Sea"
+msgstr "Moscow+10 - Bering Sea"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Asia/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Asia/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "Aqtobe (Aktobe)"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Asia/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Asia/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Asia/Baghdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Asia/Bahrain"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Asia/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Asia/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Asia/Beirut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Asia/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Asia/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Asia/Calcutta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Asia/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "Dornod, Sukhbaatar"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Asia/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Asia/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Asia/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Asia/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Asia/Damascus"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Asia/Dhaka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Asia/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Asia/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Asia/Dushanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Asia/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Asia/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "Heilongjiang (except Mohe), Jilin"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Asia/Ho_Chi_Minh"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Asia/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Asia/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Asia/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Moscow+05 - Lake Baikal"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Asia/Istanbul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Asia/Jakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "Java & Sumatra"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Asia/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "Irian Jaya & the Moluccas"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Asia/Jerusalem"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Asia/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Asia/Kamchatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+#, fuzzy
+msgid "Moscow+08 - Kamchatka"
+msgstr "Moscow+09 - Kamchatka"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Asia/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Asia/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "west Tibet & Xinjiang"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "Asia/Kathmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Asia/Katmandu"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "Asia/Kolkata"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Asia/Krasnoyarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "Moscow+04 - Yenisei River"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Asia/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "peninsular Malaysia"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Asia/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "Sabah & Sarawak"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Asia/Kuwait"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Asia/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Asia/Macau"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Asia/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "Moscow+08 - Magadan"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Asia/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Asia/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Asia/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Asia/Nicosia"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "Asia/Irkutsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Moscow+03 - Novosibirsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Asia/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Moscow+03 - Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Asia/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "Moscow+03 - west Siberia"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Asia/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "West Kazakhstan"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Asia/Phnom_Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Asia/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "west & central Borneo"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Asia/Pyongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Asia/Qatar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Asia/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Asia/Rangoon"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Asia/Riyadh"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Asia/Riyadh87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Asia/Riyadh88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Asia/Riyadh89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Asia/Saigon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Asia/Sakhalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "Moscow+07 - Sakhalin Island"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Asia/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "west Uzbekistan"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Asia/Seoul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Asia/Shanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "east China - Beijing, Guangdong, Shanghai, etc."
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Asia/Singapore"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Asia/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Asia/Tashkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "east Uzbekistan"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Asia/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Asia/Tehran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Asia/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Asia/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Asia/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Asia/Tokyo"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Asia/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Asia/Ulaanbaatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Asia/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Asia/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "most of Tibet & Xinjiang"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Asia/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Asia/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "Moscow+07 - Amur River"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Asia/Yakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "Moscow+06 - Lena River"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Asia/Yekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "Moscow+02 - Urals"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Asia/Yerevan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlantic/Azores"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "Azores"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlantic/Bermuda"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlantic/Canary"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "Canary Islands"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlantic/Cape_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlantic/Faeroe"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "Atlantic/Faroe"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlantic/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlantic/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "Madeira Islands"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlantic/Reykjavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlantic/South_Georgia"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlantic/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlantic/St_Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Australia/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Australia/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "South Australia"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Australia/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "Queensland - most locations"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Australia/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "New South Wales - Yancowinna"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Australia/Canberra"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Australia/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "Tasmania - King Island"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Australia/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "Northern Territory"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "Australia/Eucla"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "Western Australia - Eucla area"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Australia/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "Tasmania - most locations"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Australia/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Australia/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "Queensland - Holiday Islands"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Australia/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "Lord Howe Island"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Australia/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Australia/North"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Australia/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Australia/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "Western Australia - most locations"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Australia/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Australia/South"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Australia/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "New South Wales - most locations"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Australia/Tasmania"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Australia/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Australia/West"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Australia/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brazil/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brazil/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brazil/East"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brazil/West"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Canada/Atlantic"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Canada/Central"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Canada/Eastern"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Canada/East-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Canada/Mountain"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Canada/Newfoundland"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Canada/Pacific"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Canada/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Canada/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Chile/Continental"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Chile/EasterIsland"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Cuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Egypt"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Eire"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Europe/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Europe/Andorra"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Europe/Athens"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Europe/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Europe/Belgrade"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Europe/Berlin"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Europe/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Europe/Brussels"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Europe/Bucharest"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Europe/Budapest"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Europe/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Europe/Copenhagen"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Europe/Dublin"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Europe/Gibraltar"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Europe/Guernsey"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Europe/Helsinki"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Europe/Isle_of_Man"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Europe/Istanbul"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Europe/Jersey"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Europe/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Moscow-01 - Kaliningrad"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Europe/Kiev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Europe/Lisbon"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Europe/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Europe/London"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Europe/Luxembourg"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Europe/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Europe/Malta"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Europe/Mariehamn"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Europe/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Europe/Monaco"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Europe/Moscow"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "Moscow+00 - west Russia"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Europe/Nicosia"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Europe/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Europe/Paris"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Europe/Podgorica"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Europe/Prague"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Europe/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Europe/Rome"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Europe/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+#, fuzzy
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Moscow+01 - Samara, Udmurtia"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Europe/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Europe/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Europe/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "central Crimea"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Europe/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Europe/Sofia"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Europe/Stockholm"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Europe/Tallinn"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Europe/Tirane"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Europe/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Europe/Uzhgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "Ruthenia"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Europe/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Europe/Vatican"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Europe/Vienna"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Europe/Vilnius"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Europe/Volgograd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "Moscow+00 - Caspian Sea"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Europe/Warsaw"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Europe/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Europe/Zaporozhye"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Europe/Zurich"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Factory"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Eire"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Iceland"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Indian/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Indian/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Indian/Christmas"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Indian/Cocos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Indian/Comoro"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Indian/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Indian/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Indian/Maldives"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Indian/Mauritius"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Indian/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Indian/Reunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Iran"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Israel"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamaica"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Japan"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Libya"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Mexico/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Mexico/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Mexico/General"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Mideast/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Mideast/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Mideast/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Pacific/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Pacific/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Pacific/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "Chatham Islands"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "Pacific/Truk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+#, fuzzy
+msgid "Chuuk (Truk) and Yap"
+msgstr "Truk (Chuuk) and Yap"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Pacific/Easter"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "Easter Island & Sala y Gomez"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Pacific/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Pacific/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "Phoenix Islands"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Pacific/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Pacific/Fiji"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Pacific/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Pacific/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "Galapagos Islands"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Pacific/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "Gambier Islands"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Pacific/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Pacific/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Pacific/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "Hawaii"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Pacific/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "Johnston Atoll"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Pacific/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "Line Islands"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Pacific/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "Kosrae"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Pacific/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Pacific/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Pacific/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "Marquesas Islands"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Pacific/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "Midway Islands"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Pacific/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Pacific/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Pacific/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Pacific/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Pacific/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Pacific/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Pacific/Pitcairn"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "Pacific/Ponape"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+#, fuzzy
+msgid "Pohnpei (Ponape)"
+msgstr "Ponape (Pohnpei)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Pacific/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Pacific/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Pacific/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Pacific/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Pacific/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Pacific/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "Society Islands"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Pacific/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "Gilbert Islands"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Pacific/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Pacific/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Pacific/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "Wake Island"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Pacific/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Pacific/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Poland"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugal"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapore"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Turkey"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "US/Alaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "US/Aleutian"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "US/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "US/Central"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "US/Eastern"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "US/East-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "US/Hawaii"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "US/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "US/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "US/Mountain"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "US/Pacific"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "US/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
diff --git a/panels/datetime/po-timezones/es.po b/panels/datetime/po-timezones/es.po
new file mode 100644
index 0000000..a9573d4
--- /dev/null
+++ b/panels/datetime/po-timezones/es.po
@@ -0,0 +1,3252 @@
+# translation of timezones.tip.es.po to Spanish
+# translation of es.po to
+# Copyright (C) 2004, 2006, 2008 Free Software Foundation, Inc.
+#
+# Tullio Dovera <tdovera@redhat.it>, 2000.
+# Yelitza Louze <ylouze@redhat.com>, 2004.
+# Manuel Ospina <mospina@redhat.com>, 2006.
+# Domingo Becker <domingobecker@gmail.com>, 2008.
+# Héctor Daniel Cabrera <logan@fedoraproject.org>, 2010.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones.tip.es\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-08-25 09:11-0300\n"
+"Last-Translator: Claudio Rodrigo Pereyra Diaz <claudiorodrigo@pereyradiaz.com.ar>\n"
+"Language-Team: Fedora Spanish <trans-es@lists.fedoraproject.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: \n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Spanish\n"
+"X-Poedit-Country: ARGENTINA\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "África/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "África/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "África/Addis_Abeba"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "África/Argelia"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "África/Asmera"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "África/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "África/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "África/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "África/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "África/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "África/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "África/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "África/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "África/El_Cairo"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "África/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "África/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "Ceuta & Melilla"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "África/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "África/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "África/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "África/Djibouti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "África/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "África/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "África/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "África/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "África/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "África/Johannesburgo"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "África/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "África/Khartoum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "África/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "África/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "Rep. Dem. del Congo oeste"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "África/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "África/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "África/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "África/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "África/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "Rep. Dem. del Congo este"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "África/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "África/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "África/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "África/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "África/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "África/Mogadisco"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "África/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "África/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "África/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "África/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "África/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "África/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "África/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "África/Santo_Tomé"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "África/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "África/Trípoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "África/Túnez"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "África/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "América/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Islas Aleutianas"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "América/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Hora de Alaska"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "América/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "América/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "América/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "Tocantins"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "América/Argentina/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Buenos Aires (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "América/Argentina/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "Catamarca (CT), Chubut (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "América/Argentina/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "América/Argentina/Cordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "mayoría de las localidades (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "América/Argentina/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Jujuy (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "América/Argentina/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "La Rioja (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "América/Argentina/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "Mendoza (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "América/Argentina/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "Santa Cruz (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "America/Argentina/Salta"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "América/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "San Juan (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "America/Argentina/San_Luis"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "San Luis (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "América/Argentina/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "Tucuman (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "América/Argentina/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "Tierra del Fuego (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "América/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "América/Asunción"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "América/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "Hora estándar del este - Atikokan, Ontario e Southampton I, Nunavut"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "América/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "América/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "Bahia"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "América/Bahia_Banderas"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "Tiempo Central Mexicano - Bahía de Banderas"
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "América/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "América/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "Amapa, Para E"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "América/Belice"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "América/Blanc-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "Hora estándar del atlántico - Quebec - Lower North Shore"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "América/Boa Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "Roraima"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "América/Bogotá"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "América/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "Hora de la Montaña - Idaho sur & Oregon este"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "América/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "América/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "Hora de la Montaña - Nunavut oeste"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "América/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "Mato Grosso do Sul"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "América/Cancún"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "Hora Central - Quintana Roo"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "América/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "América/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "América/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "América/Caimán"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "América/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "Hora Central"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "América/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "Hora mexicana de montaña - Chihuahua, lejos de la frontera norteamericana"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "América/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "América/Córdoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "América/Costa_Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "América/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "Mato Grosso"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "América/Curacao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "América//Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "costa este, norte de Socresbysund"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "América/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "Hora del Pacífico - Yukon norte"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "América/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid "Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr "Hora estándar de Montaña - Dawson Creek & Fort Saint John, British Columbia"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "América/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "Hora de Montaña"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "América/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "Hora del Este - Michigan - la mayoría de las localidades"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "América/Dominica"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "América/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "Hora de Montaña - Alberta, east British Columbia & west Saskatchewan"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "América/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "Amazonas O"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "América/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "América/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "América/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "NE de Brasil (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "América/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "América/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr "Hora del Atlántico - Nueva Escocia - lugares que no observan el DST 1966-1971"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "América/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195
+#: timezones.h:364
+#: timezones.h:453
+#: timezones.h:591
+#: timezones.h:754
+#: timezones.h:852
+#: timezones.h:894
+msgid "most locations"
+msgstr "la mayoría de las localidades"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "América/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "Hora del Atlántico - Labrador - la mayoría de las localidades"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "América/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "América/Granada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "América/Guadalupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "América/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "América/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205
+#: timezones.h:757
+#: timezones.h:763
+msgid "mainland"
+msgstr "área principal"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "América/Guyana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "América/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "Hora del Atlántico - Nueva Escocia (la mayoría de las localidades), PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "América/Habana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "América/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "Hora estándar de la Montaña - Sonora"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "América/Indiana/Indianápolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "Hora del Este - Indiana - la mayoría de las localidades"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "América/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "Hora del Este - Indiana - Condado Starke"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "América/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "Hora del Este - Indiana - Condado Crawford"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "América/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "Hora del Este - Indiana - Condado Pike"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "América/Indianápolis"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "América/Indiana/Tell_City"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "Hora del Este - Indiana - Condado Perry"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "América/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "Hora del Este - Indiana - Condado Suiza"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "América/Indiana/Vencennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "Hora del Este - Indiana - Condados Daviess, Dubois, Knox & Martin"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "América/Indiana/Winamac"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "Hora del Este - Indiana - Condado Pulaski"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "América/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "Hora de la Montaña - Territorios Noroestes del oeste"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "América/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "Hora del Este - Nunavut del este - la mayoría de las localidades"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "América/Jamaica"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "América/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "América/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "Hora de Alaska - Península de Alaska"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "América//Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Hora del Este - Area Kentucky - Louisville"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "América/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "Hora del este - Kentucky - Condado de Wayne"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "América/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "América/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "América/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "América/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "Hora del Pacífico"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "América/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "América/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "Alagoas, Sergipe"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "América/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "América/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "Amazonas E"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "América/Marigot"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "América/Martinica"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "América/Matamoros"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid "US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr "Hora norteamericana central - Coahuila, Durango, Nuevo Leon, Tamaulipas, cerca de la frontera con los Estados Unidos"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "América/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "Hora de la Montaña - S Baja, Nayarit, Sinaloa"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "América/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "América/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "Hora Central - Michigan - Condados de Dickinson, Gogebic, Iron & Menominee"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "América/Mendoza"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "Hora Central - Campeche, Yucatán"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "América/Ciudad_de_México"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "Hora Central - la mayoría de las localidades"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "América/Miquelon"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "América/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "Hora del Atlántico - Nueva Brunswick"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "América/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid "Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from US border"
+msgstr "Hora mexicana central - Coahuila, Durango, Nuevo Leon, Tamaulipas, lejos de la frontera norteamericana"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "América/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "América/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "Hora del Este - Quebec - la mayoría de las localidades"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "América/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "América/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "América/Nueva_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "Hora del Este"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "América/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid "Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr "Hora del Este - Ontario & Quebec - lugares no adheridos al DST 1967-1973"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "América/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "Hora de Alaska - Alaska oeste"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "América/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "Islas del Atlántico"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "América/Dakota del Norte/Centro"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "Hora Central - North Dakota - Condado de Oliver"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "América/Dakota del Norte/Nueva Salem"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "Hora Central - North Dakota - Condado de Morton (excepto el área de Mandan)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "América/Ojinaga"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "Hora norteamericana de montaña - Chihuahua, cerca de la frontera con los Estados Unidos"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "América/Panamá"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "América/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "Hora del Este - Pangnirtung, Nunavut"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "América/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "América/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "Hora Estándar de la Montaña - Arizona"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "América/Puerto-Príncipe"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "América/Puerto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "América/Puerto_de_España"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "América/Puerto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "Rondonia"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "América/Puerto_Rico"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "América/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "Hora Central - Rainy River & Fort Frances, Ontario"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "América/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "Hora Central - Nunavut central"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "América/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "Pernambuco"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "América/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "Hora Estándar Central - Saskatchewan - la mayoría de las localidades"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "América/Resolute"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "Hora Estándar del Este - Resolute, Nunavut"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "América/Río Blanco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "Acre"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "América/Rosario"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "America/Santa_Isabel"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "Hora mexicana del Pacífico - Baja California, lejos de la frontera norteamericana"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "America/Santarem"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "Para O"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "América/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "América/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "América/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "Brasil S & SE (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "América/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "Scoresbysund / Ittoqqortoormiit"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "América/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "Hora de Montaña - Navajo"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "América/San_Bartolomé"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "América/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "Hora de Newfoundland,incluyendo Labrador SE"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "América/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "América/St_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "América/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "América/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "América/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "Hora Estándar Central - Saskatchewan - medio oeste"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "América/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "América/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "Thule / Pituffik"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "América/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "Hora del Este - Bahía Thunder, Ontario"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "América/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "Hora norteamericana del Pacífico - Baja California, cerca de la frontera con los Estados Unidos"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "América/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "Hora del Este - Ontario - la mayoría de las localidades"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "América/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "América/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "Hora del Pacífico - Columbia Británica oeste"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "América/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "América/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "Hora del Pacífico - Yukon sur"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "América/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "Hora Central - Manitoba & Ontario oeste"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "América/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "Hora de Alaska - cuello panhandle de Alaska"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "América/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "Hora de la Montaña - Territorios Noroeste centrales"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antártida/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "Estación Casey, Península de Bailey"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antártida/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "Estación Davis, Vestfold Hills"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antártida/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "Estación Dumont-d'Urville, Terre Adelie"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "Antártida/Macquarie"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "Estación de la Isla Macquarie, Isla Macquarie"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antártida/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "Estación Mawson, Bahía de Holme"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antártida/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "Estación McMurdo, Isla Ross"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antártida/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "Estación Palmer, Isla Anvers"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antárctica/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "Estación Rothera, Isla Adelaida"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antártida/Polo_sur"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "Estación Amundsen-Scott, Polo Sur"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antártida/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "Syowa Station, E Ongul I"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antártida/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "Estación Vostok, Polo Magnético Sur"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Ártico/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Asia/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Asia/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Asia/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Asia/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "Moscú+08 - Mar de Bering"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Asia/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Asia/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "Aqtobe (Aktobe)"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Asia/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Asia/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Asia/Bagdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Asia/Bahrain"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Asia/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Asia/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Asia/Beirut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Asia/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Asia/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Asia/Calcuta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Asia/Choibalsán"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "Dornod, Sukhbaatar"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Asia/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "China central - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Asia/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Asia/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Asia/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Asia/Damasco"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Asia/Dhaka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Asia/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Asia/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Asia/Dushanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Asia/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Asia/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "Heilongjiang (excepto Mohe), Jilin"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Asia/Ho_Chi_Minh"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Asia/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Asia/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Asia/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Moscú+05 - Lago Baikal"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Asia/Estambul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Asia/Yakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "Java & Sumatra"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Asia/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "Irian Jaya & las Moluccas"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Asia/Jerusalén"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Asia/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Asia/Kamchatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "Moscú+08 - Kamchatka"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Asia/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Asia/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "Tibet oeste & Xinjiang"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "Asia/Kathmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Asia/Katmandú"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "Asia/Kolkata"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Asia/Krasnoyarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "Moscú+04 - Yenisei River"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Asia/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "Malasia peninsular"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Asia/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "Sabah & Sarawak"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Asia/Kuwait"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Asia/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Asia/Macao"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Asia/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "Moscú+08 - Magadán"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Asia/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "este & sur de Borneo, Celebes, Bali, Nusa Tengarra, Timor oeste"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Asia/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Asia/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Asia/Nicosia"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "Asia/Novokuznetsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Moscú+03 - Novokuznetsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Asia/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Moscú+03 - Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Asia/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "Moscú+03 - west Siberia"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Asia/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "Kazajistán Oeste"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Asia/Phnom_Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Asia/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "Borneo oeste & central"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Asia/Pyongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Asia/Qatar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Asia/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Asia/Rangún"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Asia/Riyadh"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Asia/Riyadh87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Asia/Riyadh88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Asia/Riyadh89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Asia/Saigón"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Asia/Sakhalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "Moscú+07 - Isla Sakhalin"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Asia/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "Uzbekistán oeste"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Asia/Seúl"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Asia/Shanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "China del este - Beijing, Guangdong, Shanghai, etc."
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Asia/Singapur"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Asia/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Asia/Tashkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "Uzbekistán este"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Asia/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Asia/Teheran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Asia/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Asia/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Asia/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Asia/Tokio"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Asia/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Asia/Ulan_Bator"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Asia/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Asia/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "mayor parte del Tibet & Xinjiang"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Asia/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Asia/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "Moscú+07 - Amur River"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Asia/Yakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "Moscú+06 - Lena River"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Asia/Yekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "Moscú+02 - Urales"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Asia/Yerevan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlántico/Azores"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "Azores"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlántico/Bermudas"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlántico/Canarias"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "Islas Canarias"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlántico/Cabo_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlántico/Feroe"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "Atlántico/Feroe"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlántico/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlántico/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "Islas Madeira"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlántico/Reykjavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlántico/Georgia_del_Sur"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlántico/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlántico/St_Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Australia/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Australia/Adelaida"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "Sur de Australia"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Australia/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "Queensland - mayoría de las localidades"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Australia/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "Nueva Gales del Sur - Yancowinna"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Australia/Camberra"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Australia/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "Tasmania - Isla del Rey"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Australia/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "Territorio Norte"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "Australia/Eucla"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "Australia Oeste - Area Eucla"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Australia/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "Tasmania - mayoría de las localidades"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Australia/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Australia/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "Queensland - Islas Holiday"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Australia/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "Isla Lord Howe"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Australia/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Australia/Norte"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Australia/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Australia/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "Australia Oeste - la mayoría de las localidades"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Australia/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Australia/Sur"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Australia/Sidney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "Nueva Gales del Sur - la mayoría de las localidades"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Australia/Tasmania"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Australia/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Australia/Oeste"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Australia/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brasil/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brasil/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brasil/Este"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brasil/Oeste"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Canadá/Atlántico"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Canadá/Central"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Canadá/Oriental"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Canadá/East-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Canadá/Mountain"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Canadá/Newfoundland"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Canadá/Pacífico"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Canadá/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Canadá/Saskatchewan"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Chile/Continental"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Chile/Isla_de_Pascua"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Cuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Egipto"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Irlanda"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulú"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Europa/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Europa/Andorra"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Europa/Atenas"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Europa/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Europa/Belgrado"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Europa/Berlín"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Europa/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Europa/Bruselas"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Europa/Bucarest"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Europa/Budapest"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Europa/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Europa/Copenague"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Europa/Dublín"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Europa/Gibraltar"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Europa/Guernsey"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Europa/Helsinki"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Europa/Isla del Hombre"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Europa/Estambul"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Europa/Jersey"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Europa/Kaliningrado"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Moscú-01 - Kaliningrado"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Europa/Kiev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Europa/Lisboa"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Europa/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Europa/Londres"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Europa/Luxemburgo"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Europa/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Europa/Malta"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Europa/Mariehamn"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Europa/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Europa/Mónaco"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Europa/Moscú"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "Moscú+00 - oeste de Rusia"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Europa/Nicosia"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Europa/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Europa/París"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Europa/Podgorica"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Europa/Praga"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Europa/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Europa/Roma"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Europa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Moscú - Samara, Udmurtia"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Europa/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Europa/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Europa/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "Crimea central"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Europa/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Europa/Sofía"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Europa/Estocolmo"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Europa/Tallinn"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Europa/Tirana"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Europa/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Europa/Uzhgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "Ruthenia"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Europa/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Europa/Vaticano"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Europa/Viena"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Europa/Vilnius"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Europa/Volgogrado"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "Moscú+00 - Mar Caspio"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Europa/Warsaw"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Europa/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Europa/Zaporozheye"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Europa/Zúrich"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Factory"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Eire"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hong-Kong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Islandia"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Indico/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Indico/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Indico/Christmas"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Indico/Cocos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Indico/Comoro"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Indico/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Indico/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Indico/Maldivas"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Indico/Mauricio"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Índico/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Índico/Reunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Irán"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Israel"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamaica"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Japón"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835
+#: timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Libia"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Mexico/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Mexico/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Mexico/General"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Oriente_Medio/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Oriente_Medio/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Oriente_Medio/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Pacífico/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Pacífico/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Pacífico/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "Islas Chatham"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "Pacífico/Truk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "Truk (Chuuk) y Yap"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Pacífico/Isla de Pascua"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "Isla Easter & Sala y Gomez"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Pacífico/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Pacífico/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "Islas Phoenix"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Pacífico/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Pacífico/Fiji"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Pacífico/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Pacífico/Galápagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "Islas Galápagos"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Pacífico/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "Islas Gambier"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Pacífico/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Pacífico/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Pacífico/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "Hawaii"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Pacífico/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "Johnston Atoll"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Pacífico/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "Islas Line"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Pacífico/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "Kosrae"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Pacífico/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Pacífico/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Pacífico/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "Islas Marquesas"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Pacífico/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "Islas Midway"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Pacífico/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Pacífico/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Pacífico/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Pacífico/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Pacífico/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Pacífico/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Pacífico/Pitcairn"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "Pacífico/Ponape"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "Ponape (Pohnpei)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Pacífico/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Pacífico/Puerto_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Pacífico/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Pacífico/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Pacífico/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Pacífico/Tahití"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "Islas Sociedad"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Pacífico/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "Islas Gilbert"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Pacífico/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Pacífico/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Pacífico/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "Isla Wake"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Pacífico/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Pacífico/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Polonia"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugal"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapur"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Turquía"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "EEUU/Alaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "EEUU/Aleutian"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "EEUU/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "EEUU/Central"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "EEUU/Oriental"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "EEUU/Indiana-Este"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "EEUU/Hawai"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "EEUU/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "EEUU/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "EEUU/Mountain"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "EEUU/Pacífico"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "EEUU/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulú"
+
+#~ msgid "US/Pacific-New"
+#~ msgstr "EEUU/Nuevo Pacífico"
diff --git a/panels/datetime/po-timezones/et.po b/panels/datetime/po-timezones/et.po
new file mode 100644
index 0000000..16863e5
--- /dev/null
+++ b/panels/datetime/po-timezones/et.po
@@ -0,0 +1,3351 @@
+# translation of et.po to Estonian
+# This file is distributed under the same license as the PACKAGE package.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER.
+# Allan Sims <allsi@eau.ee>, 2004.
+# Antti Markus <antti.markus@starman.ee>, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: et\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2004-02-17 22:49+0200\n"
+"Last-Translator: Antti Markus <antti.markus@starman.ee>\n"
+"Language-Team: Estonian\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.3\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Aafrika/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Aafrika/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Aafrika/Addis_Ababa"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Aafrika/Alžeeria"
+
+#: timezones.h:5
+#, fuzzy
+msgid "Africa/Asmara"
+msgstr "Aafrika/Asmera"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Aafrika/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Aafrika/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Aafrika/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Aafrika/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Aafrika/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Aafrika/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Aafrika/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Aafrika/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Aafrika/Kairo"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Aafrika/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Aafrika/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Aafrika/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Aafrika/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Aafrika/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Aafrika/Djibouti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Aafrika/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Aafrika/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Aafrika/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Aafrika/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Aafrika/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Aafrika/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Aafrika/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Aafrika/Khartoum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Aafrika/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Aafrika/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Aafrika/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Aafrika/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Aafrika/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Aafrika/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Aafrika/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Aafrika/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Aafrika/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Aafrika/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Aafrika/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Aafrika/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Aafrika/Mogadishu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Aafrika/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Aafrika/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Aafrika/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Aafrika/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Aafrika/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Aafrika/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Aafrika/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Aafrika/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Aafrika/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Aafrika/Tripoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Aafrika/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Aafrika/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Ameerika/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+#, fuzzy
+msgid "Aleutian Islands"
+msgstr "Austraalia/Queensland"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Ameerika/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+#, fuzzy
+msgid "Alaska Time"
+msgstr "US/Alaska"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Ameerika/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Ameerika/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Ameerika/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+#, fuzzy
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Ameerika/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+#, fuzzy
+msgid "America/Argentina/Catamarca"
+msgstr "Ameerika/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+#, fuzzy
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Ameerika/Indiana/Indianapolis"
+
+#: timezones.h:78
+#, fuzzy
+msgid "America/Argentina/Cordoba"
+msgstr "Ameerika/Cordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+#, fuzzy
+msgid "America/Argentina/Jujuy"
+msgstr "Ameerika/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+#, fuzzy
+msgid "America/Argentina/La_Rioja"
+msgstr "Ameerika/Araguaina"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+#, fuzzy
+msgid "America/Argentina/Mendoza"
+msgstr "Ameerika/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+#, fuzzy
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Ameerika/Indiana/Marengo"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+#, fuzzy
+msgid "America/Argentina/Salta"
+msgstr "Ameerika/Antigua"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+#, fuzzy
+msgid "America/Argentina/San_Juan"
+msgstr "Ameerika/Antigua"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+#, fuzzy
+msgid "America/Argentina/San_Luis"
+msgstr "Ameerika/Antigua"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+#, fuzzy
+msgid "America/Argentina/Tucuman"
+msgstr "Ameerika/Antigua"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+#, fuzzy
+msgid "America/Argentina/Ushuaia"
+msgstr "Ameerika/Araguaina"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Ameerika/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Ameerika/Asuncion"
+
+#: timezones.h:110
+#, fuzzy
+msgid "America/Atikokan"
+msgstr "Ameerika/Atka"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Ameerika/Atka"
+
+#: timezones.h:114
+#, fuzzy
+msgid "America/Bahia"
+msgstr "Ameerika/Boa_Vista"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "Ameerika/Boa_Vista"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Ameerika/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Ameerika/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Ameerika/Belize"
+
+#: timezones.h:125
+#, fuzzy
+msgid "America/Blanc-Sablon"
+msgstr "Ameerika/Cancun"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Ameerika/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Ameerika/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Ameerika/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Ameerika/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Ameerika/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+#, fuzzy
+msgid "America/Campo_Grande"
+msgstr "Ameerika/Cayman"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Ameerika/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Ameerika/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Ameerika/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Ameerika/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Ameerika/Cayman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Ameerika/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+#, fuzzy
+msgid "Central Time"
+msgstr "US/Kesk"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Ameerika/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+#, fuzzy
+msgid "America/Coral_Harbour"
+msgstr "Ameerika/Curacao"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Ameerika/Cordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Ameerika/Costa_Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Ameerika/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Ameerika/Curacao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Ameerika/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Ameerika/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Ameerika/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Ameerika/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+#, fuzzy
+msgid "Mountain Time"
+msgstr "US/Mountain"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Ameerika/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Ameerika/Dominica"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Ameerika/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Ameerika/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Ameerika/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Ameerika/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Ameerika/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Ameerika/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Ameerika/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Ameerika/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Ameerika/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Ameerika/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Ameerika/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Ameerika/Guadeloupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Ameerika/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Ameerika/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Ameerika/Guyana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Ameerika/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Ameerika/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Ameerika/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Ameerika/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Ameerika/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Ameerika/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+#, fuzzy
+msgid "America/Indiana/Petersburg"
+msgstr "Ameerika/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Ameerika/Indianapolis"
+
+#: timezones.h:227
+#, fuzzy
+msgid "America/Indiana/Tell_City"
+msgstr "Ameerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Ameerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+#, fuzzy
+msgid "America/Indiana/Vincennes"
+msgstr "Ameerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+#, fuzzy
+msgid "America/Indiana/Winamac"
+msgstr "Ameerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Ameerika/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Ameerika/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Ameerika/Jamaica"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Ameerika/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Ameerika/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Ameerika/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+#, fuzzy
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Ameerika/Kentucky/Louisville"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Ameerika/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Ameerika/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Ameerika/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Ameerika/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Ameerika/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+#, fuzzy
+msgid "Pacific Time"
+msgstr "Pacific/Niue"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Ameerika/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Ameerika/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Ameerika/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Ameerika/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+#, fuzzy
+msgid "America/Marigot"
+msgstr "Ameerika/Maceio"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Ameerika/Martinique"
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "Ameerika/Manaus"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Ameerika/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Ameerika/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Ameerika/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Ameerika/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Ameerika/Mexico_City"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Ameerika/Miquelon"
+
+#: timezones.h:289
+#, fuzzy
+msgid "America/Moncton"
+msgstr "Ameerika/Edmonton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Ameerika/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Ameerika/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Ameerika/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Ameerika/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Ameerika/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Ameerika/New_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+#, fuzzy
+msgid "Eastern Time"
+msgstr "US/Ida"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Ameerika/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Ameerika/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Ameerika/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+#, fuzzy
+msgid "Atlantic islands"
+msgstr "Atlandi/Kanaari"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Ameerika/North_Dakota/Center"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+#, fuzzy
+msgid "America/North_Dakota/New_Salem"
+msgstr "Ameerika/North_Dakota/Center"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "Ameerika/Managua"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Ameerika/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Ameerika/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Ameerika/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Ameerika/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Ameerika/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Ameerika/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Ameerika/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Ameerika/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Ameerika/Puerto_Rico"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Ameerika/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Ameerika/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Ameerika/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Ameerika/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+#, fuzzy
+msgid "America/Resolute"
+msgstr "Ameerika/Belem"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Ameerika/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Ameerika/Rosario"
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "Ameerika/Santiago"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+#, fuzzy
+msgid "America/Santarem"
+msgstr "Ameerika/Santiago"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Ameerika/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Ameerika/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Ameerika/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Ameerika/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Ameerika/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+#, fuzzy
+msgid "America/St_Barthelemy"
+msgstr "Ameerika/Belem"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Ameerika/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Ameerika/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Ameerika/St_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Ameerika/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Ameerika/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Ameerika/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Ameerika/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Ameerika/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Ameerika/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Ameerika/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+#, fuzzy
+msgid "America/Toronto"
+msgstr "Ameerika/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Ameerika/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Ameerika/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Ameerika/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Ameerika/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Ameerika/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Ameerika/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Ameerika/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antarktika/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antarktika/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antarktika/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+#, fuzzy
+msgid "Antarctica/Macquarie"
+msgstr "Antarktika/McMurdo"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antarktika/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antarktika/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antarktika/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+#, fuzzy
+msgid "Antarctica/Rothera"
+msgstr "Antarktika/Lõunapoolus"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antarktika/Lõunapoolus"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antarktika/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antarktika/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Arctic/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Aasia/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Aasia/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Aasia/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Aasia/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Aasia/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Aasia/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Aasia/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Aasia/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Aasia/Baghdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Aasia/Bahrain"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Aasia/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Aasia/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Aasia/Beirut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Aasia/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Aasia/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Aasia/Calcutta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Aasia/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Aasia/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Aasia/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Aasia/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Aasia/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Aasia/Damascus"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Aasia/Dhaka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Aasia/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Aasia/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Aasia/Dushanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Aasia/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Aasia/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+#, fuzzy
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Aasia/Chongqing"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Aasia/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Aasia/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Aasia/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Aasia/Istanbul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Aasia/Jakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Aasia/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Aasia/Jeruusalemm"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Aasia/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Aasia/Kamchatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Aasia/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Aasia/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+#, fuzzy
+msgid "Asia/Kathmandu"
+msgstr "Aasia/Katmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Aasia/Katmandu"
+
+#: timezones.h:518
+#, fuzzy
+msgid "Asia/Kolkata"
+msgstr "Aasia/Jakarta"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Aasia/Krasnoyarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Aasia/Kuala Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Aasia/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Aasia/Kuwait"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Aasia/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Aasia/Macau"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Aasia/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Aasia/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Aasia/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Aasia/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Aasia/Nicosia"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "Aasia/Irkutsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Aasia/Novosibirsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Aasia/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+#, fuzzy
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Aasia/Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Aasia/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Aasia/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Aasia/Phnom_Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Aasia/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Aasia/Pyongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Aasia/Katar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Aasia/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Aasia/Rangoon"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Aasia/Riyadh"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Aasia/Riyadh87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Aasia/Riyadh88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Aasia/Riyadh89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Aasia/Saigon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Aasia/Sakhalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Aasia/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Aasia/Söul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Aasia/Shanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Aasia/Singapore"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Aasia/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Aasia/Tashkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Aasia/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Aasia/Tehran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Aasia/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Aasia/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Aasia/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Aasia/Tokyo"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Aasia/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Aasia/Ulaanbaatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Aasia/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Aasia/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Aasia/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Aasia/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Aasia/Jakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Aasia/Yekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Aasia/Yerevan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlandi/Assoorid"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlandi/Bermuuda"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlandi/Kanaari"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlandi/Cape_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlandi/Fääri"
+
+#: timezones.h:616
+#, fuzzy
+msgid "Atlantic/Faroe"
+msgstr "Atlandi/Fääri"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlandi/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlandi/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlandi/Reikjavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlandi/Lõuna_Georgia"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlandi/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlandi/St_Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Austraalia/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Austraalia/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+#, fuzzy
+msgid "South Australia"
+msgstr "Austraalia/ACT"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Austraalia/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Austraalia/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Austraalia/Canberra"
+
+#: timezones.h:636
+#, fuzzy
+msgid "Australia/Currie"
+msgstr "Austraalia/Canberra"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Austraalia/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+#, fuzzy
+msgid "Australia/Eucla"
+msgstr "Austraalia/Queensland"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+#, fuzzy
+msgid "Western Australia - Eucla area"
+msgstr "Austraalia/Queensland"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Austraalia/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Austraalia/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Austraalia/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Austraalia/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Austraalia/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+#, fuzzy
+msgid "Victoria"
+msgstr "Austraalia/Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Austraalia/Põhi"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Austraalia/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Austraalia/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Austraalia/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Austraalia/Lõuna"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Austraalia/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Austraalia/Tasmaania"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Austraalia/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Austraalia/Lääne"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Austraalia/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brasiilia/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brasiilia/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brasiilia/Ida"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brasiilia/Lääne"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Kanada/Atlandi"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Kanada/Kesk"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Kanada/Ida"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Kanada/Ida-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Kanada/Mountain"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Kanada/Newfoundland"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Kanada/Pacific"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Kanada/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Kanada/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Tšiili/Manner"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Tšiili/Lihavõttesaar"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Kuuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Egiptus"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Iirimaa"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Suulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Euroopa/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Euroopa/Andorra"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Euroopa/Ateena"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Euroopa/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Euroopa/Belgrad"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Euroopa/Berliin"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Euroopa/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Euroopa/Brüssel"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Euroopa/Bukarest"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Euroopa/Budapest"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Euroopa/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Euroopa/Kopenhaagen"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Euroopa/Dublin"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Euroopa/Gibraltar"
+
+#: timezones.h:744
+#, fuzzy
+msgid "Europe/Guernsey"
+msgstr "Euroopa/Ateena"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Euroopa/Helsinki"
+
+#: timezones.h:746
+#, fuzzy
+msgid "Europe/Isle_of_Man"
+msgstr "Euroopa/Oslo"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Euroopa/Istanbul"
+
+#: timezones.h:748
+#, fuzzy
+msgid "Europe/Jersey"
+msgstr "Euroopa/Pariis"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Euroopa/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Euroopa/Kiiev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Euroopa/Lissabon"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Euroopa/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Euroopa/London"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Euroopa/Luxemburg"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Euroopa/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Euroopa/Malta"
+
+#: timezones.h:765
+#, fuzzy
+msgid "Europe/Mariehamn"
+msgstr "Euroopa/Madrid"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Euroopa/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Euroopa/Monaco"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Euroopa/Moskva"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Euroopa/Nicosia"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Euroopa/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Euroopa/Pariis"
+
+#: timezones.h:774
+#, fuzzy
+msgid "Europe/Podgorica"
+msgstr "Euroopa/Andorra"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Euroopa/Praha"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Euroopa/Riia"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Euroopa/Rooma"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Euroopa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Euroopa/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Euroopa/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Euroopa/Simferoopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Euroopa/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Euroopa/Sofia"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Euroopa/Stockholm"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Euroopa/Tallinn"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Euroopa/Tirana"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Euroopa/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Euroopa/Uzhgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Euroopa/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Euroopa/Vatikan"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Euroopa/Viin"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Euroopa/Vilnius"
+
+#: timezones.h:799
+#, fuzzy
+msgid "Europe/Volgograd"
+msgstr "Euroopa/Belgrad"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Euroopa/Varssav"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Euroopa/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Euroopa/Zaporožje"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Euroopa/Zürich"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Factory"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Iiri"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Island"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Indian/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Indian/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Indian/Christmas"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Indian/Cocos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Indian/Comoro"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Indian/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Indian/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Indian/Maldives"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Indian/Mauritius"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Indian/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Indian/Reunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Iraan"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Iisrael"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamaika"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Jaapan"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Liibüa"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Mehhiko/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Mehhiko/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Mehhiko/Üldine"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Mideast/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Mideast/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Mideast/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navaho"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Pacific/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Pacific/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Pacific/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+#, fuzzy
+msgid "Chatham Islands"
+msgstr "Tšiili/Lihavõttesaar"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "Pacific/Truk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+#, fuzzy
+msgid "Pacific/Easter"
+msgstr "Pacific/Easter"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Pacific/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Pacific/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Pacific/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Pacific/Fidži"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Pacific/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Pacific/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Pacific/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Pacific/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Pacific/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Pacific/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+#, fuzzy
+msgid "Hawaii"
+msgstr "US/Havai"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Pacific/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Pacific/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Pacific/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+#, fuzzy
+msgid "Kosrae"
+msgstr "Iisrael"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Pacific/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Pacific/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Pacific/Markiisisaared"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Pacific/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Pacific/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Pacific/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Pacific/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Pacific/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Pacific/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Pacific/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Pacific/Pitcairn"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "Pacific/Ponape"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Pacific/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Pacific/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Pacific/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Pacific/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Pacific/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Pacific/Tahiiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Pacific/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+#, fuzzy
+msgid "Gilbert Islands"
+msgstr "Tšiili/Lihavõttesaar"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Pacific/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Pacific/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Pacific/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Pacific/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Pacific/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Poola"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugal"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapur"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Türgi"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "US/Alaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "US/Aleuudi"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "US/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "US/Kesk"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "US/Ida"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "US/Ida-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "US/Havai"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "US/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "US/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "US/Mountain"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "US/Pacific"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "US/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Suulu"
+
+#, fuzzy
+#~ msgid "US/Pacific-New"
+#~ msgstr "US/Pacific"
+
+#~ msgid "SystemV/AST4"
+#~ msgstr "SystemV/AST4"
+
+#~ msgid "SystemV/AST4ADT"
+#~ msgstr "SystemV/AST4ADT"
+
+#~ msgid "SystemV/CST6"
+#~ msgstr "SystemV/CST6"
+
+#~ msgid "SystemV/CST6CDT"
+#~ msgstr "SystemV/CST6CDT"
+
+#~ msgid "SystemV/EST5"
+#~ msgstr "SystemV/EST5"
+
+#~ msgid "SystemV/EST5EDT"
+#~ msgstr "SystemV/EST5EDT"
+
+#~ msgid "SystemV/HST10"
+#~ msgstr "SystemV/HST10"
+
+#~ msgid "SystemV/MST7"
+#~ msgstr "SystemV/MST7"
+
+#~ msgid "SystemV/MST7MDT"
+#~ msgstr "SystemV/MST7MDT"
+
+#~ msgid "SystemV/PST8"
+#~ msgstr "SystemV/PST8"
+
+#~ msgid "SystemV/PST8PDT"
+#~ msgstr "SystemV/PST8PDT"
+
+#~ msgid "SystemV/YST9"
+#~ msgstr "SystemV/YST9"
+
+#~ msgid "SystemV/YST9YDT"
+#~ msgstr "SystemV/YST9YDT"
diff --git a/panels/datetime/po-timezones/fa.po b/panels/datetime/po-timezones/fa.po
new file mode 100644
index 0000000..7689e92
--- /dev/null
+++ b/panels/datetime/po-timezones/fa.po
@@ -0,0 +1,3304 @@
+# Persian translation for timezones package.
+# Copyright (C) 2004, 2005 Sharif FarsiWeb, Inc.
+# This file is distributed under the same license as the timezones package.
+#
+# Roozbeh Pournader <roozbeh@farsiweb.info>, 2004, 2005.
+# Meelad Zakaria <meelad@farsiweb.info>, 2005.
+# Hedayat Vatankhah <hedayat@fedoraproject.org>, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-09-23 16:25+0330\n"
+"Last-Translator: Hedayat Vatankhah <hedayat@fedoraproject.org>\n"
+"Language-Team: Persian <trans-fa@lists.fedoraproject.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: fa\n"
+"X-Generator: Lokalize 1.0\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "افریفا/آبیجان"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "افریقا/آگرا"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "افریقا/آدیس‌آبابا"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "افریقا/الجزیره"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "افریقا/اسمره"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "افریقا/اسمرا"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "افریقا/باماکو"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "افریقا/باتگوئی"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "افریقا/بانجول"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "افریقا/بیسائو"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "افریقا/بلنتایر"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "افریقا/برازاویل"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "افریقا/بوجومبورا"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "افریقا/قاهره"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "افریقا/دارالبیضاء"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "افریقا/سئوتا"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "افریقا/کوناکری"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "افریقا/داکار"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "افریقا/دارالسلام"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "افریقا/جیبوتی"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "افریقا/دوالا"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "افریقا/العیون"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "افریقا/فری‌تاون"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "افریقا/گابورونی"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "افریقا/هراره"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "افریقا/یوهانسبورگ"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "افریقا/کامپالا"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "افریقا/خارطوم"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "افریقا/کیگالی"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "افریقا/کینشاسا"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "افریقا/لاگوس"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "افریقا/لیبرویل"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "افریقا/لومه"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "افریقا/لواندا"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "افریقا/لوبومباشی"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "افریقا/لوزاکا"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "افریقا/مالابو"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "افریقا/ماپوتو"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "افریقا/مزرو"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "افریقا/مبابان"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "افریقا/موگادیشو"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "افریقا/مونروویا"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "افریقا/نایروبی"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "افریقا/نجامنا"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "افریقا/نیامه"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "افریقا/نواکشوت"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "افریقا/واگادوگو"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "افریقا/پورتونوو"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "افریقا/سائو تومه"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "افریقا/تیمبوکتو"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "افریقا/طرابلس"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "افریقا/تونس"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "افریقا/ویندهوک"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "امریکا/ایدک"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+#, fuzzy
+msgid "Aleutian Islands"
+msgstr "استرالیا/کوئینزلند"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "امریکا/انکریج"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "زمان آلاسکا"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "امریکا/انگویلا"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "امریکا/انتیگا"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "امریکا/آراگواینا"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "امریکا/آرژانتین/بوئنوس‌آیرس"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "امریکا/آرژانتین/کاتامارکا"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+#, fuzzy
+msgid "America/Argentina/ComodRivadavia"
+msgstr "امریکا/ایندیانا/ایندیاناپولیس"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "امریکا/آرژانتین/کوردووا"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "امریکا/آرژانتین/خوخوئی"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+#, fuzzy
+msgid "America/Argentina/La_Rioja"
+msgstr "امریکا/آرژانتین/آراگواینا"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "امریکا/آرژانتین/مندوسا"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+#, fuzzy
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "امریکا/ایندیانا/مارنگو"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+#, fuzzy
+msgid "America/Argentina/Salta"
+msgstr "امریکا/انتیگا"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+#, fuzzy
+msgid "America/Argentina/San_Juan"
+msgstr "امریکا/انتیگا"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+#, fuzzy
+msgid "America/Argentina/San_Luis"
+msgstr "امریکا/انتیگا"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+#, fuzzy
+msgid "America/Argentina/Tucuman"
+msgstr "امریکا/انتیگا"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+#, fuzzy
+msgid "America/Argentina/Ushuaia"
+msgstr "امریکا/آراگواینا"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "امریکا/آروبا"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "امریکا/آسونسیون"
+
+#: timezones.h:110
+#, fuzzy
+msgid "America/Atikokan"
+msgstr "امریکا/انتیگا"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr ""
+
+#: timezones.h:114
+#, fuzzy
+msgid "America/Bahia"
+msgstr "امریکا/بوئاویشتا"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "امریکا/بوئاویشتا"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "امریکا/باربادوس"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "امریکا/بلئین"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "امریکا/بلیز"
+
+#: timezones.h:125
+#, fuzzy
+msgid "America/Blanc-Sablon"
+msgstr "امریکا/کانکون"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "امریکا/بوئاویشتا"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "امریکا/بوگوتا"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "امریکا/بویسی"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "امریکا/بوئنوس‌آیرس"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "امریکا/خلیج کمبریج"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+#, fuzzy
+msgid "America/Campo_Grande"
+msgstr "امریکا/کیمن"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "امریکا/کانکون"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "امریکا/کاراکاس"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "امریکا/کاتامارکا"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "امریکا/کاین"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "امریکا/کیمن"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "امریکا/شیکاگو"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+#, fuzzy
+msgid "Central Time"
+msgstr "ایالات متحده/مرکزی"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "امریکا/چیئوائوا"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+#, fuzzy
+msgid "America/Coral_Harbour"
+msgstr "امریکا/کوراسائو"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "امریکا/کوردووا"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "امریکا/کاستاریکا"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "امریکا/کویاوا"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "امریکا/کوراسائو"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr ""
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "امریکا/داوسن"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "امریکا/داوسن کریک"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "امریکا/دنور"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+#, fuzzy
+msgid "Mountain Time"
+msgstr "ایالات متحده/کوهستانی"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "امریکا/دترویت"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "امریکا/دومینیکا"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "امریکا/ادمونتون"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr ""
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "امریکا/السالوادور"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "امریکا/انسنادا"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "امریکا/فورتالزا"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "امریکا/فورت وین"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "امریکا/گلیس بی"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "امریکا/گودهوب"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "بیش‌تر مکان‌ها"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "امریکا/خلیج گوس"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "امریکا/گراند تورک"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "امریکا/گرنیدا"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "امریکا/گوادلوپ"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "امریکا/گواتمالا"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "امریکا/گوایاکیل"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "امریکا/گویانا"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "امریکا/هلیفکس"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "امریکا/هاوانا"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "امریکا/ارموسیو"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "امریکا/ایندیانا/ایندیاناپولیس"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "امریکا/ایندیانا/ناکس"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "امریکا/ایندیانا/مارنگو"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "امریکا/ایندیانا/پترزبورگ"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "امریکا/ایندیاناپولیس"
+
+#: timezones.h:227
+#, fuzzy
+msgid "America/Indiana/Tell_City"
+msgstr "امریکا/ایندیانا/ویوی"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "امریکا/ایندیانا/ویوی"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+#, fuzzy
+msgid "America/Indiana/Vincennes"
+msgstr "امریکا/ایندیانا/ویوی"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+#, fuzzy
+msgid "America/Indiana/Winamac"
+msgstr "امریکا/ایندیانا/ویوی"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "امریکا/اینوویک"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "امریکا/ایکلوئت"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "امریکا/جامائیکا"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "امریکا/خوخوئی"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "امریکا/جونو"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "امریکا/کنتاکی/لوئیزویل"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+#, fuzzy
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "امریکا/کنتاکی/لوئیزویل"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "امریکا/کنتاکی/مانتیسلو"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "امریکا/ناکس ایندیانا"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "امریکا/لاپاس"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "امریکا/لیما"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "امریکا/لوس‌آنجلس"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+#, fuzzy
+msgid "Pacific Time"
+msgstr "اقیانوس آرام/نیوئه"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "امریکا/لوئیزویل"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "امریکا/ماسیو"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "امریکا/ماناگوئا"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "امریکا/ماناوس"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+#, fuzzy
+msgid "America/Marigot"
+msgstr "امریکا/ماسیو"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "امریکا/مارتینیک"
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "امریکا/ماناوس"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "امریکا/ماساتلان"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "امریکا/مندوسا"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "امریکا/منامینی"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "امریکا/مریدا"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "امریکا/مکزیکوسیتی"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "امریکا/میکلون"
+
+#: timezones.h:289
+#, fuzzy
+msgid "America/Moncton"
+msgstr "امریکا/ادمونتون"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "امریکا/مونترئی"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "امریکا/مونته‌ویدئو"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "امریکا/مانتریال"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "امریکا/مانتسرت"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "امریکا/ناسائو"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "امریکا/نیویورک"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+#, fuzzy
+msgid "Eastern Time"
+msgstr "ایالات متحده/شرقی"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "امریکا/نیپیگان"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "امریکا/نوم"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "زمان آلاسکا - آلاسکای غربی"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "امریکا/نورونیا"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "جزیره‌های آتلانتیک"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "امریکا/داکوتای‌شمالی/مرکز"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+#, fuzzy
+msgid "America/North_Dakota/New_Salem"
+msgstr "امریکا/داکوتای‌شمالی/مرکز"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "امریکا/ماناگوئا"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "امریکا/پاناما"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "امریکا/پانگنیرتونگ"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "امریکا/پاراماریبو"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "امریکا/فینیکس"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "امریکا/پورتوپرنس"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "امریکا/پورتو آکری"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "امریکا/پورت آو اسپین"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "امریکا/پورترولیو"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "امریکا/پورتوریکو"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "امریکا/رینی‌ریور"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "امریکا/خلیجک رنکین"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "امریکا/رسیفی"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "امریکا/رجاینا"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+#, fuzzy
+msgid "America/Resolute"
+msgstr "امریکا/بلئین"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "امریکا/ریوبرانکو"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "امریکا/روساریو"
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "امریکا/سانتیاگو"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+#, fuzzy
+msgid "America/Santarem"
+msgstr "امریکا/سانتیاگو"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "امریکا/سانتیاگو"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "امریکا/سانتودومینگو"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "امریکا/سائوپائولو"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "امریکا/اسکورسبیسون"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "امریکا/شیپ‌راک"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+#, fuzzy
+msgid "America/St_Barthelemy"
+msgstr "امریکا/بلئین"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "امریکا/سنت جانز"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "امریکا/سنت کیتس"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "امریکا/سنت لوشا"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "امریکا/سنت تامس"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "امریکا/سنت وینسنت"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "امریکا/سویفت کرنت"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "امریکا/تگوسیگالپا"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "امریکا/توله"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "امریکا/تاندر بی"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "امریکا/تیخوانا"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+#, fuzzy
+msgid "America/Toronto"
+msgstr "امریکا/تورتولا"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "امریکا/تورتولا"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "امریکا/ونکوور"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "امریکا/ویرجین"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "امریکا/وایت‌هورس"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "امریکا/وینیپگ"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "امریکا/یاکوتات"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "امزیکا/یلونایف"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "جنوبگان/کیسی"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "جنوبگان/دیویس"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "جنوبگان/دومون دورویل"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+#, fuzzy
+msgid "Antarctica/Macquarie"
+msgstr "جنوبگان/مک‌مردو"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "جنوبگان/موسن"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "جنوبگان/مک‌مردو"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "جنوبگان/پالمر"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+#, fuzzy
+msgid "Antarctica/Rothera"
+msgstr "جنوبگان/قطب جنوب"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "جنوبگان/قطب جنوب"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "جنوبگان/سیووا"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "جنوبگان/واستوک"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "شمالگان/لانگ‌ییر‌باین"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "آسیا/عدن"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "آسیا/آلماتی"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "آسیا/امان"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "آسیا/انادیر"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "آسیا/آق‌تاو"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "آسیا/آق‌توبه"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "آسیا/عشق‌آباد"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "آسیا/عشق‌آباد"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "آسیا/بغداد"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "آسیا/بحرین"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "آسیا/باکو"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "آسیا/بانکوک"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "آسیا/بیروت"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "آسیا/بیشکک"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "آسیا/برونئی"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "آسیا/کلکته"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "آسیا/چویبالسان"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "آسیا/چونگ‌کینگ"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "آسیا/چونگ‌کینگ"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "آسیا/کلمبو"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "آسیا/داکا"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "آسیا/دمشق"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "آسیا/داکا"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "آسیا/دیلی"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "آسیا/دوبی"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "آسیا/دوشنبه"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "آسیا/غزه"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "آسیا/هاربن"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+#, fuzzy
+msgid "Asia/Ho_Chi_Minh"
+msgstr "آسیا/چونگ‌کینگ"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "آسیا/هنگ‌کنگ"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "آسیا/هوود"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "آسیا/ایرکوتسک"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "آسیا/استانبول"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "آسیا/جاکارتا"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "آسیا/جایاپورا"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "آسیا/دارالسلام"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "آسیا/کابل"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "آسیا/کامچاتکا"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "آسیا/کراچی"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "آسیا/کاشغر"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+#, fuzzy
+msgid "Asia/Kathmandu"
+msgstr "آسیا/کاتماندو"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "آسیا/کاتماندو"
+
+#: timezones.h:518
+#, fuzzy
+msgid "Asia/Kolkata"
+msgstr "آسیا/جاکارتا"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "آسیا/کرسنایارسک"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "آسیا/کوالالامپور"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "آسیا/کوچینگ"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "آسیا/کویت"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "آسیا/ماکائو"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "آسیا/ماکائو"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "آسیا/مگادان"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "آسیا/ماکاسار"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "آسیا/مانیل"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "آسیا/مسقط"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "آسیا/نیکوزیا"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "آسیا/ایرکوتسک"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "آسیا/نووسیبریسک"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "آسیا/نووسیبریسک"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+#, fuzzy
+msgid "Moscow+03 - Novosibirsk"
+msgstr "آسیا/نووسیبریسک"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "آسیا/اومسک"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "آسیا/اورال"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "آسیا/پنوم‌پن"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "آسیا/پونتیاناک"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "آسیا/پیونگ‌یانگ"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "آسیا/قطر"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "آسیا/قزل‌اوردا"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "آسیا/رانگون"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "آسیا/ریاض"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "آسیا/ریاض۸۷"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "آسیا/ریاض۸۸"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "آسیا/ریاض۸۹"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "آسیا/سایگون"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "آسیا/ساخالین"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "آسیا/سمرقند"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "آسیا/سئول"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "آسیا/شانگهای"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "آسیا/سنگاپور"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "آسیا/تایپه"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "آسیا/تاشکند"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "آسیا/تفلیس"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "آسیا/تهران"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "آسیا/تل‌آویو"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "آسیا/تیمبو"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "آسیا/تیمپو"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "آسیا/توکیو"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "آسیا/اوجونگ پاندانگ"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "آسیا/اولان‌باتور"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "آسیا/اولان‌باتور"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "آسیا/اورومچی"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "آسیا/وینتیان"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "آسیا/ولادیواستوک"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "آسیا/یاکوتسک"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "آسیا/یکاترینبورگ"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "آسیا/ایروان"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "اقیانوس اطلس/آسور"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "اقیانوس اطلس/برمودا"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "اقیانوس اطلس/قناری"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "اقیانوس اطلس/کیپ ورد"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "اقیانوس اطلس/فارو"
+
+#: timezones.h:616
+#, fuzzy
+msgid "Atlantic/Faroe"
+msgstr "اقیانوس اطلس/فارو"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "اقیانوس اطلس/یان ماین"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "اقیانوس اطلس/مادئیرا"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "اقیانوس اطلس/ریکیاویک"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "اقیانوس اطلس/جورجیای جنوبی"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "اقیانوس اطلس/استنلی"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "اقیانوس اطلس/سنت هللنا"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "استرالیا/سرزمین پایتخت استرالیا"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "استرالیا/آدلاید"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+#, fuzzy
+msgid "South Australia"
+msgstr "استرالیا/سرزمین پایتخت استرالیا"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "استرالیا/بریزبن"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "استرالیا/بروکن هیل"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "استرالیا/کانبرا"
+
+#: timezones.h:636
+#, fuzzy
+msgid "Australia/Currie"
+msgstr "استرالیا/کانبرا"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "استرالیا/داروین"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+#, fuzzy
+msgid "Australia/Eucla"
+msgstr "استرالیا/کوئینزلند"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+#, fuzzy
+msgid "Western Australia - Eucla area"
+msgstr "استرالیا/کوئینزلند"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "استرالیا/هوبارت"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "استرالیا/جزیره‌ی لرد هاو"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "استرالیا/لیندمن"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "استرالیا/لرد هاو"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "استرالیا/ملبورن"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+#, fuzzy
+msgid "Victoria"
+msgstr "استرالیا/ویکتوریا"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "استرالیا/شمال"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "استرالیا/نیو ویلز جنوبی"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "استرالیا/پرت"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "استرالیا/کوئینزلند"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "استرالیا/جنوب"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "استرالیا/سیدنی"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "استرالیا/تاسمانی"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "استرالیا/ویکتوریا"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "استرالیا/غرب"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "استرالیا/ینکاوینا"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "برزیل/آکری"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "برزیل/دنورونیا"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "برزیل/شرق"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "برزیل/غرب"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "کانادا/اطلس"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "کانادا/مرکزی"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "کانادا/شرقی"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "کانادا/شرق ساسکچیوان"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "کانادا/کوهستانی"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "کانادا/نیوفاندلند"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "کانادا/آرام"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "کانادا/ساسکچیوان"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "کانادا/یوکان"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "وقت مرکزی اروپا"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "شیلی/سرزمین اصلی"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "شیلی/جزیره‌ی ایستر"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr ""
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "کوبا"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "وقت شرق اروپا"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "مصر"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "اِیره"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "وقت استاندارد اروپا"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr ""
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "غیره/وقت گرینیچ"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "غیره/وقت گرینیچ۰"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "غیره/وقت گرینیچ−۰"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "غیره/وقت گرینیچ+۰"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "غیره/وقت گرینیچ−۱"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "غیره/وقت گرینیچ+۱"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "غیره/وقت گرینیچ−۱۰"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "غیره/وقت گرینیچ+۱۰"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "غیره/وقت گرینیچ−۱۱"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "غیره/وقت گرینیچ+۱۱"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "غیره/وقت گرینیچ−۱۲"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "غیره/وقت گرینیچ+۱۲"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "غیره/وقت گرینیچ−۱۳"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "غیره/وقت گرینیچ−۱۴"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "غیره/وقت گرینیچ−۲"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "غیره/وقت گرینیچ+۲"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "غیره/وقت گرینیچ−۳"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "غیره/وقت گرینیچ+۳"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "غیره/وقت گرینیچ−۴"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "غیره/وقت گرینیچ+۴"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "غیره/وقت گرینیچ−۵"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "غیره/وقت گرینیچ+۵"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "غیره/وقت گرینیچ−۶"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "غیره/وقت گرینیچ+۶"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "غیره/وقت گرینیچ−۷"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "غیره/وقت گرینیچ+۷"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "غیره/وقت گرینیچ−۸"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "غیره/وقت گرینیچ+۸"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "غیره/وقت گرینیچ−۹"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "غیره/وقت گرینیچ+۹"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "غیره/گرینیچ"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr ""
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "غیره/جهانی"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "غیره/زمان هماهنگ جهانی"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "غیره/زولو"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "اروپا/آمستردام"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "اروپا/آندورا"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "اروپا/آتن"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "ااروپا/بلفاست"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "اروپا/بلگراد"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "اروپا/برلین"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "اروپا/براتیسلاوا"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "اروپا/بروکسل"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "اروپا/بخارست"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "اروپا/بوداپست"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "اروپا/کیشینئو"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "اروپا/کپنهاگ"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "اروپا/دوبلین"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "اروپا/خیورالتار"
+
+#: timezones.h:744
+#, fuzzy
+msgid "Europe/Guernsey"
+msgstr "اروپا/آتن"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "اروپا/هلسینکی"
+
+#: timezones.h:746
+#, fuzzy
+msgid "Europe/Isle_of_Man"
+msgstr "اروپا/اسلو"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "اروپا/استانبول"
+
+#: timezones.h:748
+#, fuzzy
+msgid "Europe/Jersey"
+msgstr "اروپا/پاریس"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "اروپا/کالینینگراد"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "اروپا/کیف"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "اروپا/لیسبون"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "اروپا/لیوبلیانا"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "اروپا/لندن"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "اروپا/لوکزامبورگ"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "اروپا/مادرید"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "اروپا/مالت"
+
+#: timezones.h:765
+#, fuzzy
+msgid "Europe/Mariehamn"
+msgstr "اروپا/مادرید"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "اروپا/مینسک"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "اروپا/موناکو"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "اروپا/مسکو"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "اروپا/نیکوزیا"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "اروپا/اسلو"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "اروپا/پاریس"
+
+#: timezones.h:774
+#, fuzzy
+msgid "Europe/Podgorica"
+msgstr "اروپا/آندورا"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "اروپا/پراگ"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "اروپا/ریگا"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "اروپا/رم"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "اروپا/سامارا"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "اروپا/سان مارینو"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "اروپا/سارایوو"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "اروپا/سیمفروپل"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "اروپا/اسکوپیه"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "اروپا/صوفیه"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "اروپا/استکهلم"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "اروپا/تالین"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "اروپا/تیرانا"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "اروپا/تیراسپل"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "اروپا/اوژگرت"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "اروپا/فادوتس"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "اروپا/واتیکان"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "اروپا/وین"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "اروپا/ویلنیوس"
+
+#: timezones.h:799
+#, fuzzy
+msgid "Europe/Volgograd"
+msgstr "اروپا/بلگراد"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "اروپا/ورشو"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "اروپا/زاگرب"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "اروپا/زاپاروژیه"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "اروپا/زوریخ"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "کارخانه"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "بریتانیای کبیر"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "بریتانیای کبیر-ایره"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "وقت گرینیچ"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr ""
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "وقت گرینیچ−۰"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "وقت گرینیچ+۰"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "گرینیچ"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "هنگ‌کنگ"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "وقت استاندار هاوایی"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "ایسلند"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "اقیانوس هند/آنتاناناریوو"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "اقیانوس هند/چاگوس"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "اقیانوس هند/کریسمس"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "اقیانوس هند/کوکوس"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "اقیانوس هند/کومور"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "اقیانوس هند/کرگلن"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "اقیانوس هند/مائه"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "اقیانوس هند/مالدیو"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "اقیانوس هند/موریس"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "اقیانوس هند//مایوت"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "اقیانوس هند/رئونیون"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "ایران"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "اسرائیل"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "جامائیکا"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "ژاپن"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "کواجالین"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "لیبی"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "وقت اروپای میانه"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "مکزیک/شمال باخا"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "مکزیک/جنوب باخا"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "مکزیک/عمومی"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "خاور میانه/ریاض۸۷"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "خاور میانه/ریاض۸۸"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "خاور میانه/ریاض۸۹"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "وقت استاندارد کوهستانی"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr ""
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "نواهو"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "نیوزیلند"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr ""
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "اقیانوس آرام/آپیا"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "اقیانوس آرام/اوکلند"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "اقیانوس آرام/چتم"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+#, fuzzy
+msgid "Chatham Islands"
+msgstr "شیلی/جزیره‌ی ایستر"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "اقیانوس آرام/تروک"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+#, fuzzy
+msgid "Pacific/Easter"
+msgstr "اقیانوس آرام/ایستر"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "اقیانوس آرام/افاته"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "اقیانوس آرام/اندربری"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "اقیانوس آرام/فاکائوفو"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "اقیانوس آرام/فیجی"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "اقیانوس آرام/فونافوتی"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "اقیانوس آرام/گالاپاگوس"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "اقیانوس آرام/'گامبیه"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "اقیانوس آرام/گوادالکانال"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "اقیانوس آرام/گوام"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "اقیانوس آرام/هونولولو"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "هاوائی"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "اقیانوس آرام/جانستون"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "اقیانوس آرام/کریسمس"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "اقیانوس آرام/کوسرای"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+#, fuzzy
+msgid "Kosrae"
+msgstr "اسرائیل"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "اقیانوس آرام/کواجالین"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "اقیانوس آرام/مجورو"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "اقیانوس آرام/مارکیزاس"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "اقیانوس آرام/میدوی"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "اقیانوس آرام/نائورو"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "اقیانوس آرام/نیوئه"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "اقیانوس آرام/نورفولک"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "اقیانوس آرام/نومئا"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "اقیانوس آرام/پاگو پاگو"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "اقیانوس آرام/پالاو"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "اقیانوس آرام/پیتکرن"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "اقیانوس آرام/پوناپی"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "اقیانوس آرام/پوناپی"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "اقیانوس آرام/پورت مورزبی"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "اقیانوس آرام/راروتونگا"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "اقیانوس آرام/سایپان"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "اقیانوس آرام/ساموا"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "اقیانوس آرام/تاهیتی"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "اقیانوس آرام/تاراوا"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+#, fuzzy
+msgid "Gilbert Islands"
+msgstr "شیلی/جزیره‌ی ایستر"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "اقیانوس آرام/تونگاتاپو"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "اقیانوس آرام/تروک"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "اقیانوس آرام/ویک"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "اقیانوس آرام/والیس"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "اقیانوس آرام/یپ"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "لهستان"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "پرتغال"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr ""
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr ""
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "جمهوری خلق چین"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "جمهوری کره"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "سنگاپور"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "ترکیه"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr ""
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "جهانی"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "ایالات متحده/آلاسکا"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "ایالات متحده/الوشن"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "ایلات متحده/آریزونا"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "ایالات متحده/مرکزی"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "ایالات متحده/شرقی"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "ایالات متحده/شرق ایندیانا"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "ایالات متحده/هاوائی"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "ایالات متحده/ایندیانا‐استارک"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "ایالات متحده/میشیگان"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "ایالات متحده/کوهستانی"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "ایالات متحده/آرام"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "ایلات متحده/ساموا"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "زمان هماهنگ جهانی"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "وقت غربی اروپا"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr ""
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "زولو"
+
+#, fuzzy
+#~ msgid "US/Pacific-New"
+#~ msgstr "ایالات متحده/آرام"
diff --git a/panels/datetime/po-timezones/fi.po b/panels/datetime/po-timezones/fi.po
new file mode 100644
index 0000000..860d078
--- /dev/null
+++ b/panels/datetime/po-timezones/fi.po
@@ -0,0 +1,3272 @@
+# Finnish translation of timezones.
+# TODO Many translations probably need work: I wasn't sure of all the
+# place-names in Finnish and accents aren't used consistently, because
+# some names were copied from the msgids (no accents) and some from Wikipedia
+# (with accents). -vpv
+# Lauri Nurmi <lanurmi@iki.fi>, 2004.
+# Ville-Pekka Vainio <vpivaini@cs.helsinki.fi>, 2007-2009, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-08-29 20:02+0300\n"
+"Last-Translator: Ville-Pekka Vainio <vpivaini@cs.helsinki.fi>\n"
+"Language-Team: Finnish <gnome-fi-laatu@lists.sourceforge.net>\n"
+"Language: fi\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Virtaal 0.6.1\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Afrikka/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Afrikka/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Afrikka/Addis-Abeba"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Afrikka/Algiers"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "Afrikka/Asmara"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Afrikka/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Afrikka/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Afrikka/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Afrikka/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Afrikka/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Afrikka/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Afrikka/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Afrikka/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Afrikka/Cairo"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Afrikka/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Afrikka/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "Ceuta & Melilla"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Afrikka/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Afrikka/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Afrikka/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Afrikka/Djibouti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Afrikka/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Afrikka/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Afrikka/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Afrikka/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Afrikka/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Afrikka/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Afrikka/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Afrikka/Khartoum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Afrikka/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Afrikka/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "Kongon demokraattisen tasavallan länsiosa"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Afrikka/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Afrikka/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Afrikka/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Afrikka/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Afrikka/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "Kongon demokraattisen tasavallan itäosa"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Afrikka/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Afrikka/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Afrikka/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Afrikka/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Afrikka/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Afrikka/Mogadishu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Afrikka/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Afrikka/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Afrikka/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Afrikka/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Afrikka/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Afrikka/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Afrikka/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Afrikka/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Afrikka/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Afrikka/Tripoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Afrikka/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Afrikka/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Amerikka/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Aleutit"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Amerikka/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Alaskan aikavyöhyke"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Amerikka/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Amerikka/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Amerikka/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "Tocantins"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Amerikka/Argentiina/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Buenos Aires (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Amerikka/Argentiina/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "Catamarca (CT), Chubut (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Amerikka/Argentiina/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Amerikka/Argentiina/Cordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "useimmat paikat (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Amerikka/Argentiina/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Jujuy (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Amerikka/Argentiina/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "La Rioja (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Amerikka/Argentiina/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "Mendoza (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Amerikka/Argentiina/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "Santa Cruz (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "Amerikka/Argentiina/Salta"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Amerikka/Argentiina/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "San Juan (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "Amerikka/Argentiina/San_Luis"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "San Luis (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Amerikka/Argentiina/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "Tucuman (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Amerikka/Argentiina/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "Tierra del Fuego (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Amerikka/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Amerikka/Asuncion"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Amerikka/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+"Itäinen normaaliaika - Atikokan, Ontario ja Southamptoninsaari, Nunavut"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Amerikka/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Amerikka/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "Bahia"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "Amerikka/Bahia_Banderas"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "Meksikon keskinen aikavyöhyke - Bahia de Banderas"
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Amerikka/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Amerikka/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "Amapa, Itä-Para"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Amerikka/Belize"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "Amerikka/Bahia"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "Atlantin normaaliaika - Quebec - Basse-Côte-Nord"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Amerikka/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "Roraima"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Amerikka/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Amerikka/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "Kalliovuorten aikavyöhyke - Etelä-Idaho & Itä-Oregon"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Amerikka/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Amerikka/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "Kalliovuorten aikavyöhyke - Länsi-Nunavut"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "Amerikka/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "Mato Grosso do Sul"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Amerikka/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "Keskinen aikavyöhyke - Quintana Roo"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Amerikka/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Amerikka/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Amerikka/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Amerikka/Cayman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Amerikka/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "Keskinen normaaliaika"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Amerikka/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+"Kalliovuorten aikavyöhyke (Meksiko) - Chihuahua kauempana Yhdysvaltojen "
+"rajasta"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "Amerikka/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Amerikka/Cordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Amerikka/Costa_Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Amerikka/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "Mato Grosso"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Amerikka/Curacao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Amerikka/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "itärannikko, Ittoqqortoormiitistä (Scoresbysundista) pohjoiseen"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Amerikka/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "Tyynenmeren aikavyöhyke - Pohjois-Yukon"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Amerikka/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+"Kalliovuorten normaaliaika - Dawson Creek & Fort Saint John, Brittiläinen "
+"Kolumbia"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Amerikka/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "Kalliovuorten aikavyöhyke"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Amerikka/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "Itäinen aikavyöhyke - Michigan - useimmat paikat"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Amerikka/Dominica"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Amerikka/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+"Kalliovuorten aikavyöhyke - Alberta, Brittiläisen Kolumbian itäosa & "
+"Saskatchewanin länsiosa"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Amerikka/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "Länsi-Amazonas"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Amerikka/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Amerikka/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Amerikka/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "Koillis-Brasilia (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Amerikka/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Amerikka/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+"Atlantin aikavyöhyke - Nova Scotia - paikat joissa ei käytetty kesäaikaa "
+"vuosina 1966-1971"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Amerikka/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "useimmat paikat"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Amerikka/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "Atlantin aikavyöhyke - Labrador - useimmat paikat"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Amerikka/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Amerikka/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Amerikka/Guadeloupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Amerikka/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Amerikka/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "manner"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Amerikka/Guyana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Amerikka/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+"Atlantin aikavyöhyke - Nova Scotia (useimmat paikat), Prinssi Edwardin saari"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Amerikka/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Amerikka/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "Kalliovuorten normaaliaika - Sonora"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Amerikka/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "Itäinen aikavyöhyke - Indiana - useimmat paikat"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Amerikka/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "Keskinen aikavyöhyke - Indiana - Starken piirikunta"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Amerikka/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "Itäinen aikavyöhyke - Indiana - Crawfordin piirikunta"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "Amerikka/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "Itäinen aikavyöhyke - Indiana - Piken piirikunta"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Amerikka/Indianapolis"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "Amerikka/Indiana/Tell City"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "Keskinen aikavyöhyke - Indiana - Perryn piirikunta"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Amerikka/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "Itäinen aikavyöhyke - Indiana - Switzerlandin piirikunta"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "Amerikka/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+"Itäinen aikavyöhyke - Daviessin, Duboisin, Knoxin ja Martinin piirikunnat"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "Amerikka/Indiana/Winamac"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "Itäinen aikavyöhyke - Indiana - Pulaskin piirikunta"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Amerikka/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "Kalliovuorten aikavyöhyke - Luoteisterritorioiden länsiosa"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Amerikka/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "Itäinen aikavyöhyke - Itä-Nunavut - useimmat paikat"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Amerikka/Jamaica"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Amerikka/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Amerikka/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "Alaskan aikavyöhyke - Kaakkois-Alaska (panhandle)"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Amerikka/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Itäinen aikavyöhyke - Kentucky - Louisvillen alue"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Amerikka/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "Itäinen aikavyöhyke - Indiana - Waynen piirikunta"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Amerikka/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Amerikka/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Amerikka/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Amerikka/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "Tyynenmeren aikavyöhyke"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Amerikka/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Amerikka/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "Alagoas, Sergipe"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Amerikka/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Amerikka/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "Itä-Amazonas"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "Amerikka/Marigot"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Amerikka/Martinique"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "Amerikka/Matamoros"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+"Keskinen aikavyöhyke (Yhdysvallat) - Coahuila, Durango, Nuevo Leon, "
+"Tamaulipas lähellä Yhdysvaltojen rajaa"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Amerikka/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "Kalliovuorten aikavyöhyke - Etelä-Baja, Nayarit, Sinaloa"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Amerikka/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Amerikka/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+"Keskinen aikavyöhyke - Michigan - Dickinsonin, Gogebicin, Ironin ja "
+"Menomineen piirikunnat"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Amerikka/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "Keskinen aikavyöhyke - Campeche, Yucatan"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Amerikka/Mexico_City"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "Keskinen aikavyöhyke - useimmat paikat"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Amerikka/Miquelon"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "Amerikka/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "Atlantin aikavyöhyke - New Brunswick"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Amerikka/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+"Keskinen aikavyöhyke (Meksiko) - Coahuila, Durango, Nuevo Leon, Tamaulipas "
+"kauempana Yhdysvaltojen rajasta"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Amerikka/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Amerikka/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "Itäinen aikavyöhyke - Quebec - useimmat paikat"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Amerikka/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Amerikka/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Amerikka/New_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "Itäinen aikavyöhyke"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Amerikka/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+"Itäinen aikavyöhyke - Ontario & Quebec - paikat joissa ei käytetty kesäaikaa "
+"vuosina 1967-1973"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Amerikka/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "Alaskan aikavyöhyke - Länsi-Alaska"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Amerikka/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "Atlantin saaret"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Amerikka/North_Dakota/Center"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "Keskinen aikavyöhyke - Pohjois-Dakota - Oliverin piirikunta"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "Amerikka/North_Dakota/New_Salem"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+"Keskinen aikavyöhyke - Pohjois-Dakota - Mortonin piirikunta (paitsi Mandanin "
+"alue)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "Amerikka/Ojinaga"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+"Kalliovuorten aikavyöhyke (Yhdysvallat) - Chihuahua lähellä Yhdysvaltojen "
+"rajaa"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Amerikka/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Amerikka/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "Itäinen aikavyöhyke - Pangnirtung, Nunavut"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Amerikka/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Amerikka/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "Kalliovuorten normaaliaika - Arizona"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Amerikka/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Amerikka/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Amerikka/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Amerikka/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "Rondonia"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Amerikka/Puerto_Rico"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Amerikka/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "Keskinen aikavyöhyke - Rainy River & Fort Frances, Ontario"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Amerikka/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "Keskinen aikavyöhyke - Keski-Nunavut"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Amerikka/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "Pernambuco"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Amerikka/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "Keskinen normaaliaika - Saskatchewan - useimmat paikat"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "Amerikka/Resolute"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "Itäinen normaaliaika - Resolute, Nunavut"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Amerikka/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "Acre"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Amerikka/Rosario"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "Amerikka/Santa_Isabel"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+"Tyynenmeren aikavyöhyke (Meksiko) - Baja California kauempana Yhdysvaltojen "
+"rajasta"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "Amerikka/Santarem"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "Länsi-Para"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Amerikka/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Amerikka/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Amerikka/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "Etelä- ja Kaakkois-Brasilia (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Amerikka/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "Scoresbysund / Ittoqqortoormiit"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Amerikka/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "Kalliovuorten aikavyöhyke - Navajo"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "Amerikka/Saint Barthélemy"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Amerikka/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "Newfoundlandin aikavyöhyke, mukaan lukien Kaakkois-Labrador"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Amerikka/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Amerikka/St_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Amerikka/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Amerikka/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Amerikka/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "Keskinen normaaliaika - Saskatchewan - keskilänsi"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Amerikka/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Amerikka/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "Thule / Pituffik"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Amerikka/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "Itäinen aikavyöhyke - Thunder Bay, Ontario"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Amerikka/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+"Tyynenmeren aikavyöhyke (Yhdysvallat) - Baja California lähellä "
+"Yhdysvaltojen rajaa"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "Amerikka/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "Itäinen aikavyöhyke - Ontario - useimmat paikat"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Amerikka/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Amerikka/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "Tyynenmeren aikavyöhyke - Brittiläisen Kolumbian länsiosa"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Amerikka/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Amerikka/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "Tyynenmeren aikavyöhyke - Etelä-Yukon"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Amerikka/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "Keskinen aikavyöhyke - Manitoba & Länsi-Ontario"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Amerikka/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "Alaskan aikavyöhyke - Kaakkois-Alaska (panhandle neck)"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Amerikka/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "Kalliovuorten aikavyöhyke - Luoteisterritorioiden keskiosa"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Etelämanner/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "Casey-asema, Bailey Peninsula"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Etelämanner/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "Davis-asema, Vestfold Hills"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Etelämanner/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "Dumont-d'Urville-asema, Adélienmaa"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "Etelämanner/Macquariesaari"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "Macquariesaaren asema, Macquariesaari"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Etelämanner/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "Mawson-asema, Holme Bay"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Etelämanner/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "McMurdo-asema, Rossin saari"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Etelämanner/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "Palmer-asema, Anvers Island"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Etelämanner/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "Rothera-asema, Adelaide Island"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Etelämanner/Etelänapa"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "Amundsen-Scott-asema, Etelänapa"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Etelämanner/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "Syowa-asema, East Ongul Island"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Etelämanner/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "Vostok-asema, magneettinen etelänapa"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Arctic/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Aasia/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Aasia/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Aasia/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Aasia/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "Moskova+08 - Beringinmeri"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Aasia/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "Atıraw, Mañğıstaw"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Aasia/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "Aqtöbe"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Aasia/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Aasia/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Aasia/Bagdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Aasia/Bahrain"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Aasia/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Aasia/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Aasia/Beirut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Aasia/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Aasia/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Aasia/Calcutta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Aasia/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "Dornod, Sühbaatar"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Aasia/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "Keski-Kiina - Sichuan, Yunnan, Guanxi, Shaanxi, Guizhou jne."
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Aasia/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Aasia/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Aasia/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Aasia/Damaskos"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Aasia/Dhaka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Aasia/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Aasia/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Aasia/Dushanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Aasia/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Aasia/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "Heilongjiang (paitsi Mohe), Jilin"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Aasia/Ho_Chi_Minh"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Aasia/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Aasia/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "Bajan-Ölgii, Govi-Altai, Hovd, Uvs, Zavhan"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Aasia/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Moskova+05 - Baikaljärvi"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Aasia/Istanbul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Aasia/Jakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "Jaava & Sumatra"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Aasia/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "Papua & Molukit"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Aasia/Jerusalem"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Aasia/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Aasia/Kamchatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "Moskova+08 - Kamtšatka"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Aasia/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Aasia/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "Länsi-Tiibet & Xinjiang"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "Aasia/Kathmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Aasia/Katmandu"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "Asia/Kalkutta"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Aasia/Krasnoyarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "Moskova+04 - Jenisei"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Aasia/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "Malesian niemimaa-alue"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Aasia/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "Sabah & Sarawak"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Aasia/Kuwait"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Aasia/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Aasia/Macau"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Aasia/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "Moskova+08 - Magadan"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Aasia/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "Itä- & Etelä-Bornea, Sulawesi, Bali, Pienet Sundasaaret, Länsi-Timor"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Aasia/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Aasia/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Aasia/Nicosia"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "Aasia/Novokuznetsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Moskova+03 - Novokuznetsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Aasia/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Moskova+03 - Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Aasia/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "Moskova+03 - Länsi-Siperia"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Aasia/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "Länsi-Kazakstan"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Aasia/Phnom_Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Aasia/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "Länsi- & Keski-Borneo"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Aasia/Pyongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Aasia/Qatar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Aasia/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "Qızılorda"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Aasia/Rangoon"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Aasia/Riyadh"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Aasia/Riyadh87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Aasia/Riyadh88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Aasia/Riyadh89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Aasia/Saigon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Aasia/Sakhalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "Moskova+07 - Sahalin"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Aasia/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "Länsi-Uzbekistan"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Aasia/Seoul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Aasia/Shanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "Itä-Kiina - Peking, Guangdong, Shanghai jne."
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Aasia/Singapore"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Aasia/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Aasia/Tashkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "Itä-Uzbekistan"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Aasia/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Aasia/Tehran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Aasia/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Aasia/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Aasia/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Aasia/Tokyo"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Aasia/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Aasia/Ulaanbaatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Aasia/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Aasia/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "suurin osa Tiibetistä & Xinjiangista"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Aasia/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Aasia/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "Moskova+07 - Amur"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Aasia/Yakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "Moskova+06 - Lena"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Aasia/Yekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "Moskova+02 - Ural"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Aasia/Yerevan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlantti/Azores"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "Azorit"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlantti/Bermuda"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlantti/Canary"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "Kanariansaaret"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlantti/Kap_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlantti/Färsaaret"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "Atlantti/Färsaaret"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlantti/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlantti/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "Madeira"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlantti/Reykjavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlantti/South_Georgia"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlantti/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlantti/St_Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Australia/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Australia/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "Etelä-Australia"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Australia/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "Queensland - useimmat paikat"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Australia/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "Uusi Etelä-Wales - Yancowinna"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Australia/Canberra"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Australia/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "Tasmania - King Island"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Australia/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "Pohjoisterritorio"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "Australia/Eucla"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "Länsi-Australia - Euclan alue"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Australia/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "Tasmania - useimmat paikat"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Australia/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Australia/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "Queensland - Holiday Islands"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Australia/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "Lord Howe -saari"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Australia/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Australia/Pohjoinen"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Australia/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Australia/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "Länsi-Australia - useimmat paikat"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Australia/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Australia/Etelä"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Australia/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "Uusi Etelä-Wales - useimmat paikat"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Australia/Tasmania"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Australia/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Australia/Länsi"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Australia/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brasilia/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brasilia/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brasilia/Itä"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brasilia/Länsi"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Kanada/Atlantic"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Kanada/Central"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Kanada/Eastern"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Kanada/East-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Kanada/Mountain"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Kanada/Newfoundland"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Kanada/Pacific"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Kanada/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Kanada/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Chile/Manner"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Chile/Pääsiäissaari"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Kuuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Egypti"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Eire"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Muut/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Muut/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Muut/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Muut/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Muut/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Muut/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Muut/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Muut/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Muut/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Muut/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Muut/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Muut/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Muut/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Muut/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Muut/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Muut/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Muut/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Muut/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Muut/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Muut/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Muut/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Muut/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Muut/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Muut/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Muut/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Muut/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Muut/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Muut/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Muut/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Muut/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Muut/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Muut/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Muut/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Muut/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Muut/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Eurooppa/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Eurooppa/Andorra"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Eurooppa/Ateena"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Eurooppa/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Eurooppa/Belgrad"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Eurooppa/Berliini"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Eurooppa/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Eurooppa/Bryssel"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Eurooppa/Bukarest"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Eurooppa/Budapest"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Eurooppa/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Eurooppa/Kööpenhamina"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Eurooppa/Dublin"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Eurooppa/Gibraltar"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Eurooppa/Guernsey"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Eurooppa/Helsinki"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Eurooppa/Mansaari"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Eurooppa/Istanbul"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Eurooppa/Jersey"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Eurooppa/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Moskova-01 - Kaliningrad"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Eurooppa/Kiova"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Eurooppa/Lissabon"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Eurooppa/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Eurooppa/Lontoo"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Eurooppa/Luxemburg"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Eurooppa/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Eurooppa/Malta"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Eurooppa/Maarianhamina"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Eurooppa/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Eurooppa/Monaco"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Eurooppa/Moskova"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "Moskova+00 - Länsi-Venäjä"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Eurooppa/Nicosia"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Eurooppa/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Eurooppa/Pariisi"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Eurooppa/Podgorica"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Eurooppa/Praha"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Eurooppa/Riika"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Eurooppa/Rooma"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Eurooppa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Moskova - Samara, Udmurtia"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Eurooppa/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Eurooppa/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Eurooppa/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "Keski-Krim"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Eurooppa/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Eurooppa/Sofia"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Eurooppa/Tukholma"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Eurooppa/Tallinna"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Eurooppa/Tirana"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Eurooppa/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Eurooppa/Uzhgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "Rutenia"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Eurooppa/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Eurooppa/Vatikaani"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Eurooppa/Wien"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Eurooppa/Vilna"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Eurooppa/Volgograd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "Moskova+00 - Kaspianmeri"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Eurooppa/Varsova"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Eurooppa/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Eurooppa/Zaporozhye"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "Zaporižžja, Itä-Luhansk"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Eurooppa/Zürich"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Tehdas"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "Iso-Britannia"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "Iso-Britannia-Eire"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Islanti"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Intian_valtameri/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Intian_valtameri/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Intian_valtameri/Christmas"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Intian_valtameri/Cocos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Intian_valtameri/Comoro"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Intian_valtameri/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Intian_valtameri/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Intian_valtameri/Maldives"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Intian_valtameri/Mauritius"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Intian_valtameri/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Intian_valtameri/Réunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Iran"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Israel"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamaika"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Japani"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Libya"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Meksiko/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Meksiko/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Meksiko/General"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Lähi-Itä/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Lähi-Itä/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Lähi-Itä/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Tyyni_valtameri/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Tyyni_valtameri/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Tyyni_valtameri/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "Chathamsaaret"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "Tyyni_valtameri/Chuuk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "Chuuk (Truk) ja Yap"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Tyyni_valtameri/Easter"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "Pääsiäissaari & Sala y Gómez"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Tyyni_valtameri/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Tyyni_valtameri/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "Phoenixsaaret"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Tyyni_valtameri/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Tyyni_valtameri/Fiji"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Tyyni_valtameri/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Tyyni_valtameri/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "Galápagossaaret"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Tyyni_valtameri/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "Gambiersaaret"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Tyyni_valtameri/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Tyyni_valtameri/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Tyyni_valtameri/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "Havaiji"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Tyyni_valtameri/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "Johnstonin atolli"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Tyyni_valtameri/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "Linesaaret"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Tyyni_valtameri/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "Kosrae"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Tyyni_valtameri/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Tyyni_valtameri/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Tyyni_valtameri/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "Marquesassaaret"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Tyyni_valtameri/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "Midwaysaaret"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Tyyni_valtameri/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Tyyni_valtameri/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Tyyni_valtameri/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Tyyni_valtameri/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Tyyni_valtameri/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Tyyni_valtameri/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Tyyni_valtameri/Pitcairn"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "Tyyni_valtameri/Pohnpei"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "Pohnpei (Ponape)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Tyyni_valtameri/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Tyyni_valtameri/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Tyyni_valtameri/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Tyyni_valtameri/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Tyyni_valtameri/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Tyyni_valtameri/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "Seurasaaret"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Tyyni_valtameri/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "Gilbertsaaret"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Tyyni_valtameri/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Tyyni_valtameri/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Tyyni_valtameri/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "Wakensaari"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Tyyni_valtameri/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Tyyni_valtameri/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Puola"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugali"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapore"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Turkki"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "Yhdysvallat/Alaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "Yhdysvallat/Aleutian"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "Yhdysvallat/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "Yhdysvallat/Central"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "Yhdysvallat/Eastern"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "Yhdysvallat/East-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "Yhdysvallat/Hawaii"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "Yhdysvallat/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "Yhdysvallat/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "Yhdysvallat/Mountain"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "Yhdysvallat/Pacific"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "Yhdysvallat/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+# Tämä on oikein.
+#: timezones.h:955
+msgid "Zulu"
+msgstr "UTC"
+
+#~ msgid "US/Pacific-New"
+#~ msgstr "Yhdysvallat/Pacific-New"
diff --git a/panels/datetime/po-timezones/fr.po b/panels/datetime/po-timezones/fr.po
new file mode 100644
index 0000000..cd2b8ff
--- /dev/null
+++ b/panels/datetime/po-timezones/fr.po
@@ -0,0 +1,3263 @@
+# translation of timezones.tip.po to french
+# translation of fr.po to
+# Copyright (C) 2001 Red Hat, Inc.
+#
+# Bettina De Monti <bdemonti@redhat.it>, 2001, 2006.
+# Thomas Canniot <thomas.canniot@laposte.net>, 2006.
+# Alain PORTAL <aportal@univ-montp2.fr>, 2007.
+# Gauthier Ancelin <gauthier.ancelin@laposte.net>, 2008.
+# Thomas Canniot <mrtom@fedoraproject.org>, 2009, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones.tip\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-09-05 17:53+0200\n"
+"Last-Translator: Thomas Canniot <mrtom@fedoraproject.org>\n"
+"Language-Team: French <fedora-trans-fr@fedoraproject.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: fr\n"
+"X-Generator: Lokalize 1.1\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Afrique/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Afrique/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Afrique/Addis_Abeba"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Afrique/Alger"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "Afrique/Asmara"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Afrique/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Afrique/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Afrique/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Afrique/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Afrique/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Afrique/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Afrique/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Afrique/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Afrique/Le Caire"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Afrique/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Afrique/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "Ceuta & Melilla"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Afrique/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Afrique/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Afrique/Dar_Es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Afrique/Djibouti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Afrique/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Afrique/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Afrique/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Afrique/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Afrique/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Afrique/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Afrique/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Afrique/Khartoum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Afrique/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Afrique/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "Ouest de la République démocratique du Congo"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Afrique/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Afrique/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Afrique/Lomé"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Afrique/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Afrique/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "Est de la République démocratique du Congo"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Afrique/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Afrique/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Afrique/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Afrique/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Afrique/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Afrique/Mogadiscio"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Afrique/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Afrique/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Afrique/NDjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Afrique/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Afrique/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Afrique/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Afrique/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Afrique/Sao_Tomé"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Afrique/Tombouctou"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Afrique/Tripoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Afrique/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Afrique/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Amérique/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Îles Aléoutiennes"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Amérique/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Heure de l'Alaska"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Amérique/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Amérique/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Amérique/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "Tocantins"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Amérique/Argentine/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Buenos Aires (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Amérique/Argentine/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "Catamarca (CT), Chubut (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Amérique/Argentine/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Amérique/Argentine/Cordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "lieux divers (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Amérique/Argentine/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Jujuy (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Amérique/Argentine/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "La Rioja (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Amérique/Argentine/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "Mendoza (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Amérique/Argentine/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "Santa Cruz (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "Amérique/Argentine/Salta"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Amérique/Argentine/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "San Juan (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "Amérique/Argentine/San_Luis"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "San Luis (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Amérique/Argentine/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "Tucuman (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Amérique/Argentine/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "Terre de Feu (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Amérique/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Amérique/Asuncion"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Amérique/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "Heure de l'Est - Atikokan, Ontario et Southampton I, Nunavut"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Amérique/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Amérique/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "Bahia"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "Amérique/Bahia_Banderas"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Amérique/Barbade"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Amérique/Belém"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "Amapa, Est du Paraguay"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Amérique/Belize"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "Amérique/Blanc-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "Heure de l'Atlantique - Québec - Côte Nord"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Amerique/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "Roraima"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Amérique/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Amérique/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "Heure des Montagnes - Idaho du Sud & Orégon de l'Est"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Amérique/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Amerique/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "Heure des Montagnes - Nunavut de l'Ouest"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "Amérique/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "Mato Grosso du Sud"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Amérique/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "Heure du Centre - Quintana Roo"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Amérique/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Amérique/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Amérique/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Amérique/Cayman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Amérique/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "Heure du Centre"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Amérique/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+"Heure des Montagnes Méxicaines - État de Chihuahua loin de la frontière"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "Amérique/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Amérique/Cordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Amérique/Costa_Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Amérique/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "Mato Grosso"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Amérique/Curaçao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Amérique/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "Ittoqqortoormiit du Nord, côte Est"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Amérique/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "Heure du Pacifique - Yukon du Nord"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Amérique/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+"Heure des Montagnes - Dawson Creek & Fort Saint John, Colombie-Britannique"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Amérique/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "Heure des Montagnes"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Amérique/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "Heure de l'Est - Michigan - lieux divers"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Amérique/Dominique"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Amérique/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+"Heure des Montagnes - Alberta, Colombie-Britannique de l'Est & Saskatchewan "
+"de l'Ouest"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Amérique/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "Ouest de l'Amazonas"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Amérique/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Amérique/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Amérique/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "Nord-Est du Brésil (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Amérique/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Amérique/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+"Heure de l'Atlantique - Nouvelle-Écosse - lieux n'ayant pas respecté DST de "
+"1966 à 1971"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Amérique/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "lieux divers"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Amérique/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "Heure de l'Atlantique - Labrador - lieux divers"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Amérique/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Amérique/Grenade"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Amérique/Guadeloupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Amérique/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Amérique/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "principale région"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Amérique/Guyane"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Amérique/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+"Heure de l'Atlantique - Nouvelle-Écosse (lieux divers), Île-du-Prince-Édouard"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Amérique/La Havane"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Amerique/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "Heure des Montagnes - Sonora"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Amérique/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "Heure de l'Est - Indiana - lieux divers"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Amérique/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "Heure du Centre - Indiana - Comté de Starke"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Amérique/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "Heure de l'Est - Indiana - Comté de Crawford"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "Amérique/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "Heure de l'Est - Indiana - Comté de Pike"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Amérique/Indianapolis"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "Amérique/Indiana/Tell_City"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "Heure du Centre - Indiana - Comté de Perry"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Amérique/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "Heure de l'Est - Indiana - Comté de Switzerland"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "Amérique/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "Heure de l'Est - Indiana - Comtés de Daviess, Dubois, Knox & Martin"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "Amérique/Indiana/Winamac"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "Heure de l'Est - Indiana - Comté de Pulaski"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Amérique/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "Heure des Montagnes - Ouest des Territoires du Nord-Ouest"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Amérique/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "Heure de l'Est - Nunavut de l'Est - lieux divers"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Amérique/Jamaïque"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Amérique/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Amérique/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "Heure de l'Alaska - Queue de poêle de l'Alaska"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Amérique/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Heure de l'Est - Kentucky - Zone de Louisville"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Amérique/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "Heure de l'Est - Kentucky - Comté de Wayne"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Amérique/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Amérique/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Amérique/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Amérique/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "Heure du Pacifique"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Amérique/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Amérique/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "Alagoas, Sergipe"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Amérique/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Amérique/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "Est de l'Amazone"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "Amérique/Marigot"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Amérique/Martinique"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "Amérique/Matamoros"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+"Heure du Centre des États-Unis - Coahuila, État du Durango, Nouveau León, "
+"Tamaulipas"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Amérique/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "Heure des Montagnes - S Baja, Nayarit, Sinaloa"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Amérique/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Amérique/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+"Heure du Centre - Michigan - Comtés de Dickinson, Gogebic, Iron & Menominee"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Amérique/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "Heure du Centre - État du Campeche, Yucatan"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Amérique/Mexico"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "Heure du Centre - lieux divers"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Amérique/Miquelon"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "Amérique/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "Heure de l'Atlantique - Nouveau-Brunswick"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Amérique/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+"Heure du Centre, Méxique - Coahuila, État du Durango, Nouveau León, "
+"Tamaulipas"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Amérique/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Amérique/Montréal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "Heure de l'Est - Québec - lieux divers"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Amérique/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Amérique/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Amérique/New_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "Heure de l'Est"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Amérique/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+"Heure de l'Est - Ontario & Québec - lieux n'ayant pas respecté le DST 1967-"
+"1973"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Amérique/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "Heure de l'Alaska - Alaska de l'Ouest"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Amérique/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "Îles de l'Atlantique"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Amérique/Dakota_du_Nord/Centre"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "Heure du Centre - Dakota du Nord - Comté d'Oliver"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "Amérique/Dakota_du_Nord/New_Salem"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+"Heure du Centre - Dakota du Nord - Comté du Morton (sauf la région Mandan)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "Amérique/Ojinaga"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "Heure des Montagnes des États-Unis - État de Chihuahua"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Amérique/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Amérique/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "Heure de l'Est - Pangnirtung, Nunavut"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Amérique/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Amérique/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "Heure des Montagnes - Arizona"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Amérique/Port_au_Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Amérique/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Amérique/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Amérique/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "Rondonia"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Amérique/Puerto_Rico"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Amérique/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "Heure du Centre - Rainy River & Fort Frances, Ontario"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Amérique/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "Heure du Centre - Nunavut du Centre"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Amérique/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "Pernambuco"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Amérique/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "Heure du Centre - Saskatchewan - lieux divers"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "Amérique/Resolute"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "Heure de l'Est - Resolute, Nunavut"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Amérique/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "Acre"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Amérique/Rosario"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "Amérique/Santa_Isabel"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "Heure du Méxique côte Pacifique - Baja California loin de la frontière"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "Amérique/Santarém"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "Ouest du Paraguay"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Amérique/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Amérique/Saint_Domingue"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Amérique/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "Sud et du Sud-Est du Brésil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Amérique/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "Scoresbysund / Ittoqqortoormiit"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Amérique/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "Heure des Montagnes - Navajo"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "Amérique/Saint_Barthélemy"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Amérique/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "Heure de Terre-Neuve, inclut le Labrador du Sud-Est"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Amérique/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Amérique/Sainte_Lucie"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Amérique/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Amérique/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Amérique/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "Heure du Centre - Saskatchewan - Middle West"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Amérique/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Amérique/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "Thule / Pituffik"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Amérique/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "Heure de l'Est - Thunder Bay, Ontario"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Amérique/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+"Heure des États-Unis / Côte Pacifique - Baja California proche de la "
+"frontière US"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "Amérique/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "Heure de l'Est - Ontario - lieux divers"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Amérique/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Amérique/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "Heure du Pacifique - Colombie-Britannique de l'Ouest"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Amérique/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Amérique/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "Heure du Pacifique - Yukon du Sud"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Amérique/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "Heure du Centre - Manitôbe & Ontario de l'Ouest"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Amérique/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "Heure de l'Alaska - Queue de poêle de l'Alaska"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Amérique/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "Heure des Montagnes - Centre des Territoires du Nord-Ouest"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antarctique/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "Base antarctique Casey, Péninsule de Bailey"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antarctique/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "Base antarctique Davis, Vestfold Hills"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antarctique/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "Base antarctique Dumont d'Urville, Terre Adélie"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "Antarctique/Macquarie"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "Station de l'île Macquarie, Île de Macquarie"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antarctique/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "Base antarctique Mawson, Holme Bay"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antarctique/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "Base antarctique McMurdo, Île de Ross"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antarctique/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "Station Palmer, Île Anvers"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antarctique/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "Base antarctique Rothera, Île Adélaïde"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antarctique/Pôle_Sud"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "Station d'Amundsen-Scott, Pôle Sud"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antarctique/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "Station Syowa, E Ongul I"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antarctique/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "Base antarctique Vostok, Pôle Sud"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Arctique/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Asie/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Asie/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Asie/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Asie/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "Moscou+08 - Mer de Béring"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Asie/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "Atyraou, Manguistaou"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Asie/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "Aktioubé"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Asie/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Asie/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Asie/Bagdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Asie/Bahraïn"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Asie/Bakou"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Asie/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Asie/Beyrouth"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Asie/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Asie/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Asie/Calcutta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Asie/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "Dornod, Sukhbaatar"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Asie/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "Centre de la Chine - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Asie/Chung_ching"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Asie/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Asie/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Asie/Damas"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Asie/Dhaka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Asie/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Asie/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Asie/Dushanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Asie/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Asie/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "Heilongjiang (sauf Mohe), Jilin"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Asie/Ho_Chi_Minh"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Asie/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Asie/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Asie/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Moscou+05 - Lac Baïkal"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Asie/Istanbul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Asie/Jakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "Java & Sumatra"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Asie/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "Nouvelle-Guinée occidentale & les Moluques"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Asie/Jérusalem"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Asie/Kaboul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Asie/Kamchatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "Moscou+08 - Kamtchatka"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Asie/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Asie/Kachgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "Tibet Ouest & Xinjiang"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "Asie/Katmandou"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Asie/Katmandou"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "Asie/Calcutta"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Asie/Krasnoyarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "Moscou+04 - Rivière Ienisseï"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Asie/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "Malaisie péninsulaire"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Asie/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "Sabah & Sarawak"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Asie/Koweit"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Asie/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Asie/Macao"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Asie/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "Moscou+08 - Magadan"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Asie/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "Bornéo Est et Sud, Celebes, Bali, Nusa Tengarra, Timor Ouest"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Asie/Manille"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Asie/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Asie/Nicosie"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "Asie/Novokuznetsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Moscou+03 - Novokuznetsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Asie/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Moscou+03 - Novossibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Asie/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "Moscou+03 - Sibérie de l'Ouest"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Asie/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "Kazakhstan-Occidental"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Asie/Phnom_Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Asie/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "Bornéo Ouest et Centrale"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Asie/Pyongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Asie/Qatar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Asie/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "Kyzylorda"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Asie/Rangoon"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Asie/Riyadh"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Asie/Riyadh87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Asie/Riyadh88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Asie/Riyadh89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Asie/Saigon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Asie/Sakhaline"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "Moscou+07 - Île Sakhalin"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Asie/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "Ouzbékistan de l'Ouest"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Asie/Séoul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Asie/Shanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "Est de la Chine - Beijing, Guangdong, Shanghai, etc."
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Asie/Singapour"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Asie/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Asie/Tachkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "Ouzbékistan de l'Est"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Asie/Tbilissi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Asie/Téhéran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Asie/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Asie/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Asie/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Asie/Tokyo"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Asie/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Asie/Ulaanbaatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Asie/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Asie/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "La plupart du Tibet & Xinjiang"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Asie/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Asie/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "Moscou+07 - Fleuve Amour"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Asie/Yakoutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "Moscou+06 - Fleuve Léna"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Asie/Ekaterinbourg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "Moscou+02 - Oural"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Asie/Erevan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlantique/Açores"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "Açores"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlantique/Bermudes"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlantique/Canaries"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "Îles Canaries"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlantique/Cap_Vert"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlantique/Féroé"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "Atlantique/Féroé"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlantique/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlantique/Madère"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "Îles Madère"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlantique/Reykjavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlantique/Géorgie_du_sud"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlantique/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlantique/Sainte_Hélène"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Australie/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Australie/Adelaïde"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "Australie du Sud"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Australie/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "Queensland - lieux divers"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Australie/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "Nouvelle-Galles du Sud - Yancowinna"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Australie/Canberra"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Australie/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "Tasmanie - Île King"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Australie/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "Territoire du Nord"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "Australie/Eucla"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "Australie de l'Ouest - zone de l'Eucla"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Australie/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "Tasmanie - lieux divers"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Australie/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Australie/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "Queensland - Îles Holiday"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Australie/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "île Lord Howe"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Australie/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Australie/Nord"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Australie/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Australie/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "Australie de l'Ouest - lieux divers"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Australie/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Australie/Sud"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Australie/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "Nouvelle-Galles du Sud - lieux divers"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Australie/Tasmanie"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Australie/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Australie/Ouest"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Australie/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brésil/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brésil/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brésil/Est"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brésil/Ouest"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Canada/Atlantique"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Canada/Central"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Canada/Est"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Canada/Saskatchewan_de_LEst"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Canada/Montagnes"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Canada/Terre_Neuve"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Canada/Pacifique"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Canada/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Canada/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Chili/Continental"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Chili/Ile de Pâques"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Cuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Egypte"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Irlande"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universel"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Europe/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Europe/Andorre"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Europe/Athènes"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Europe/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Europe/Belgrade"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Europe/Berlin"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Europe/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Europe/Bruxelles"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Europe/Bucarest"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Europe/Budapest"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Europe/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Europe/Copenhague"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Europe/Dublin"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Europe/Gibraltar"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Europe/Guernsey"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Europe/Helsinki"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Europe/Isle_Of_Man"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Europe/Istanbul"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Europe/Jersey"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Europe/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Moscou-01 - Kaliningrad"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Europe/Kiev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Europe/Lisbonne"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Europe/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Europe/Londres"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Europe/Luxembourg"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Europe/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Europe/Malte"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Europe/Mariehamn"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Europe/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Europe/Monaco"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Europe/Moscou"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "Moscou+00 - Russie de l'Ouest"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Europe/Nicosie"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Europe/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Europe/Paris"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Europe/Podgorica"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Europe/Prague"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Europe/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Europe/Rome"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Europe/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Moscou - Samara, Udmurtia"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Europe/Saint_Marin"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Europe/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Europe/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "Crimée Centrale"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Europe/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Europe/Sofia"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Europe/Stockholm"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Europe/Tallinn"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Europe/Tirana"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Europe/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Europe/Uzhgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "Ruthénie"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Europe/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Europe/Vatican"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Europe/Vienne"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Europe/Vilnius"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Europe/Volgograd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "Moscou+00 - Mer Caspienne"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Europe/Varsovie"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Europe/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Europe/Zaporozhye"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "Zaporijia, Louhansk de l'Est"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Europe/Zurich"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Usine"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "Grande-Bretagne"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Irlande"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "Heure de Hawaii"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Islande"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Inde/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Inde/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Inde/Christmas"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Inde/Cocos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Inde/Comores"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Inde/Kerguélen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Inde/Mahé"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Inde/Maldives"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Inde/Maurice"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Inde/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Inde/Réunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Iran"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Israël"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamaïque"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Japon"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Libye"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Mexique/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Mexique/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Mexique/Général"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Moyen-Orient/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Moyen-Orient/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Moyen-Orient/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "HNR"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "Nouvelle-Zélande"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Pacifique/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Pacifique/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Pacifique/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "Îles Chatham"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "Pacifique/Chuuk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "Chuuk (Truk) et Yap"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Pacifique/Île de Pâques"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "Île de Pâques & Île Sala y Gómez"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Pacifique/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Pacifique/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "Îles Phœnix"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Pacifique/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Pacifique/Fidji"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Pacifique/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Pacifique/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "Îles Galápagos"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Pacifique/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "Îles Gambier"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Pacifique/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Pacifique/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Pacifique/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "USA/Hawaï"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Pacifique/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "Atoll de Johnston"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Pacifique/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "Îles de la Ligne"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Pacifique/Kosraé"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "Kosrae"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Pacifique/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Pacifique/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Pacifique/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "Îles Marquises"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Pacifique/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "Atoll de Midway"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Pacifique/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Pacifique/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Pacifique/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Pacifique/Nouméa"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Pacifique/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Pacifique/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Pacifique/Pitcairn"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "Pacifique/Pohnpei"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "Pohnpei (Ponape)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Pacifique/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Pacifique/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Pacifique/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Pacifique/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Pacifique/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Pacifique/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "Îles de la Société"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Pacifique/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "Îles Gilbert"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Pacifique/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Pacifique/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Pacifique/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "Wake"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Pacifique/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Pacifique/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Pologne"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugal"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapour"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Turquie"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universel"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "USA/Alaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "USA/Aléoutiennes"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "USA/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "USA/Central"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "USA/Est"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "USA/Indiana (Est)"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "USA/Hawaii"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "USA/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "USA/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "USA/Montagnes"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "USA/Pacifique"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "USA/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
+
+#~ msgid "US/Pacific-New"
+#~ msgstr "USA/Nouveau_Pacifique"
diff --git a/panels/datetime/po-timezones/gl.po b/panels/datetime/po-timezones/gl.po
new file mode 100644
index 0000000..a0d07a8
--- /dev/null
+++ b/panels/datetime/po-timezones/gl.po
@@ -0,0 +1,3348 @@
+# translation of gl.po to
+# , 2006.
+# , 2006.
+msgid ""
+msgstr ""
+"Project-Id-Version: gl\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2006-07-19 21:58+0200\n"
+"Last-Translator: \n"
+"Language-Team: <gl@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.9.1\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "África/Abidxán"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "África/Acra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "África/Adís_Abeba"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "África/Alxer"
+
+#: timezones.h:5
+#, fuzzy
+msgid "Africa/Asmara"
+msgstr "África/Asmara"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "África/Asmara"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "África/Bamaco"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "África/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "África/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "África/Bisau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "África/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "África/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "África/Buiumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "África/O_Cairo"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "África/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "África/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "África/Conacri"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "África/Dacar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "África/Dar_Es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "África/Xibutí"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "África/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "África/O_Aiún"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "África/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "África/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "África/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "África/Johannesburgo"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "África/Campala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "África/Khartún"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "África/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "África/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "África/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "África/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "África/Lomé"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "África/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "África/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "África/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "África/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "África/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "África/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "África/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "África/Mogadixo"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "África/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "África/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "África/Xamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "África/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "África/Nuakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "África/Uagadugu"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "África/Porto_Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "África/San_Tomé"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "África/Tombouctou"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "África/Trípoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "África/Túnez"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "África/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "América/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+#, fuzzy
+msgid "Aleutian Islands"
+msgstr "Australia/Queensland"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "América/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+#, fuzzy
+msgid "Alaska Time"
+msgstr "Estados_Unidos/Alaska"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "América/Anguila"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "América/Antiga"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "América/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "América/Arxentina/Bos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "América/Arxentina/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+#, fuzzy
+msgid "America/Argentina/ComodRivadavia"
+msgstr "América/Indiana/Indianapolis"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Amárica/Arxentina/Córdoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+#, fuzzy
+msgid "America/Argentina/Jujuy"
+msgstr "América/Juyjuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+#, fuzzy
+msgid "America/Argentina/La_Rioja"
+msgstr "América/Araguaina"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "América/Arxentina/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+#, fuzzy
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "América/Indiana/Marengo"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+#, fuzzy
+msgid "America/Argentina/Salta"
+msgstr "América/Antiga"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+#, fuzzy
+msgid "America/Argentina/San_Juan"
+msgstr "América/Antiga"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+#, fuzzy
+msgid "America/Argentina/San_Luis"
+msgstr "América/Antiga"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "América/Arxentina/Tucumán"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "América/Arxentina/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "América/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "América/Asunción"
+
+#: timezones.h:110
+#, fuzzy
+msgid "America/Atikokan"
+msgstr "América/Atka"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "América/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "América/Baía"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "América/Baía"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "América/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "América/Belém"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "América/Belice"
+
+#: timezones.h:125
+#, fuzzy
+msgid "America/Blanc-Sablon"
+msgstr "América/Cancún"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "América/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "América/Bogotá"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "América/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "América/Bos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "América/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+#, fuzzy
+msgid "America/Campo_Grande"
+msgstr "América/Caymán"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "América/Cancún"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "América/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "América/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "América/Cayena"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "América/Caymán"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "América/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+#, fuzzy
+msgid "Central Time"
+msgstr "Estados_Unidos/Central"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "América/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+#, fuzzy
+msgid "America/Coral_Harbour"
+msgstr "América/Curaçao"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "América/Córdoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "América/Costa_Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "América/Cuiabá"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "América/Curaçao"
+
+#: timezones.h:162
+#, fuzzy
+msgid "America/Danmarkshavn"
+msgstr "América/Caymán"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "América/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "América/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "América/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+#, fuzzy
+msgid "Mountain Time"
+msgstr "Estados_Unidos/Montaña"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "América/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "América/Dominica"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "América/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "América/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "América/O_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "América/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "América/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "América/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "América/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "América/Godthåb"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "América/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "América/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "América/Granada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "América/Guadalupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "América/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "América/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "América/Güiana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "América/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "América/A_Habana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "América/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "América/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "América/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "América/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+#, fuzzy
+msgid "America/Indiana/Petersburg"
+msgstr "América/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "América/Indianapolis"
+
+#: timezones.h:227
+#, fuzzy
+msgid "America/Indiana/Tell_City"
+msgstr "América/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "América/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+#, fuzzy
+msgid "America/Indiana/Vincennes"
+msgstr "América/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+#, fuzzy
+msgid "America/Indiana/Winamac"
+msgstr "América/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "América/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "América/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "América/Xamaica"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "América/Juyjuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "América/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "América/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+#, fuzzy
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "América/Kentucky/Louisville"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "América/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "América/Knox"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "América/A_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "América/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "América/Los_Ángeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+#, fuzzy
+msgid "Pacific Time"
+msgstr "Pacífico/Niue"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "América/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "América/Maceió"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "América/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "América/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+#, fuzzy
+msgid "America/Marigot"
+msgstr "América/Maceió"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "América/Martinica"
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "América/Manaus"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "América/Mazatlán"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "América/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "América/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "América/Mérida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "América/Cidade_de_México"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "América/Miquelon"
+
+#: timezones.h:289
+#, fuzzy
+msgid "America/Moncton"
+msgstr "América/Edmonton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "América/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "América/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "América/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "América/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "América/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "América/Nova_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+#, fuzzy
+msgid "Eastern Time"
+msgstr "Estados_Unidos/Leste"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "América/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "América/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "América/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+#, fuzzy
+msgid "Atlantic islands"
+msgstr "Atlántico/Canarias"
+
+#: timezones.h:313
+#, fuzzy
+msgid "America/North_Dakota/Center"
+msgstr "América/Fort_Wayne"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+#, fuzzy
+msgid "America/North_Dakota/New_Salem"
+msgstr "América/Fort_Wayne"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "América/Managua"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "América/Panamá"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "América/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "América/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "América/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "América/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "América/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "América/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "América/Pôrto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "América/Porto_Rico"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "América/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "América/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "América/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "América/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+#, fuzzy
+msgid "America/Resolute"
+msgstr "América/Belém"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+#, fuzzy
+msgid "America/Rio_Branco"
+msgstr "América/Curaçao"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "América/Rosario"
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "América/Santiago"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+#, fuzzy
+msgid "America/Santarem"
+msgstr "América/Santiago"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "América/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "América/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "América/São_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "América/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "América/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+#, fuzzy
+msgid "America/St_Barthelemy"
+msgstr "América/Belém"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "América/Saint_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "América/Saint_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "América/Santa_Lucía"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "América/Saint_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "América/San_Vicente"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "América/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "América/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "América/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "América/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "América/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "América/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "América/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "América/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "América/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "América/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "América/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "América/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "América/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antártida/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antártida/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antártida/Dumont_d'Urville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+#, fuzzy
+msgid "Antarctica/Macquarie"
+msgstr "Antártida/Mac_Murdo"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antártida/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antártida/Mac_Murdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antártida/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antártida/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antártida/Polo_Sur"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antártida/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antártida/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Ártico/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Asia/Adén"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Asia/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Asia/Ammán"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Asia/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Asia/Aqtaü"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Asia/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Asia/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Asia/Ashjabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Asia/Bagdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Asia/Bahrain"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Asia/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Asia/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Asia/Beirut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Asia/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Asia/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Asia/Calcuta"
+
+#: timezones.h:474
+#, fuzzy
+msgid "Asia/Choibalsan"
+msgstr "Asia/Calcuta"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+#, fuzzy
+msgid "Asia/Chongqing"
+msgstr "Asia/Chungking"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Asia/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Asia/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Asia/Daca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Asia/Damasco"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Asia/Dhaka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Asia/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Asia/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Asia/Dushanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Asia/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Asia/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+#, fuzzy
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Asia/Chungking"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Asia/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Asia/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Asia/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Asia/Istambul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Asia/Iakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Asia/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Asia/Xerusalén"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Asia/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Asia/Kamchatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Asia/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Asia/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+#, fuzzy
+msgid "Asia/Kathmandu"
+msgstr "Asia/Katmandú"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Asia/Katmandú"
+
+#: timezones.h:518
+#, fuzzy
+msgid "Asia/Kolkata"
+msgstr "Asia/Iakarta"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Asia/Krasnojarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Asia/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Asia/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Asia/Kuvait"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Asia/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Asia/Macau"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Asia/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+#, fuzzy
+msgid "Asia/Makassar"
+msgstr "Asia/Iakarta"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Asia/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Asia/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Asia/Nicosia"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "Asia/Irkutsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Asia/Novosibirsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Asia/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+#, fuzzy
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Asia/Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Asia/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Asia/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Asia/Phnom_Penh"
+
+#: timezones.h:553
+#, fuzzy
+msgid "Asia/Pontianak"
+msgstr "Asia/Piongiang"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Asia/Piongiang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Asia/Qatar"
+
+#: timezones.h:558
+#, fuzzy
+msgid "Asia/Qyzylorda"
+msgstr "Asia/Gaza"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Asia/Rangún"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Asia/Riyad"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Asia/Riyad87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Asia/Riyad88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Asia/Riyad89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Asia/Saigón"
+
+#: timezones.h:567
+#, fuzzy
+msgid "Asia/Sakhalin"
+msgstr "Asia/Bahrain"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Asia/Samarkanda"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Asia/Seul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Asia/Shanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Asia/Singapur"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Asia/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Asia/Tashkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Asia/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Asia/Teherán"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Asia/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Asia/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Asia/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Asia/Toquio"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Asia/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Asia/Ulaanbaatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Asia/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Asia/Ürümqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Asia/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Asia/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Asia/Yakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Asia/Yekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Asia/Yerevan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlántico/Azores"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlántico/Bermudas"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlántico/Canarias"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlántico/Cabo_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlántico/Feroe"
+
+#: timezones.h:616
+#, fuzzy
+msgid "Atlantic/Faroe"
+msgstr "Atlántico/Feroe"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlántico/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlántico/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlántico/Reiquiavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlántico/Xeorxias_do_Sur"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlántico/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlántico/Santa_Elena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Australia/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Australia/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+#, fuzzy
+msgid "South Australia"
+msgstr "Australia/ACT"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Australia/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Australia/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Australia/Canberra"
+
+#: timezones.h:636
+#, fuzzy
+msgid "Australia/Currie"
+msgstr "Australia/Canberra"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Australia/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+#, fuzzy
+msgid "Australia/Eucla"
+msgstr "Australia/Queensland"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+#, fuzzy
+msgid "Western Australia - Eucla area"
+msgstr "Australia/Queensland"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Australia/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Australia/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Australia/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Australia/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Australia/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+#, fuzzy
+msgid "Victoria"
+msgstr "Australia/Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Australia/Norte"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Australia/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Australia/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Australia/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Australia/Sur"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Australia/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Australia/Tasmania"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Australia/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Australia/Oeste"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Australia/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brasil/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brasil/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brasil/Leste"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brasil/Oeste"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Canadá/Atlántico"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Canadá/Central"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Canadá/Leste"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Canadá/Leste-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Canadá/Montaña"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Canadá/Newfoundland"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Canadá/Pacífico"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Canadá/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Canadá/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Chile/Continental"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Chile/Illa_de_Pascua"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Cuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Exipto"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Irlanda"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulú"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Europa/Ámsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Europa/Andorra"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Europa/Atenas"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Europa/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Europa/Belgrado"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Europa/Berlín"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Europa/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Europa/Bruxelas"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Europa/Bucarest"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Europa/Budapest"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Europa/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Europa/Copenhaguen"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Europa/Dublín"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Europa/Xibraltar"
+
+#: timezones.h:744
+#, fuzzy
+msgid "Europe/Guernsey"
+msgstr "Europa/Atenas"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Europa/Helsinki"
+
+#: timezones.h:746
+#, fuzzy
+msgid "Europe/Isle_of_Man"
+msgstr "Europa/Oslo"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Europa/Istambul"
+
+#: timezones.h:748
+#, fuzzy
+msgid "Europe/Jersey"
+msgstr "Europa/París"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Europa/Kaliningrado"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Europa/Kiev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Europa/Lisboa"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Europa/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Europa/Londres"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Europa/Luxemburgo"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Europa/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Europa/Malta"
+
+#: timezones.h:765
+#, fuzzy
+msgid "Europe/Mariehamn"
+msgstr "Europa/Madrid"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Europa/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Europa/Mónaco"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Europa/Moscova"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Europa/Nicosia"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Europa/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Europa/París"
+
+#: timezones.h:774
+#, fuzzy
+msgid "Europe/Podgorica"
+msgstr "Europa/Andorra"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Europa/Praga"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Europa/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Europa/Roma"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Europa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Europa/San_Mariño"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Europa/Saraxevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Europa/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Europa/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Europa/Sofía"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Europa/Estocolmo"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Europa/Tallinn"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Europa/Tirana"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Europa/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Europa/Uzgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Europa/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Europa/Vaticano"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Europa/Viena"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Europa/Vilnius"
+
+#: timezones.h:799
+#, fuzzy
+msgid "Europe/Volgograd"
+msgstr "Europa/Belgrado"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Europa/Varsovia"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Europa/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Europa/Zaporozje"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Europa/Zurich"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Fábrica"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Irlanda"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Islandia"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Índico/Tananarive"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Índico/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Índico/Christmas"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Índico/Cocos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Índico/Comores"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Índico/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Índico/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Índico/Maldivas"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Índico/Mauricio"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Índico/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Índico/Reunión"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Irán"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Israel"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Xamaica"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Xapón"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Libia"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "México/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "México/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "México/General"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Oriente_Medio/Riyad87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Oriente_Medio/Riyad88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Oriente_Medio/Riyad89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Pacífico/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Pacífico/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Pacífico/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+#, fuzzy
+msgid "Chatham Islands"
+msgstr "Chile/Illa_de_Pascua"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "Pacífico/Truk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+#, fuzzy
+msgid "Pacific/Easter"
+msgstr "Pacífico/Illa_de_Pascua"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Pacífico/Efaté"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Pacífico/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Pacífico/Fakaofu"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Pacífico/Fidji"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Pacífico/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Pacífico/Galápagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Pacífico/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Pacífico/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Pacífico/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Pacífico/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+#, fuzzy
+msgid "Hawaii"
+msgstr "Estados_Unidos/Hawaii"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Pacífico/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Pacífico/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Pacífico/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+#, fuzzy
+msgid "Kosrae"
+msgstr "Israel"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Pacífico/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Pacífico/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Pacífico/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Pacífico/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Pacífico/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Pacífico/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Pacífico/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Pacífico/Nouméa"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Pacífico/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Pacífico/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Pacífico/Pitcairn"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "Pacífico/Ponape"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Pacífico/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Pacífico/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Pacífico/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Pacífico/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Pacífico/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Pacífico/Tahití"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Pacífico/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+#, fuzzy
+msgid "Gilbert Islands"
+msgstr "Chile/Illa_de_Pascua"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Pacífico/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Pacífico/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Pacífico/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Pacífico/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Pacífico/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Polonia"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugal"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapur"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Turquía"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "Estados_Unidos/Alaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "Estados_Unidos/Aleutianas"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "Estados_Unidos/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "Estados_Unidos/Central"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "Estados_Unidos/Leste"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "Estados_Unidos/Leste-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "Estados_Unidos/Hawaii"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "Estados_Unidos/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "Estados_Unidos/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "Estados_Unidos/Montaña"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "Estados_Unidos/Pacífico"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "Estados_Unidos/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulú"
+
+#, fuzzy
+#~ msgid "US/Pacific-New"
+#~ msgstr "Estados_Unidos/Pacífico"
+
+#~ msgid "SystemV/AST4"
+#~ msgstr "SystemV/AST4"
+
+#~ msgid "SystemV/AST4ADT"
+#~ msgstr "SystemV/AST4ADT"
+
+#~ msgid "SystemV/CST6"
+#~ msgstr "SystemV/CST6"
+
+#~ msgid "SystemV/CST6CDT"
+#~ msgstr "SystemV/CST6CDT"
+
+#~ msgid "SystemV/EST5"
+#~ msgstr "SystemV/EST5"
+
+#~ msgid "SystemV/EST5EDT"
+#~ msgstr "SystemV/EST5EDT"
+
+#~ msgid "SystemV/HST10"
+#~ msgstr "SystemV/HST10"
+
+#~ msgid "SystemV/MST7"
+#~ msgstr "SystemV/MST7"
+
+#~ msgid "SystemV/MST7MDT"
+#~ msgstr "SystemV/MST7MDT"
+
+#~ msgid "SystemV/PST8"
+#~ msgstr "SystemV/PST8"
+
+#~ msgid "SystemV/PST8PDT"
+#~ msgstr "SystemV/PST8PDT"
+
+#~ msgid "SystemV/YST9"
+#~ msgstr "SystemV/YST9"
+
+#~ msgid "SystemV/YST9YDT"
+#~ msgstr "SystemV/YST9YDT"
diff --git a/panels/datetime/po-timezones/gu.po b/panels/datetime/po-timezones/gu.po
new file mode 100644
index 0000000..f50176c
--- /dev/null
+++ b/panels/datetime/po-timezones/gu.po
@@ -0,0 +1,3241 @@
+# translation of gu.po to Gujarati
+# This file is distributed under the same license as the PACKAGE package.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER.
+# Ankit Patel <ankit@redhat.com>, 2004, 2006, 2008, 2010.
+# Sweta Kothari <swkothar@redhat.com>, 2009, 2010.
+# Ankitkumar Patel <ankit@redhat.com>, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: gu\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-12-06 14:52+0530\n"
+"Last-Translator: Ankitkumar Patel <ankit@redhat.com>\n"
+"Language-Team: fedora-trans-gu@lists.fedoraproject.org\n"
+"Language: gu\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Virtaal 0.6.1\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "આફ્રિકા/અબિડ્જાન"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "આફ્રિકા/એક્રા"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "આફ્રિકા/એડિસ_એબાબા"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "આફ્રિકા/એલ્જીર્સ"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "આફ્રિકા/અસ્મેરા"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "આફ્રિકા/અસ્મેરા"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "આફ્રિકા/બામાકો"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "આફ્રિકા/બાન્ગ્યુઈ"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "આફ્રિકા/બાન્જુલ"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "આફ્રિકા/બિસાઉ"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "આફ્રિકા/બ્લાન્ટીર"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "આફ્રિકા/બ્રાઝાવિલ્લે"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "આફ્રિકા/બુજુમ્બુરા"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "આફ્રિકા/કેઈરો"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "આફ્રિકા/કાસાબ્લાન્કા"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "આફ્રિકા/સેયુટા"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "સેઉતા & મેલિલ્લા"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "આફ્રિકા/કોનાક્રી"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "આફ્રિકા/ડાકાર"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "આફ્રિકા/દારુસેલ્લામ"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "આફ્રિકા/ડિજીબૌટી"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "આફ્રિકા/ડોઉલા"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "આફ્રિકા/ઈઆઈઓઈઉન"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "આફ્રિકા/ફ્રીટાઉન"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "આફ્રિકા/ગાબોરોન"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "આફ્રિકા/હારારે"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "આફ્રિકા/જ્હોનીસબર્ગ"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "આફ્રિકા/કામ્પાલા"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "આફ્રિકા/ખાર્ટોઉમ"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "આફ્રિકા/કિગાલી"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "આફ્રિકા/કિન્સાહા"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "પશ્ચિમ ડેમોક્રેટીક રિપબ્લીક ઑફ કોંન્ગો"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "આફ્રિકા/લાગોસ"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "આફ્રિકા/લિબ્રેવિલ્લે"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "આફ્રિકા/લોમ"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "આફ્રિકા/લાઉન્દા"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "આફ્રિકા/લુબુમ્બાશી"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "પૂર્વ ડેમોક્રેટીક રિપબ્લીક ઑફ કોંન્ગો"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "આફ્રિકા/લુસાકા"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "આફ્રિકા/માલાકો"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "આફ્રિકા/માપુટો"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "આફ્રિકા/માસેરુ"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "આફ્રિકા/મ્બાબાને"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "આફ્રિકા/મોગાડીશુ"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "આફ્રિકા/મોન્રોવિયા"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "આફ્રિકા/નૈરોબી"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "આફ્રિકા/નીદ્જામેના"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "આફ્રિકા/નિયામે"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "આફ્રિકા/નૌકચોટ્ટ"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "આફ્રિકા/ઔગાડૌગુ"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "આફ્રિકા/પોર્ટો-નોવો"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "આફ્રિકા/સાઓટોમ"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "આફ્રિકા/તિમ્બુક્તુ"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "આફ્રિકા/ટ્રિપોલી"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "આફ્રિકા/ટ્યુનિસ"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "આફ્રિકા/વિન્ડહોક"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "અમેરિકા/અડાક"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "ઍલ્યુટિયન ટાપુ"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "અમેરિકા/એન્કોરેજ"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "અલાસ્કા સમય"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "અમેરિકા/એન્ગ્યુઈલ્લા"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "અમેરિકા/એન્ટીગ્વા"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "અમેરિકા/આરાગ્યુઆઈના"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "ટૉકૅન્ટીન્સ"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "અમેરિકા/આર્જેન્ટિના/બ્યુએનોસ એર્સ"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "બ્યૂએનોજ્ આયરીજ (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "અમેરિકા/આર્જેન્ટિના/કાટામાર્કા"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "કટામાર્કા (CT), ચુબુટ (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "અમેરિકા/આર્જેન્ટિના/કોમોડરીવાડાવીયા"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "અમેરિકા/આર્જેન્ટિના/કોર્ડોબા"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "મોટાભાગનાં સ્થાનો (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "અમેરિકા/આર્જેન્ટિના/જ્યુજય"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "જુજુય (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "અમેરિકા/આર્જેન્ટિના/લા રીયોજા"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "લા રીઓજા (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "અમેરિકા/આર્જેન્ટિના/મેન્ડોઝા"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "મેન્ડોઝા (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "અમેરિકા/આર્જેન્ટિના/રાયો ગાલેગોસ"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "સાન્તા ક્રુઝ (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "અમેરિકા/આર્જેન્ટિના/સાલ્ટા"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "અમેરિકા/આર્જેન્ટિના/સાન જ્યુઆન"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "સાન જૂઆન (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "અમેરિકા/આર્જેન્ટિના/સાન લૂઇસ (_L)"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "સાન લૂઇસ (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "અમેરિકા/આર્જેન્ટિના/તુકુમન"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "તુકુમાન (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "અમેરિકા/આર્જેન્ટિના/યુશુઆઈયા"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "તૈર્રા ડેલ ફુએગો (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "અમેરિકા/એરુબા"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "અમેરિકા/અસુન્સીઓન"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "અમેરિકા/અટિકોકાન"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "પૂર્વીય મૂળભૂત સમય - અટિકોકન, ઓન્ટારીયો અને સાઉથહૅમ્પટન ઇ, નુનાવુટ"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "અમેરિકા/અટ્કા"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "અમેરિકા/બાહિયા"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "બાહિઆ"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "અમેરિકા/બાહિયા બાન્ડેરાસ (_B)"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "મેક્સિકી કેન્દ્રિય સમય - બાહિયા ડે બાન્ડેરાસ"
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "અમેરિકા/બાર્બાડોસ"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "અમેરિકા/બેલેમ"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "ઍમ્પારા, ઇ પારા"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "અમેરિકા/બેલિઝ"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "અમેરિકા/બ્લેન્ક-સાબ્લોન"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "ઍટલાન્ટિક મૂળભૂત સમય - ક્યુબેક - લોવર ઇત્તરીય શોર"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "અમેરિકા/બોઆવિત્સા"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "રોરાઇમા"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "અમેરિકા/બોગોટા"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "અમેરિકા/બોઈસ"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "પર્વતીય સમય - દક્ષિણ ઇડાહો અને પૂર્વ ઓરેગોન"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "અમેરિકા/બ્યુએનોસ એર્સ"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "અમેરિકા/કેમ્બ્રિજ બે"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "પર્વતીય સમય - પશ્ચિમ નુનાવુટ"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "અમેરિકા/કામ્પો ગ્રાન્ડે"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "માટો ગ્રોસ્સો ડુ સુલ"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "અમેરિકા/કેનકન"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "મધ્ય સમય - કુઇંટાવા રુ"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "અમેરિકા/કારાક્સ"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "અમેરિકા/કાટામાર્કા"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "અમેરિકા/કેયેન્ન"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "અમેરિકા/કેયમેન"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "અમેરિકા/શિકાગો"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "કેન્દ્રિય સમય"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "અમેરિકા/ચિહુઆહુઆ"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "મેક્સિકન માઉન્ટેન ટાઈમ - ચિહુઆહુઆ US બોર્ડરથી દૂર"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "અમેરિકા/કોરાલ ટાપુ"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "અમેરિકા/કોર્ડોબા"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "અમેરિકા/કોસ્ટા રિકા"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "અમેરિકા/ક્યુઈબા"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "માટો ગ્રોસ્સો"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "અમેરિકા/ક્યુરાકાઓ"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "અમેરિકા/ડેન્માર્કશોન"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "પૂર્વીય તટ, ઉત્તરીય સ્કોર્સબાયસુંડ"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "અમેરિકા/ડાઉનસન"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "પેસિફીક સમય - ઉત્તર યુકોન"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "અમેરિકા/ડાઉનસન ક્રીક"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr "પર્વતીય મૂળભૂત સમય - દાવ્સોન ક્રિક અને ફોર્ટ સૈંટ જૉન, બ્રિટીશ કોલ્મબીયા"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "અમેરિકા/ડેન્વેર"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "પર્વતીય સમય"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "અમેરિકા/ડેટ્રોઈટ"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "પૂર્વીય સમય - મિસિગન - મોટાભાગનાં સ્થાનો"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "અમેરિકા/ડોમિનિકા"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "અમેરિકા/એડમેન્ટોન"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "પર્વતીય સમય - અલ્બેર્ટા, પૂર્વીય બ્રિટીશ કોલ્મબીયા અને પશ્ચિમ સ્કાત્વેવાન"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "અમેરિકા/યુરુનેપે"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "W Amazonas"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "અમેરિકા/ઈઆઈ સેલ્વેડોર"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "અમેરિકા/એન્સેનાડા"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "અમેરિકા/ફોર્ટાલીઝા"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "NE બ્રાઝિલ (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "અમેરિકા/ફોર્ટ વેયને"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "અમેરિકા/ગ્લેસ બે"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr "ઍટલાન્ટિક સમય - નોવા સ્કોટીયા - જગ્યાઓ કે જે DST 1966-1971 નું ધ્યાન રાખતુ નથી"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "અમેરિકા/ગોડથેબ"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "મોટાભાગનાં સ્થાનો"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "અમેરિકા/ગુઝ બે"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "ઍટલાન્ટિક સમય - લૅબ્રડોર - મોટાભાગનાં સ્થાનો"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "અમેરિકા/ગ્રાન્ડ તુર્ક"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "અમેરિકા/ગ્રેનાડા"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "અમેરિકા/ગ્યુઆડેલોપ"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "અમેરિકા/ગૌટેમાલા"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "અમેરિકા/ગ્યુઆયાકીલ"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "મેઇનલૅન્ડ"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "અમેરિકા/ગ્યુઆના"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "અમેરિકા/હેલિફેક્સ"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "ઍટલાન્ટિક સમય - નોવા સ્કોટીઆ (મોટાભાગનાં સ્થાનો), PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "અમેરિકા/હેવાના"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "અમેરિકા/હર્મોસિલ્લો"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "પર્વતીય મૂળભૂત સમય - સોનોરા"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "અમેરિકા/ઈન્ડિયાના/ઈન્ડિયાનાપોલિસ"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "પૂર્વીય સમય - ઇન્ડિયાના - મોટાભાગનાં સ્થાનો"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "અમેરિકા/ઈન્ડિયાના/ક્નોક્સ"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "મધ્ય સમય- ઇન્ડિયાના - સ્ટાર્કે દેશ"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "અમેરિકા/ઈન્ડિયાના/મારેંગો"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "પૂર્વીય સમય - ઇન્ડિયાના - ક્રૉવ્ફોર્ડ દેશ"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "અમેરિકા/ઈન્ડિયાના/પીટર્સબર્ગ"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "પૂર્વીય સમય - ઇન્ડિયાના - પાઇક દેશ"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "અમેરિકા/ઈન્ડિયાનાપોલિસ"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "અમેરિકા/ઈન્ડિયાના/ટેલે_શહેર"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "મધ્ય સમય - ઇન્ડિયાના - પેર્રી દેશ"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "અમેરિકા/ઈન્ડિયાના/વેવે"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "પૂર્વીય સમય - ઇન્ડિયાના - સ્વિઝરલૅન્ડ દેશ"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "અમેરિકા/ઈન્ડિયાના/વિન્સેનીઝ"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "પૂર્વીય સમય - ઇન્ડિયાના - ડાવીએસ, ડુબૌસ, ક્નોક્સ અને માર્ટીન દેશ"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "અમેરિકા/ઈન્ડિયાના/વિનામેક"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "પૂર્વીય સમય - ઇન્ડિયાના - પુલાસ્કી દેશ"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "અમેરિકા/ઈનુવિક"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "પર્વતીય સમય - પશ્ચિમ ઉત્તરપશ્ચિમ પ્રાંત"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "અમેરિકા/ઈક્વાલ્યુટ"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "પૂર્વીય સમય - પૂર્વ નુનાવુટ - મોટાભાગનાં સ્થાનો"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "અમેરિકા/જમૈકા"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "અમેરિકા/જ્યુજય"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "અમેરિકા/જુનેઉ"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "અલાસ્કા સમય - અલાસ્કા પૅનહૅન્ડલ"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "અમેરિકા/કેન્ટુકી/લુઈસવિલ્લે"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "પૂર્વીય સમય - કેન્ટુકી - લુઈસવિલ્લે વિસ્તાર"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "અમેરિકા/કેન્ટુકી/મોન્ટીસેલો"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "પૂર્વીય સમય - કૅન્ટુકી - વેય્ન દેશ"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "અમેરિકા/ક્નોક્સ ઈન"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "અમેરિકા/લા પાઝ"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "અમેરિકા/લિમા"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "અમેરિકા/લોસ એન્જેલસ"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "પેસિફિક સમય"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "અમેરિકા/લુઈસવિલ્લે"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "અમેરિકા/માકાઈઓ"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "અલ્ગોઆસ, સેર્ગીપે"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "અમેરિકા/માનાગુઆ"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "અમેરિકા/માનાઉસ"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "E અમાજોનાસ"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "અમેરિકા/મેરીગોટ"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "અમેરિકા/માર્ટીનીક"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "અમેરિકા/માટામોરોસ"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr "US કેન્દ્રિય સમય - કોઆહુઈલા, ડુરાન્ગો, ન્યુએવો લીઓન, તમાઉલિપાસ US બોર્ડર નજીક"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "અમેરિકા/માઝાટ્લાન"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "પર્વતીય સમય - S બજા, નયારીત, સિનાલોઆ"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "અમેરિકા/મેન્ડોઝા"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "અમેરિકા/મેનોમીનિ"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "મધ્ય સમય - મિસિગન - ડિકિંસન, ગોગેબીક, આર્ન અને મેનોમિની દેશો"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "અમેરિકા/મેરિડા"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "મધ્ય સમય - કૅપેચે, યુકૅટન"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "અમેરિકા/મેક્સિકો શહેર"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "મધ્ય સમય - મોટાભાગનાં સ્થાનો"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "અમેરિકા/મિકેલોન"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "અમેરિકા/મોન્ક્ટન"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "ઍટલાન્ટિક સમય - નવું બ્રુંસ્વીક"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "અમેરિકા/મોન્ટેરી"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+"મેક્સિકન કેન્દ્રિય સમય - કોઆહુઈલા, ડુરાન્ગો, ન્યુએવો લીઓન, તમાઉલિપાસ US બોર્ડરથી દૂર"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "અમેરિકા/મોન્ટેવિડીયો"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "અમેરિકા/મોન્ટેરીયલ"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "પૂર્વીય સમય - ક્યુબેક - મોટાભાગનાં સ્થાનો"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "અમેરિકા/મોન્ટેસેરાટ"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "અમેરિકા/નાસાઉ"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "અમેરિકા/ન્યુ યોર્ક"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "પૂર્વીય સમય"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "અમેરિકા/નિપિગોન"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr "પૂર્વીય સમય - ઓંટારીયો અને ક્યુબેક - સ્થાનો કે જે DST 1967-1973 નું ધ્યાન રાખતા નથી"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "અમેરિકા/નોમ"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "અલાસ્કા સમય - પશ્ચિમ અલાસ્કા"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "અમેરિકા/નોરોન્હા"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "એટલાન્ટિક ટાપુઓ"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "અમેરિકા/ઉત્તર ડાકોતા/સેન્ટર"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "મધ્ય સમય - ઉત્તરીય ડકોટા - ઓલીવ્હર દેશ"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "અમેરિકા/ઉત્તર ડાકોતા/ન્યુ સાલેમ"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "મધ્ય સમય - ઉત્તરીય ડકોટા - મોર્ટન દેશ (મંદાન વિસ્તારને બાદ કરતા)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "અમેરિકા/ઓજીનાગા"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "US માઉન્ટેન ટાઈમ - ચિહુઆહુઆ US બોર્ડર નજીક"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "અમેરિકા/પનામા"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "અમેરિકા/પેન્ગનીર્ટુંગ"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "પૂર્વીય સમય - પાંગ્નીર્તુગ, નુનાવુટ"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "અમેરિકા/પેરામારીબો"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "અમેરિકા/ફોનિક્સ"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "પર્વતીય મૂળભૂત સમય - ઍરિઝોના"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "અમેરિકા/પોર્ટ ઓ પ્રિન્સ"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "અમેરિકા/પોર્ટો એકર"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "અમેરિકા/પોર્ટ ઓફ સ્પેન"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "અમેરિકા/પોર્ટો વેલ્હો"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "રોંડોનીયા"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "અમેરિકા/પ્યુઅર્ટો રિકો"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "અમેરિકા/રેઈની નદી"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "મધ્ય સમય - રૈની રિવ્હર અને ફોર્ટ ફ્રાંસેસ, ઓંટારીયો"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "અમેરિકા/રેન્કીન ઈનલેટ"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "મધ્ય સમય - મધ્ય નુનાવુટ"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "અમેરિકા/રીસીફ"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "પેર્નામ્બુકો"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "અમેરિકા/રેગિના"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "મધ્ય મૂળભૂત સમય - સાસ્કાત્ચેવાન - મોટાભાગનાં સ્થાનો"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "અમેરિકા/રીસોલ્યુટ"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "પૂર્વીય મૂળભૂત સમય - રેસોલ્યૂટ, નુનાવુટ"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "અમેરિકા/રિયો બ્રાન્કો"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "એકર"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "અમેરિકા/રોઝારિયો"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "અમેરિકા/સાન્તા ઈસાબેલ (_I)"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "મેક્સિકન પેસિફિક સમય - બાજા કેલિફોર્નિયા US બોર્ડરથી દૂર"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "અમેરિકા/સાન્તારેમ"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "W પૅરા"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "અમેરિકા/સાન્ટીઆગો"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "અમેરિકા/સાન્ટો ડોમિન્ગો"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "અમેરિકા/સાઉ પૌલો"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "અમેરિકા/સ્કોર્સ બાયસન્ડ"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "સ્કોર્સબીસુંડ / ઇટ્ટોક્કોર્તૂર્મીત"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "અમેરિકા/શીપરોક"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "પર્વતીય સમય - નાવાજો"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "અમેરિકા/સંત_બાર્થેલેમી"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "અમેરિકા/સંત જ્હોન્સ"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "નવીનફાઉંડવૅંડ સમય, SE લૅબ્રડોરને સમાવી રહ્યા છે"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "અમેરિકા/સંત કિટ્સ"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "અમેરિકા/સંત લ્યુસીઆ"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "અમેરિકા/સંત થોમસ"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "અમેરિકા/સંત વિન્સેન્ટ"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "અમેરિકા/સ્વીફ્ટ કરંટ"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "મધ્ય મૂળભૂત સમય - સાસ્કાત્ચેવાન - મીડવેસ્ટ"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "અમેરિકા/ટેગ્યુસિગાલ્પા"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "અમેરિકા/થુલે"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "થુલે / પીટુફ્ફીક"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "અમેરિકા/થન્ડર બે"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "પૂર્વીય સમય - થન્ડર બે, ઓંટારીયો"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "અમેરિકા/ટાઈજુઆના"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "US પેસિફિક સમય - બાજા કેલિફોર્નિયા US બોર્ડર નજીક"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "અમેરિકા/ટોરંટો"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "પૂર્વીય સમય - ઓંટારીયો - મોટાભાગનાં સ્થાનો"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "અમેરિકા/ટોર્ટોલા"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "અમેરિકા/વાન્કોવેર"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "પેસિફીક સમય - પશ્ચિમ બ્રિટીશ કૉલમ્બીયા"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "અમેરિકા/વર્જીન"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "અમેરિકા/સફેદ ઘોડો"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "પેસિફીક સમય - દક્ષિણ યુકોન"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "અમેરિકા/વિનીપેગ"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "મધ્ય સમય - મનીટોબો અને પશ્ચિમ ઓન્ટારીયો"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "અમેરિકા/યાકુતાત"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "અલાસ્કા સમય - અલાસ્કા પૅનહૅન્ડલ નેક"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "અમેરિકા/યેલોક્નાઈફ"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "પર્વતીય સમય - મધ્ય ઉત્તરપશ્ચિમ પ્રાંત"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "એન્ટાર્કટીકા/કેસે"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "કેસી સ્ટેશન, બૈલે પેનીંસુલા"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "એન્ટાર્કટીકા/ડેવિસ"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "ડેવીસ સ્ટેશન, વેસ્ટફોલ્ડ હિલ્સ"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "એન્ટાર્કટીકા/ડુમાઉન્ટડુર્વિલ્લે"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "ડ્યુમોંટ-ડઉર્વીલ્લે સ્ટેશન, ટેર્રે અડીલ્લે"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "એન્ટાર્કટીકા/મેક્કરી"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "મેક્કરી ટાપુ સ્ટેશન, મેક્કરી ટાપુ"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "એન્ટાર્કટીકા/મોસોન"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "મવ્હોસન સ્ટેશન, હોલ્મ બે"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "એન્ટાર્કટીકા/મેકમર્ડો"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "મૅકમુર્ડો સ્ટેશન, રૉસ ટાપુ"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "એન્ટાર્કટીકા/પાલ્મર"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "પાલ્મર સ્ટેશન, અંવેર્સ ટાપુ"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "એન્ટાર્કટીકા/રોથેરા"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "રોથેરા સ્ટેશન, અડેલૈડ ટાપુ"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "એન્ટાર્કટીકા/દક્ષિણ ધ્રુવ"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "અમુંડ્સેન-સ્કૉટ સ્ટેશન, દક્ષિણ પોલ"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "એન્ટાર્કટીકા/સ્યોવા"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "સ્યોવા સ્ટેશન, એ ઓંગુલ ઇ"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "એન્ટાર્કટીકા/વોસ્ટોક"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "વોસ્ટોક સ્ટેશન, દક્ષિણ મૅગનેટિક પોલ"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "આર્કટીક/લોંગયરબાઈન"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "એશિયા/એડેન"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "એશિયા/એલ્માટી"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "એશિયા/એમાન"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "એશિયા/એનાડીર"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "મોસ્કો+૦૮ - બેરીંગ સમુદ્ર"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "એશિયા/એક્ટાઉ"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "અત્યરૌ (અતીરૌ, ગુર્યેવ), મંઘ્ઘીસ્તૌ (મનકીસ્તૌ)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "એશિયા/એક્ટોબે"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "અક્તોબે (અક્તોબે)"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "એશિયા/એશગાબાટ"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "એશિયા/એશખાબાદ"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "એશિયા/બગદાદ"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "એશિયા/બહૈરિન"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "એશિયા/બાકુ"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "એશિયા/બેંગકોક"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "એશિયા/બૈરટ"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "એશિયા/બિશકેક"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "એશિયા/બ્રુનેઈ"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "એશિયા/કલકત્તા"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "એશિયા/ચોઈસબાલ્સાન"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "ડોર્નોડ, સુખબાતર"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "એશિયા/ચોંગકીંગ"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "મધ્ય ચાઇના - સાચુઆન, યુનાન, ગુઆંગ્ક્ષી, શાન્ક્ષી, ગુઇજૌ, ઇત્યા."
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "એશિયા/ચંગકીંગ"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "એશિયા/કોલોમ્બો"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "એશિયા/ડાકા"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "એશિયા/ડોમાસ્કસ"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "એશિયા/ઢાકા"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "એશિયા/ડીલી"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "એશિયા/દુબઈ"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "એશિયા/દુશાન્બે"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "એશિયા/ગાઝા"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "એશિયા/હાર્બિન"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "હૈલોંજીઆંગ (મોહે ને બાદ કરતા), જીલીન"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "એશિયા/હો_ચી_મીન"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "એશિયા/હોંગ કોંગ"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "એશિયા/હોવ્ડ"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "બયાન-ઓલ્ગી, ગોવી-અલ્તૈ, હોવ્ડ, ઉવ્સ, જવ્ખાન"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "એશિયા/ઈર્કુત્સક"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "મૉસ્કો+૦૫ - લૅક બૈકલ"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "એશિયા/ઈસ્તંબુલ"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "એશિયા/જકાર્તા"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "જાવા અને સુમાત્રા"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "એશિયા/જયાપુરા"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "ઇરિયન જયા અને ધ મોલુક્કાસ"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "એશિયા/જેરુસલેમ"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "એશિયા/કાબુલ"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "એશિયા/કામચાત્કા"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "મોસ્કો+૦૮ - Kamchatka"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "એશિયા/કરાંચી"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "એશિયા/કાશગર"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "પશ્ચિમ તીબેટ અને ક્સીંજીઆંગચે"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "એશિયા/કાઠમંડુ"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "એશિયા/કાઠમંડુ"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "એશિયા/કલકત્તા"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "એશિયા/ક્રાસનોયાર્સ્ક"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "મૉસ્કો+૦૪ - યેનીસૈ નદી"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "એશિયા/કુઆલા લમ્પર"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "પેનીંસ્યુલાર મલેશીયા"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "એશિયા/કુચીંગ"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "સાબાહ અને સારાવાક"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "એશિયા/કુવૈત"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "એશિયા/મકાઓ"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "એશિયા/માકાઉ"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "એશિયા/મગાદાન"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "મૉસ્કો+૦૮ - મગદાન"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "એશિયા/માકાસાર"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "પૂર્વ અને દક્ષિણ બોર્નીઓ, સેલેબેજ, બાલી, નુસા ટેંગાર્રા, પશ્ચિમ તીમોર"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "એશિયા/માનિલા"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "એશિયા/મસ્કત"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "એશિયા/નાઈકોસિયા"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "એશિયા/નોવોકુઝનેત્સ્ક"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "મોસ્કો+૦૩ - નોવોકુઝનેત્સ્ક"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "એશિયા/નોવોસીબિર્સ્ક"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "મોસ્કો+03 - નોવોસીબિર્સ્ક"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "એશિયા/ઓમાસ્ક"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "મૉસ્કો+૦૩ - પશ્ચિમ સાયબેરીયા"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "એશિયા/ઓરાલ"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "પશ્ચિમ કઝાખસ્તાન"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "એશિયા/ફ્નોમ પેન્હ"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "એશિયા/પોન્ટીઆનાક"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "પશ્ચિમ અને મધ્ય બોર્નીઓ"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "એશિયા/પાયોંગયાંગ"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "એશિયા/કતાર"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "એશિયા/કીઝીલોર્ડા"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "ક્જીલોર્ડા (કાયજીલોર્ડા, ક્જીલ-ઓર્ડા)"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "એશિયા/રંગુન"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "એશિયા/રિયાધ"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "એશિયા/રીયાધ૮૭"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "એશિયા/રીયાધ૮૮"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "એશિયા/રીયાધ૮૯"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "એશિયા/સાઈગોન"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "એશિયા/સાખાલિન"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "મૉસ્કો+૦૭ - સક્હાલીન ટાપુ"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "એશિયા/સામાર્કંડ"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "પશ્ચિમ ઉજ્બેકિસ્તાન"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "એશિયા/સેયુલ"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "એશિયા/શાંગહાઈ"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "પૂર્વીય ચાઇના - બૈજીંગ, ગુઆંગડોંગ, શાંઘાઇ, વગેરે."
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "એશિયા/સિંગાપુર"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "એશિયા/તાઈપેઈ"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "એશિયા/તાશકેંટ"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "પૂર્વ ઉઝબેકિસ્તાન"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "એશિયા/ત્બિલીસી"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "એશિયા/તેહરાન"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "એશિયા/તેલએવીવ"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "એશિયા/થીંબુ"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "એશિયા/થીમ્પુ"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "એશિયા/ટોક્યો"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "એશિયા/ઉજુંગ પાન્ડાંગ"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "એશિયા/ઉલાનબાટાર"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "એશિયા/ઉલાન બાટર"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "એશિયા/ઉરુમ્કી"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "તીબેટ અને ક્સીંજીઆંગ નો ભાગ"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "એશિયા/વિયેન્ટાઈન"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "એશિયા/વિલાડીવોસ્ટોક"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "મૉસ્કો+૦૭ - અમુર નદી"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "એશિયા/યાકુત્સક"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "મૉસ્કો+૦૬ - લૅના નદી"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "એશિયા/યોકાટેરીંગબર્ગ"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "મૉસ્કો+૦૨ - યૂરલ્સ"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "એશિયા/યેરેવાન"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "એટલાન્ટિક/એઝોર્સ"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "અઝોરેસ"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "એટલાન્ટિક/બર્મ્યુડા"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "એટલાન્ટિક/કેનેરી"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "કનૅરી ટાપુ"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "એટલાન્ટિક/કેપ વેર્ડે"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "એટલાન્ટિક/ફેરો"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "એટલાન્ટિક/ફેરો"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "એટલાન્ટિક/જાન મેયેન"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "એટલાન્ટિક/મેડૈરા"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "મડૈરા ટાપુ"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "એટલાન્ટિક/રીયક્જાવિક"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "એટલાન્ટિક/દક્ષિણ જ્યોર્જિયા"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "એટલાન્ટિક/સ્ટેન્લી"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "એટલાન્ટિક/સંત હેલેના"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "ઓસ્ટ્રેલિયા/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "ઓસ્ટ્રેલિયા/અડિલેડ"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "દક્ષિણ ઓસ્ટ્રેલિયા"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "ઓસ્ટ્રેલિયા/બ્રિઝબેન"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "ક્વીંસલૅન્ડ - મોટાભાગનાં સ્થાનો"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "ઓસ્ટ્રેલિયા/બ્રોકન હિલ"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "નવીન દક્ષિણ વેલ્સ - યાંકોવિન્ના"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "ઓસ્ટ્રેલિયા/કેન્બેરા"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "ઓસ્ટ્રેલિયા/કરી"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "તસ્માનીયા - કિંગ ટાપુ"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "ઓસ્ટ્રેલિયા/ડાર્વિન"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "ઉત્તરીય પ્રાંત"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "ઓસ્ટ્રેલિયા/યુક્લા"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "પશ્ચિમી ઓસ્ટ્રેલિયા - યુક્લા વિસ્તાર"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "ઓસ્ટ્રેલિયા/હોબાર્ટ"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "તસ્માનીયા - મોટાભાગનાં સ્થાનો"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "ઓસ્ટ્રેલિયા/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "ઓસ્ટ્રેલિયા/લિન્ડેમન"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "ક્વીન્સવેંડ - હૉલીડે ટાપુઓ"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "ઓસ્ટ્રેલિયા/લોર્ડ હોવે"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "લોર્ડ હોવે ટાપુ"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "ઓસ્ટ્રેલિયા/મેલબોર્ન"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "વિક્ટોરિયા"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "ઓસ્ટ્રેલિયા/ઉત્તર"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "ઓસ્ટ્રેલિયા/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "ઓસ્ટ્રેલિયા/પર્થ"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "પશ્ચિમી ઑસ્ટ્રેલીયા - મોટાભાગનાં સ્થાનો"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "ઓસ્ટ્રેલિયા/ક્વીન્સલેન્ડ"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "ઓસ્ટ્રેલિયા/દક્ષિણ"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "ઓસ્ટ્રેલિયા/સીડની"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "નવું દક્ષિણ વેલ્સ - મોટા ભાગનાં સ્થાનો"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "ઓસ્ટ્રેલિયા/તાસ્માનિયા"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "ઓસ્ટ્રેલિયા/વિક્ટોરિયા"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "ઓસ્ટ્રેલિયા/પશ્ચિમ"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "ઓસ્ટ્રેલિયા/યાન્કોવિન્ના"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "બ્રાઝિલ/એકર"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "બ્રાઝિલ/ડિનોરોન્હા"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "બ્રાઝિલ/પૂર્વ"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "બ્રાઝિલ/પશ્ચિમ"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "કેનાડા/એટલાન્ટિક"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "કેનાડા/કેન્દ્રિય"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "કેનાડા/પૂર્વીય"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "કેનાડા/પૂર્વ સાસ્કાચેવાન"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "કેનાડા/પર્વતમાળા"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "કેનાડા/ન્યુફાઉન્ડલેન્ડ"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "કેનાડા/પેસિફિક"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "કેનાડા/સાસ્કાચેવાન"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "કેનાડા/યુકોન"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "ચિલે/કોન્ટીનેન્ટલ"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "ચિલે/પૂર્વીય ટાપુ"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "ક્યુબા"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "ઈજીપ્ત"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "આયર"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "યુરોપ/એમસ્ટેરડમ"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "યુરોપ/એન્ડોરા"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "યુરોપ/એથેન્સ"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "યુરોપ/બેલ્ફાસ્ટ"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "યુરોપ/બેલ્ગ્રેડ"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "યુરોપ/બર્લિન"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "યુરોપ/બ્રાટીસ્લાવા"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "યુરોપ/બ્રુસેલ્સ"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "યુરોપ/બુકારેસ્ટ"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "યુરોપ/બ્યુડાપેસ્ટ"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "યુરોપ/ચિસિનાઉ"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "યુરોપ/કોપેન્હાગેન"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "યુરોપ/ડબ્લીન"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "યુરોપ/ગિબ્રાલ્ટાર"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "યુરોપ/ગ્યુર્નસી"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "યુરોપ/હેલ્સીન્કી"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "યુરોપ/ઈસલ ઓફ મેન"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "યુરોપ/ઈસ્તંબુલ"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "યુરોપ/જર્સી"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "યુરોપ/કાલિનીન્ગ્રાડ"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "મૉસ્કો-૦૧ - કલીનીંગ્રૅડ"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "યુરોપ/કીવ"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "યુરોપ/લિસ્બોન"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "યુરોપ/લ્જુબ્લાજ્ના"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "યુરોપ/લંડન"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "યુરોપ/લક્ઝેમ્બર્ગ"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "યુરોપ/માડ્રિડ"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "યુરોપ/માલ્ટા"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "યુરોપ/મેરીહામ્ન"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "યુરોપ/મિન્સ્ક"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "યુરોપ/મોનેકો"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "યુરોપ/મોસ્કો"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "મૉસ્કો+૦૦ - પશ્ચિમ રશિયા"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "યુરોપ/નિકોસિયા"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "યુરોપ/ઓસ્લો"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "યુરોપ/પેરિસ"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "યુરોપ/પોડગોરીકા"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "યુરોપ/પ્રાગ્યુ"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "યુરોપ/રીગા"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "યુરોપ/રોમ"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "યુરોપ/સમારા"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "મોક્સો - સમારા, ઉડમુર્શીયા"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "યુરોપ/સાન મારિનો"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "યુરોપ/સરાજેવો"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "યુરોપ/સિમ્ફેરોપોલ"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "સેંન્ટ્રલ ક્રિમે"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "યુરોપ/સ્કોપ્જે"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "યુરોપ/સોફિયા"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "યુરોપ/સ્ટોકહોલ્મ"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "યુરોપ/તાલિન"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "યુરોપ/ટિરાને"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "યુરોપ/ટિરાસ્પોલ"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "યુરોપ/ઉઝગોરોડ"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "રુથેનીયા"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "યુરોપ/વાડુઝ"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "યુરોપ/વાટિકન"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "યુરોપ/વિયેના"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "યુરોપ/વિલનિયસ"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "યુરોપ/વોલ્ગોગ્રેડ"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "મૉસ્કો+00 - કાસ્પીયન સમુદ્ર"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "યુરોપ/વોરસો"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "યુરોપ/ઝેગ્રેબ"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "યુરોપ/ઝાપોરોઝી"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "જાપોરોજ્યે, ઇ લુગાંસ્ક / જાપોરિજીયા, એ લુહાંસ્ક"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "યુરોપ/ઝ્યુરીચ"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "કારખાનું"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Eire"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "હોંગકોંગ"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "ટાપુ"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "ભારતીય/એન્ટાનાનારીવો"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "ભારતીય/ચાગોઝ"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "ભારતીય/ક્રિસમસ"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "ભારતીય/કોકોસ"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "ભારતીય/કોમોરો"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "ભારતીય/કર્ગ્યુલેન"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "ભારતીય/માહે"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "ભારતીય/માલદીવ"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "ભારતીય/મોરેશિયસ"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "ભારતીય/મેયોટે"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "ભારતીય/રીયુનિયન"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "ઈરાન"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "ઈઝરાયલ"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "જમૈકા"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "જાપાન"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "ક્વાજાલેઈન"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "લિબ્યા"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "મેક્સિકો/બાજાનોર્ટે"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "મેક્સિકો/બાજાસુર"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "મેક્સિકો/સામાન્ય"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "મધ્યપૂર્વ/રિયાધ૮૭"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "મધ્યપૂર્વ/રિયાધ૮૮"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "મધ્યપૂર્વ/રિયાધ૮૯"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "નાવાજો"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "પેસિફિક/એપિયા"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "પેસિફિક/ઑકલેન્ડ"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "પેસિફિક/ચાથમ"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "ચાટહામ ટાપુ"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "પેસિફિક/ચુક"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "ચુક (ત્રુક) અને યાપ"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "પેસિફિક/પૂર્વીય"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "ઇસ્ટર ટાપુ અને સાલા વાય ગોમેઝ"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "પેસિફિક/એફેટ"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "પેસિફિક/એન્ડબરી"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "ફિનીક્સ ટાપુ"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "પેસિફિક/ફાકાઓફો"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "પેસિફિક/ફિજી"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "પેસિફિક/ફુનાફુટી"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "પેસિફિક/ગેલેપેગોઝ"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "ગાલાપાગોસ ટાપુ"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "પેસિફિક/ગામ્બીયર"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "ગૅમ્બૈર ટાપુ"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "પેસિફિક/ગ્યુઆડેલ્કાનાલ"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "પેસિફિક/ગ્યુઆમ"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "પેસિફિક/હોનોલુલુ"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "હવાઈ"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "પેસિફિક/જ્હોન્સ્ટન"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "જૉનસ્ટોન એટોલ્લ"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "પેસિફિક/કિરિટિમાટી"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "લાઇન ટાપુ"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "પેસિફિક/કોસરે"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "કોસરાઇ"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "પેસિફિક/ક્વાજાલેન"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "પેસિફિક/મજુરો"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "પેસિફિક/માર્કીસાસ"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "માર્ક્યૂસાસ ટાપુ"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "પેસિફિક/મિડવે"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "મિડવે ટાપુ"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "પેસિફિક/નૌરુ"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "પેસિફિક/નિયુ"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "પેસિફિક/નોરફોલ્ક"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "પેસિફિક/નૌમીયા"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "પેસિફિક/પાગો પાગો"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "પેસિફિક/પલાઉ"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "પેસિફિક/પિટકેર્ન"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "પેસિફિક/પોનપેઈ"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "પોનપેઈ (પોહ્નપૈ)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "પેસિફિક/પોનાપે"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "પેસિફિક/પોર્ટ મોરેસ્બી"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "પેસિફિક/રારોટોંગા"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "પેસિફિક/સેઈપાન"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "પેસિફિક/સામોઆ"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "પેસિફિક/ટાહિટી"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "સોસાયટી ટાપુ"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "પેસિફિક/ટારાવા"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "ગિલબર્ટ ટાપુ"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "પેસિફિક/ટોંગાટાપુ"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "પેસિફિક/તુર્ક"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "પેસિફિક/વેક"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "વૅક ટાપુ"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "પેસિફિક/વાલિસ"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "પેસિફિક/યાપ"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "પોલેન્ડ"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "પોર્ટુગલ"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "સિંગાપુર"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "તુર્કી"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "સાર્વત્રિક"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "US/અલાસ્કા"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "US/એલેયુટિઆન"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "US/એરિઝોના"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "US/કેન્દ્રિય"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "US/પૂર્વીય"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "US/પૂર્વ-ઈન્ડિયાના"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "US/હવાઈ"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "US/ઈન્ડિયાના-સ્ટાર્કે"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "US/મિચીગન"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "US/પર્વતમાળા"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "US/પેસિફિક"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "US/સમોઆ"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
diff --git a/panels/datetime/po-timezones/he.po b/panels/datetime/po-timezones/he.po
new file mode 100644
index 0000000..f09fc56
--- /dev/null
+++ b/panels/datetime/po-timezones/he.po
@@ -0,0 +1,3274 @@
+# translation of timezones.tip.po to Hebrew
+# Hebrew translations for PACKAGE package.
+# Copyright (C) 2004 THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# Automatically generated, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones.tip\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2008-10-15 02:36GMT\n"
+"Last-Translator: Oron Peled <oron@actcom.co.il>\n"
+"Language-Team: Hebrew\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "אפריקה/אבידז'אן"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "אפריקה/אקרה"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "אפריקה/אדיס אבבה"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "אפריקה/אלגיירס"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "אפריקה/אסמרה"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "אפריקה/אסֶמרה"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "אפריקה/במקו"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "אפריקה/בנגוי"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "אפריקה/בנג'ול"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "אפריקה/ביסאו"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "אפריקה/בלנטירה"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "אפריקה/בראזאוויל"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "אפריקה/בוג'ומבורה"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "אפריקה/קהיר"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "אפריקה/קזבלנקה"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "אפריקה/קהוטה"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "אפריקה/קונקרי"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "אפריקה/דקאר"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "אפריקה/דאר-א-סאלאם"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "אפריקה/ג'יבוטי"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "אפריקה/דואלה"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "אפריקה/אל-עיון"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "אפריקה/פריטאון"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "אפריקה/גאבורונה"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "אפריקה/הרארה"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "אפריקה/יוהנסבורג"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "אפריקה/קמפלה"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "אפריקה/חרטום"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "אפריקה/קיגלי"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "אפריקה/קינשאסה"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "אפריקה/לאגוס"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "אפריקה/ליברוויל"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "אפריקה/לומה"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "אפריקה/לואנדה"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "אפריקה/לובומבאשי"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "אפריקה/לוקאסה"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "אפריקה/מלבו"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "אפריקה/מפוטו"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "אפריקה/מסרו"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "אפריקה/מבאבנה"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "אפריקה/מוגדישו"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "אפריקה/מונרוביה"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "אפריקה/נאירובי"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "אפריקה/נג'מנה"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "אפריקה/נאימאי"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "אפריקה/נוקצ'וט"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "אפריקה/אוגדוגו"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "אפריקה/פורטו-נובו"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "אפריקה/סאו-טומה"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "אפריקה/טימבוקטו"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "אפריקה/טריפולי"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "אפריקה/טוניס"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "אפריקה/ווינדהק"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "אמריקה/אדק"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+#, fuzzy
+msgid "Aleutian Islands"
+msgstr "אוסטרליה/קווינסלנד"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "אמריקה/אנקורג'"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+#, fuzzy
+msgid "Alaska Time"
+msgstr "ארה\"ב/אלסקה"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "אמריקה/אנגוילה"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "אמריקה/אנטיגואה"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "אמריקה/ארגווינה"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "אמריקה/ארגנטינה/בואנוס-איירס"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "אמריקה/ארגנטינה/קטמרקה"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "אמריקה/ארגנטינה/קומודריוודוויה"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "אמריקה/ארגנטינה/קורדובה"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "אמריקה/ארגנטינה/ג'וג'וי"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "אמריקה/ארגנטינה/לה-ריוג'ה"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "אמריקה/ארגנטינה/מנדוזה"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "אמריקה/ארגנטינה/ריו-גייגוס"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+#, fuzzy
+msgid "America/Argentina/Salta"
+msgstr "אמריקה/ארגנטינה/סן-חואן"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "אמריקה/ארגנטינה/סן-חואן"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+#, fuzzy
+msgid "America/Argentina/San_Luis"
+msgstr "אמריקה/ארגנטינה/סן-חואן"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "אמריקה/ארגנטינה/טוקומאן"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "אמריקה/ארגנטינה/אושואיה"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "אמריקה/ארובה"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "אמריקה/אסונסיון"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "אמריקה/אטיקוקאן"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "אמריקה/אטקה"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "אמריקה/בהיה"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "אמריקה/בהיה"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "אמריקה/ברבדוס"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "אמריקה/בלם"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "אמריקה/בליז"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "אמריקה/בלנק-סבלון"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "אמריקה/בואה-וויסטה"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "אמריקה/בוגוטה"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "אמריקה/בויז"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "אמריקה/בואנוס-איירס"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "אמריקה/קיימברידג'-ביי"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "אמריקה/קמפו-גרנדה"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "אמריקה/קנקון"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "אמריקה/קאראקס"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "אמריקה/קטמרקה"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "אמריקה/קיין"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "אמריקה/קיימן"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "אמריקה/שיקגו"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+#, fuzzy
+msgid "Central Time"
+msgstr "ארה\"ב/מרכז"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "אמריקה/צ'יווהווה"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "אמריקה/קורל-הרבור"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "אמריקה/קורדובה"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "אמריקה/קוסטה-ריקה"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "אמריקה/קוייבה"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "אמריקה/קורקאו"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "אמריקה/דנמרקשבן"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "אמריקה/דאוסון"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "אמריקה/דאוסון-קריק"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "אמריקה/דנבר"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+#, fuzzy
+msgid "Mountain Time"
+msgstr "ארה\"ב/הרים"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "אמריקה/דטרויט"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "אמריקה/דומיניקה"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "אמריקה/אדמונטון"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "אמריקה/אירונפה"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "אמריקה/אל-סלוודור"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "אמריקה/אנסנדה"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "אמריקה/פורטלסה"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "אמריקה/פורט-ווין"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "אמריקה/גלייס-ביי"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "אמריקה/גודת'אב"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "אמריקה/גוז-ביי"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "אמריקה/גרנד-טורק"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "אמריקה/גרנדה"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "אמריקה/גואדלופה"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "אמריקה/גואטמלה"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "אמריקה/גואייקיל"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "אמריקה/גואיינה"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "אמריקה/הליפקס"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "אמריקה/הוואנה"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "אמריקה/הרמוסיו"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "אמריקה/אינדיאנה/אינדיאנפוליס"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "אמריקה/אינדיאנה/נוקס"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "אמריקה/אינדיאנה/מרנגו"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "אמריקה/אינדיאנה/פטרסבורג"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "אמריקה/אינדיאנפוליס"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "אמריקה/אינדיאנה/טל-סיטי"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "אמריקה/אינדיאנה/ווהווי"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "אמריקה/אינדיאנה/וינסנס"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "אמריקה/אינדיאנה/ווינמק"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "אמריקה/אינוויק"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "אמריקה/איקלואיט"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "אמריקה/ג'מאיקה"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "אמריקה/ג'וג'וי"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "אמריקה/ג'וניאו"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "אמריקה/קנטקי/לואיסוויל"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+#, fuzzy
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "אמריקה/קנטקי/לואיסוויל"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "אמריקה/קנטקי/מונטיסלו"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "אמריקה/נוקס-אין"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "אמריקה/לה-פז"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "אמריקה/לימה"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "אמריקה/לוס-אנג'לס"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+#, fuzzy
+msgid "Pacific Time"
+msgstr "האוקיינוס-השקט/ניוה"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "אמריקה/לואיסוויל"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "אמריקה/מסאיו"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "אמריקה/מנגואה"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "אמריקה/מנאוס"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "אמריקה/מריגוט"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "אמריקה/מרטיניק"
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "אמריקה/מנאוס"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "אמריקה/מזטלן"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "אמריקה/מנדוזה"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "אמריקה/מנומיני"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "אמריקה/מרידה"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "אמריקה/מקסיקו-סיטי"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "אמריקה/מיקולון"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "אמריקה/מונקטון"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "אמריקה/מונטריי"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "אמריקה/מונטווידאו"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "אמריקה/מונטריאול"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "אמריקה/מונטסראט"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "אמריקה/נסאו"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "אמריקה/ניו-יורק"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+#, fuzzy
+msgid "Eastern Time"
+msgstr "ארה\"ב/מזרח"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "אמריקה/ניפיגון"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "אמריקה/נום"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "אמריקה/נורונהה"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+#, fuzzy
+msgid "Atlantic islands"
+msgstr "האוקיינוס-האטלנטי/האיים-הקנריים"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "אמריקה/דקוטה-הצפונית/מרכז"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "אמריקה/דקוטה-הצפונית/ניו-סאלם"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "אמריקה/מנגואה"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "אמריקה/פנמה"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "אמריקה/פנגנירטונג"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "אמריקה/פרמריבו"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "אמריקה/פניקס"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "אמריקה/פורט-או-פרינס"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "אמריקה/פורט-אקרה"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "אמריקה/פורט-אוף-ספיין"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "אמריקה/פורטו-בלו"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "אמריקה/פוארטו-ריקו"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "אמריקה/רייני-ריבר"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "אמריקה/רנקין-אינלט"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "אמריקה/רסיפה"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "אמריקה/רגינה"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "אמריקה/רזולוט"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "אמריקה/ריו-ברנקו"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "אמריקה/רוסריו"
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "אמריקה/סנטיאגו"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+#, fuzzy
+msgid "America/Santarem"
+msgstr "אמריקה/סנטיאגו"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "אמריקה/סנטיאגו"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "אמריקה/סנטו-דומינגו"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "אמריקה/סאו-פאולו"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "אמריקה/סקורסבייסונד"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "אמריקה/שיפרוק"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "אמריקה/סט.ברטולומיי"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "אמריקה/סט.ג'והן"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "אמריקה/סט.קיטס"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "אמריקה/סט.לוסיה"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "אמריקה/סט.תומס"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "אמריקה/סט.ווינסנט"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "אמריקה/סוויפט-קורנט"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "אמריקה/טגוצ'יגלפה"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "אמריקה/תולה"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "אמריקה/ת'אנדר-ביי"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "אמריקה/טיחואנה"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "אמריקה/טורונטו"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "אמריקה/טורטולה"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "אמריקה/וואנקובר"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "אמריקה/ווריג'ין"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "אמריקה/ווייטהורס"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "אמריקה/וויניפג"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "אמריקה/יקוטט"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "אמריקה/יילואונייף"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "אנטרקטיקה/קייסי"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "אנטרקטיקה/דייויס"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "אנטרקטיקה/דומונטדורוויל"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+#, fuzzy
+msgid "Antarctica/Macquarie"
+msgstr "אנטרקטיקה/מקמורדו"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "אנטרקטיקה/מאוסון"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "אנטרקטיקה/מקמורדו"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "אנטרקטיקה/פלמר"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "אנטרקטיקה/רות'רה"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "אנטרקטיקה/הקוטב-הדרומי"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "אנטרקטיקה/סיווה"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "אנטרקטיקה/ווסטוק"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "ארקטי/לונגירביין"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "אסיה/עדן"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "אסיה/אלמטי"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "אסיה/עמאן"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "אסיה/אנדיר"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "אסיה/אקטאו"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "אסיה/אקטובה"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "אסיה/אשגבט"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "אסיה/אשחבד"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "אסיה/בגדד"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "אסיה/בחריין"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "אסיה/בקו"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "אסיה/בנגקוק"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "אסיה/ביירות"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "אסיה/בישקק"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "אסיה/ברוניי"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "אסיה/כלכותה"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "אסיה/צ'ויבלסן"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "אסיה/צ'ונגקינג"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "אסיה/צ'נגקינג"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "אסיה/קולומבו"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "אסיה/דאכה"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "אסיה/דמשק"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "אסיה/דאקה"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "אסיה/דילי"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "אסיה/דובאי"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "אסיה/דושנבה"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "אסיה/עזה"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "אסיה/חרבין"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+#, fuzzy
+msgid "Asia/Ho_Chi_Minh"
+msgstr "אסיה/צ'ונגקינג"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "אסיה/הונג-קונג"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "אסיה/הובד"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "אסיה/אירקוצק"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "אסיה/איסטנבול"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "אסיה/ג'אקרטה"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "אסיה/ג'איהפורה"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "אסיה/ירושליים"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "אסיה/קאבול"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "אסיה/קמצ'טקה"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "אסיה/קאראצ'י"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "אסיה/קשגאר"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+#, fuzzy
+msgid "Asia/Kathmandu"
+msgstr "אסיה/קטמנדו"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "אסיה/קטמנדו"
+
+#: timezones.h:518
+#, fuzzy
+msgid "Asia/Kolkata"
+msgstr "אסיה/ג'אקרטה"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "אסיה/קרסנוירסק"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "אסיה/קואלה-לומפור"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "אסיה/קוצ'ינג"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "אסיה/כווית"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "אסיה/מקאֹו"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "אסיה/מקאְו"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "אסיה/מגדאן"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "אסיה/מקסאר"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "אסיה/מנילה"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "אסיה/מוסקט"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "אסיה/ניקוסיה"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "אסיה/אירקוצק"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "אסיה/נובוסיבירסק"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "אסיה/נובוסיבירסק"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+#, fuzzy
+msgid "Moscow+03 - Novosibirsk"
+msgstr "אסיה/נובוסיבירסק"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "אסיה/אומסק"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "אסיה/אורל"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "אסיה/פנום-פן"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "אסיה/פונטיאנק"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "אסיה/פיונג-ינג"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "אסיה/קטר"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "אסיה/קיזילורדה"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "אסיה/ראנגון"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "אסיה/ריאד"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "אסיה/ריאד-‎87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "אסיה/ריאד-‎88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "אסיה/ריאד-‎89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "אסיה/סייגון"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "אסיה/סחאלין"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "אסיה/סמרקנד"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "אסיה/סאול"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "אסיה/שנגחאי"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "אסיה/סינגפור"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "אסיה/טאייפיי"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "אסיה/טשקנט"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "אסיה/טביליסי"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "אסיה/טהרן"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "אסיה/תל-אביב"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "אסיה/ת'ימבו"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "אסיה/ת'ימפו"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "אסיה/טוקיו"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "אסיה/אוג'ונג-פאנדאנג"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "אסיה/אולאנבאטאר"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "אסיה/אולנ-בטור"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "אסיה/אורומקי"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "אסיה/וויאנטיאן"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "אסיה/וולדיווסטוק"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "אסיה/יקוצק"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "אסיה/יקטרינבורג"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "אסיה/ירוואן"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "האוקיינוס-האטלנטי/האיים-האזוריים"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "האוקיינוס-האטלנטי/ברמודה"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "האוקיינוס-האטלנטי/האיים-הקנריים"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "האוקיינוס-האטלנטי/קייפ-וורדה"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "האוקיינוס-האטלנטי/פֶארו"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "האוקיינוס-האטלנטי/פארו"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "האוקיינוס-האטלנטי/ג'אן-מאיין"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "האוקיינוס-האטלנטי/מדיירה"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "האוקיינוס-האטלנטי/רייקייויק"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "האוקיינוס-האטלנטי/דרום-ג'ורג'יה"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "האוקיינוס-האטלנטי/סטאנלי"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "האוקיינוס-האטלנטי/סט.הלן"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "אוסטרליה/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "אוסטרליה/אדלייד"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+#, fuzzy
+msgid "South Australia"
+msgstr "אוסטרליה/ACT"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "אוסטרליה/בריסביין"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "אוסטרליה/ברוקן-היל"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "אוסטרליה/קנברה"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "אוסטרליה/קורי"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "אוסטרליה/דרווין"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "אוסטרליה/אאוקלה"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+#, fuzzy
+msgid "Western Australia - Eucla area"
+msgstr "אוסטרליה/אאוקלה"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "אוסטרליה/הוברט"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "אוסטרליה/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "אוסטרליה/לינדמן"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "אוסטרליה/לורד-הווה"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "אוסטרליה/מלבורן"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+#, fuzzy
+msgid "Victoria"
+msgstr "אוסטרליה/וויקטוריה"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "אוסטרליה/צפון"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "אוסטרליה/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "אוסטרליה/פרת'"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "אוסטרליה/קווינסלנד"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "אוסטרליה/דרום"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "אוסטרליה/סידני"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "אוסטרליה/טסמניה"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "אוסטרליה/וויקטוריה"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "אוסטרליה/מערב"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "אוסטרליה/ינקובינה"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "ברזיל/אקרה"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "ברזיל/דה-נורונהה"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "ברזיל/מזרח"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "ברזיל/מערב"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "קנדה/אטלנטי"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "קנדה/מרכז"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "קנדה/מזרח"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "קנדה/מזרח-ססקצ'וואן"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "קנדה/הרים"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "קנדה/ניו-פאונדלנד"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "קנדה/האוקינוס-השקט"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "קנדה/ססקצ'וואן"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "קנדה/יוקון"
+
+#: timezones.h:685
+msgid "CET"
+msgstr ""
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "צ'ילה/היבשת"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "צ'ילה/איי-הפסחא"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr ""
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "קובה"
+
+#: timezones.h:690
+msgid "EET"
+msgstr ""
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "מצריים"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "אירלנד"
+
+#: timezones.h:693
+msgid "EST"
+msgstr ""
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr ""
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr ""
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr ""
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr ""
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr ""
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr ""
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr ""
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr ""
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr ""
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr ""
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr ""
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr ""
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr ""
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr ""
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr ""
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr ""
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr ""
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr ""
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr ""
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr ""
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr ""
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr ""
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr ""
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr ""
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr ""
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr ""
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr ""
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr ""
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr ""
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr ""
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr ""
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr ""
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr ""
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr ""
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr ""
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr ""
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "אירופה/אמסטרדם"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "אירופה/אנדורה"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "אירופה/אתונה"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "אירופה/בלפסט"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "אירופה/בלגרד"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "אירופה/ברלין"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "אירופה/ברטיסלבה"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "אירופה/בריסל"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "אירופה/בוקרשט"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "אירופה/בודפשט"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "אירופה/צ'יסינאו"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "אירופה/קופנהאגן"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "אירופה/דבלין"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "אירופה/גיברלטר"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "אירופה/גוארנסיי"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "אירופה/הלסינקי"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "אירופה/אי-האדם"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "אירופה/איסטנבול"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "אירופה/ג'רסי"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "אירופה/קלינינגרד"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "אירופה/קייב"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "אירופה/ליסבון"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "אירופה/לובליאנה"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "אירופה/לונדון"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "אירופה/לוקסמבורג"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "אירופה/מדריד"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "אירופה/מלטה"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "אירופה/מריהם"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "אירופה/מינסק"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "אירופה/מונקו"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "אירופה/מוסקווה"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "אירופה/ניקוסיה"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "אירופה/אוסלו"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "אירופה/פריס"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "אירופה/פודגוריקה"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "אירופה/פראג"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "אירופה/ריגה"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "אירופה/רומא"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "אירופה/סמרה"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "אירופה/סן-מרינו"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "אירופה/סרייבו"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "אירופה/סימפרופול"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "אירופה/סקופייה"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "אירופה/סופיה"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "אירופה/סטוקהולם"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "אירופה/טאלין"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "אירופה/טירנה"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "אירופה/טירספול"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "אירופה/אוזגורוד"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "אירופה/וודוז"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "אירופה/ווטיקן"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "אירופה/וינה"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "אירופה/וילניוס"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "אירופה/וולגוגרד"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "אירופה/ווארשה"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "אירופה/זאגרב"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "אירופה/זפורוזי"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "אירופה/ציריך"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "מפעל"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "בריטניה"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "בריטניה-אירלנד"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr ""
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr ""
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr ""
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr ""
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "גריניץ'"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "הונג-קונג"
+
+#: timezones.h:817
+msgid "HST"
+msgstr ""
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "איסלנד"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "הודו/אנטננריבו"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "הודו/צ'אגוס"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "הודו/כריסטמס"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "הודו/קוקוס"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "הודו/קומורו"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "הודו/קרגואלן"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "הודו/מהה"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "הודו/האיים-המלדיביים"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "הודו/מאוריציוס"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "הודו/מיוטה"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "הודו/איחוד"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "אירן"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "ישראל"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "ג'מאיקה"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "יפן"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "קוואג'אלין"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "לוב"
+
+#: timezones.h:837
+msgid "MET"
+msgstr ""
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "מקסיקו/בחה-נורטה"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "מקסיקו/בחה-סור"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "מקסיקו/כללי"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "מזרח-תיכון/ריאד87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "מזרח-תיכון/ריאד88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "מזרח-תיכון/ריאד89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr ""
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr ""
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "נבאחו"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "ניו-זילנד"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "ניו-זילנד-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "האוקיינוס-השקט/אפיה"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "האוקיינוס-השקט/אוקלנד"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "האוקיינוס-השקט/צ'תם"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+#, fuzzy
+msgid "Chatham Islands"
+msgstr "צ'ילה/איי-הפסחא"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "האוקיינוס-השקט/טרוק"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "האוקיינוס-השקט/איסטר"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "האוקיינוס-השקט/אפאט"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "האוקיינוס-השקט/אנדרבורי"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "האוקיינוס-השקט/פקאופו"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "האוקיינוס-השקט/פיג'י"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "האוקיינוס-השקט/פונהפוטי"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "האוקיינוס-השקט/גלאפגוס"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "האוקיינוס-השקט/גמבייר"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "האוקיינוס-השקט/גואדל-קנאל"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "האוקיינוס-השקט/גואם"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "האוקיינוס-השקט/הונולולו"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+#, fuzzy
+msgid "Hawaii"
+msgstr "ארה\"ב/הוואי"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "האוקיינוס-השקט/ג'ונסון"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "האוקיינוס-השקט/קיריטימטי"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "האוקיינוס-השקט/קוסרה"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+#, fuzzy
+msgid "Kosrae"
+msgstr "ישראל"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "האוקיינוס-השקט/קואג'ליין"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "האוקיינוס-השקט/מג'ורו"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "האוקיינוס-השקט/מרקסס"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "האוקיינוס-השקט/מידווי"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "האוקיינוס-השקט/נאורו"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "האוקיינוס-השקט/ניוה"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "האוקיינוס-השקט/נורפולק"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "האוקיינוס-השקט/נומאה"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "האוקיינוס-השקט/פגו-פגו"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "האוקיינוס-השקט/פלאו"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "האוקיינוס-השקט/פיטקרן"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "האוקיינוס-השקט/פונפה"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "האוקיינוס-השקט/פונפה"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "האוקיינוס-השקט/פורט-מורסבי"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "האוקיינוס-השקט/ררוטונגה"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "האוקיינוס-השקט/סאייפן"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "האוקיינוס-השקט/סמואה"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "האוקיינוס-השקט/טהיטי"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "האוקיינוס-השקט/טראווה"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+#, fuzzy
+msgid "Gilbert Islands"
+msgstr "צ'ילה/איי-הפסחא"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "האוקיינוס-השקט/טונגהטפו"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "האוקיינוס-השקט/טרוק"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "האוקיינוס-השקט/ווייק"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "האוקיינוס-השקט/ווליס"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "האוקיינוס-השקט/ייאפ"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "פולין"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "פורטוגל"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr ""
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr ""
+
+#: timezones.h:934
+msgid "ROC"
+msgstr ""
+
+#: timezones.h:935
+msgid "ROK"
+msgstr ""
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "סינגפור"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "טורקיה"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr ""
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "עולמי"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "ארה\"ב/אלסקה"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "ארה\"ב/האיים-האלוטים"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "ארה\"ב/אריזונה"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "ארה\"ב/מרכז"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "ארה\"ב/מזרח"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "ארה\"ב/מזרח-אינדיאנה"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "ארה\"ב/הוואי"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "ארה\"ב/אינדיאנה-סטרקה"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "ארה\"ב/מישיגן"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "ארה\"ב/הרים"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "ארה\"ב/האוקיינוס-השקט"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "ארה\"ב/סמואה"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "זמן מתואם עולמי (UTC)"
+
+#: timezones.h:953
+msgid "WET"
+msgstr ""
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr ""
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "זולו"
+
+#~ msgid "US/Pacific-New"
+#~ msgstr "ארה\"ב/האוקיינוס-השקט-חדש"
diff --git a/panels/datetime/po-timezones/hi.po b/panels/datetime/po-timezones/hi.po
new file mode 100644
index 0000000..05b7ed1
--- /dev/null
+++ b/panels/datetime/po-timezones/hi.po
@@ -0,0 +1,3247 @@
+# translation of system-config-date.master-timezones.po to Hindi
+# This file is distributed under the same license as the PACKAGE package.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER.
+#
+# Rajesh Ranjan <rranjan@redhat.com>, 2005, 2006, 2008, 2010.
+# Rajesh Ranjan <rajesh672@gmail.com>, 2009.
+msgid ""
+msgstr ""
+"Project-Id-Version: system-config-date.master-timezones\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-12-06 15:26+0530\n"
+"Last-Translator: Rajesh Ranjan <rranjan@redhat.com>\n"
+"Language-Team: Hindi <hindi@hindi>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: hi\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: nplurals=2; plural=(n!=1);\n\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "अफ्रीका/अबीड्जन"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "अफ्रीका/अक्रा"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "अफ्रीका/एदिस_अबाबा"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "अफ्रीका/अलजियर्स"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "अफ्रीका/असमारा"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "अफ्रीका/असमेरा"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "अफ्रीका/बामाको"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "अफ्रीका/बंगुई"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "अफ्रीका/बंजल"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "अफ्रीका/बिसू"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "अफ्रीका/ब्लेनतरी"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "अफ्रीका/ब्राजाविल"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "अफ्रीका/बुजमबुरा"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "अफ्रीका/कैरो"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "अफ्रीका/कासाब्लांका"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "अफ्रीका/सियूटा"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "सेटुआ व मेलिया"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "अफ्रीका/कोनाक्री"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "अफ्रीका/डकर"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "अफ्रीका/दार_एस_स्लेम"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "अफ्रीका/ड्जिबोटी"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "अफ्रीका/डूअला"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "अफ्रीका/एल_ऐन"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "अफ्रीका/फ्रीटाउन"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "अफ्रीका/गैब्रोन"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "अफ्रीका/हरारे"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "अफ्रीका/जोहांन्सबर्ग"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "अफ्रीका/कम्पाला"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "अफ्रीका/खार्तुम"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "अफ्रीका/किगाली"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "अफ्रीका/किंसासा"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "कांगो का पश्चिमी लोकतांत्रिक गणराज्य"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "अफ्रीका/लागोस"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "अफ्रीका/लिबरविल"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "अफ्रीका/लोम"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "अफ्रीका/लुआंडा"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "अफ्रीका/लुबूंबशी"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "कांगो का पूर्वी लोकतांत्रिक गणराज्य"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "अफ्रीका/लुसाका"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "अफ्रीका/मलाबो"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "अफ्रीका/मपुतो"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "अफ्रीका/मैसेरु"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "अफ्रीका/मेबाबाने"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "अफ्रीका/मोगाडीशू"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "अफ्रीका/मोनरोविया"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "अफ्रीका/नैरोबी"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "अफ्रीका/नजेमेना"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "अफ्रीका/नेमै"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "अफ्रीका/नाकचाट"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "अफ्रीका/ऊगोदूगो"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "अफ्रीका/पोर्टो_नोवो"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "अफ्रीका/सावो टोम "
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "अफ्रीका/तिंबकटू"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "अफ्रीका/त्रिपोली"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "अफ्रीका/ट्यूनिस"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "अफ्रीका/विंडहॉक"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "अमेरिका/अदक"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "एल्युशियन द्वीप"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "अमेरिका/एंकरेज"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "अलास्का समय"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "अमेरिका/अंग्यूला"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "अमेरिका/एंटीगुआ"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "अमेरिका/अराग्वेना"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "टोकान्टिन्स"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "अमेरिका/अर्जेंटीना/ब्युनसआयर्स"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "ब्यूनस आयर्स (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "अमेरिका/अर्जेंटीना/कैटामारका"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "काटामर्का (CT), चुबुट (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "अमेरिका/अर्जेंटीना/कोमोडरिवाडाविया"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "अमेरिका/अर्जेंटीना/कारडोबा"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "अधिकतर स्थान (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "अमेरिका/अर्जेंटीना/जुजै"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "जुजुए (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "अमेरिका/अर्जेंटीना/लारियोजा"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "ला रियोजा (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "अमेरिका/अर्जेंटीना/मेनडोजा"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "मेंडोजा (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "अमेरिका/अर्जेंटीना/रियो गैलियस"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "सांता क्रूज (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "अमेरिका/अर्जेंटीना/साल्टा"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "अमेरिका/अर्जेंटीना/सान जुआन"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "सान जुआन (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "अमेरिका/अर्जेंटीना/सान_लुइस"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "सान लुइस (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "अमेरिका/अर्जेंटीना/टकमैन"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "टुकुमैन (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "अमेरिका/अर्जेंटीना/उशुआहिया"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "टियेरा डेल फ्यूगो (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "अमेरिका/अरुबा"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "अमेरिका/असनशियन"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "अमेरिका/एटिकोकान"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "पूर्वी मानक समय - एटिकोकन, ओंटारियो और साउथंपटन आई, नूनावुट"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "अमेरिका/अटका"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "अमेरिका/विस्ता"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "बाहिया"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "अमेरिका/वाहिया_बैंडरेस"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "मैक्सिको केंद्रीय समय - बाहिया डे बैंडेरस"
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "अमेरिका/बारबाडोस"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "अमेरिका/बेलेम"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "अमापा, ई पारा"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "अमेरिका/बेलिज़"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "अमेरिका/ब्लांक-सैब्लॉन"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "अटलांटिक मानक समय - क्यूबेक - निचला उत्तरी किनारा"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "अमेरिका/बोआ_विस्ता"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "रोराइमा"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "अमेरिका/बोगोटा"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "अमेरिका/बोइस"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "पर्वतीय समय - दक्षिणी इदाहो और पूर्वी ओरेगांव"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "अमेरिका/ब्युनसआयर्स"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "अमेरिका/कैम्बरीज़_बे"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "पर्वतीय समय - पश्चिमी नूनावट"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "अमेरिका/कंपो ग्रैंड"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "माटो ग्रोसो डो सुल"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "अमेरिका/कानकुन"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "केंद्रीय समय - क्विंटाना रू"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "अमेरिका/कैराकस"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "अमेरिका/कैटामारका"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "अमेरिका/कैयेन"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "अमेरिका/कैमेन"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "अमेरिका/शिकागो"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "केन्द्रीय समय"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "अमेरिका/चिहूआहुआ"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "मैक्सिकन पर्वतीय समय - यू.एस. सीमा से दूर चिहुआहुआ"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "अमेरिका/कोरल हार्बर"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "अमेरिका/कारडोबा"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "अमेरिका/कोस्टा_रिका"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "अमेरिका/क्यूबा"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "मातो ग्रोसो"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "अमेरिका/कुराकाओ"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "अमेरिका/डेनमार्कशान"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "पूर्वी तट, स्कोर्सबीसंड के उत्तर"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "अमेरिका/डॉशन"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "प्रशांत समय - उत्तरी यूकोन"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "अमेरिका/डॉशन_क्रीक"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid "Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr "पर्वतीय मानक समय - डॉउसन क्रीक और फोर्ट सैंट जॉन, ब्रिटिश कोलंबिया"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "अमेरिका/डेनवर"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "पर्वतीय समय"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "अमेरिका/डेट्रोइट"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "पूर्वी समय - मिशिगन - अधिकतर स्थान"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "अमेरिका/डोमिनिका"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "अमेरिका/एड्मनटन"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "पर्वतीय समय - अलबर्टा, पूर्वी ब्रिटिश कोलंबिया व पश्चिमी सास्कचावान"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "अमेरिका/युरीनएप"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "पश्चिमी आमेजन"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "अमेरिका/एल_सेल्वाडोर"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "अमेरिका/एनसेनेडा"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "अमेरिका/फोर्टलेजा"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "NE ब्राजील (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "अमेरिका/फोर्ट_वेन"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "अमेरिका/ग्लेस_बे"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr "अटलांटिक समय - नोवा स्कोशिय - स्थान जो DST 1966-1971 को नहीं देखता है"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "अमेरिका/गाडथब"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "अधिकतर स्थान"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "अमेरिका/गूस_बे"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "अटलांटिक समय - लैब्रोडोर - अधिकतर स्थान"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "अमेरिका/ग्रैंड_टर्क"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "अमेरिका/ग्रैंनेडा"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "अमेरिका/ग्वाडेलोपे"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "अमेरिका/ग्वाटेमाला"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "अमेरिका/गुआयाकिल"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "मेनलैंड"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "अमेरिका/गयाना"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "अमेरिका/हैलीफेक्स"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "अटलांटिक समय - नोवा स्कोशिया (अधिकतर जगह), PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "अमेरिका/हवाना"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "अमेरिका/हरमोसिलो"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "पर्वतीय मानक समय - सोनोरा"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "अमेरिका/इंडियाना/इंडियानापोलिस"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "पूर्वी समय - इंडियाना - अधिकतर स्थान"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "अमेरिका/इंडियाना/नाक्स"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "केंद्रीय समय - इंडियाना - स्टार्क काउंटी"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "अमेरिका/इंडियाना/मेरेंगो"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "पूर्वी समय - इंडियाना - क्रॉउफोर्ड काउंटी"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "अमेरिका/इंडियाना/पीटर्सवर्ग"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "पूर्वी समय - इंडियाना - पाइक काउंटी"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "अमेरिका/इंडियानापोलिस"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "अमेरिका/इंडियाना/टेल_सिटी"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "केंद्रीय समय - इंडियाना - पेरी काउंटी"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "अमेरिका/इंडियाना/वेवे"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "पूर्वी समय - इंडियाना - स्विटजरलैंड काउंटी"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "अमेरिका/इंडियाना/विंसिनेस"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "पूर्वी समय - इंडियाना - डैविस, ड्यूवोइस, नोक्स, व मार्टिन काउंटी"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "अमेरिका/इंडियाना/विनामेक"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "पूर्वी समय - इंडियाना - पुलास्की काउंटी"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "अमेरिका/इनुविक"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "पर्वतीय समय - पश्चिम उत्तरपश्चिम क्षेत्र"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "अमेरिका/इकालूइत"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "पूर्वी समय - पूर्वी नूनावट - अधिकतर स्थान"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "अमेरिका/जमैका"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "अमेरिका/जुजै"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "अमेरिका/जूनो"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "अलास्का समय - अलास्का पैनहैंडल"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "अमेरिका/कैंटकी/लुईविल"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "पूर्वी समय - केंटुकी - लुईविले क्षेत्र"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "अमेरिका/कैंटकी/मोनटिकलो"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "पूर्वी समय - केंटुकी - वाएने काउंटी"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "अमेरिका/नोक्सइन"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "अमेरिका/ला_पाज"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "अमेरिका/लिमा"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "अमेरिका/लॉस_एंजिल्स"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "प्रशांत समय"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "अमेरिका/लुईविल"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "अमेरिका/मैसियो"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "एलागोआस, सर्जीपे"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "अमेरिका/मेनेगुआ"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "अमेरिका/मैनास"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "पूर्वी आमेजन"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "अमेरिका/मैरिगोट"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "अमेरिका/मॉरटिनिक"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "अमेरिका/मेटामोरोस"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid "US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr "यू.एस. केंद्रीय समय - यू.एस. सीमा के नजदीक कोआहुइला, ड्यूरैंगो, न्यूवो लियोन, तमालिपास"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "अमेरिका/मेजेटलेन"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "पर्वतीय समय - दक्षिणी बाजा, नेयारिट, सिनालोआ"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "अमेरिका/मेनडोजा"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "अमेरिका/मेनोमिनी"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "केंद्रीय समय - मिशिगन - डिकिन्शन, गोजेबिक, आइरन व मेनोमीनी काउंटी"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "अमेरिका/मेरीडा"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "केंद्रीय समय - कैंपेची, यूकाटन"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "अमेरिका/मैक्सिको_सिटी"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "केंद्रीय समय - अधिकतर स्थान"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "अमेरिका/मिक्लॉन"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "अमेरिका/मोंकटन"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "अटलांटिक समय - न्यू ब्रंसबिक"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "अमेरिका/मांटेरी"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr "मैक्सिकन केंद्रीय समय - यू.एस. सीमा से दूर कोआहुइला, ड्यूरैंगो, न्यूवो लियोन, तमालिपास"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "अमेरिका/मांटेविडीयो"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "अमेरिका/मांट्रियल"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "पूर्वी समय - क्यूबेक - अधिकतर स्थान"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "अमेरिका/मांटेसेराट"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "अमेरिका/नसो"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "अमेरिका/न्यू_यार्क"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "पूर्वी समय"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "अमेरिका/निपीगन"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid "Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr "पूर्वी समय - ओंटारियो & क्यूबेक - स्थान जो इसे नहीं देखता है DST 1967-1973"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "अमेरिका/नोम"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "अलास्का समय - पश्चिम अलास्का"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "अमेरिका/नोरोंहा"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "अटलांटिक द्वीप"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "अमेरिका/उत्तर_डकोटा/मध्य"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "केंद्रीय समय - उत्तरी डकोटा - ओलिवर काउंटी"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "अमेरिका/उत्तर_डकोटा/नया_सलेम"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "केंद्रीय समय - उत्तरी डकोटा - मार्टन काउंटी (सिवाय मंदान क्षेत्र)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "अमेरिका/ओजीनागा"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "यू.एस. पर्वतीय समय - यू.एस. सीमा के निकट चिहुआहुआ"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "अमेरिका/पनामा"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "अमेरिका/पैंगनीरटंग"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "पूर्वी समय - पैनग्निरतुंग, नूनावट"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "अमेरिका/पारामारीबो"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "अमेरिका/फिनिक्स"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "पर्वतीय मानक समय - अरिजोना"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "अमेरिका/पोर्ट_ओ_प्रिंस"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "अमेरिका/पोर्ट_एकर"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "अमेरिका/पोर्ट_आफ_स्पेन"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "अमेरिका/पोर्टो_वेलो"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "रोंडोनिया"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "अमेरिका/प्यूरिटो_रिको"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "अमेरिका/रैनी_रिवर"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "केंद्रीय समय - रेनी रिवर व फोर्ट फ्रांस, ओंटारियो"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "अमेरिका/रेनकीन_इनलेट"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "केंद्रीय समय - मध्य नूनावट"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "अमेरिका/रिसीफ"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "पर्नामब्यूको"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "अमेरिका/रेजीना"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "केंद्रीय मानक समय - ससाक्चावान - अधिकतर स्थान"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "अमेरिका/रिजॉल्यूट"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "पूर्वी मानक समय - रिजॉल्यूट, नूनावट"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "अमेरिका/राये_ब्रानको"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "एकर"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "अमेरिका/रोसारियो"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "अमेरिका/संता_इसाबेल"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "मैक्सिकन प्रशांत समय - यू.एस. सीमा से दूर Baja कैलिफोर्निया"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "अमेरिका/संतारेम"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "प. पैरा"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "अमेरिका/सेंटीयगो"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "अमेरिका/सेंटो_डोमिंगो"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "अमेरिका/सावो_पोलो"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "द. व द.प. ब्राजील (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "अमेरिका/स्कोर्सबायसंड"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "स्कोरर्सबेयंड / Ittoqqortoormiit"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "अमेरिका/शिपरॉक"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "पर्वतीय समय - नवाजो"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "अमेरिका/सेंट_बार्थेलेमे"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "अमेरिका/सेंट_जाँस"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "न्यूफाउंडलैंड समय, SE लैब्रोडोर"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "अमेरिका/सेंट_किट्स"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "अमेरिका/सेंट_लुसिया"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "अमेरिका/सेंट_थामस"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "अमेरिका/सेंट_विंसेंट"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "अमेरिका/स्विफ्ट_करंट"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "केंद्रीय मानक समय - ससाक्चावान - मिडवेस्ट"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "अमेरिका/तेगुसीगालपा"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "अमेरिका/थुले"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "थुले / Pituffik"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "अमेरिका/थंडर_बे"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "पूर्वी समय - थंडर बे, ओंटारियो"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "अमेरिका/तीजुना"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "यू.एस. प्रशांत समय - यू.एस. सीमा के निकट बाजा कैलिफोर्निया"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "अमेरिका/टोरोंटो"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "पूर्वी समय - ओंटारियो - अधिकतर स्थान"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "अमेरिका/टोर्टोला"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "अमेरिका/वेंकोवेर"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "प्रशांत समय - पश्चिम ब्रिटिश कोलंबिया"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "अमेरिका/वर्जिन"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "अमेरिका/व्हाइटहॉर्स"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "प्रशांत समय - दक्षिणी यूकोन"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "अमेरिका/विनीपेग"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "केंद्रीय समय - मैनटोबा व पश्चिम ओंटारियो"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "अमेरिका/यकुटेट"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "अलास्का समय - अलास्का पैनहैंडल नेक"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "अमेरिका/यलोनाइफ"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "पर्वतीय समय - मध्य उत्तरपश्चिम क्षेत्र"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "अंटार्कटिका/केसे"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "कैसे स्टेशन, बेली प्रायद्वीप"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "अंटार्कटिका/डेविस"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "डेविस स्टेशन, वेस्टफोर्ड हिल्स"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "अंटार्कटिका/डूमांटडरविल"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "ड्यूमा-डीउरिविले स्टेशन, टेरे एडीले"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "अंटार्कटिका/मेकुरी"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "मैकमुरी द्वीपीय स्टेशन, मैकुरी द्वीप"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "अंटार्कटिका/मॉसन"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "मॉउसन स्टेशन, होल्मे खाड़ी"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "अंटार्कटिका/मेकमुरडो"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "मैकमुर्डो स्टेशन, रॉस द्वीप"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "अंटार्कटिका/पामर"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "पामर स्टेशन, एंवर्स द्वीप"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "अंटार्कटिका/रोथेरिया"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "रोथेरा स्टेशन, एडीलेड द्वीप"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "अंटार्कटिका/साउथ_पोल"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "एम्यूसडेन-स्कॉट स्टेशन, द. ध्रुव"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "अंटार्कटिका/सय्वा"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "सेओवा स्टेशन, ई ओंगुल I"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "अंटार्कटिका/वोस्तोक"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "वोस्टोक स्टेशन, द. चुम्बकीय ध्रुव"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "आर्किटक/लांगईयरबायेन"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "एशिया/अदन"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "एशिया/अलमटी"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "एशिया/अम्मान"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "एशिया/अनाडिर"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "मास्को+8 - बेरिंग सागर"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "एशिया/एकतो"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "अतैराउ (Atirau, Gur'yev), Mangghystau (Mankistau)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "एशिया/अकतूब"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "एकटोबे (एकटोबे)"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "एशिया/अशगाबट"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "एशिया/अश्खाबाद"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "एशिया/बगदाद"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "एशिया/बहरीन"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "एशिया/बाकू"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "एशिया/बैंकाक"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "एशिया/बेरुट"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "एशिया/बिशकेक"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "एशिया/ब्रुनेई"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "एशिया/कोलकाता"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "एशिया/छोईबलसन"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "दोर्नड, सुखबतार"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "एशिया/चांगकिंग"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "मध्य चीन - सिचुआन, यून्नान, गुआंगक्सी, सांक्सी, गुइजो, आदि."
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "एशिया/चुंगकिंग"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "एशिया/कोलोंबो"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "एशिया/डक्का"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "एशिया/डमस्कस"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "एशिया/ढाका "
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "एशिया/दिली"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "एशिया/दुबई"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "एशिया/दुसानबे"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "एशिया/गाजा"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "एशिया/हरबीन "
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "Heilongjiang (except Mohe), Jilin"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "एशिया/हो ची मिन्ह"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "एशिया/हांग_कांग"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "एशिया/हावड"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "एशिया/इरकुट्स्क"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "मास्को+05 - बैकाल झील"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "एशिया/इस्तांबुल"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "एशिया/जकार्ता"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "जावा व सुमात्रा"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "एशिया/जयपुर"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "इरियन जाया व मोलस्क"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "एशिया/जेरुशलम"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "एशिया/काबुल"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "एशिया/कमचटका"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "मास्को+08 - कमचटका"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "एशिया/कराची"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "एशिया/केशगर"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "पश्चिम तिब्बत व जिनियांग"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "एशिया/काठमांडू"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "एशिया/काठमांडू"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "एशिया/कोलकाता"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "एशिया/क्रस्नोयास्क"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "मास्को+04 - येनेसी नदी"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "एशिया/क्वालामपुर"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "प्रायद्वीपीय मलेशिया"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "एशिया/कुचिंग"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "सबाह व सारावाक"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "एशिया/कुवैत"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "एशिया/मकाओ"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "एशिया/मकाउ"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "एशिया/मगाडन"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "मास्को+08 - मैगाडन"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "एशिया/मकस्सर"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "पूर्वी & दक्षिणी बोर्नियो, सेलेबीज, बाली, न्यूसा टेनेगरा, पश्चिम तिमोर"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "एशिया/मनीला"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "एशिया/मस्कट"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "एशिया/निकोसिया"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "एशिया/नोवोकुजनेत्स्क"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "मास्को+03 - नोवोकुजेनेत्स्क"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "एशिया/नोवोसिब्रिस्क"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "मास्को+03 - नोवोसिबिर्स्क"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "एशिया/ओमस्क"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "मास्को+03 - पश्चिम साइबेरिया"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "एशिया/ओरल"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "पश्चिमी कजाखस्तान"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "एशिया/नॉम_पेन्ह"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "एशिया/पोनट्यानक"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "पश्चिम & मध्य बोर्नियो"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "एशिया/प्योंगयांग"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "एशिया/कतार"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "एशिया/कैजीलोरडा"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "एशिया/रंगून"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "एशिया/रियाद"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "एशिया/रियाद87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "एशिया/रियाद88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "एशिया/रियाद89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "एशिया/शैगांव"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "एशिया/साखालीन"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "मास्को+07 - सखालीन द्वीप"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "एशिया/समरकंड"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "पश्चिम उजबेकिस्तान"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "एशिया/सियोल"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "एशिया/शंघाई"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "पूर्वी चीन - बीजिंग, गुआंगडोंग, शंघाई, आदि."
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "एशिया/सिंगापुर"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "एशिया/ताईपे"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "एशिया/ताशकंद"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "पूर्वी उजबेकिस्तान"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "एशिया/तबीलिसी"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "एशिया/तेहरान"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "एशिया/तेल_अवीव"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "एशिया/तिमबू"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "एशिया/थिंफू"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "एशिया/टोक्यो"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "एशिया/ऊजूंग_पन्दांग"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "एशिया/उलानबतर"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "एशिया/उलन_बतोर"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "एशिया/उरुमकी"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "अधिकतर तिब्बत व सिनियांग"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "एशिया/वेटीयेन"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "एशिया/व्लाडीवास्टक"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "मास्को+07 - अमूर नदी"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "एशिया/यकुट्स्क"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "मास्को+06 - लीना नदी"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "एशिया/येकातरीनबर्ग"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "मास्को+02 - उराल"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "एशिया/येराविन"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "अटलांटिक/अजोर्स"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "अजोर्स"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "अटलांटिक/बरमुडा"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "अटलांटिक/कैनेरी"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "कैनारी द्वीप"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "अटलांटिक/कैप_वर्द"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "अटलांटिक/फैरो"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "अटलांटिक/फराओ"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "अटलांटिक/जन_मयन"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "अटलांटिक/मेडिरा"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "मैडिरा द्वीप"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "अटलांटिक/रिक्याज्विक"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "अटलांटिक/दक्षिण_जार्जिया"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "अटलांटिक/स्टेनली"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "अटलांटिक/सेंट_हेलेना"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "ऑस्ट्रेलिया/एसीटी"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "ऑस्ट्रेलिया/एडीलेड"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "दक्षिणी ऑस्ट्रेलिया"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "ऑस्ट्रेलिया/ब्रिसबेन"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "क्वींसलैंड - अधिकतर स्थान"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "ऑस्ट्रेलिया/ब्रोकन_हिल"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "न्यू साउथ वेल्स - यानकोइना"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "ऑस्ट्रेलिया/केनबेरा"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "ऑस्ट्रेलिया/क्यूरी"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "तस्मानिया - किंग द्वीप"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "ऑस्ट्रेलिया/डारविन"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "उत्तरी क्षेत्र"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "ऑस्ट्रेलिया/यूक्ला"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "पश्चिमी ऑस्ट्रेलिया - यूक्ला क्षेत्र"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "ऑस्ट्रेलिया/होबर्ट"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "तस्मानिया - अधिकतर स्थान"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "ऑस्ट्रेलिया/एलएचआई"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "ऑस्ट्रेलिया/लिंडेमेन"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "क्वींसलैंड - होलीडे द्वीप"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "ऑस्ट्रेलिया/लार्ड_होव"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "लॉर्ड होवे द्वीप"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "ऑस्ट्रेलिया/मेलबॉर्न"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "विक्टोरिया"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "ऑस्ट्रेलिया/उत्तर"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "ऑस्ट्रेलिया/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "ऑस्ट्रेलिया/पर्थ"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "पश्चिमी ऑस्ट्रेलिया - अधिकतर स्थान"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "ऑस्ट्रेलिया/क्वींसलैंड"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "ऑस्ट्रेलिया/दक्षिण"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "ऑस्ट्रेलिया/सिडनी"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "न्यू साउथ वेल्स - अधिकतर स्थान"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "ऑस्ट्रेलिया/टस्मेनिया"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "ऑस्ट्रेलिया/विक्टोरिया"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "ऑस्ट्रेलिया/पश्चिम"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "ऑस्ट्रेलिया/यानकोविना"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "ब्राजिल/एक्रे"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "ब्राजिल/डेनोरोना"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "ब्राजिल/पूरब"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "ब्राजिल/पश्चिम"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "कनाडा/अटलांटिक"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "कनाडा/मध्य"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "कनाडा/पूर्वी"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "कनाडा/पूर्व-सस्कचवन"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "कनाडा/माउन्टेन"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "कनाडा/न्यूफोन्डलैंड"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "कनाडा/प्रशांत"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "कनाडा/सस्कचवन"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "कनाडा/यूकन"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "चिली/कॉन्टीनेन्टल"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "चिली/कोन्टीनेन्टल"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "क्यूबा"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "मिश्र"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "आयर"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/ग्रीनविच"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/यूनिवर्सल"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/ज़ुलू"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "यूरोप/एम्स्टरडेम"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "यूरोप/एंडोरा"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "यूरोप/एथेंस"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "यूरोप/बेलफास्ट"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "यूरोप/बेलग्रेड"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "यूरोप/बर्लिन"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "यूरोप/ब्रटिसलेवा"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "यूरोप/ब्रस्सेल्स"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "यूरोप/बुखारेस्ट"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "यूरोप/बुडापेस्ट"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "यूरोप/चीसीनो"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "यूरोप/कोपनहेगन"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "यूरोप/डब्लिन"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "यूरोप/जिब्राल्टर"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "यूरोप/गुयेर्न्से"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "यूरोप/हेलसिंकी"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "यूरोप/आइल_ऑफ_मैन"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "यूरोप/इस्तांबुल"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "यूरोप/जर्सी"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "यूरोप/कालिनीग्राड"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "मास्को-01 - कालिनिनग्राद"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "यूरोप/कीव"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "यूरोप/लिसबन"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "यूरोप/लजुबलजाना"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "यूरोप/लंदन"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "यूरोप/लक्समबर्ग"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "यूरोप/मेड्रिड"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "यूरोप/माल्टा"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "यूरोप/मेरीहैम"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "यूरोप/मिंसक"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "यूरोप/मोनाको"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "यूरोप/मॉस्को"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "मास्को+00 - पश्चिम रूस"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "यूरोप/निकोसिया"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "यूरोप/ओसलो"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "यूरोप/पेरिस"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "यूरोप/पॉडगोरिका"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "यूरोप/प्राग"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "यूरोप/रिगा"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "यूरोप/रोम"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "यूरोप/समारा"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "मास्को - समारा, उदमुर्तिया"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "यूरोप/सेन_मरीनो"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "यूरोप/सराजेवो"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "यूरोप/सिमफेरोपोल"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "मध्य क्रीमिया"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "यूरोप/स्कपजे"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "यूरोप/सोफिया"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "यूरोप/स्टॉकहोम"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "यूरोप/तालीन"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "यूरोप/तिरेन"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "यूरोप/तिरसपोल"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "यूरोप/उर्गोराड"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "रूथेनिया"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "यूरोप/वाडूज"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "यूरोप/वेटीकेन"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "यूरोप/वियेना"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "यूरोप/विलनियस"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "यूरोप/वोल्गोग्रैड"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "मास्को+00 - कैस्पियन सागर"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "यूरोप/वारसो"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "यूरोप/जेगरीब"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "यूरोप/जपोरोजाई"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "यूरोप/ज्यूरिख"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "फैक्टरी"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-आइर"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "ग्रीनविच"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "हांगकॉग"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "आइसलैंड"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "इंडियन/अंतानानरिवो"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "इंडियन/चागोस"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "इंडियन/क्रिसमस"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "इंडियन/कोकोस"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "इंडियन/कोमोरो"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "इंडियन/करगलन"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "इंडियन/माहे"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "इंडियन/मालदीव"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "इंडियन/मॉरीसस"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "इंडियन/मायोट"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "इंडियन/रियूनियन"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "इरान"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "इज़राइल"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "जमाईका"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "जापान"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "ख्वाजालेन"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "लीबिया"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "मैक्सिको/बजनोर्ट"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "मैक्सिको/बजासुर"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "मैक्सिको/जनरल"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "मध्यपूर्वी/रियाद87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "मध्यपूर्वी/रियाद88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "मध्यपूर्वी/रियाद89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "नवजो"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "प्रशांत/एपिया"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "प्रशांत/आकलैंड"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "प्रशांत/चाथम"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "चाथम द्वीप"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "प्रशांत/चूक"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "चूक (Truk) और याप"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "प्रशांत/इस्टर"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "इस्टर द्वीप व साला वाई गोमेज"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "प्रशांत/इफेट"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "प्रशांत/इनडरबरी"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "फीनिक्स द्वीप"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "प्रशांत/फकाओफो"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "प्रशांत/फिजी"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "प्रशांत/फुनाफुटी"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "प्रशांत/गलपगोस"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "गालापैगोस द्वीप"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "प्रशांत/गेम्बियर"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "गैंबियर द्वीप"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "प्रशांत/गुवादलकनल"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "प्रशांत/गुआम"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "प्रशांत/होनोलूलू"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "हवाई"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "प्रशांत/जांस्टन"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "जॉन्स्टन एटॉल"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "प्रशांत/किर्तीमति"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "लाइन द्वीप"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "प्रशांत/कसरे"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "कोसरे"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "प्रशांत/क्वाजालेन"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "प्रशांत/मजूरो"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "प्रशांत/मार्कसास"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "मार्क्वीसास द्वीप"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "प्रशांत/मिडवे"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "मिडवे द्वीप"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "प्रशांत/नोरु"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "प्रशांत/नीयू"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "प्रशांत/नारफोक"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "प्रशांत/नामिया"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "प्रशांत/पैगो_पैगो"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "प्रशांत/पलाउ"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "प्रशांत/पिटकेरीन"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "प्रशांत/पोह्न्पी"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "पोह्न्पी (पोनापे)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "प्रशांत/पोनापे"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "प्रशांत/पोर्ट_मोर्सबी"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "प्रशांत/ररोतंगा"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "प्रशांत/सैपेन"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "प्रशांत/समोआ"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "प्रशांत/ताहिटी"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "सोसायटी द्वीप"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "प्रशांत/तारावा"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "गिलबर्ट द्वीप"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "प्रशांत/टंगटपू"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "प्रशांत/त्रुक"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "प्रशांत/वेक"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "वेक द्वीप"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "प्रशांत/वालिस"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "प्रशांत/याप"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "पोलंड"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "पुर्तगाल"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "सिंगापुर"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "तुर्की"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "यूनिवर्सल"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "US/अलास्का"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "US/एल्यूशन"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "US/एरीजोना"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "US/केन्द्रीय"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "US/पूर्वी"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "US/पूर्व-इंडियाना"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "US/हवाई"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "US/इंडियाना-स्टार्क"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "US/मिसिगन"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "US/माउन्टेन"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "US/प्रशांत"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "US/समोवा"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "ज़ुलू"
+
diff --git a/panels/datetime/po-timezones/hr.po b/panels/datetime/po-timezones/hr.po
new file mode 100644
index 0000000..3a2dd35
--- /dev/null
+++ b/panels/datetime/po-timezones/hr.po
@@ -0,0 +1,3281 @@
+# Translation of timezones to Croatian
+# Copyright (C) Croatian team
+# Translators: Dario Lah <>,Robert Sedak <robert.sedak@sk.tel.hr>,Vedran Vyroubal <vedran.vyroubal@inet.hr>,
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones 0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2007-06-04 23:41+0100\n"
+"Last-Translator: Renato Pavicic <renato@translator-shop.org>\n"
+"Language-Team: Croatian Reanto Pavicic <lokalizacija@linux.hr "
+"repavici@globalnet.hr>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: TransDict server\n"
+"X-Poedit-Language: Croatian\n"
+"X-Poedit-Country: CROATIA\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Afrika/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Afrika/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Afrika/Adis_Ababa"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Afrika/Algiers"
+
+#: timezones.h:5
+#, fuzzy
+msgid "Africa/Asmara"
+msgstr "Afrika/Asmera"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Afrika/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Afrika/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Afrika/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Afrika/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Afrika/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Afrika/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Afrika/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Afrika/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Afrika/Kairo"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Afrika/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Afrika/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Afrika/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Afrika/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Afrika/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Afrika/Djibouti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Afrika/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Afrika/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Afrika/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Afrika/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Afrika/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Afrika/Johannesbur"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Afrika/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Afrika/Khartoum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Afrika/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Afrika/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Afrika/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Afrika/Liberville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Afrika/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Afrika/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Afrika/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Afrika/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Afrika/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Afrika/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Afrika/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Afrika/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Afrika/Mogadishu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Afrika/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Afrika/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Afrika/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Afrika/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Afrika/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Afrika/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Afrika/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Afrika/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Afrika/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Afrika/Tripoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Afrika/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Afrika/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Amerika/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+#, fuzzy
+msgid "Aleutian Islands"
+msgstr "Australija/Queensland"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Amerika/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+#, fuzzy
+msgid "Alaska Time"
+msgstr "SAD/Aljaska"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Amerika/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Amerika/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Amerika/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Amerika/Argentina/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Amerika/Argentina/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Amerika/Argentina/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Amerika/Argentina/Cordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Amerika/Argentina/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Amerika/Argentina/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Amerika/Argentina/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Amerika/Argentina/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+#, fuzzy
+msgid "America/Argentina/Salta"
+msgstr "Amerika/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Amerika/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+#, fuzzy
+msgid "America/Argentina/San_Luis"
+msgstr "Amerika/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Amerika/Argentina/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Amerika/Argentina/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Amerika/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Amerika/Asuncion"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Amerika/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Amerika/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Amerika/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "Amerika/Bahia"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Amerika/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Amerika/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Amerika/Belize"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "Amerika/Blanc-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Amerika/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Amerika/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Amerika/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Amerika/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Amerika/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "Amerika/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Amerika/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Amerika/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Amerika/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Amerika/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Amerika/Cayman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Amerika/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+#, fuzzy
+msgid "Central Time"
+msgstr "SAD/Središnje"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Amerika/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "Amerika/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Amerika/Cordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Amerika/Costa_Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Amerika/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Amerika/Curacao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Amerika/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Amerika/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Amerika/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Amerika/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+#, fuzzy
+msgid "Mountain Time"
+msgstr "SAD/Planine"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Amerika/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Amerika/Dominica"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Amerika/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Amerika/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Amerika/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Amerika/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Amerika/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Amerika/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Amerika/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Amerika/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Amerika/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Amerika/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Amerika/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Amerika/Guadaloupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Amerika/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Amerika/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Amerika/Guyana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Amerika/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Amerika/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Amerika/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Amerika/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Amerika/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Amerika/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "Amerika/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Amerika/Indianapolis"
+
+#: timezones.h:227
+#, fuzzy
+msgid "America/Indiana/Tell_City"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "Amerika/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+#, fuzzy
+msgid "America/Indiana/Winamac"
+msgstr "Amerika/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Amerika/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Amerika/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Amerika/Jamaica"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Amerika/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Amerika/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Amerika/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+#, fuzzy
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Amerika/Kentucky/Louisville"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Amerika/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Amerika/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Amerika/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Amerika/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Amerika/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+#, fuzzy
+msgid "Pacific Time"
+msgstr "Tihi_ocean/Niue"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Amerika/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Amerika/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Amerika/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Amerika/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+#, fuzzy
+msgid "America/Marigot"
+msgstr "Amerika/Maceio"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Amerika/Martinique"
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "Amerika/Manaus"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Amerika/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Amerika/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Amerika/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Amerika/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Amerika/Mexico_City"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Amerika/Miquelon"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "Amerika/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Amerika/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Amerika/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Amerika/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Amerika/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Amerika/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Amerika/New_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+#, fuzzy
+msgid "Eastern Time"
+msgstr "SAD/Istočno"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Amerika/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Amerika/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Amerika/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+#, fuzzy
+msgid "Atlantic islands"
+msgstr "Atlantik/Kanari"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Amerika/Sjeverna_Dakota/Center"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "Amerika/Sjeverna_Dakota/New_Salem"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "Amerika/Managua"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Amerika/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Amerika/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Amerika/Paramari"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Amerika/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Amerika/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Amerika/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Amerika/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Amerika/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Amerika/Puerto_Rico"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Amerika/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Amerika/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Amerika/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Amerika/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+#, fuzzy
+msgid "America/Resolute"
+msgstr "Amerika/Belem"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Amerika/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Amerika/Rosario"
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "Amerika/Santiago"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+#, fuzzy
+msgid "America/Santarem"
+msgstr "Amerika/Santiago"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Amerika/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Amerika/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Amerika/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Amerika/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Amerika/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+#, fuzzy
+msgid "America/St_Barthelemy"
+msgstr "Amerika/Belem"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Amerika/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Amerika/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Amerika/St_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Amerika/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Amerika/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Amerika/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Amerika/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Amerika/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Amerika/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Amerika/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "Amerika/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Amerika/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Amerika/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Amerika/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Amerika/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Amerika/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Amerika/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Amerika/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antarktika/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antarktika/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antarktika/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+#, fuzzy
+msgid "Antarctica/Macquarie"
+msgstr "Antarktika/McMurdo"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antarktika/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antarktika/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antarktika/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antarktika/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antarktika/South_Pole"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antarktika/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antarktika/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Arktik/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Azija/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Azija/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Azija/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Azija/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Azija/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Azija/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Azija/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Azija/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Azija/Bagdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Azija/Bahrain"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Azija/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Azija/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Azija/Bejrut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Azija/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Azija/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Azija/Kalkuta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Azija/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Azija/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Azija/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Azija/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Azija/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Azija/Damascus"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Azija/Dhaka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Azija/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Azija/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Azija/Dushanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Azija/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Azija/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+#, fuzzy
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Azija/Chongqing"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Azija/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Azija/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Azija/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Azija/Istanbul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Azija/Jakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Azija/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Azija/Jeruzalem"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Azija/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Azija/Kamchatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Azija/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Azija/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+#, fuzzy
+msgid "Asia/Kathmandu"
+msgstr "Azija/Katmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Azija/Katmandu"
+
+#: timezones.h:518
+#, fuzzy
+msgid "Asia/Kolkata"
+msgstr "Azija/Jakarta"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Azija/Krasnoyarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Azija/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Azija/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Azija/Kuvajt"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Azija/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Azija/Macau"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Azija/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Azija/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Azija/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Azija/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Azija/Nicosia"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "Azija/Irkutsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Azija/Novosibirsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Azija/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+#, fuzzy
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Azija/Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Azija/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Azija/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Azija/Phnom_Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Azija/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Azija/Pyongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Azija/Qatar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Azija/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Azija/Rangoon"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Azija/Riyadh"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Azija/Riyadh87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Azija/Riyadh88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Azija/Riyadh89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Azija/Saigon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Azija/Sakhalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Azija/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Azija/Seul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Azija/Shanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Azija/Singapore"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Azija/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Azija/Tashkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Azija/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Azija/Tehran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Azija/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Azija/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Azija/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Azija/Tokyo"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Azija/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Azija/Ulaanbaatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Azija/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Azija/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Azija/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Azija/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Azija/Yakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Azija/Yekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Azija/Yerevan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlantik/Azores"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlantik/Bermuda"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlantik/Kanari"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlantik/Cape_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlantik/Faeroe"
+
+#: timezones.h:616
+#, fuzzy
+msgid "Atlantic/Faroe"
+msgstr "Atlantik/Faeroe"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlantik/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlantik/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlantik/Reykjavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlantik/South_Georgia"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlantik/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlantik/Sv._Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Australija/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Australija/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+#, fuzzy
+msgid "South Australia"
+msgstr "Australija/ACT"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Australija/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Australija/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Australija/Canberra"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Australija/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Australija/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+#, fuzzy
+msgid "Australia/Eucla"
+msgstr "Australija/Queensland"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+#, fuzzy
+msgid "Western Australia - Eucla area"
+msgstr "Australija/Queensland"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Australija/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Australija/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Australija/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Australija/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Australija/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+#, fuzzy
+msgid "Victoria"
+msgstr "Australija/Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Australija/Sjever"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Australija/New South Wels"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Australija/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Australija/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Australija/Jug"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Australija/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Australija/Tasmania"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Australija/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Australija/Zapad"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Australija/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brazil/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brazil/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brazil/Istok"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brazil/Zapad"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Kanada/Atlantik"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Kanada/Središnje"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Kanada/Istočna"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Kanada/Istok-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Kanada/Planine"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Kanada/Newfoundland"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Kanada/Tihi_ocean"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Kanada/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Kanada/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Čile/Kontinentalno"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Čile/Istočni otoci"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Kuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Egipat"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Irska"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Ostalo/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Ostalo/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Ostalo/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Ostalo/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Ostalo/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Ostalo/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Ostalo/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Ostalo/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Ostalo/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Ostalo/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Ostalo/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Ostalo/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Ostalo/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Ostalo/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Ostalo/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Ostalo/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Ostalo/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Ostalo/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Ostalo/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Ostalo/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Ostalo/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Ostalo/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Ostalo/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Ostalo/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Ostalo/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Ostalo/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Ostalo/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Ostalo/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Ostalo/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Ostalo/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Ostalo/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Ostalo/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Ostalo/Univerzalno"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Ostalo/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Ostalo/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Europa/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Europa/Andora"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Europa/Atena"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Europa/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Europa/Beograd"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Europa/Berlin"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Europa/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Europa/Bruxelles"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Europa/Bukurešt"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Europa/Budimpešta"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Europa/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Europa/Kopenhagen"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Europa/Dublin"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Europa/Gibraltar"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Europa/Guernsey"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Europa/Helsinki"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Europa/Isle_of_Man"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Europa/Istanbul"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Europa/Jersey"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Europa/Kalinjingrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Europa/Kijev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Europa/Lisabon"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Europa/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Europa/London"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Europa/Luxemburg"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Europa/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Europa/Malta"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Europa/Mariehamn"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Europa/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Europa/Monaco"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Europa/Moskva"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Europa/Nikozija"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Europa/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Europa/Pariz"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Europa/Podgorica"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Europa/Prag"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Europa/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Europa/Rim"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Europa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Europa/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Europa/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Europa/Sevastopolj"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Europa/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Europa/Sofija"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Europa/Stockholm"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Europa/Tallinn"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Europa/Tirana"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Europa/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Europa/Užgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Europa/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Europa/Vatikan"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Europa/Beč"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Europa/Vilnius"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Europa/Volgograd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Europa/Varšava"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Europa/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Europa/Zaporožje"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Europa/Zurich"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Izvorno"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "VB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "VB-Irska"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hong_Kong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Island"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Indijski_ocean/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Indijski_ocean/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Indijski_ocean/Božićni_otoci"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Indijski_ocean/Kokosovi otoci"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Indijski_ocean/Komoro otoci"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Indijski_ocean/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Indijski_ocean/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Indijski_ocean/Maldivi"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Indijski_ocean/Mauricijus"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Indijski_ocean/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Indijski_ocean/Reunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Iran"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Izrael"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamajka"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Japan"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Libija"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Meksiko/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Meksiko/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Meksiko/General"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Srednji Istok/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Srednji Istok/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Srednji Istok/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Tihi_ocean/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Tihi_ocean/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Tihi_ocean/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+#, fuzzy
+msgid "Chatham Islands"
+msgstr "Čile/Istočni otoci"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "Tihi_ocean/Truk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Tihi_ocean/Easter"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Tihi_ocean/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Tihi_ocean/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Tihi_ocean/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Tihi_ocean/Fiji"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Tihi_ocean/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Tihi_ocean/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Tihi_ocean/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Tihi_ocean/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Tihi_ocean/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Tihi_ocean/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+#, fuzzy
+msgid "Hawaii"
+msgstr "SAD/Havaji"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Tihi_ocean/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Tihi_ocean/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Tihi_ocean/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+#, fuzzy
+msgid "Kosrae"
+msgstr "Izrael"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Tihi_ocean/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Tihi_ocean/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Tihi_ocean/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Tihi_ocean/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Tihi_ocean/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Tihi_ocean/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Tihi_ocean/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Tihi_ocean/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Tihi_ocean/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Tihi_ocean/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Tihi_ocean/Pitcairn"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "Tihi_ocean/Ponape"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Tihi_ocean/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Tihi_ocean/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Tihi_ocean/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Tihi_ocean/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Tihi_ocean/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Tihi_ocean/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Tihi_ocean/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+#, fuzzy
+msgid "Gilbert Islands"
+msgstr "Čile/Istočni otoci"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Tihi_ocean/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Tihi_ocean/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Tihi_ocean/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Tihi_ocean/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Tihi_ocean/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Poljska"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugal"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "NR Kina"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "Republika Kina"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "Republika Koreja"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapur"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Turska"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Univerzalno"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "SAD/Aljaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "SAD/Aleuti"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "SAD/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "SAD/Središnje"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "SAD/Istočno"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "SAD/Istok-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "SAD/Havaji"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "SAD/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "SAD/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "SAD/Planine"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "SAD/Tihi_ocean"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "SAD/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
+
+#~ msgid "US/Pacific-New"
+#~ msgstr "SAD/Tihi_ocean-Novo"
diff --git a/panels/datetime/po-timezones/hu.po b/panels/datetime/po-timezones/hu.po
new file mode 100644
index 0000000..7c98c8c
--- /dev/null
+++ b/panels/datetime/po-timezones/hu.po
@@ -0,0 +1,3258 @@
+# Arpad Biro <biro_arpad@yahoo.com>, 2004, 2007.
+# Szentiványi Gábor <szentivanyi.gabor@ulx.hu>, 2006.
+msgid ""
+msgstr ""
+"Project-Id-Version: system-config-date/timezones\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-04-03 14:23+0100\n"
+"Last-Translator: Zoltan Hoppar <zoltanh721@fedoraproject.org>\n"
+"Language-Team: Hungarian <fedora-trans-hu@redhat.com>\n"
+"Language: hu\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: nplurals=2; plural=(n!=1);\n"
+"X-Poedit-Language: Hungarian\n"
+"X-Poedit-Country: HUNGARY\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Afrika/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Afrika/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Afrika/Addisz-Abeba"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Afrika/Algír"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "Afrika/Asmara"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Afrika/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Afrika/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Afrika/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Afrika/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Afrika/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Afrika/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Afrika/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Afrika/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Afrika/Kairó"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Afrika/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Afrika/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "Ceuta & Melilla"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Afrika/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Afrika/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Afrika/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Afrika/Dzsibuti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Afrika/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Afrika/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Afrika/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Afrika/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Afrika/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Afrika/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Afrika/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Afrika/Kartum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Afrika/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Afrika/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "ny-i Demokratikus Kongó-i Közt."
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Afrika/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Afrika/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Afrika/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Afrika/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Afrika/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "K-i Demokratikus Kongó-i Közt."
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Afrika/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Afrika/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Afrika/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Afrika/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Afrika/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Afrika/Mogadishu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Afrika/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Afrika/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Afrika/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Afrika/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Afrika/Noukachott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Afrika/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Afrika/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Afrika/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Afrika/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Afrika/Tripoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Afrika/Tunisz"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Afrika/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Amerika/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Ausztrália/Aleutian szigetek"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Amerika/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Alaszka-i idő"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Amerika/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Amerika/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Amerika/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "Tokantin állam (Brazilia, Amazónia - Palmas)"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Amerika/Argentína/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Buenos Aires (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Amerika/Argentína/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "Catamarca (CT), Chubut (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Amerika/Argentína/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Amerika/Argentína/Cordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "leggyakoribb helyein (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Amerika/Argentína/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Jujuy (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Amerika/Argentína/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "La Rioja (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Amerika/Argentína/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "Mendoza (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Amerika/Argentína/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "Santa Cruz (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "America/Argentina/Salta"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Amerika/Argentína/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "San Juan (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "Amerika/Argentína/San_Luis"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "San Luis (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Amerika/Argentína/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "Tucuman (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Amerika/Argentína/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "Tierra del Fuego (TF) (Patagónia)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Amerika/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Amerika/Asuncion"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Amerika/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "EST - Atikokan, Ontario és Southampton I, Nunavut"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Amerika/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Amerika/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "Bahia"
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "Amerika/Bahia"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Amerika/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Amerika/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "Amapa, E Para"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Amerika/Beliz"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "Amerika/Blanc-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Amerika/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "Roraima"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Amerika/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Amerika/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Amerika/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Amerika/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "Amerika/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "Mato Grosso do Sul"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Amerika/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Amerika/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Amerika/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Amerika/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Amerika/Cayman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Amerika/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "Közép Amerikai idő"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Amerika/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "Amerika/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Amerika/Cordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Amerika/Costa_Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Amerika/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "Mato Grosso"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Amerika/Curacao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Amerika/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "keleti part, É-i része Scoresbysund-nak"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Amerika/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Amerika/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Amerika/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "Mountain Time"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Amerika/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Amerika/Dominika"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Amerika/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Amerika/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "Ny. Amazonas"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Amerika/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Amerika/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Amerika/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "ÉK Brazilia (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Amerika/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Amerika/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Amerika/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "leggyakoribb helyein"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Amerika/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Amerika/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Amerika/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Amerika/Guadaloupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Amerika/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Amerika/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Amerika/Guyana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Amerika/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Amerika/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Amerika/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Amerika/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Amerika/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Amerika/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "Amerika/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Amerika/Indianapolis"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "Amerika/Indiana/Tell_City"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "Amerika/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "Amerika/Indiana/Winamac"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Amerika/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Amerika/Iqualit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Amerika/Jamaica"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Amerika/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Amerika/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Amerika/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Amerika/Kentucky/Louisville területe"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Amerika/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Amerika/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Amerika/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Amerika/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Amerika/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "Nyugati partok szerinti idő"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Amerika/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Amerika/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "Alagoas, Sergipe"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Amerika/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Amerika/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "K Amazonas"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "Amerika/Marigot"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Amerika/Martinique"
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "Amerika/Manaus"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Amerika/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Amerika/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Amerika/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Amerika/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Amerika/Mexico_City"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Amerika/Miquelon"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "Amerika/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Amerika/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Amerika/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Amerika/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Amerika/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Amerika/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Amerika/New_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "Keleti partok szerinti idő"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Amerika/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Amerika/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "Alaszkai Idő - NY Alaszka"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Amerika/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "Atlanti szigetek"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Amerika/Észak-Dakota/Közép"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "Amerika/Észak-Dakota/New_Salem"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "Amerika/Managua"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Amerika/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Amerika/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Amerika/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Amerika/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Amerika/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Amerika/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Amerika/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Amerika/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "Rondonia"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Amerika/Puerto_Rico"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Amerika/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Amerika/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Amerika/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "Pernambuco"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Amerika/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "Amerika/Resolute"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Amerika/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "Acre"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Amerika/Rosario"
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "Amerika/Santarem"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "Amerika/Santarem"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "Ny. Para"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Amerika/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Amerika/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Amerika/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "K & DK Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Amerika/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "Scoresbysund / Ittoqqortoormiit"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Amerika/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "Mountain Time - Navajo"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "Amerika/St_Barthelemy"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Amerika/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Amerika/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Amerika/St_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Amerika/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Amerika/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Amerika/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Amerika/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Amerika/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "Thule / Pituffik"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Amerika/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "Keleti parti idő - Thunder Bay, Ontario"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Amerika/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "Amerika/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "Keleti Idő - Ontario - legtöbb helyein"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Amerika/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Amerika/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Amerika/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Amerika/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Amerika/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "Central Time - Manitoba & nyugat Ontario"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Amerika/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "Alaszkai idő szerint - Alaszka"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Amerika/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "Mountain Time - közép ÉNY-i területek"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antarktisz/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "Casey Állomás, Bailey Peninsula"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antarktisz/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "Davis Állomás, Vestfold Hills"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antarktisz/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "Dumont-d'Urville Állomás, Terre Adelie"
+
+#: timezones.h:425
+#, fuzzy
+msgid "Antarctica/Macquarie"
+msgstr "Antarktisz/McMurdo"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+#, fuzzy
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "McMurdo Állomás, Ross sziget"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antarktisz/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "Mawson Állomás, Holme-öböl"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antarktisz/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "McMurdo Állomás, Ross sziget"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antarktisz/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "Palmer állomás, Anvers sziget"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antarktisz/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "Rothera Állomás, Adelaide sziget"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antarktisz/Déli-sark"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "Amundsen-Scott Állomás, Déli sark"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antarktisz/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "Syowa Állomás, E Ongul I"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antarktisz/Vosztok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "Vosztok Állomás, Déli sark"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Antarktisz/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Ázsia/Áden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Ázsia/Alma-Ata"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Ázsia/Ammán"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Ázsia/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+#, fuzzy
+msgid "Moscow+08 - Bering Sea"
+msgstr "Moszkva+10 - Bering tenger"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Ázsia/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Ázsia/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "Aqtobe (Aktobe)"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Ázsia/Ashkabad"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Ázsia/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Ázsia/Bagdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Ázsia/Bahrein"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Ázsia/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Ázsia/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Ázsia/Bejrút"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Ázsia/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Ázsia/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Ázsia/Calcutta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Ázsia/Csojbalszán"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "Dornod, Sukhbaatar"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Ázsia/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "Kína központja - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, stb."
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Ázsia/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Ázsia/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Ázsia/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Ázsia/Damaszkusz"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Ázsia/Dacca"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Ázsia/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Ázsia/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Ázsia/Dushanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Ázsia/Gáza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Ázsia/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "Heilongjiang (Mohe kivételével), Jilin"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Ázsia/Ho-Chi-Minh"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Ázsia/Hongkong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Ázsia/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Ázsia/Irkutszk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Moszkva+05 - Bajkál tó környéke"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Ázsia/Isztambul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Ázsia/Dzsakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "Java & Szumátra"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Ázsia/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "Irian Jaya & Molokai"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Ázsia/Jeruzsálem"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Ázsia/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Ázsia/Kamcsatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+#, fuzzy
+msgid "Moscow+08 - Kamchatka"
+msgstr "Moszkva+09 - Kamcsatka"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Ázsia/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Ázsia/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "Tibet & Xinjiang nyugai része"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "Ázsia/Kathmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Ázsia/Katmandu"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "Ázsia/Kolkata"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Ázsia/Krasznojarszk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "Moszkva+04 - Jeniszei folyó"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Ázsia/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "Malajzia (belső)"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Ázsia/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "Sabah & Sarawak"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Ázsia/Kuvait"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Ázsia/Makaó"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Ázsia/Macau"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Ázsia/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "Moszkva+08 - Magadan"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Ázsia/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+"Borneo keleti és déli része, Celebes, Bali, Nusa Tengarra,Timor nyugati része"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Ázsia/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Ázsia/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Ázsia/Nicosia"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "Ázsia/Irkutszk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Moszkva+03 - Novosibirsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Ázsia/Novoszibirszk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Moszkva+03 - Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Ázsia/Omszk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "Moszkva+03 - Szibéria nyugati része"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Ázsia/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "Kazahsztán nyugati rész"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Ázsia/Phnom_Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Ázsia/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "Borneo nyugati és középső része"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Ázsia/Pyongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Ázsia/Katar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Ázsia/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Ázsia/Rangoon"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Ázsia/Rijád"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Ázsia/Rijád87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Ázsia/Rijád88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Ázsia/Rijád89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Ázsia/Saigon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Ázsia/Szahalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "Moszkva+07 - Sakhalin sziget"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Ázsia/Szamarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "Üzbegisztán - nyugat"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Ázsia/Szöul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Ázsia/Sanghaj"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "Kína keleti rész - Beijing, Guangdong, Shanghai, stb."
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Ázsia/Szingapúr"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Ázsia/Tajpej"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Ázsia/Taskent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "Üzbegisztán - kelet"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Ázsia/Tbiliszi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Ázsia/Teherán"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Ázsia/Tel-Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Ázsia/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Ázsia/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Ázsia/Tokió"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Ázsia/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Ázsia/Ulánbátor"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Ázsia/Ulánbátor"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Ázsia/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "Tibet & Xinjiang nagyobb része"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Ázsia/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Ázsia/Vlagyivosztok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "Moszkva+07 - Amur folyó"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Ázsia/Jakutszk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "Moszkva+06 - Lena folyó"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Ázsia/Jekatyerinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "Moszkva+02 - Urál környéke"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Ázsia/Jereván"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlanti-óceán/Azori-szk."
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "Azori szigetek"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlanti-óceán/Bermuda"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlanti-óceán/Kanári-szk."
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "Kanári szigetek"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlanti-óceán/Zöld-foki-szk."
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlanti-óceán/Feröer-szk."
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "Atlanti-óceán/Feröer-szk."
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlanti-óceán/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlanti-óceán/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "Madeira szigetek"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlanti-óceán/Reykjavík"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlanti-óceán/Dél-Georgia"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlanti-óceán/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlanti-óceán/St_Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Ausztrália/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Ausztrália/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "Dél Ausztrália"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Ausztrália/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "Queensland- a legtöbb helyein"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Ausztrália/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "Új Dél Wales - Yancowinna"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Ausztrália/Canberra"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Ausztrália/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "Tazmánia - King sziget"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Ausztrália/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "Északi területek"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "Ausztrália/Eucla"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "Nyugat Ausztrália - Eucla területe"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Ausztrália/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "Tazmánia - legtöbb helyein"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Ausztrália/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Ausztrália/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "Queensland - Holiday szigetek"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Ausztrália/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "Lord Howe sziget"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Ausztrália/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "Ausztrália/Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Ausztrália/Észak"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Ausztrália/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Ausztrália/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "Nyugat Ausztrália - legtöbb helyein"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Ausztrália/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Ausztrália/Dél"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Ausztrália/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "Új Dél Wales - legtöbb helyein"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Ausztrália/Tasmánia"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Ausztrália/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Ausztrália/Nyugat"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Ausztrália/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brazília/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brazília/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brazília/Kelet"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brazília/Nyugat"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Kanada/Atlanti-óceán"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Kanada/Közép"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Kanada/Kelet"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Kanada/Kelet-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Kanada/Mountain"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Kanada/Újfundland"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Kanada/Csendes-óceán"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Kanada/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Kanada/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Chile/Szárazföld"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Chile/Húsvét-sziget"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Kuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Egyiptom"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Írország"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Egyéb/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Egyéb/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Egyéb/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Egyéb/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Egyéb/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Egyéb/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Egyéb/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Egyéb/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Egyéb/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Egyéb/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Egyéb/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Egyéb/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Egyéb/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Egyéb/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Egyéb/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Egyéb/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Egyéb/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Egyéb/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Egyéb/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Egyéb/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Egyéb/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Egyéb/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Egyéb/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Egyéb/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Egyéb/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Egyéb/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Egyéb/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Egyéb/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Egyéb/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Egyéb/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Egyéb/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Egyéb/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Egyéb/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Egyéb/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Egyéb/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Európa/Amszterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Európa/Andorra"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Európa/Athén"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Európa/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Európa/Belgrád"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Európa/Berlin"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Európa/Pozsony"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Európa/Brüsszel"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Európa/Bukarest"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Európa/Budapest"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Európa/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Európa/Koppenhága"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Európa/Dublin"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Európa/Gibraltár"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Európa/Guernsey"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Európa/Helsinki"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Európa/Man-sziget"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Európa/Isztambul"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Európa/Jersey"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Európa/Kalinyingrád"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Moscow-01 - Kaliningrad"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Európa/Kijev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Európa/Lisszabon"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Európa/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Európa/London"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Európa/Luxemburg"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Európa/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Európa/Málta"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Európa/Mariehamn"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Európa/Minszk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Európa/Monaco"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Európa/Moszkva"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "Moscow+00 - Oroszország, nyugati rész"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Európa/Nicosia"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Európa/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Európa/Párizs"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Európa/Podgorica"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Európa/Prága"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Európa/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Európa/Róma"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Európa/Szamara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+#, fuzzy
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Moszkva+01 - Samara, Udmurtia"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Európa/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Európa/Szarajevó"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Európa/Szimferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "Krím - középső része"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Európa/Szkopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Európa/Szófia"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Európa/Stockholm"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Európa/Tallinn"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Európa/Tirana"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Európa/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Európa/Érsekújvár"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "Ruthenia"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Európa/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Európa/Vatikán"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Európa/Bécs"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Európa/Vilnius"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Európa/Volgográd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "Moszkva+00 - Kaszpi tenger"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Európa/Varsó"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Európa/Zágráb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Európa/Zaporozsje"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Európa/Zürich"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Factory"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Írország"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Izland"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Indiai-óceán/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Indiai-óceán/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Indiai-óceán/Karácsony-szk."
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Indiai-óceán/Cocos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Indiai-óceán/Comoro"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Indiai-óceán/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Indiai-óceán/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Indiai-óceán/Maldív-szk."
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Indiai-óceán/Mauritius"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Indiai-óceán/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Indiai-óceán/Reunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Irán"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Izrael"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamaica"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Japán"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Líbia"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Mexikó/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Mexikó/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Mexikó/Általános"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Közép-Kelet/Rijád87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Közép-Kelet/Rijád88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Közép-Kelet/Rijád89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Csendes-óceán/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Csendes-óceán/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Csendes-óceán/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "Chile/Chatham-szigetek"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "Csendes-óceán/Truk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+#, fuzzy
+msgid "Chuuk (Truk) and Yap"
+msgstr "Truk (Chuuk) és Yap"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Csendes-óceán/Húsvét-sziget"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "Húsvét szigetek & Sala y Gomez"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Csendes-óceán/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Csendes-óceán/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "Főnix szigetek"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Csendes-óceán/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Csendes-óceán/Fidzsi"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Csendes-óceán/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Csendes-óceán/Galápagos-szk."
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "Galapagos szigetek"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Csendes-óceán/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "Gambier szigetek"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Csendes-óceán/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Csendes-óceán/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Csendes-óceán/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "USA/Hawaii"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Csendes-óceán/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "Johnston Atoll"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Csendes-óceán/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "Line szigetek"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Csendes-óceán/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "Kosrae (Mikronézia)"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Csendes-óceán/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Csendes-óceán/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Csendes-óceán/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "Marquesas szigetek (Fr. Polinézia)"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Csendes-óceán/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "Midway szigetek"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Csendes-óceán/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Csendes-óceán/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Csendes-óceán/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Csendes-óceán/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Csendes-óceán/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Csendes-óceán/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Csendes-óceán/Pitcairn"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "Csendes-óceán/Panape"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+#, fuzzy
+msgid "Pohnpei (Ponape)"
+msgstr "Ponape (Ponpei)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Csendes-óceán/Panape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Csendes-óceán/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Csendes-óceán/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Csendes-óceán/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Csendes-óceán/Szamoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Csendes-óceán/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "Society szigetek"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Csendes-óceán/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "Chile/Gilbert-szigetek"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Csendes-óceán/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Csendes-óceán/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Csendes-óceán/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "Wake sziget"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Csendes-óceán/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Csendes-óceán/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Lengyelország"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugália"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "Posix szabvány szerinti"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Szingapúr"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Törökország"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "USA/Alaszka"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "USA/Aleutian"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "USA/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "USA/Közép"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "USA/Kelet"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "USA/Kelet-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "USA/Hawaii"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "USA/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "USA/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "USA/Mountain"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "USA/Csendes-óceán"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "USA/Szamoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
+
+#~ msgid "US/Pacific-New"
+#~ msgstr "USA/Csendes-óceán-új"
diff --git a/panels/datetime/po-timezones/id.po b/panels/datetime/po-timezones/id.po
new file mode 100644
index 0000000..91f196e
--- /dev/null
+++ b/panels/datetime/po-timezones/id.po
@@ -0,0 +1,3332 @@
+# timezones Bahasa Indonesia
+# Copyright (C) 1999 Free Software Foundation, Inc.
+# Mohammad DAMT <mdamt@linux.or.id>, 1999.
+# Teguh DC <dheche@brawijaya.ac.id>, 2004-2006.
+# $Id: id.po,v 1.10 2007/04/27 09:16:28 nphilipp Exp $
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ID-timezones 1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2006-03-10 23:59+0700\n"
+"Last-Translator: Teguh DC <dheche@bradjamoesti.or.id>\n"
+"Language-Team: LDP Indonesia <http://www.linux.or.id>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Afrika/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Afrika/Akra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Afrika/Addis_Ababa"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Afrika/Aljazair"
+
+#: timezones.h:5
+#, fuzzy
+msgid "Africa/Asmara"
+msgstr "Afrika/Asmera"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Afrika/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Afrika/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Afrika/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Afrika/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Afrika/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Afrika/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Afrika/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Afrika/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Afrika/Kairo"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Afrika/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Afrika/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Afrika/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Afrika/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Afrika/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Afrika/Djibouti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Afrika/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Afrika/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Afrika/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Afrika/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Afrika/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Afrika/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Afrika/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Afrika/Khartoum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Afrika/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Afrika/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Afrika/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Afrika/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Afrika/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Afrika/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Afrika/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Afrika/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Afrika/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Afrika/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Afrika/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Afrika/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Afrika/Mogadishu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Afrika/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Afrika/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Afrika/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Afrika/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Afrika/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Afrika/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Afrika/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Afrika/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Afrika/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Afrika/Tripoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Afrika/Tunisia"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Afrika/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Amerika/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+#, fuzzy
+msgid "Aleutian Islands"
+msgstr "Australia/Queensland"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Amerika/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+#, fuzzy
+msgid "Alaska Time"
+msgstr "US/Alaska"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Amerika/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Amerika/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Amerika/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Amerika/Argentina/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Amerika/Argentina/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Amerika/Argentina/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Amerika/Argentina/Kordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Amerika/Argentina/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Amerika/Argentina/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Amerika/Argentina/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Amerika/Argentina/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+#, fuzzy
+msgid "America/Argentina/Salta"
+msgstr "Amerika/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Amerika/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+#, fuzzy
+msgid "America/Argentina/San_Luis"
+msgstr "Amerika/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Amerika/Argentina/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Amerika/Argentina/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Amerika/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Amerika/Asuncion"
+
+#: timezones.h:110
+#, fuzzy
+msgid "America/Atikokan"
+msgstr "Amerika/Atka"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Amerika/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Amerika/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "Amerika/Bahia"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Amerika/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Amerika/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Amerika/Belize"
+
+#: timezones.h:125
+#, fuzzy
+msgid "America/Blanc-Sablon"
+msgstr "Amerika/Cancun"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Amerika/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Amerika/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Amerika/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Amerika/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Amerika/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "Amerika/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Amerika/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Amerika/Karakas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Amerika/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Amerika/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Amerika/Cayman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Amerika/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+#, fuzzy
+msgid "Central Time"
+msgstr "US/Central"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Amerika/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "Amerika/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Amerika/Kordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Amerika/Kosta_Rika"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Amerika/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Amerika/Curacao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Amerika/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Amerika/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Amerika/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Amerika/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+#, fuzzy
+msgid "Mountain Time"
+msgstr "US/Mountain"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Amerika/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Amerika/Dominica"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Amerika/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Amerika/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Amerika/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Amerika/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Amerika/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Amerika/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Amerika/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Amerika/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Amerika/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Amerika/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Amerika/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Amerika/Guadeloupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Amerika/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Amerika/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Amerika/Guyana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Amerika/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Amerika/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Amerika/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Amerika/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Amerika/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Amerika/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+#, fuzzy
+msgid "America/Indiana/Petersburg"
+msgstr "Amerika/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Amerika/Indianapolis"
+
+#: timezones.h:227
+#, fuzzy
+msgid "America/Indiana/Tell_City"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+#, fuzzy
+msgid "America/Indiana/Vincennes"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+#, fuzzy
+msgid "America/Indiana/Winamac"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Amerika/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Amerika/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Amerika/Jamaika"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Amerika/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Amerika/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Amerika/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+#, fuzzy
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Amerika/Kentucky/Louisville"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Amerika/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Amerika/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Amerika/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Amerika/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Amerika/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+#, fuzzy
+msgid "Pacific Time"
+msgstr "Pasifik/Niue"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Amerika/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Amerika/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Amerika/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Amerika/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+#, fuzzy
+msgid "America/Marigot"
+msgstr "Amerika/Maceio"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Amerika/Martinique"
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "Amerika/Manaus"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Amerika/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Amerika/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Amerika/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Amerika/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Amerika/Mexico_City"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Amerika/Miquelon"
+
+#: timezones.h:289
+#, fuzzy
+msgid "America/Moncton"
+msgstr "Amerika/Edmonton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Amerika/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Amerika/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Amerika/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Amerika/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Amerika/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Amerika/New_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+#, fuzzy
+msgid "Eastern Time"
+msgstr "US/Eastern"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Amerika/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Amerika/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Amerika/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+#, fuzzy
+msgid "Atlantic islands"
+msgstr "Atlantik/Canary"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Amerika/NOrth_Dakota/Center"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+#, fuzzy
+msgid "America/North_Dakota/New_Salem"
+msgstr "Amerika/NOrth_Dakota/Center"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "Amerika/Managua"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Amerika/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Amerika/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Amerika/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Amerika/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Amerika/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Amerika/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Amerika/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Amerika/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Amerika/Puerto_Rico"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Amerika/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Amerika/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Amerika/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Amerika/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+#, fuzzy
+msgid "America/Resolute"
+msgstr "Amerika/Belem"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Amerika/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Amerika/Rosario"
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "Amerika/Santiago"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+#, fuzzy
+msgid "America/Santarem"
+msgstr "Amerika/Santiago"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Amerika/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Amerika/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Amerika/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Amerika/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Amerika/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+#, fuzzy
+msgid "America/St_Barthelemy"
+msgstr "Amerika/Belem"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Amerika/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Amerika/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Amerika/St_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Amerika/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Amerika/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Amerika/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Amerika/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Amerika/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Amerika/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Amerika/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "Amerika/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Amerika/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Amerika/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Amerika/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Amerika/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Amerika/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Amerika/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Amerika/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antartika/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antartika/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antartika/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+#, fuzzy
+msgid "Antarctica/Macquarie"
+msgstr "Antartika/McMurdo"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antartika/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antartika/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antartika/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antartika/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antartika/Kutub_Selatan"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antartika/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antartika/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Artik/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Asia/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Asia/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Asia/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Asia/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Asia/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Asia/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Asia/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Asia/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Asia/Baghdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Asia/Bahrain"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Asia/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Asia/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Asia/Beirut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Asia/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Asia/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Asia/Kalkuta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Asia/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Asia/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Asia/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Asia/Kolombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Asia/Daka"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Asia/Damaskus"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Asia/Dhaka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Asia/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Asia/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Asia/Dushanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Asia/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Asia/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+#, fuzzy
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Asia/Chongqing"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Asia/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Asia/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Asia/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Asia/Istanbul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Asia/Jakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Asia/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Asia/Jerusalem"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Asia/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Asia/Kamchatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Asia/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Asia/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+#, fuzzy
+msgid "Asia/Kathmandu"
+msgstr "Asia/Katmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Asia/Katmandu"
+
+#: timezones.h:518
+#, fuzzy
+msgid "Asia/Kolkata"
+msgstr "Asia/Jakarta"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Asia/Krasnoyarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Asia/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Asia/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Asia/Kuwait"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Asia/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Asia/Makau"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Asia/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Asia/Makasar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Asia/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Asia/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Asia/Nicosia"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "Asia/Irkutsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Asia/Novosibirsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Asia/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+#, fuzzy
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Asia/Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Asia/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Asia/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Asia/Phnom_Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Asia/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Asia/Pyongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Asia/Qatar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Asia/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Asia/Rangoon"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Asia/Riyadh"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Asia/Riyadh87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Asia/Riyadh88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Asia/Riyadh89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Asia/Saigon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Asia/Sakhalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Asia/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Asia/Seoul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Asia/Shanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Asia/Singapura"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Asia/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Asia/Tashkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Asia/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Asia/Tehran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Asia/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Asia/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Asia/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Asia/Tokyo"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Asia/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Asia/Ulaanbaatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Asia/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Asia/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Asia/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Asia/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Asia/Yakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Asia/Yekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Asia/Yerevan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlantik/Azores"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlantik/Bermuda"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlantik/Canary"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlantik/Cape_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlantik/Faeroe"
+
+#: timezones.h:616
+#, fuzzy
+msgid "Atlantic/Faroe"
+msgstr "Atlantik/Faeroe"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlantik/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlantik/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlantik/Reykjavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlantik/South_Georgia"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlantik/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlantik/St_Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Australia/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Australia/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+#, fuzzy
+msgid "South Australia"
+msgstr "Australia/ACT"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Australia/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Australia/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Australia/Canberra"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Australia/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Australia/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+#, fuzzy
+msgid "Australia/Eucla"
+msgstr "Australia/Queensland"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+#, fuzzy
+msgid "Western Australia - Eucla area"
+msgstr "Australia/Queensland"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Australia/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Australia/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Australia/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Australia/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Australia/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+#, fuzzy
+msgid "Victoria"
+msgstr "Australia/Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Australia/North"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Australia/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Australia/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Australia/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Australia/South"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Australia/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Australia/Tasmania"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Australia/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Australia/Barat"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Australia/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brazil/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brazil/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brazil/Timur"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brazil/Barat"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Kanada/Atlantik"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Kanada/Central"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Kanada/Eastern"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Kanada/East-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Kanada/Mountain"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Kanada/Newfoundland"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Kanada/Pasifik"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Kanada/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Kanada/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Chili/Kontinental"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Chili/EasterIsland"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Kuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Mesir"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Eire"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Eropa/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Eropa/Andorra"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Eropa/Athens"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Eropa/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Eropa/Belgrade"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Eropa/Berlin"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Eropa/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Eropa/Brussels"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Eropa/Bucharest"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Eropa/Budapest"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Eropa/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Eropa/Kopenhagen"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Eropa/Dublin"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Eropa/Gibraltar"
+
+#: timezones.h:744
+#, fuzzy
+msgid "Europe/Guernsey"
+msgstr "Eropa/Athens"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Eropa/Helsinki"
+
+#: timezones.h:746
+#, fuzzy
+msgid "Europe/Isle_of_Man"
+msgstr "Eropa/Oslo"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Eropa/Istanbul"
+
+#: timezones.h:748
+#, fuzzy
+msgid "Europe/Jersey"
+msgstr "Eropa/Paris"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Eropa/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Eropa/Kiev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Eropa/Lisbon"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Eropa/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Eropa/London"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Eropa/Luxembourg"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Eropa/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Eropa/Malta"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Eropa/Mariehamn"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Eropa/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Eropa/Monako"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Eropa/Moskow"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Eropa/Nicosia"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Eropa/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Eropa/Paris"
+
+#: timezones.h:774
+#, fuzzy
+msgid "Europe/Podgorica"
+msgstr "Eropa/Andorra"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Eropa/Prague"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Eropa/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Eropa/Rome"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Eropa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Eropa/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Eropa/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Eropa/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Eropa/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Eropa/Sofia"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Eropa/Stockholm"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Eropa/Tallinn"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Eropa/Tirane"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Eropa/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Eropa/Uzhgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Eropa/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Eropa/Vatikan"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Eropa/Wina"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Eropa/Vilnius"
+
+#: timezones.h:799
+#, fuzzy
+msgid "Europe/Volgograd"
+msgstr "Eropa/Belgrade"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Eropa/Warsawa"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Eropa/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Eropa/Zaporozhye"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Eropa/Zurich"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Factory"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Eire"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Islandia"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Indian/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Indian/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Indian/Christmas"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Indian/Cocos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Indian/Komoro"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Indian/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Indian/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Indian/Maladewa"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Indian/Mauritius"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Indian/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Indian/Reunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Iran"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Israel"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamaika"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Jepang"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Libya"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Mexico/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Mexico/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Mexico/General"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Mideast/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Mideast/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Mideast/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Pasifik/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Pasifik/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Pasifik/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+#, fuzzy
+msgid "Chatham Islands"
+msgstr "Chili/EasterIsland"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "Pasifik/Truk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+#, fuzzy
+msgid "Pacific/Easter"
+msgstr "Pasifik/Easter"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Pasifik/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Pasifik/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Pasifik/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Pasifik/Fiji"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Pasifik/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Pasifik/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Pasifik/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Pasifik/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Pasifik/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Pasifik/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+#, fuzzy
+msgid "Hawaii"
+msgstr "US/Hawaii"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Pasifik/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Pasifik/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Pasifik/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+#, fuzzy
+msgid "Kosrae"
+msgstr "Israel"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Pasifik/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Pasifik/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Pasifik/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Pasifik/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Pasifik/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Pasifik/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Pasifik/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Pasifik/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Pasifik/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Pasifik/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Pasifik/Pitcairn"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "Pasifik/Ponape"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Pasifik/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Pasifik/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Pasifik/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Pasifik/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Pasifik/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Pasifik/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Pasifik/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+#, fuzzy
+msgid "Gilbert Islands"
+msgstr "Chili/EasterIsland"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Pasifik/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Pasifik/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Pasifik/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Pasifik/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Pasifik/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Polandia"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugal"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapore"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Turki"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "US/Alaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "US/Aleutian"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "US/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "US/Central"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "US/Eastern"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "US/East-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "US/Hawaii"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "US/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "US/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "US/Mountain"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "US/Pasifik"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "US/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
+
+#, fuzzy
+#~ msgid "US/Pacific-New"
+#~ msgstr "US/Pasifik"
+
+#~ msgid "SystemV/AST4"
+#~ msgstr "SystemV/AST4"
+
+#~ msgid "SystemV/AST4ADT"
+#~ msgstr "SystemV/AST4ADT"
+
+#~ msgid "SystemV/CST6"
+#~ msgstr "SystemV/CST6"
+
+#~ msgid "SystemV/CST6CDT"
+#~ msgstr "SystemV/CST6CDT"
+
+#~ msgid "SystemV/EST5"
+#~ msgstr "SystemV/EST5"
+
+#~ msgid "SystemV/EST5EDT"
+#~ msgstr "SystemV/EST5EDT"
+
+#~ msgid "SystemV/HST10"
+#~ msgstr "SystemV/HST10"
+
+#~ msgid "SystemV/MST7"
+#~ msgstr "SystemV/MST7"
+
+#~ msgid "SystemV/MST7MDT"
+#~ msgstr "SystemV/MST7MDT"
+
+#~ msgid "SystemV/PST8"
+#~ msgstr "SystemV/PST8"
+
+#~ msgid "SystemV/PST8PDT"
+#~ msgstr "SystemV/PST8PDT"
+
+#~ msgid "SystemV/YST9"
+#~ msgstr "SystemV/YST9"
+
+#~ msgid "SystemV/YST9YDT"
+#~ msgstr "SystemV/YST9YDT"
diff --git a/panels/datetime/po-timezones/ilo.po b/panels/datetime/po-timezones/ilo.po
new file mode 100644
index 0000000..1d14812
--- /dev/null
+++ b/panels/datetime/po-timezones/ilo.po
@@ -0,0 +1,3232 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2006-11-25 10:33-0800\n"
+"Last-Translator: Joseph S. Maza <joemaza@comcast.net>\n"
+"Language-Team: \n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr ""
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr ""
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr ""
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr ""
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr ""
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr ""
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr ""
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr ""
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr ""
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr ""
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr ""
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr ""
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr ""
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr ""
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr ""
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr ""
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr ""
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr ""
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr ""
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr ""
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr ""
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr ""
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr ""
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr ""
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr ""
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr ""
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr ""
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr ""
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr ""
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr ""
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr ""
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr ""
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr ""
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr ""
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr ""
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr ""
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr ""
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr ""
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr ""
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr ""
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr ""
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr ""
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr ""
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr ""
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr ""
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr ""
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr ""
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr ""
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr ""
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr ""
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr ""
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr ""
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr ""
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr ""
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr ""
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr ""
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr ""
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr ""
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr ""
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr ""
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr ""
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr ""
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr ""
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr ""
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr ""
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr ""
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr ""
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr ""
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr ""
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr ""
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr ""
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr ""
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr ""
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr ""
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr ""
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr ""
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr ""
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr ""
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr ""
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr ""
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr ""
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr ""
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr ""
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr ""
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr ""
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr ""
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr ""
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr ""
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr ""
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr ""
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr ""
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr ""
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr ""
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr ""
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr ""
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr ""
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr ""
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr ""
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr ""
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr ""
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr ""
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr ""
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr ""
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr ""
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr ""
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr ""
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr ""
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr ""
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr ""
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr ""
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr ""
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr ""
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr ""
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr ""
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr ""
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr ""
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr ""
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr ""
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr ""
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr ""
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr ""
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr ""
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr ""
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr ""
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr ""
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr ""
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr ""
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr ""
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr ""
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr ""
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr ""
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr ""
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr ""
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr ""
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr ""
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr ""
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr ""
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr ""
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr ""
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr ""
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr ""
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr ""
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr ""
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr ""
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr ""
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr ""
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr ""
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr ""
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr ""
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr ""
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr ""
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr ""
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr ""
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr ""
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr ""
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr ""
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr ""
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr ""
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr ""
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr ""
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr ""
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr ""
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr ""
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr ""
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr ""
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr ""
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr ""
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr ""
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr ""
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr ""
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr ""
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr ""
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr ""
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr ""
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr ""
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr ""
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr ""
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr ""
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr ""
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr ""
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr ""
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr ""
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr ""
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr ""
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr ""
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr ""
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr ""
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr ""
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr ""
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr ""
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr ""
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr ""
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr ""
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr ""
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr ""
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr ""
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr ""
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr ""
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr ""
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr ""
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr ""
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr ""
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr ""
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr ""
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr ""
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr ""
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr ""
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr ""
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr ""
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr ""
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr ""
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr ""
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr ""
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr ""
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr ""
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr ""
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr ""
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr ""
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr ""
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr ""
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr ""
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr ""
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr ""
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr ""
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr ""
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr ""
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr ""
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr ""
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr ""
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr ""
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr ""
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr ""
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr ""
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr ""
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr ""
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr ""
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr ""
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr ""
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr ""
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr ""
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr ""
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr ""
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr ""
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr ""
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr ""
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr ""
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr ""
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr ""
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr ""
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr ""
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr ""
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr ""
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr ""
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr ""
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr ""
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr ""
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr ""
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr ""
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr ""
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr ""
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr ""
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr ""
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr ""
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr ""
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr ""
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr ""
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr ""
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr ""
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr ""
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr ""
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr ""
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr ""
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr ""
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr ""
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr ""
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr ""
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr ""
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr ""
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr ""
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr ""
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr ""
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr ""
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr ""
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr ""
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr ""
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr ""
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr ""
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr ""
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr ""
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr ""
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr ""
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr ""
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr ""
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr ""
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr ""
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr ""
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr ""
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr ""
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr ""
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr ""
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr ""
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr ""
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr ""
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr ""
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr ""
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr ""
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr ""
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr ""
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr ""
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr ""
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr ""
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr ""
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr ""
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr ""
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr ""
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr ""
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr ""
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr ""
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr ""
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr ""
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr ""
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr ""
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr ""
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr ""
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr ""
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr ""
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr ""
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr ""
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr ""
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr ""
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr ""
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr ""
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr ""
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr ""
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr ""
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr ""
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr ""
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr ""
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr ""
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr ""
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr ""
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr ""
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr ""
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr ""
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr ""
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr ""
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr ""
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr ""
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr ""
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr ""
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr ""
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr ""
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr ""
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr ""
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr ""
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr ""
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr ""
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr ""
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr ""
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr ""
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr ""
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr ""
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr ""
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr ""
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr ""
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr ""
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr ""
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr ""
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr ""
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr ""
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr ""
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr ""
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr ""
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr ""
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr ""
+
+#: timezones.h:685
+msgid "CET"
+msgstr ""
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr ""
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr ""
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr ""
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr ""
+
+#: timezones.h:690
+msgid "EET"
+msgstr ""
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr ""
+
+#: timezones.h:692
+msgid "Eire"
+msgstr ""
+
+#: timezones.h:693
+msgid "EST"
+msgstr ""
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr ""
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr ""
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr ""
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr ""
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr ""
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr ""
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr ""
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr ""
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr ""
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr ""
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr ""
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr ""
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr ""
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr ""
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr ""
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr ""
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr ""
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr ""
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr ""
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr ""
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr ""
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr ""
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr ""
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr ""
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr ""
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr ""
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr ""
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr ""
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr ""
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr ""
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr ""
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr ""
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr ""
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr ""
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr ""
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr ""
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr ""
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr ""
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr ""
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr ""
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr ""
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr ""
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr ""
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr ""
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr ""
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr ""
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr ""
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr ""
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr ""
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr ""
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr ""
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr ""
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr ""
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr ""
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr ""
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr ""
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr ""
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr ""
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr ""
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr ""
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr ""
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr ""
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr ""
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr ""
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr ""
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr ""
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr ""
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr ""
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr ""
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr ""
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr ""
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr ""
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr ""
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr ""
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr ""
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr ""
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr ""
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr ""
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr ""
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr ""
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr ""
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr ""
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr ""
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr ""
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr ""
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr ""
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr ""
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr ""
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr ""
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr ""
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr ""
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr ""
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr ""
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr ""
+
+#: timezones.h:808
+msgid "Factory"
+msgstr ""
+
+#: timezones.h:809
+msgid "GB"
+msgstr ""
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr ""
+
+#: timezones.h:811
+msgid "GMT"
+msgstr ""
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr ""
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr ""
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr ""
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr ""
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr ""
+
+#: timezones.h:817
+msgid "HST"
+msgstr ""
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr ""
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr ""
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr ""
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr ""
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr ""
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr ""
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr ""
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr ""
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr ""
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr ""
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr ""
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr ""
+
+#: timezones.h:830
+msgid "Iran"
+msgstr ""
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr ""
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr ""
+
+#: timezones.h:834
+msgid "Japan"
+msgstr ""
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr ""
+
+#: timezones.h:836
+msgid "Libya"
+msgstr ""
+
+#: timezones.h:837
+msgid "MET"
+msgstr ""
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr ""
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr ""
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr ""
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr ""
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr ""
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr ""
+
+#: timezones.h:844
+msgid "MST"
+msgstr ""
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr ""
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr ""
+
+#: timezones.h:847
+msgid "NZ"
+msgstr ""
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr ""
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr ""
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr ""
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr ""
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr ""
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr ""
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr ""
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr ""
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr ""
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr ""
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr ""
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr ""
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr ""
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr ""
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr ""
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr ""
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr ""
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr ""
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr ""
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr ""
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr ""
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr ""
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr ""
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr ""
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr ""
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr ""
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr ""
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr ""
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr ""
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr ""
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr ""
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr ""
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr ""
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr ""
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr ""
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr ""
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr ""
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr ""
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr ""
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr ""
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr ""
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr ""
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr ""
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr ""
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr ""
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr ""
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr ""
+
+#: timezones.h:929
+msgid "Poland"
+msgstr ""
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr ""
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr ""
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr ""
+
+#: timezones.h:934
+msgid "ROC"
+msgstr ""
+
+#: timezones.h:935
+msgid "ROK"
+msgstr ""
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr ""
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr ""
+
+#: timezones.h:938
+msgid "UCT"
+msgstr ""
+
+#: timezones.h:939
+msgid "Universal"
+msgstr ""
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr ""
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr ""
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr ""
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr ""
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr ""
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr ""
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr ""
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr ""
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr ""
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr ""
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr ""
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr ""
+
+#: timezones.h:952
+msgid "UTC"
+msgstr ""
+
+#: timezones.h:953
+msgid "WET"
+msgstr ""
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr ""
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr ""
diff --git a/panels/datetime/po-timezones/is.po b/panels/datetime/po-timezones/is.po
new file mode 100644
index 0000000..43cc200
--- /dev/null
+++ b/panels/datetime/po-timezones/is.po
@@ -0,0 +1,3251 @@
+# translation of system-config-date.master-timezones.is.po to Icelandic
+# Sveinn í Felli <sveinki@nett.is>, 2009, 2010.
+# íslensk þýðing system-config-date.master-timezones.is.po
+msgid ""
+msgstr ""
+"Project-Id-Version: system-config-date.master-timezones.is\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-05-05 10:23+0000\n"
+"Last-Translator: Sveinn í Felli <sveinki@nett.is>\n"
+"Language-Team: Icelandic <rglug@rglug.org>\n"
+"Language: is\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: Plural-Forms: nplurals=2; plural=1;\n"
+"\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Afríka/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Afríka/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Afríka/Addis_Ababa"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Afríka/Algiers"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "Afríka/Asmara"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Afríka/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Afríka/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Afríka/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Afríka/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Afríka/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Afríka/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Afríka/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Afríka/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Afríka/Cairo"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Afríka/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Afríka/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "Ceuta & Melilla"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Afríka/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Afríka/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Afríka/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Afríka/Djibouti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Afríka/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Afríka/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Afríka/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Afríka/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Afríka/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Afríka/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Afríka/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Afríka/Khartoum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Afríka/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Afríka/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "Vestur Kongó"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Afríka/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Afríka/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Afríka/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Afríka/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Afríka/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "Austur Kongó"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Afríka/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Afríka/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Afríka/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Afríka/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Afríka/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Afríka/Mogadishu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Afríka/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Afríka/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Afríka/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Afríka/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Afríka/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Afríka/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Afríka/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Afríka/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Afríka/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Afríka/Tripoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Afríka/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Afríka/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Ameríka/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Aljútaeyjar"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Ameríka/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Alaskatími"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Ameríka/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Ameríka/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Ameríka/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "Tocantin"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Ameríka/Argentina/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Buenos Aires (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Ameríka/Argentina/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "Catamarca (CT), Chubut (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Ameríka/Argentina/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Ameríka/Argentina/Cordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "flestar staðsetningar (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Ameríka/Argentina/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Jujuy (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Ameríka/Argentina/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "La Rioja (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Ameríka/Argentina/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "Mendoza (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Ameríka/Argentina/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "Santa Cruz (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "Ameríka/Argentína/Salta"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Ameríka/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "San Juan (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "Ameríka/Argentína/San_Juan"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "San Luis (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Ameríka/Argentina/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "Tucuman (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Ameríka/Argentina/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "Tierra del Fuego - Eldlandið (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Ameríka/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Ameríka/Asuncion"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Ameríka/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "Austurstrandartími EST - Atikokan, Ontario og Southampton I, Nunavut"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Ameríka/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Ameríka/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "Bahia"
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "Ameríka/Bahia"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Ameríka/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Ameríka/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "Amapa, A-Para"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Ameríka/Belize"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "Ameríka/Blanc-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "Atlantshafstími AST - Quebec - Lower North Shore"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Ameríka/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "Roraima"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Ameríka/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Ameríka/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "Klettafjallatími - suður Idaho & austur Oregon"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Ameríka/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Ameríka/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "Klettafjallatími - vestur Nunavut"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "Ameríka/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "Mato Grosso do Sul"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Ameríka/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "Miðríkjatími - Quintana Roo"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Ameríka/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Ameríka/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Ameríka/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Ameríka/Cayman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Ameríka/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "Miðríkjatími"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Ameríka/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "Mexíkanskur Klettafjallatími - Chihuahua frá landamærum BNA"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "Ameríka/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Ameríka/Cordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Ameríka/Costa_Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Ameríka/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "Mato Grosso"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Ameríka/Curacao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Ameríka/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "austurströndin, norðan Scoresbysunds"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Ameríka/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "Kyrrahafstími - norður Yukon"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Ameríka/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr "Klettafjallatími MST - Dawson Creek & Fort Saint John, Breska-Kólumbía"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Ameríka/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "Klettafjallatími"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Ameríka/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "Austurstrandartími - Michigan - flestir staðir"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Ameríka/Dominica"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Ameríka/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+"Klettafjallatími - Alberta, austur-Breska-Kólumbía & vestur-Saskatchewan"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Ameríka/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "Vestur-Amazon"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Ameríka/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Ameríka/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Ameríka/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "NA-Brasilía (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Ameríka/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Ameríka/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr "Atlantshafstími - Nova Scotia - staðir sem ekki tóku upp DST 1966-1971"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Ameríka/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "flestar staðsetningar"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Ameríka/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "Atlantshafstími - Labrador - flestir staðir"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Ameríka/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Ameríka/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Ameríka/Guadeloupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Ameríka/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Ameríka/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "meginlands"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Ameríka/Guyana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Ameríka/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "Atlantshafstími - Nova Scotia (flestir staðir), PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Ameríka/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Ameríka/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "Klettafjallatími MST - Sonora"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Ameríka/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "Austurstrandartími - Indiana - flestir staðir"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Ameríka/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "Miðríkjatími - Indiana - Starke County"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Ameríka/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "Austurstrandartími - Indiana - Crawford County"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "Ameríka/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "Austurstrandartími - Indiana - Pike County"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Ameríka/Indianapolis"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "Ameríka/Indiana/Tell_City"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "Miðríkjatími - Indiana - Perry County"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Ameríka/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "Austurstrandartími - Indiana - Switzerland County"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "Ameríka/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "Austurstrandartími - Indiana - Daviess, Dubois, Knox & Martin Counties"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "Ameríka/Indiana/Winamac"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "Austurstrandartími - Indiana - Pulasky County"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Ameríka/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "Klettafjallatími - vestur Northwest Territories"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Ameríka/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "Austurstrandartími - austur Nunavut - flestir staðir"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Ameríka/Jamaica"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Ameríka/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Ameríka/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "Alaskatími - Alaska panhandle"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Ameríka/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Austurstrandartími - Kentucky - Louisville svæðið"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Ameríka/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "Austurstrandartími - Kentucky - Wayne-sýsla"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Ameríka/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Ameríka/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Ameríka/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Ameríka/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "Kyrrahafstími"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Ameríka/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Ameríka/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "Alagoas, Sergipe"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Ameríka/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Ameríka/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "Austur-Amazon"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "Ameríka/Marigot"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Ameríka/Martinique"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "Ameríka/Matamoros"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+"Miðríkjatími - Coahuila, Durango, Nuevo Leon, Tamaulipas nálægt landamærum "
+"BNA"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Ameríka/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "Klettafjallatími - S Baja, Nayarit, Sinaloa"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Ameríka/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Ameríka/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "Miðríkjatími - Michigan - Dickinson, Gogebic, Iron & Menominee-sýslur"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Ameríka/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "Miðríkjatími - Campeche, Yucatan"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Ameríka/Mexíkóborg"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "Miðríkjatími - flestir staðir"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Ameríka/Miquelon"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "Ameríka/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "Atlantshafstími - New Brunswick"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Ameríka/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+"Mexíkanskur miðtími - Coahuila, Durango, Nuevo Leon, Tamaulipas fjarri "
+"landamærum BNA"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Ameríka/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Ameríka/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "Austurstrandartími - Quebec - flestir staðir"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Ameríka/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Ameríka/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Ameríka/New_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "Austurstrandartími"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Ameríka/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+"Austurstrandartími - Ontario & Quebec - staðir sem ekki tóku upp DST "
+"1967-1973"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Ameríka/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "Alaskatími - vestur Alaska"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Ameríka/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "Atlantshafseyjar"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Ameríka/North_Dakota/Center"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "Austurstrandartími - Norður Dakóta - Oliver County"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "Ameríka/North_Dakota/New_Salem"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+"Austurstrandartími - Norður Dakóta - Morton County (nema Mandan svæðið)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "Ameríka/Ojinaga"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "Klettafjallatími - Chihuahua nálægt landamærum BNA"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Ameríka/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Ameríka/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "Austurstrandartími - Pangnirtung, Nunavut"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Ameríka/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Ameríka/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "Klettafjallatími MST - Arizona"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Ameríka/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Ameríka/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Ameríka/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Ameríka/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "Rondonia"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Ameríka/Puerto_Rico"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Ameríka/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "Miðríkjatími - Rainy River & Fort Frances, Ontario"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Ameríka/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "Miðríkjatími - mið-Nunavut"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Ameríka/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "Pernambuco"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Ameríka/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "Miðríkjatími CST - Saskatchewan - flestir staðir"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "Ameríka/Resolute"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "Austurstrandartími EST - Resolute, Nunavut"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Ameríka/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "Acre"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Ameríka/Rosario"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "Ameríka/Santa_Isabel"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "Mexíkanskur Kyrrahafstími - Baja California fjarri landamærum BNA"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "Ameríka/Santarem"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "Vestur-Para"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Ameríka/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Ameríka/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Ameríka/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "S- & SA-Brasilía (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Ameríka/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "Scoresbysund / Ittoqqortoormiit"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Ameríka/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "Klettafjallatími - Navajo"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "Ameríka/St_Barthelemy"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Ameríka/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "Nýfundnalandstími, þar með talið SA-Labrador"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Ameríka/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Ameríka/St_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Ameríka/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Ameríka/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Ameríka/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "Miðríkjatími CST - Saskatchewan - miðvestur"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Ameríka/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Ameríka/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "Thule / Pituffik"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Ameríka/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "Austurstrandartími - Thunder Bay, Ontario"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Ameríka/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "Kyrrahafstími - Baja California nálægt landamærum BNA"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "Ameríka/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "Austurstrandartími - Ontario - flestir staðir"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Ameríka/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Ameríka/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "Kyrrahafstími - vestur-Breska-Kólumbía"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Ameríka/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Ameríka/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "Kyrrahafstími - suður-Yukon"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Ameríka/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "Miðríkjatími - Manitoba & vestur-Ontario"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Ameríka/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "Alaskatími - Alaska panhandle neck"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Ameríka/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "Klettafjallatími - mið-Northwest Territories"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Suðurskautslandið/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "Casey stöðin, Bailey-skaga"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Suðurskautslandið/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "Davis stöðin, Vestfold-hæðum"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Suðurskautslandið/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "Dumont-d'Urville stöðin, Terre Adelie"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "Suðurskautslandið/Macquarie"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "Macquarie Island stöðin, Macquarie-eyju"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Suðurskautslandið/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "Mawson stöðin, Holme-flóa"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Suðurskautslandið/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "McMurdo stöðin, Ross-eyju"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Suðurskautslandið/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "Palmer stöðin, Anvers-eyju"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Suðurskautslandið/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "Rothera stöðin, Adelaide-eyju"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Suðurskautslandið/South_Pole"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "Amundsen-Scott stöðin, Suðurpól"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Suðurskautslandið/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "Syowa stöðin, Austur-Ongul-eyju"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Suðurskautslandið/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "Vostok stöðin, Suðursegulpól"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Heimskautið/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Asía/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Asía/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Asía/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Asía/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "Moskva+08 - Beringshaf"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Asía/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Asía/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "Aqtobe (Aktobe)"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Asía/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Asía/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Asía/Baghdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Asía/Bahrain"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Asía/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Asía/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Asía/Beirut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Asía/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Asía/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Asía/Calcutta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Asía/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "Dornod, Sukhbaatar"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Asía/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "Mið-Kína - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, o.s.frv."
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Asía/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Asía/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Asía/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Asía/Damascus"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Asía/Dhaka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Asía/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Asía/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Asía/Dushanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Asía/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Asía/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "Heilongjiang (fyrir utan Mohe), Jilin"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Asía/Ho_Chi_Minh"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Asía/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Asía/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Asía/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Moscow+05 - Baikalvatn"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Asía/Istanbul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Asía/Jakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "Java & Súmatra"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Asía/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "Iríanska Jaya & Moluccaeyjar"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Asía/Jerusalem"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Asía/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Asía/Kamchatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "Moskva+08 - Kamchatka"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Asía/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Asía/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "Vestur-Tibet & Xinjiang"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "Asía/Katmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Asía/Katmandu"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "Asía/Kolkata"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Asía/Krasnoyarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "Moscow+04 - Yeniseifljót"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Asía/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "Malaysíuskagi"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Asía/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "Sabah & Sarawak"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Asía/Kuwait"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Asía/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Asía/Macau"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Asía/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "Moskva+08 - Magadan"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Asía/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "austur- & suður-Borneó, Celebes, Balí, Nusa Tengarra, vestur-Tímor"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Asía/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Asía/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Asía/Nicosia"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "Asía/Novokuznetsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Moskva+03 - Novokuznetsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Asía/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Moskva+03 - Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Asía/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "Moscow+03 - Vestur-Síbería"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Asía/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "Vestur-Kazakhstan"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Asía/Phnom_Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Asía/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "vestur- & mið-Borneó"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Asía/Pyongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Asía/Qatar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Asía/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Asía/Rangoon"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Asía/Riyadh"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Asía/Riyadh87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Asía/Riyadh88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Asía/Riyadh89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Asía/Saigon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Asía/Sakhalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "Moskva+07 - Sakhalíneyja"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Asía/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "vestur Uzbekistan"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Asía/Seoul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Asía/Shanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "Austur-Kína - Beijing, Guangdong, Shanghai, o.s.frv."
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Asía/Singapore"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Asía/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Asía/Tashkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "austur Uzbekistan"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Asía/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Asía/Tehran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Asía/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Asía/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Asía/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Asía/Tokyo"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Asía/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Asía/Ulaanbaatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Asía/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Asía/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "mest af Tibet & Xinjiang"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Asía/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Asía/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "Moscow+07 - Amurfljót"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Asía/Yakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "Moscow+06 - Lenafljót"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Asía/Yekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "Moscow+02 - Úralfjöll"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Asía/Yerevan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlandshafið/Azores"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "Asoreyjar"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlandshafið/Bermuda"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlandshafið/Canary"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "Kanaríeyjar"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlandshafið/Cape_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlandshafið/Faeroe"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "Atlantshaf/Færeyjar"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlandshafið/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlandshafið/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "Madeira-eyjar"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlandshafið/Reykjavík"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlandshafið/Suður_Georgia"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlandshafið/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlandshafið/St_Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Ástralía/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Ástralía/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "Suður-Ástralía"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Ástralía/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "Queensland - flestir staðir"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Ástralía/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "Nýja Suður-Wales - Yancowinna"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Ástralía/Canberra"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Ástralía/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "Tasmanía - King-eyja"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Ástralía/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "Norðursvæðið - Northern Territory"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "Ástralía/Eucla"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "Vestur-Ástralía - Eucla svæðið"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Ástralía/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "Tasmanía - flestir staðir"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Ástralía/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Ástralía/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "Queensland - Holiday-eyjar"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Ástralía/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "Lord Howe-eyja"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Ástralía/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "Viktoría"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Ástralía/Norður"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Ástralía/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Ástralía/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "Vestur-Ástralía - flestir staðir"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Ástralía/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Ástralía/Suður"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Ástralía/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "Nýja Suður-Wales - flestir staðir"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Ástralía/Tasmania"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Ástralía/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Ástralía/Vestur"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Ástralía/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Barsilía/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Barsilía/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Barsilía/Austur"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Barsilía/West"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Kanada/Atlantic"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Kanada/Central"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Kanada/Eastern"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Kanada/East-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Kanada/Mountain"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Kanada/Newfoundland"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Kanada/Pacific"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Kanada/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Kanada/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Chile/Continental"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Chile/EasterIsland"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Kúba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Egyptaland"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Eire"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Evrópa/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Evrópa/Andorra"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Evrópa/Athens"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Evrópa/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Evrópa/Belgrade"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Evrópa/Berlin"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Evrópa/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Evrópa/Brussels"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Evrópa/Bucharest"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Evrópa/Budapest"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Evrópa/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Evrópa/Copenhagen"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Evrópa/Dublin"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Evrópa/Gibraltar"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Evrópa/Guernsey"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Evrópa/Helsinki"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Evrópa/Isle_of_Man"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Evrópa/Istanbul"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Evrópa/Jersey"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Evrópa/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Moskva-01 - Kaliningrad"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Evrópa/Kiev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Evrópa/Lisbon"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Evrópa/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Evrópa/London"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Evrópa/Luxembourg"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Evrópa/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Evrópa/Malta"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Evrópa/Mariehamn"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Evrópa/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Evrópa/Monaco"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Evrópa/Moscow"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "Moskva+00 - Vestur-Rússland"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Evrópa/Nicosia"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Evrópa/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Evrópa/Paris"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Evrópa/Podgorica"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Evrópa/Prague"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Evrópa/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Evrópa/Rome"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Evrópa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Moskva - Samara, Udmurtia"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Evrópa/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Evrópa/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Evrópa/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "Mið-Krímskagi"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Evrópa/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Evrópa/Sofia"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Evrópa/Stockholm"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Evrópa/Tallinn"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Evrópa/Tirane"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Evrópa/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Evrópa/Uzhgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "Ruthenia"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Evrópa/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Evrópa/Vatican"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Evrópa/Vienna"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Evrópa/Vilnius"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Evrópa/Volgograd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "Moskva+00 - Kaspíahaf"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Evrópa/Warsaw"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Evrópa/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Evrópa/Zaporozhye"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Evrópa/Zurich"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Factory"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Eire"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Ísland"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Indland/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Indland/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Indland/Christmas"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Indland/Cocos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Indland/Comoro"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Indland/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Indland/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Indland/Maldives"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Indland/Mauritius"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Indland/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Indland/Reunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Iran"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Israel"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamaica"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Japan"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Líbía"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Mexikó/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Mexikó/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Mexikó/General"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Miðaustur/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Miðaustur/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Miðaustur/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Kyrrahafið/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Kyrrahafið/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Kyrrahafið/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "Chatham-eyjar"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "Kyrrahafið/Truk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+#, fuzzy
+msgid "Chuuk (Truk) and Yap"
+msgstr "Truk (Chuuk) og Yap"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Kyrrahafið/Páska"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "Páskaeyja & Sala y Gomez"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Kyrrahafið/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Kyrrahafið/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "Phoenix-eyjar"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Kyrrahafið/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Kyrrahafið/Fiji"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Kyrrahafið/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Kyrrahafið/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "Galapagos-eyjar"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Kyrrahafið/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "Gambier-eyjar"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Kyrrahafið/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Kyrrahafið/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Kyrrahafið/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "Hawaii"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Kyrrahafið/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "Johnston kóralrifið"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Kyrrahafið/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "Línueyjar"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Kyrrahafið/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "Kosrae"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Kyrrahafið/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Kyrrahafið/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Kyrrahafið/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "Marquesas-eyjar"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Kyrrahafið/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "Midway-eyjar"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Kyrrahafið/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Kyrrahafið/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Kyrrahafið/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Kyrrahafið/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Kyrrahafið/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Kyrrahafið/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Kyrrahafið/Pitcairn"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "Kyrrahafið/Ponape"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+#, fuzzy
+msgid "Pohnpei (Ponape)"
+msgstr "Ponape (Pohnpei)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Kyrrahafið/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Kyrrahafið/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Kyrrahafið/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Kyrrahafið/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Kyrrahafið/Samóa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Kyrrahafið/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "Society-eyjar"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Kyrrahafið/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "Gilbert-eyjar"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Kyrrahafið/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Kyrrahafið/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Kyrrahafið/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "Wake eyja"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Kyrrahafið/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Kyrrahafið/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Pólland"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugal"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapore"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Tyrkland"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Alheims"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "BNA/Alaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "BNA/Aljútaeyjar"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "BNA/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "BNA/Miðfylki"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "BNA/Austurfylki"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "BNA/Austur-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "BNA/Hawaii"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "BNA/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "BNA/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "BNA/Klettafjöll"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "BNA/Kyrrahafs"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "BNA/Samóa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "Vestur-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zúlu"
diff --git a/panels/datetime/po-timezones/it.po b/panels/datetime/po-timezones/it.po
new file mode 100644
index 0000000..9207cd3
--- /dev/null
+++ b/panels/datetime/po-timezones/it.po
@@ -0,0 +1,3242 @@
+# translation of timezones.po to italian
+# Copyright (C) 2001 Red Hat, Inc.
+#
+# Bettina De Monti <bdemonti@redhat.it>, 2000, 2004.
+# Francesco Tombolini <tombo@adamantio.net>, 2006, 2007, 2008, 2010.
+# Luigi Votta <luigi.votta@alice.it>, 2010
+# Silvio Pierro <perplesso82@gmail.com>, 2010
+msgid ""
+msgstr ""
+"MIME-Version: 1.0\n"
+"Project-Id-Version: 0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-11-15 14:35+0100\n"
+"Last-Translator: luigi votta <lewis41@fedoraproject.org>\n"
+"Language-Team: Italian <trans-it@lists-fedoraproject.org>\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Africa/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Africa/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Africa/Addis_Abeba"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Africa/Algeri"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "Africa/Asmara"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Africa/Asmara"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Africa/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Africa/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Africa/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Africa/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Africa/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Africa/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Africa/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Africa/Il_Cairo"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Africa/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Africa/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "Ceuta e Melilla"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Africa/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Africa/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Africa/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Africa/Gibuti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Africa/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Africa/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Africa/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Africa/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Africa/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Africa/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Africa/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Africa/Khartoum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Africa/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Africa/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "Area Occidentale della Rep. Dem. del Congo"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Africa/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Africa/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Africa/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Africa/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Africa/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "Area Orientale della Rep. Dem. del Congo"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Africa/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Africa/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Africa/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Africa/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Africa/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Africa/Mogadiscio"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Africa/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Africa/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Africa/NDjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Africa/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Africa/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Africa/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Africa/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Africa/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Africa/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Africa/Tripoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Africa/Tunisi"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Africa/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "America/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Isole Aleutine"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "America/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Alaska Time"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "America/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "America/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "America/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "Tocantins"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "America/Argentina/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Buenos Aires (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "America/Argentina/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "Catamarca (CT), Chubut (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "America/Argentina/Comodoro_Rivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "America/Argentina/Cordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "(CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "America/Argentina/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Jujuy (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "America/Argentina/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "La Rioja (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "America/Argentina/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "Mendoza (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "America/Argentina/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "Santa Cruz (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "America/Argentina/Salta"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "America/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "San Juan (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "America/Argentina/San_Luis"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "San Luis (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "America/Argentina/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "Tucuman (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "America/Argentina/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "Terra del Fuoco (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "America/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "America/Asuncion"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "America/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "Eastern Time - Atikokan, Ontario e Southampton I, Nunavut"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "America/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "America/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "Bahia"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "America/Bahia_Banderas"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "Mexican Central Time - Bahia de Banderas"
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "America/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "America/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "Amapa, Parà Orientale"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "America/Belize"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "America/Blanc-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "Atlantic Time - Quebec - Lower North Shore"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "America/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "Roraima"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "America/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "America/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "Mountain Time - Area Meridionale dell'Idaho ed area Orientale dell'Oregon"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "America/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "America/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "Mountain Time - Area Occidentale del Nunavut"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "America/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "Mato Grosso do Sul"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "America/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "Central Time - Quintana Roo"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "America/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "America/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "America/Caienna"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "America/Cayman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "America/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "Central Time"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "America/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "Mexican Mountain Time - Chihuahua lontano dalla frontiera del Nord America"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "America/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "America/Cordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "America/Costa_Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "America/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "Mato Grosso"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "America/Curacao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "America/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "Costa orientale e settentrionale di Scoresbysund"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "America/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "Pacific Time - Yukon settentrionale"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "America/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid "Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr "Mountain Time - Dawson Creek e Fort Saint John, British Columbia"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "America/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "Mountain Time"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "America/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "Eastern Time - Michigan"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "America/Dominica"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "America/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "Mountain Time - Alberta, British Columbia orientale e Saskatchewan occidentale"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "America/Eirunepé"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "Area Occidentale delle Amazonas"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "America/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "America/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "America/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "Area Nord-Orientale del Brasile (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "America/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "America/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr "Atlantic Time - Nuova Scozia - luoghi che non osservano il DST 1966-1971"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "America/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195
+#: timezones.h:364
+#: timezones.h:453
+#: timezones.h:591
+#: timezones.h:754
+#: timezones.h:852
+#: timezones.h:894
+msgid "most locations"
+msgstr "principali località"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "America/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "Atlantic Time - Labrador"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "America/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "America/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "America/Guadalupa"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "America/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "America/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205
+#: timezones.h:757
+#: timezones.h:763
+msgid "mainland"
+msgstr "continentale"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "America/Guyana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "America/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "Atlantic Time - Nuova Scozia, PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "America/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "America/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "Mountain Time - Sonora"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "America/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "Eastern Time - Indiana"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "America/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "Central Time - Indiana - Contea di Starke"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "America/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "Eastern Time - Indiana - Contea di Crawford"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "America/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "Eastern Time - Indiana - Contea di Pike"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "America/Indianapolis"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "America/Indiana/Tell_City"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "Central Time - Indiana - Contea di Perry"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "America/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "Eastern Time - Indiana - Contea di Switzerland"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "America/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "Eastern Time - Indiana - Contee di Daviess, Dubois, Knox e Martin"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "America/Indiana/Winamac"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "Eastern Time - Indiana - Contea di Pulaski"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "America/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "Mountain Time - Territori Ovest Nord-Ovest"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "America/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "Eastern Time - Area Orientale del Nunavut"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "America/Giamaica"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "America/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "America/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "Alaska Time - Alaska Panhandle"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "America/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Eastern Time - Kentucky - Zona di Louisville"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "America/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "Eastern Time - Kentucky - Contea di Wayne"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "America/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "America/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "America/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "America/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "Pacific Time"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "America/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "America/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "Alagoas, Sergipe"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "America/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "America/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "Area Orientale delle Amazonas"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "America/Marigot"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "America/Martinica"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "America/Matamoros"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid "US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr "US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas vicino il confine con gli USA"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "America/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "Mountain Time - Bassa California del Sud, Nayarit, Sinaloa"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "America/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "America/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "Central Time - Michigan - Contee di Dickinson, Gogebic, Iron e Menominee"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "America/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "Central Time - Campeche, Yucatan"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "America/Mexico_City"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "Central Time"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "America/Miquelon"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "America/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "Atlantic Time - Nuovo Brunswick"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "America/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid "Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from US border"
+msgstr "Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas lontano dalla frontiera del Nord America"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "America/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "America/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "Eastern Time - Quebec"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "America/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "America/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "America/New_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "Eastern Time"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "America/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid "Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr "Eastern Time - Ontario e Quebec - luoghi che non osservano DST 1967-1973"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "America/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "Alaska Time - Area Occidentale dell'Alaska"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "America/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "Isole dell'Atlantico"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "America/Dakota_del_Nord/Centro"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "Central Time - Dakota del Nord - Contea di Oliver"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "America/Dakota_del_Nord/New_Salem"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "Central Time - Dakota del Nord - Contea di Morton"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "America/Ojinaga"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "US Mountain Time - Chihuahua vicino la frontiera Nord Americana"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "America/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "America/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "Eastern Time - Pangnirtung, Nunavut"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "America/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "America/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "Mountain Time - Arizona"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "America/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "America/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "America/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "America/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "Rondonia"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "America/Porto_Rico"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "America/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "Central Time - Rainy River e Fort Frances, Ontario"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "America/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "Central Time - Nunavut Centrale"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "America/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "Pernambuco"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "America/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "Central Time - Saskatchewan"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "America/Resolute"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "Eastern Time - Resolute, Nunavut"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "America/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "Acre"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "America/Rosario"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "America/Santa_Isabel"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "Mexican Pacific Time - Baja California lontano dalla frontiera Nord Americana"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "America/Santarem"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "Parà Occidentale"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "America/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "America/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "America/San_Paolo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "Area Meridionale e Sud-Orientale del Brasile (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "America/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "Scoresbysund / Ittoqqortoormiit"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "America/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "Mountain Time - Navajo"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "America/Saint_Barthélemy"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "America/Saint_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "Ora di Terranova, comprendente l'area Sud-Orientale del Labrador"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "America/Saint_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "America/Saint_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "America/Saint_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "America/Saint_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "America/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "Central Time - Saskatchewan - Area medio-occidentale"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "America/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "America/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "Thule / Pituffik"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "America/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "Eastern Time - Thunder Bay, Ontario"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "America/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "US Pacific Time - Baja California vicino la frontiera Nord Americana"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "America/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "Eastern Time - Ontario"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "America/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "America/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "Pacific Time - Area Occidentale della Columbia Britannica"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "America/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "America/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "Pacific Time - Area Meridionale dello Yukon"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "America/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "Central Time - Manitoba e Ontario Occidentale"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "America/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "Alaska Time - Sull'Alexander Arcipelago"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "America/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "Mountain Time - Territori centrali del Nord-Ovest"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antartide/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "Stazione Casey, Penisola di Bailey"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antartide/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "Stazione Davis, Vestfold Hills"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antartide/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "Stazione Dumont-d'Urville, Terra Adelia"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "Antarctica/Macquarie"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "Stazione isola di Macquarie, Isola di Macquarie"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antartide/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "Stazione Mawson, Baia di Holme"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antartide/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "Stazione McMurdo, Isola Ross"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antartide/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "Stazione Palmer, Isola Anvers"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antartide/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "Stazione Rothera, Isola Adelaide"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antartide/Polo_Sud"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "Stazione Amundsen-Scott, Polo Sud"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antartide/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "Stazione Syowa, Area Orientale dell'isola di Ongul"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antartide/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "Stazione Vostok, Polo Sud Magnetico"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Artico/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Asia/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Asia/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Asia/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Asia/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "Mosca+8 - Mare di Bering"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Asia/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Asia/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "Aqtobe (Aktobe)"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Asia/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Asia/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Asia/Baghdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Asia/Bahrain"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Asia/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Asia/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Asia/Beirut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Asia/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Asia/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Asia/Calcutta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Asia/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "Dornod, Sukhbaatar"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Asia/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "Cina centrale - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Asia/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Asia/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Asia/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Asia/Damasco"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Asia/Dacca"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Asia/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Asia/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Asia/Dushanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Asia/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Asia/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "Heilongjiang (tranne Mohe), Jilin"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Asia/Ho_Chi_Minh"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Asia/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Asia/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Asia/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Mosca+05 - Lago Baikal"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Asia/Istanbul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Asia/Giacarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "Giava e Sumatra"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Asia/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "Irian Jaya e Le Molucche"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Asia/Gerusalemme"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Asia/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Asia/Kamchatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "Mosca+08 - Kamchatka"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Asia/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Asia/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "Tibet Occidentale e lo Xinjiang"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "Asia/Kathmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Asia/Katmandu"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "Asia/Kolkata"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Asia/Krasnoyarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "Mosca+04 - Fiume Enisej"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Asia/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "Penisola della Malesia"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Asia/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "Sabah e Sarawak"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Asia/Kuwait"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Asia/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Asia/Macao"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Asia/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "Mosca+08 - Magadan"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Asia/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "Area Orientale e Meridionale del Borneo, Area Occidentale di Timor"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Asia/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Asia/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Asia/Nicosia"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "Asia/Novokuznetsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Mosca+03 - Novokuznetsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Asia/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Mosca+03 - Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Asia/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "Mosca+03 - Area Occidentale della Siberia"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Asia/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "Area Occidentale del Kazakistan"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Asia/Phnom_Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Asia/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "Area del Borneo Centrale ed Occidentale"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Asia/Pyongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Asia/Qatar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Asia/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Asia/Rangoon"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Asia/Riyadh"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Asia/Riyadh87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Asia/Riyadh88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Asia/Riyadh89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Asia/Saigon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Asia/Sakhalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "Mosca +07 - Ostrov Sahalin"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Asia/Samarcanda"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "Area Occidentale dell'Uzbekistan"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Asia/Seoul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Asia/Shanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "Area dell Cina Orientale - Beijing, Guangdong, Shanghai, ecc."
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Asia/Singapore"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Asia/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Asia/Tashkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "Area Orientale dell'Uzbekistan"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Asia/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Asia/Tehran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Asia/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Asia/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Asia/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Asia/Tokyo"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Asia/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Asia/Ulaanbaatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Asia/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Asia/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "Gran parte del Tibet e dello Xinjiang"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Asia/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Asia/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "Mosca+07 - Fiume Amur"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Asia/Yakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "Mosca+06 - Fiume Lena"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Asia/Ekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "Mosca+02 - Urali"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Asia/Erewan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Oceano Atlantico/Azzorre"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "Azzore"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Oceano Atlantico/Bermuda"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Oceano Atlantico/Canarie"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "Isole Canarie"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Oceano Atlantico/Capo_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Oceano Atlantico/Faer_Oer"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "Atlantic/Faer_Oer"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Oceano Atlantico/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Oceano Atlantico/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "Isole Madeira"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Oceano Atlantico/Reykjavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Oceano Atlantico/Georgia_del_Sud "
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Oceano Atlantico/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Oceano Atlantico/Sant_Elena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Australia/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Australia/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "Sud Australia"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Australia/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "Queensland"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Australia/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "Nuovo Galles del Sud - Yancowinna"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Australia/Canberra"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Australia/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "Tasmania - Isola del Re"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Australia/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "Territori del nord"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "Australia/Eucla"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "Area dell'Australia Occidentale - Zona di Eucla"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Australia/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "Tasmania"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Australia/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Australia/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "Queensland - Isole Holiday"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Australia/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "Isola di Lord Howe"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Australia/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Australia/Nord"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Australia/NSO"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Australia/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "Area dell'Australia Occidentale"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Australia/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Australia/Sud"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Australia/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "Nuovo Galles del Sud"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Australia/Tasmania"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Australia/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Australia/Ovest"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Australia/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brasile/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brasile/De_Noronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brasile/Est"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brasile/Ovest"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Canada/Atlantico"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Canada/Centrale"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Canada/Orientale"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Canada/Saskatchewan-Orientale"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Canada/Montagne-Rocciose"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Canada/Terranova"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Canada/Pacifico"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Canada/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Canada/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Cile/Continentale"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Cile/Isola_di_Pasqua"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Cuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Egitto"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Eire"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universale"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Europa/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Europa/Andorra"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Europa/Atene"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Europa/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Europa/Belgrado"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Europa/Berlino"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Europa/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Europa/Bruxelles"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Europa/Bucarest"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Europa/Budapest"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Europa/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Europa/Copenaghen"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Europa/Dublino"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Europa/Gibilterra"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Europa/Guernsey"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Europa/Helsinki"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Europa/Isola_di_Man"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Europa/Istanbul"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Europa/Jersey"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Europa/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Mosca-01 - Kalingrado"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Europa/Kiev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Europa/Lisbona"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Europa/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Europa/Londra"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Europa/Lussemburgo"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Europa/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Europa/Malta"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Europa/Mariehamn"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Europa/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Europa/Monaco"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Europa/Mosca"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "Mosca+00 - Area della Russia Occidentale"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Europa/Nicosia"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Europa/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Europa/Parigi"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Europa/Podgorica"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Europa/Praga"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Europa/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Europa/Roma"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Europa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Mosca - Samara, Udmurtia"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Europa/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Europa/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Europa/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "Crimea centrale"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Europa/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Europa/Sofia"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Europa/Stoccolma"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Europa/Tallinn"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Europa/Tirana"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Europa/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Europa/Uzhgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "Ruthenia"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Europa/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Europa/Vaticano"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Europa/Vienna"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Europa/Vilnius"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Europa/Volgograd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "Mosca+00 - Mar Caspio"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Europa/Varsavia"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Europa/Zagabria"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Europa/Zaporozhye"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "Zaporozh'ye, Lugansk orientale / Zaporizhia, Luhansk orientale"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Europa/Zurigo"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Factory"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Eire"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Islanda"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Oceano Indiano/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Oceano Indiano/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Oceano Indiano/Christmas"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Oceano Indiano/Cocos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Oceano Indiano/Comoro"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Oceano Indiano/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Oceano Indiano/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Oceano Indiano/Maldive"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Oceano Indiano/Mauritius"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Oceano Indiano/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Oceano Indiano/Reunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Iran"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Israele"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Giamaica"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Giappone"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835
+#: timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Libia"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Messico/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Messico/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Messico/General"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Mideast/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Mideast/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Mideast/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Oceano Pacifico/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Oceano Pacifico/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Oceano Pacifico/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "Isole Chatham"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "Oceano Pacifico/Chuuk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "Chuuk (Truk) e Yap"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Pacifico/Orientale"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "Isola di Pasqua e Sala y Gomez"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Oceano Pacifico/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Oceano Pacifico/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "Isole Phoenix"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Oceano Pacifico/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Oceano Pacifico/Fiji"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Oceano Pacifico/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Oceano Pacifico/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "Isole Galapagos"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Oceano Pacifico/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "Isole Gambier"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Oceano Pacifico/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Oceano Pacifico/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Oceano Pacifico/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "Hawaii"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Oceano Pacifico/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "Atollo di Johnston"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Oceano Pacifico/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "Sporadi equatoriali"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Oceano Pacifico/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "Kosrae"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Oceano Pacifico/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Oceano Pacifico/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Oceano Pacifico/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "Isole Marquesas"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Oceano Pacifico/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "Isole Midway"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Oceano Pacifico/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Oceano Pacifico/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Oceano Pacifico/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Oceano Pacifico/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Oceano Pacifico/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Oceano Pacifico/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Oceano Pacifico/Pitcairn"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "Oceano Pacifico/Pohnpei"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "Pohnpei (Ponape)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Oceano Pacifico/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Oceano Pacifico/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Oceano Pacifico/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Oceano Pacifico/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Oceano Pacifico/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Oceano Pacifico/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "Isole della Società"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Oceano Pacifico/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "Isole Gilert"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Oceano Pacifico/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Oceano Pacifico/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Oceano Pacifico/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "Wake Island"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Oceano Pacifico/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Oceano Pacifico/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Polonia"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portogallo"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapore"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Turchia"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universale"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "US/Alaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "US/Aleutine"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "US/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "US/Centrale"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "US/Orientale"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "US/Indiana-Orientale"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "US/Hawaii"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "US/Indiana-Contea_di_Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "US/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "US/Montagne_Rocciose"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "US/Pacifico"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "US/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
+
diff --git a/panels/datetime/po-timezones/ja.po b/panels/datetime/po-timezones/ja.po
new file mode 100644
index 0000000..6b9f8b7
--- /dev/null
+++ b/panels/datetime/po-timezones/ja.po
@@ -0,0 +1,3264 @@
+# Time Config Tool Japanese Translation
+# translation of ja.po to Japanese
+# Copyright (C) 2001 Red Hat, Inc.
+#
+# James Hashida <khashida@redhat.com>, 2003.
+# Hirofumi Saito <hi_saito@yk.rim.or.jp>, 2006.
+# Noriko Mizumoto <noriko@redhat.com>, 2006.
+# Hyu_gabaru Ryu_ichi <hyu_gabaru@yahoo.co.jp>, 2007, 2009.
+# Makoto Mizukami <makoto@fedoraproject.org>, 2008, 2010.
+# Hajime Taira <htaira@redhat.com>, 2010.
+# Kiyoto Hashida <khashida@redhat.com>, 2010.
+# Makoto Mizukami <makoto@fedoraporject.org>, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: ja\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-09-10 09:46+0900\n"
+"Last-Translator: Makoto Mizukami <makoto@fedoraporject.org>\n"
+"Language-Team: Japanese <>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Language: ja\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: Plural-Forms: nplurals=2; plural=(n!=1);\n"
+"\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "アフリカ/アビジャン"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "アフリカ/アクラ"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "アフリカ/アディスアベバ"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "アフリカ/アルジェ"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "アフリカ/アスマラ"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "アフリカ/アスマラ"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "アフリカ/バマコ"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "アフリカ/バンギ"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "アフリカ/バンジュール"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "アフリカ/ビサウ"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "アフリカ/ブランタイヤ"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "アフリカ/ブラザビル"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "アフリカ/ブジュンブラ"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "アフリカ/カイロ"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "アフリカ/カサブランカ"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "アフリカ/セウタ"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "セウタ及びメリリャ"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "アフリカ/コナクリ"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "アフリカ/ダカール"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "アフリカ/ダルエスサラーム"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "アフリカ/ジブチ"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "アフリカ/ドゥアラ"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "アフリカ/アイウン"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "アフリカ/フリータウン"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "アフリカ/ハボローネ"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "アフリカ/ハラレ"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "アフリカ/ヨハネスブルク"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "アフリカ/カンパラ"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "アフリカ/ハルツーム"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "アフリカ/キガリ"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "アフリカ/キンシャサ"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "コンゴ民主共和国西部"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "アフリカ/ラゴス"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "アフリカ/リーブルビル"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "アフリカ/ロメ"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "アフリカ/ルアンダ"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "アフリカ/ルブンバシ"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "コンゴ民主共和国東部"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "アフリカ/ルサカ"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "アフリカ/マラボ"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "アフリカ/マプト"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "アフリカ/マセル"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "アフリカ/ムババーネ"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "アフリカ/モガディシュ"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "アフリカ/モンロビア"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "アフリカ/ナイロビ"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "アフリカ/ンジャメナ"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "アフリカ/ニアメ"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "アフリカ/ヌアクショット"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "アフリカ/ワガドゥグー"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "アフリカ/ポルトノボ"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "アフリカ/サントメ"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "アフリカ/トンブクトゥ"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "アフリカ/トリポリ"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "アフリカ/チュニス"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "アフリカ/ウィントフック"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "アメリカ/アダック島"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "アリューシャン列島"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "アメリカ/アンカレッジ"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "アラスカ標準時"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "アメリカ/アンギラ"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "アメリカ/アンティグア"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "アメリカ/アラグアイナ"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "トカンティンス州"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "アメリカ/アルゼンチン/ブエノスアイレス"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "ブエノスアイレス (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "アメリカ/アルゼンチン/カタマルカ"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "カタマルカ州 (CT)、チュブ州 (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "アメリカ/アルゼンチン/コモドーロ・リバダビア"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "アメリカ/アルゼンチン/コルドバ"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "大半の地域 (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "アメリカ/アルゼンチン/フフイ"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "フフイ州 (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "アメリカ/アルゼンチン/ラ・リオハ"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "ラ・リオハ州 (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "アメリカ/アルゼンチン/メンドーサ"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "メンドーサ州 (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "アメリカ/アルゼンチン/リオ・ガレゴス"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "サンタ・クルス州 (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "アメリカ/アルゼンチン/サルタ"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "アメリカ/アルゼンチン/サン・フアン"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "サン・フアン州 (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "アメリカ/アルゼンチン/サンルイス"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "サンルイス州 (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "アメリカ/アルゼンチン/トゥクマン"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "トゥクマン州 (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "アメリカ/アルゼンチン/ウシュアイア"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "ティエラ・デル・フエゴ州 (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "アメリカ/アルバ"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "アメリカ/アスンシオン"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "アメリカ/アティコカン"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "東部標準時 - オンタリオ州アティコカン及びヌナブト準州サウサンプトン島"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "アメリカ/アトカ島"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "アメリカ/バイーア"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "バイーア州"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "アメリカ/バイーア・デ・バンデラス"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "メキシコ中部標準時 - バイーア・デ・バンデラス"
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "アメリカ/バルバトス"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "アメリカ/ベレン"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "アマパー州、パラー州"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "アメリカ/ベリーズ"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "アメリカ/ブラン・サブロン"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "大西洋標準時 - ケベック州 - バス=コート・ノード地区"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "アメリカ/ボア・ビスタ"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "ロライマ州"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "アメリカ/ボゴタ"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "アメリカ/ボイシ"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "山岳部標準時 - アイダホ州南部及びオレゴン州東部"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "アメリカ/ブエノスアイレス"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "アメリカ/ケンブリッジベイ"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "山岳部標準時 - ヌナブト準州西部"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "アメリカ/カンポ・グランデ"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "マットグロッソ・ド・スル州"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "アメリカ/カンクン"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "中部標準時 - キンタナ・ロー州"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "アメリカ/カラカス"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "アメリカ/カタマルカ"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "アメリカ/カイエンヌ"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "アメリカ/ケイマン諸島"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "アメリカ/シカゴ"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "中部標準時"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "アメリカ/チワワ"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "メキシコ山岳部標準時 - チワワ州の米国境から遠い地域"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "アメリカ/コーラルハーバー"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "アメリカ/コルドバ"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "アメリカ/コスタリカ"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "アメリカ/クイアバ"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "マットグロッソ州"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "アメリカ/キュラソー島"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "アメリカ/デンマークシャウン"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "東海岸、スコルズビスーンの北"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "アメリカ/ドーソン"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "太平洋標準時 - ユーコン準州北部"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "アメリカ/ドーソンクリーク"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+"山岳部標準時 - ドーソンクリーク及びフォートセントジョン(ブリティッシュコロン"
+"ビア州)"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "アメリカ/デンバー"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "山岳部標準時"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "アメリカ/デトロイト"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "東部標準時 - ミシガン州 - 大部分"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "アメリカ/ドミニカ"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "アメリカ/エドモントン"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+"山岳部標準時 - アルバータ州、ブリティッシュコロンビア州東部、サスカチュワン州"
+"西部"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "アメリカ/エイルネペ"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "アマゾナス州西部"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "アメリカ/エルサルバドル"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "アメリカ/エンセナーダ"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "アメリカ/フォルタレザ"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "ブラジル北東部 (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "アメリカ/フォートウェイン"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "アメリカ/グレースベイ"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+"大西洋標準時 - ノバスコシア州 - 1966年から1971年の間夏時間を実施しなかった地"
+"域"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "アメリカ/ゴットホープ"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "大半の地域"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "アメリカ/グースベイ"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "大西洋標準時 - ラブラドール半島 - 大半の地域"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "アメリカ/グランドターク島"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "アメリカ/グレナダ"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "アメリカ/グアドループ"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "アメリカ/グアテマラ"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "アメリカ/グアヤキル"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "本土"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "アメリカ/ガイアナ"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "アメリカ/ハリファックス"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+"大西洋標準時 - ノバスコシア州(大半の地域)、プリンスエドワードアイランド州"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "アメリカ/ハバナ"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "アメリカ/エルモシージョ"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "山岳部標準時 - ソノラ州"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "アメリカ/インディアナ/インディアナポリス"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "東部標準時 - インディアナ州 - 大半の地域"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "アメリカ/インディアナ/ノックス"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "中部標準時 - インディアナ州 - スターク郡"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "アメリカ/インディアナ/マレンゴ"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "東部標準時 - インディアナ州 - クロフォード郡"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "アメリカ/インディアナ/ピーターズバーグ"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "東部標準時 - インディアナ州 - パイク郡"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "アメリカ/インディアナポリス"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "アメリカ/インディアナ/テルシティ"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "中部標準時 - インディアナ州 - ペリー郡"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "アメリカ/インディアナ/ベベイ"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "東部標準時 - インディアナ州 - スウィッツランド郡"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "アメリカ/インディアナ/ビンセンズ"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+"東部標準時 - インディアナ州 - デービス郡、デュボイス郡、ノックス郡、マーティ"
+"ン郡"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "アメリカ/インディアナ/ウィナマク"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "東部標準時 - インディアナ州 - プラスキ郡"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "アメリカ/イヌヴィック"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "山岳部標準時 - ノースウエスト準州西部"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "アメリカ/イカルイト"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "東部標準時 - ヌナブト準州東部 - 大半の地域"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "アメリカ/ジャマイカ"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "アメリカ/フフイ"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "アメリカ/ジュノー"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "アラスカ標準時 - アラスカ・パンハンドル"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "アメリカ/ケンタッキー/ルイスビル"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "東部標準時 - ケンタッキー州 - ルイスビル地域"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "アメリカ/ケンタッキー/モンティチェロ"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "東部標準時 - ケンタッキー州 - ウェイン郡"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "アメリカ/インディアナ州ノックス"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "アメリカ/ラパス"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "アメリカ/リマ"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "アメリカ/ロサンゼルス"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "太平洋標準時"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "アメリカ/ルイスビル"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "アメリカ/マセイオ"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "アラゴアス州、セルジッペ州"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "アメリカ/マナグア"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "アメリカ/マナウス"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "アマゾナス州東部"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "アメリカ/マリゴ"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "アメリカ/マルティニーク島"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "アメリカ/マタモロス"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+"米国中部標準時 - コアウイラ州、ドゥランゴ州、ヌエボ・レオン州、タマウリパス州"
+"米国境付近"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "アメリカ/マサトラン"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "山岳部標準時 - バハ・カリフォルニア・スル州、ナヤリット州、シナロア州"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "アメリカ/メンドーサ"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "アメリカ/メノミニー"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+"中央部標準時 - ミシガン州 - ディキンソン郡、ゴギービック郡、アイロン郡、メノ"
+"ミニー郡"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "アメリカ/メリダ"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "中央部標準時 - カンペチェ州、ユカタン州"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "アメリカ/メキシコシティ"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "中央部標準時 - 大半の地域"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "アメリカ/ミクロン"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "アメリカ/モンクトン"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "大西洋標準時 - ニューブランズウィック州"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "アメリカ/モンテレイ"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+"メキシコ中部標準時 - コアウイラ州、ドゥランゴ州、ヌエボ・レオン州、タマウリパ"
+"ス州の米国境から遠い地域"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "アメリカ/モンテビデオ"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "アメリカ/モントリオール"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "東部標準時 - ケベック州 - 大半の地域"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "アメリカ/モントセラト"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "アメリカ/ナッソー"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "アメリカ/ニューヨーク"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "東部標準時"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "アメリカ/ニピゴン"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+"東部標準時 - オンタリオ州及びケベック州 - 1967年から1973年の間夏時間を実施し"
+"なかった地域"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "アメリカ/ノーム"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "アラスカ標準時 - アラスカ州西部"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "アメリカ/ノローニャ"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "大西洋の諸島"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "アメリカ/ノースダコタ/センター"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "中部標準時 - ノースダコタ州 - オリバー郡"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "アメリカ/ノースダコタ/ニュー・セーラム"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "中部標準時 - ノースダコタ州 - モートン郡(マンダン地区を除く)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "アメリカ/オヒナガ"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "米国山岳部標準時 - チワワ州米国境付近"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "アメリカ/パナマ"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "アメリカ/パングナータング"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "東部標準時 - ヌナブト準州パンナータング"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "アメリカ/パラマリボ"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "アメリカ/フェニックス"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "山岳部標準時 - アリゾナ州"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "アメリカ/ポルトープランス"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "アメリカ/ポルトアクレ"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "アメリカ/ポートオブスペイン"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "アメリカ/ポルト・ヴェーリョ"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "ロンドニア州"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "アメリカ/プエルトリコ"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "アメリカ/レイニーリバー"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "中部標準時 - レイニーリバー及びフォートフランシス(オンタリオ州)"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "アメリカ/ランキンインレット"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "中部標準時 - ヌナブト準州中央部"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "アメリカ/レシフェ"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "ペルナンブコ州"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "アメリカ/レジャイナ"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "中部標準時 - サスカチュワン州 - 大半の地域"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "アメリカ/レゾリュート"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "東部標準時 - ヌナブト準州レゾリュート"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "アメリカ/リオブランコ"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "アクレ州"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "アメリカ/ロサリオ"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "アメリカ/サンタ・イザベル"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "メキシコ太平洋標準時 - バハ・カリフォルニア州の米国境から遠い地域"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "アメリカ/サンタレン"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "パラー州西部"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "アメリカ/サンティアゴ"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "アメリカ/サント・ドミンゴ"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "アメリカ/サンパウロ"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "ブラジル南部及び南東部 (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "アメリカ/スコルズビスーン"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "スコルズビスーン / イトコルトルミット"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "アメリカ/シップロック"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "山岳部標準時 - ナバホ自治区"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "アメリカ/サン・バルテルミー島"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "アメリカ/セントジョンズ"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "ニューファンドランド島(ラブラドール地方南西部を含む)"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "アメリカ/セントクリストファー島"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "アメリカ/セントルシア"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "アメリカ/セントトーマス"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "アメリカ/セントビンセント"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "アメリカ/スウィフト・カレント"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "中部標準時 - サスカチュワン州 - 中西部"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "アメリカ/テグシガルパ"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "アメリカ/チューレ"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "チューレ / ピツフィク"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "アメリカ/サンダーベイ"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "東部標準時 - オンタリオ州サンダーベイ"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "アメリカ/ティファナ"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "アメリカ太平洋標準時 - バハ・カリフォルニア州米国境付近"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "アメリカ/トロント"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "東部標準時 - オンタリオ州 - 大半の地域"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "アメリカ/トルトラ島"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "アメリカ/バンクーバー"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "太平洋標準時 - ブリティッシュコロンビア州西部"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "アメリカ/バージン"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "アメリカ/ホワイトホース"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "太平洋標準時 - ユーコン州南部"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "アメリカ/ウィニペグ"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "中部標準時 - マニトバ州及びオンタリオ州西部"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "アメリカ/ヤクタット"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "アラスカ標準時 - アラスカ・パンハンドルの付け根部分"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "アメリカ/イエローナイフ"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "山岳部標準時 - ノースウエスト準州中部"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "南極大陸/ケーシー"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "ベイリー半島ケーシー基地"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "南極大陸/デービス"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "ヴェストフォール丘陵デービス基地"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "南極大陸/デュモン・デュルヴィル"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "アデリーランド デュモン・デュルヴィル基地"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "南極大陸/マッコーリー"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "マッコーリー島マッコーリー島基地"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "南極大陸/モーソン"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "ホルム湾モーソン基地"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "南極大陸/マクマード基地"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "ロス島マクマード基地"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "南極大陸/パーマー"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "アンバース島パーマー基地"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "南極大陸/ロゼラ"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "アデレード島ロゼラ基地"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "南極大陸/南極点"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "南極点アムンゼン・スコット基地"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "南極大陸/昭和"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "東オングル島昭和基地"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "南極大陸/ボストーク"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "南磁極ボストーク基地"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "北極圏/ロングイェールビーン"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "アジア/アデン"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "アジア/アルマトイ"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "アジア/アンマン"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "アジア/アナディリ"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "モスクワ+08 - ベーリング海"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "アジア/アクタウ"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "アティラウ(グーリエフ)州、マンギスタウ(マンキスタウ)州"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "アジア/アクトベ"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "アクトベ州"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "アジア/アシガバート"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "アジア/アシカバード"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "アジア/バグダード"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "アジア/バーレーン"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "アジア/バクー"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "アジア/バンコク"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "アジア/ベイルート"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "アジア/ビシュケク"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "アジア/ブルネイ"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "アジア/カルカッタ"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "アジア/チョイバルサン"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "ドルノド県、スフバータル県"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "アジア/重慶"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "中国中部 - 四川省、雲南省、広西チワン族自治区、陝西省、貴州省、他"
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "アジア/重慶"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "アジア/コロンボ"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "アジア/ダッカ"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "アジア/ダマスカス"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "アジア/ダッカ"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "アジア/ディリ"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "アジア/ドバイ"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "アジア/ドゥシャンベ"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "アジア/ガザ"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "アジア/ハルビン"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "黒竜江省(靺鞨を除く)、吉林省"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "アジア/ホーチミン"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "アジア/香港"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "アジア/ホブド"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "バヤン・ウルギー県、ゴビ・アルタイ県、ホブド県、オブス県、ザブハン県"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "アジア/イルクーツク"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "モスクワ+05 - バイカル湖"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "アジア/イスタンブル"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "アジア/ジャカルタ"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "ジャワ島及びスマトラ島"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "アジア/ジャヤプラ"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "イリアンジャヤ州及びモルッカ諸島"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "アジア/エルサレム"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "アジア/カーブル"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "アジア/カムチャツカ"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "モスクワ+08 - カムチャツカ半島"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "アジア/カラチ"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "アジア/カシュガル"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "チベット自治区西部及び新疆ウイグル自治区"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "アジア/カトマンズ"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "アジア/カトマンズ"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "アジア/コルカタ"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "アジア/クラスノヤルスク"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "モスクワ+04 - エニセイ川"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "アジア/クアラルンプール"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "マレーシア半島部"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "アジア/クチン"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "サバ州及びサラワク州"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "アジア/クウェート"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "アジア/マカオ"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "アジア/マカオ"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "アジア/マガダン"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "モスクワ+08 - マガダン"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "アジア/マカッサル"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "ボルネオ島東部及び南部、セレベス島、バリ島、小スンダ列島、西ティモール"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "アジア/マニラ"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "アジア/マスカット"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "アジア/ニコシア"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "アジア/ノボクズネツク"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "モスクワ+03 - ノボクズネツク"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "アジア/ノボシビルスク"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "モスクワ+03 - ノボシビルスク"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "アジア/オムスク"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "モスクワ+03 - シベリア西部"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "アジア/オラル"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "カザフスタン西部"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "アジア/プノンペン"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "アジア/ポンティアナック"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "ボルネオ島西部及び中部"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "アジア/平壌"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "アジア/カタール"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "アジア/クズロルダ"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "クズロルダ州"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "アジア/ラングーン"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "アジア/リヤド"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "アジア/リヤド87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "アジア/リヤド88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "アジア/リヤド89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "アジア/サイゴン"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "アジア/サハリン"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "モスクワ+07 - サハリン島"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "アジア/サマルカンド"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "ウズベキスタン西部"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "アジア/ソウル"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "アジア/上海"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "中国西部 - 北京、広東省、上海、他"
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "アジア/シンガポール"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "アジア/台北"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "アジア/タシュケント"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "ウズベキスタン東部"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "アジア/トビリシ"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "アジア/テヘラン"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "アジア/テルアビブ"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "アジア/ティンプー"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "アジア/ティンプー"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "アジア/東京"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "アジア/ウジュン・パンダン"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "アジア/ウランバートル"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "アジア/ウランバートル"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "アジア/ウルムチ"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "チベット自治区及び新疆ウイグル自治区の大部分"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "アジア/ヴィエンチャン"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "アジア/ウラジオストク"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "モスクワ+07 - アムール川"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "アジア/ヤクーツク"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "モスクワ+06 - レナ川"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "アジア/エカテリンブルク"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "モスクワ+02 - ウラル連邦管区"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "アジア/エレバン"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "大西洋/アゾレス"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "アゾレス諸島"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "大西洋/バミューダ諸島"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "大西洋/カナリア"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "カナリア諸島"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "大西洋/カーボベルデ"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "大西洋/フェロー諸島"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "大西洋/フェロー諸島"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "大西洋/ヤンマイエン島"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "大西洋/マデイラ"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "マデイラ諸島"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "大西洋/レイキャビク"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "大西洋/サウスジョージア"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "大西洋/スタンリー"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "大西洋/セントヘレナ"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "オーストラリア/オーストラリア首都特別地域"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "オーストラリア/アデレード"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "オーストラリア南部"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "オーストラリア/ブリズベン"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "クイーンズランド州 - 大半の地域"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "オーストラリア/ブロークンヒル"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "ニューサウスウェールズ州 - ヤンコウィナ郡"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "オーストラリア/キャンベラ"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "オーストラリア/カリー"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "タスマニア諸島 - キング島"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "オーストラリア/ダーウィン"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "北部準州"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "オーストラリア/ユークラ"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "西オーストラリア州 - ユークラ地域"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "オーストラリア/ホバート"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "タスマニア州 - 大半の地域"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "オーストラリア/ロード・ハウ島"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "オーストラリア/リンデマン島"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "クイーンズランド州 - ホリデー諸島"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "オーストラリア/ロード・ハウ"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "ロード・ハウ島"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "オーストラリア/メルボルン"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "ビクトリア州"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "オーストラリア/北部"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "オーストラリア/ニューサウスウェールズ"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "オーストラリア/パース"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "西オーストラリア州 - 大半の地域"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "オーストラリア/クイーンズランド"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "オーストラリア/南部"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "オーストラリア/シドニー"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "ニューサウスウェールズ - 大半の地域"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "オーストラリア/タスマニア"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "オーストラリア/ビクトリア"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "オーストラリア/西部"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "オーストラリア/ヤンコウィナ"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "ブラジル/アクレ"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "ブラジル/デ・ノローニャ"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "ブラジル/東部"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "ブラジル/西部"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "カナダ/大西洋"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "カナダ/中部"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "カナダ/東海岸"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "カナダ/サスカチュワン東部"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "カナダ/山岳部"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "カナダ/ニューファンドランド島"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "カナダ/太平洋"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "カナダ/サスカチュワン"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "カナダ/ユーコン"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "中央ヨーロッパ時間"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "チリ/大陸部"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "チリ/イースター島"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT (夏時間のない中部標準時)"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "キューバ"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "東ヨーロッパ時間"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "エジプト"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "エール"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "東部標準時"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT (夏時間のない東部標準時)"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "その他/グリニッジ標準時"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "その他/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "その他/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "その他/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "その他/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "その他/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "その他/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "その他/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "その他/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "その他/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "その他/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "その他/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "その他/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "その他/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "その他/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "その他/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "その他/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "その他/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "その他/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "その他/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "その他/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "その他/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "その他/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "その他/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "その他/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "その他/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "その他/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "その他/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "その他/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "その他/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "その他/グリニッジ"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "その他/UCT (協定世界時)"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "その他/世界時"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "その他/UTC (協定世界時)"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "その他/ズールー"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "ヨーロッパ/アムステルダム"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "ヨーロッパ/アンドラ"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "ヨーロッパ/アテネ"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "ヨーロッパ/ベルファスト"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "ヨーロッパ/ベオグラード"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "ヨーロッパ/ベルリン"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "ヨーロッパ/ブラチスラバ"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "ヨーロッパ/ブリュッセル"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "ヨーロッパ/ブカレスト"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "ヨーロッパ/ブダペスト"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "ヨーロッパ/キシナウ"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "ヨーロッパ/コペンハーゲン"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "ヨーロッパ/ダブリン"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "ヨーロッパ/ジブラルタル"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "ヨーロッパ/ガーンジー"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "ヨーロッパ/ヘルシンキ"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "ヨーロッパ/マン島"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "ヨーロッパ/イスタンブル"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "ヨーロッパ/ジャージー"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "ヨーロッパ/カリーニングラード"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "モスクワ-01 - カリーニングラード"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "ヨーロッパ/キエフ"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "ヨーロッパ/リスボン"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "ヨーロッパ/リュブリャナ"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "ヨーロッパ/ロンドン"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "ヨーロッパ/ルクセンブルク"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "ヨーロッパ/マドリード"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "ヨーロッパ/マルタ"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "ヨーロッパ/マリエハムン"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "ヨーロッパ/ミンスク"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "ヨーロッパ/モナコ"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "ヨーロッパ/モスクワ"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "モスクワ+00 - ロシア西部"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "ヨーロッパ/ニコシア"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "ヨーロッパ/オスロ"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "ヨーロッパ/パリ"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "ヨーロッパ/ポドゴリツァ"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "ヨーロッパ/プラハ"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "ヨーロッパ/リガ"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "ヨーロッパ/ローマ"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "ヨーロッパ/サマーラ"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "モスクワ - サマーラ州、ウドムルト共和国"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "ヨーロッパ/サンマリノ"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "ヨーロッパ/サラエボ"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "ヨーロッパ/シンフェロポリ"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "クリミア半島中部"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "ヨーロッパ/スコピエ"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "ヨーロッパ/ソフィア"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "ヨーロッパ/ストックホルム"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "ヨーロッパ/タリン"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "ヨーロッパ/ティラナ"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "ヨーロッパ/ティラスポリ"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "ヨーロッパ/ウージュホロド"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "ルーシ"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "ヨーロッパ/ファドゥーツ"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "ヨーロッパ/バチカン"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "ヨーロッパ/ウィーン"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "ヨーロッパ/ビリニュス"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "ヨーロッパ/ボルゴグラード"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "モスクワ+00 - カスピ海"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "ヨーロッパ/ワルシャワ"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "ヨーロッパ/ザグレブ"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "ヨーロッパ/ザポリージャ"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "ルガンスク東部ザポロージエ/ルハンシク東部ザポリージャ"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "ヨーロッパ/チューリッヒ"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "ファクトリー"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "イギリス"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "イギリス-アイルランド"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "グリニッジ標準時"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "グリニッジ"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "香港"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "ハワイ・アリューシャン標準時"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "アイスランド"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "インド洋/アンタナナリボ"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "インド洋/チャゴス諸島"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "インド洋/クリスマス島"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "インド洋/ココス島"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "インド洋/コモロ"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "インド洋/ケルゲレン諸島"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "インド洋/マヘ島"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "インド洋/モルディブ"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "インド洋/モーリシャス"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "インド洋/マヨット"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "インド洋/レユニオン"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "イラン"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "イスラエル"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "ジャマイカ"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "日本"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "クエジェリン環礁"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "リビア"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "中央ヨーロッパ時間"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "メキシコ/バハ・カリフォルニア・ノルテ"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "メキシコ/バハ・カリフォルニア・スル"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "メキシコ/標準"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "中東/リヤド87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "中東/リヤド88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "中東/リヤド89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "山岳部標準時"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT (夏時間のない山岳部標準時)"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "ナバホ"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "ニュージーランド"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "ニュージーランド-チャタム諸島"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "太平洋/アピア"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "太平洋/オークランド"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "太平洋/チャタム"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "チャタム諸島"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "太平洋/チューク"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "チューク(トラック)諸島及びヤップ諸島"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "太平洋/イースター島"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "イースター島及びサラ・イ・ゴメス島"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "太平洋/エファテ島"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "太平洋/エンダーベリー島"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "フェニックス諸島"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "太平洋/ファカオフォ島"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "太平洋/フィジー"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "太平洋/フナフティ島"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "太平洋/ガラパゴス"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "ガラパゴス諸島"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "太平洋/ガンビエ"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "ガンビエ諸島"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "太平洋/ガダルカナル島"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "太平洋/グアム島"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "太平洋/ホノルル"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "ハワイ島"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "太平洋/ジョンストン島"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "ジョンストン環礁"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "太平洋/キリスィマスィ島"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "ライン諸島"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "太平洋/コスラエ"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "コスラエ州"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "太平洋/クエジェリン"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "太平洋/マジュロ"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "太平洋/マルキーズ"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "マルキーズ諸島"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "太平洋/ミッドウェー"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "ミッドウェー島"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "太平洋/ナウル"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "太平洋/ニウエ"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "太平洋/ノーフォーク島"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "太平洋/ヌメア"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "太平洋/パゴパゴ"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "太平洋/パラオ"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "太平洋/ピトケアン諸島"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "太平洋/ポンペイ"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "ポンペイ島(ポナペ島)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "太平洋/ポナペ"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "太平洋/ポートモレスビー"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "太平洋/ラロトンガ島"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "太平洋/サイパン島"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "太平洋/サモア島"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "太平洋/タヒチ島"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "ソシエテ諸島"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "太平洋/タラワ"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "ギルバート諸島"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "太平洋/トンガタプ島"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "太平洋/トラック諸島"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "太平洋/ウェーク"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "ウェーク島"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "太平洋/ウォリス諸島"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "太平洋/ヤップ島"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "ポーランド"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "ポルトガル"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "POSIX ルール"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "中華人民共和国"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT (夏時間のない太平洋標準時)"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "中華民国"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "大韓民国"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "シンガポール"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "トルコ"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT (協定世界時)"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "世界時"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "米国/アラスカ"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "米国/アリューシャン列島"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "米国/アリゾナ"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "米国/中部"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "米国/東部"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "米国/インディアナ州東部"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "米国/ハワイ"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "米国/インディアナ州スターク"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "米国/ミシガン"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "米国/山岳部"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "米国/太平洋"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "米国/サモア"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC (協定世界時)"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "西ヨーロッパ時間"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "ロシア西部"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "ズールー"
diff --git a/panels/datetime/po-timezones/ka.po b/panels/datetime/po-timezones/ka.po
new file mode 100644
index 0000000..181511b
--- /dev/null
+++ b/panels/datetime/po-timezones/ka.po
@@ -0,0 +1,3280 @@
+# translation of ka.po to Georgian
+# Georgian translations for PACKAGE package.
+# Copyright (C) 2004 THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Automatically generated, 2004.
+# George Machitidze <giomac@gmail.com>, 2006.
+msgid ""
+msgstr ""
+"Project-Id-Version: ka\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2006-01-02 03:03+0300\n"
+"Last-Translator: George Machitidze <giomac@gmail.com>\n"
+"Language-Team: Georgian <guiasher@mes.gov.ge>\n"
+"Language: ka\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr ""
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr ""
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr ""
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "აფრიკა/ალჟირი"
+
+#: timezones.h:5
+#, fuzzy
+msgid "Africa/Asmara"
+msgstr "აფრიკა/ქაირო"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr ""
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr ""
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr ""
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr ""
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr ""
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr ""
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr ""
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr ""
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "აფრიკა/ქაირო"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "აფრიკა/კასაბლანკა"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr ""
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr ""
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "აფრიკა/დაკარი"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr ""
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "აფრიკა/ჯიბუტი"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr ""
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr ""
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr ""
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr ""
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr ""
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr ""
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr ""
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr ""
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr ""
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr ""
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "აფრიკა/ლაგოსი"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr ""
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr ""
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr ""
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr ""
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr ""
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr ""
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "აფრიკა/მაპუტო"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr ""
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "აფრიკა/მაბაბანე"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr ""
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr ""
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "აფრიკა/ნაირობი"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr ""
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr ""
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr ""
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr ""
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr ""
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr ""
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr ""
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr ""
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "აფრიკა/ტუნისი"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr ""
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr ""
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr ""
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr ""
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+#, fuzzy
+msgid "Alaska Time"
+msgstr "აშშ/ალასკა"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr ""
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr ""
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr ""
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "ამერიკა/არგენტინა/ბუენოს_აირესი"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr ""
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr ""
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr ""
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr ""
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr ""
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr ""
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr ""
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+#, fuzzy
+msgid "America/Argentina/Salta"
+msgstr "ამერიკა/არგენტინა/ბუენოს_აირესი"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr ""
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+#, fuzzy
+msgid "America/Argentina/San_Luis"
+msgstr "ამერიკა/არგენტინა/ბუენოს_აირესი"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr ""
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr ""
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr ""
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr ""
+
+#: timezones.h:110
+#, fuzzy
+msgid "America/Atikokan"
+msgstr "ამერიკა/ტიხუანა"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr ""
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr ""
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "ამერიკა/ჰავანა"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr ""
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr ""
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr ""
+
+#: timezones.h:125
+#, fuzzy
+msgid "America/Blanc-Sablon"
+msgstr "ამერიკა/რიო_ბრანკო"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr ""
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "ამერიკა/ბოოტა"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr ""
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "ამერიკა/ბუენოს_აირესი"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr ""
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr ""
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr ""
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr ""
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr ""
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr ""
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "ამერიკა/კაიმანი"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "ამერიკა/ჩიკაგო"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+#, fuzzy
+msgid "Central Time"
+msgstr "აშშ/ცენტრალური"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "ამერიკა/ჩიხუახუა"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr ""
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr ""
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "ამერიკა/კოსტა_რიკა"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr ""
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr ""
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr ""
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr ""
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr ""
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "ამერიკა/დენვერი"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr ""
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "ამერიკა/დეტროიტი"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "ამერიკა/დომინიკა"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "ამერიკა/ედმონტონი"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr ""
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "ამერიკა/ელ_სალვადორი"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr ""
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr ""
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr ""
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr ""
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr ""
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr ""
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr ""
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr ""
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr ""
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr ""
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr ""
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr ""
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr ""
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "ამერიკა/ჰავანა"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr ""
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "ამერიკა/ინდიანა/ინდიანაპოლისი"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr ""
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr ""
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+#, fuzzy
+msgid "America/Indiana/Petersburg"
+msgstr "ამერიკა/ინდიანაპოლისი"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "ამერიკა/ინდიანაპოლისი"
+
+#: timezones.h:227
+#, fuzzy
+msgid "America/Indiana/Tell_City"
+msgstr "ამერიკა/ინდიანაპოლისი"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr ""
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+#, fuzzy
+msgid "America/Indiana/Vincennes"
+msgstr "ამერიკა/ინდიანაპოლისი"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+#, fuzzy
+msgid "America/Indiana/Winamac"
+msgstr "ამერიკა/ინდიანაპოლისი"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr ""
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr ""
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "ამერიკა/იამაიკა"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr ""
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr ""
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "ამერიკა/კენტუკი/ლუიზვილი"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+#, fuzzy
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "ამერიკა/კენტუკი/ლუიზვილი"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr ""
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr ""
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr ""
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr ""
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "ამერიკა/ლოს_ანჯელესი"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr ""
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "ამერიკა/ლუიზვიილ"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr ""
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "ამერიკა/მანაგუა"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr ""
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+#, fuzzy
+msgid "America/Marigot"
+msgstr "ამერიკა/სანტიაგო"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr ""
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "ამერიკა/სანტიაგო"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr ""
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "ამერიკა/მენდოზა"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr ""
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr ""
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "ამერიკა/მეხიკო"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr ""
+
+#: timezones.h:289
+#, fuzzy
+msgid "America/Moncton"
+msgstr "ამერიკა/ედმონტონი"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "ამერიკა/მონტერეი"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "ამერიკა/მონტევიდეო"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "ამერიკა/მონრეალი"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr ""
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr ""
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "ამერიკა/ნიუ_იორკი"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+#, fuzzy
+msgid "Eastern Time"
+msgstr "აშშ/აღმოსავლეთი"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr ""
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr ""
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr ""
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr ""
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "ამერიკა/ჩრდ_დაკოტა/ცენტრი"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+#, fuzzy
+msgid "America/North_Dakota/New_Salem"
+msgstr "ამერიკა/ჩრდ_დაკოტა/ცენტრი"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "ამერიკა/მანაგუა"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "ამერიკა/პანამა"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr ""
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr ""
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "ამერიკა/ფენიქსი"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr ""
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr ""
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr ""
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr ""
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "ამერიკა/პუერტო_რიკო"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr ""
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr ""
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr ""
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr ""
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+#, fuzzy
+msgid "America/Resolute"
+msgstr "ამერიკა/დეტროიტი"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "ამერიკა/რიო_ბრანკო"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr ""
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "ამერიკა/სანტიაგო"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+#, fuzzy
+msgid "America/Santarem"
+msgstr "ამერიკა/სანტიაგო"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "ამერიკა/სანტიაგო"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr ""
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr ""
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr ""
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr ""
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+#, fuzzy
+msgid "America/St_Barthelemy"
+msgstr "ამერიკა/მონრეალი"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr ""
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr ""
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr ""
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr ""
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr ""
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr ""
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr ""
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr ""
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr ""
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "ამერიკა/ტიხუანა"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "ამერიკა/ტორონტო"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr ""
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "ამერიკა/ვანკუვერი"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr ""
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr ""
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr ""
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr ""
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr ""
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr ""
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr ""
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr ""
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr ""
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr ""
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr ""
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr ""
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr ""
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr ""
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr ""
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr ""
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr ""
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr ""
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr ""
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr ""
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr ""
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr ""
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr ""
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr ""
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr ""
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "აზია/ბაღდადი"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "აზია/ბაჰრეინი"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "აზია/ბაქო"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "აზია/ბანგკოკი"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "აზია/ბეირუთი"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "აზია/ბიშკეკი"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "აზია/ბრუნეი"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "აზია/კალკუტა"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr ""
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr ""
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr ""
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr ""
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr ""
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr ""
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr ""
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr ""
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "აზია/დუბაი"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "აზია/დუშანბე"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "აზია/ღაზა"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr ""
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+#, fuzzy
+msgid "Asia/Ho_Chi_Minh"
+msgstr "აზია/ჰონგ_კონგი"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "აზია/ჰონგ_კონგი"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr ""
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "აზია/ირკუტსკი"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "აზია/სტამბული"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "აზია/ჯაკარტა"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr ""
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr ""
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "აზია/ქაბული"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "აზია/კამჩატკა"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "აზია/კარაჩი"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr ""
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+#, fuzzy
+msgid "Asia/Kathmandu"
+msgstr "აზია/კატმანდუ"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "აზია/კატმანდუ"
+
+#: timezones.h:518
+#, fuzzy
+msgid "Asia/Kolkata"
+msgstr "აზია/ჯაკარტა"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "აზია/კრასნოიარსკი"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "აზია/კუალა_ლიმპური"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr ""
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "აზია/კუვეიტი"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr ""
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr ""
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "აზია/მაგადანი"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr ""
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "აზია/მანილა"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr ""
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "აზია/ნიკოსია"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "აზია/ირკუტსკი"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "აზია/ნოვოსიბირსკი"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "აზია/ნოვოსიბირსკი"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+#, fuzzy
+msgid "Moscow+03 - Novosibirsk"
+msgstr "აზია/ნოვოსიბირსკი"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "აზია/ომსკი"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr ""
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr ""
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr ""
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr ""
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr ""
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr ""
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr ""
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr ""
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr ""
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr ""
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr ""
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr ""
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "აზია/სახალინი"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr ""
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr ""
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "აზია/შანხაი"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "აზია/სინგაპური"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr ""
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "აზია/ტაშკენტი"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "აზია/თბილისი"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "აზია/თეირანი"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "აზია/თელ_ავივი"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr ""
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr ""
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "აზია/ტოკიო"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr ""
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr ""
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr ""
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr ""
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr ""
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "აზია/ვლადივოსტოკი"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "აზია/იაკუტსკი"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "აზია/ეკატერინბურგი"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "აზია/ერევანი"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr ""
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr ""
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr ""
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr ""
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr ""
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr ""
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr ""
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr ""
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr ""
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr ""
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr ""
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr ""
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr ""
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr ""
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+#, fuzzy
+msgid "South Australia"
+msgstr "ავსტრალია/დასავლეთი"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr ""
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr ""
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "ავსტრალია/კანბერა"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr ""
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "ავსტრალია/დარვინი"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+#, fuzzy
+msgid "Australia/Eucla"
+msgstr "ავსტრალია/სამხრეთი"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+#, fuzzy
+msgid "Western Australia - Eucla area"
+msgstr "ავსტრალია/სამხრეთი"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr ""
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr ""
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr ""
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr ""
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "ავსტრალია/მელბურნი"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+#, fuzzy
+msgid "Victoria"
+msgstr "ავსტრალია/ვიქტორია"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "ავსტრალია/ჩრდილოეთი"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr ""
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr ""
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr ""
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "ავსტრალია/სამხრეთი"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "ავსტრალია/სიდნეი"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "ავსტრალია/ტასმანია"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "ავსტრალია/ვიქტორია"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "ავსტრალია/დასავლეთი"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr ""
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr ""
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr ""
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "ბრაზილია/აღმოსავლეთი"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "ბრაზილია/დასავლეთი"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr ""
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "კანადა/ცენტრალური"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "კანადა/აღმოსავლეთი"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr ""
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr ""
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "კანადა/ნიუფაუნლენდი"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr ""
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr ""
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr ""
+
+#: timezones.h:685
+msgid "CET"
+msgstr ""
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr ""
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr ""
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr ""
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "კუბა"
+
+#: timezones.h:690
+msgid "EET"
+msgstr ""
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "ეგვიპტე"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr ""
+
+#: timezones.h:693
+msgid "EST"
+msgstr ""
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr ""
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr ""
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr ""
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr ""
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr ""
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr ""
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr ""
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr ""
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr ""
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr ""
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr ""
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr ""
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr ""
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr ""
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr ""
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr ""
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr ""
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr ""
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr ""
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr ""
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr ""
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr ""
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr ""
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr ""
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr ""
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr ""
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr ""
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr ""
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr ""
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr ""
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr ""
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr ""
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr ""
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr ""
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr ""
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr ""
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "ევროპა/ამსტერდამი"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "ევროპა/ანდორა"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "ევრობა/ათენი"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "ევროპა/ბელფასტი"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "ევროპა/ბელგრადი"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "ევროპა/ბერლინი"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "ევროპა/ბრატისლავა"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "ევროპა/ბრუსელი"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr ""
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "ევროპა/ბუდაპეშტი"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr ""
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "ევროპა/კოპენჰაგენი"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "ევროპა/დუბლინი"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "ევროპა/გიბრალტარი"
+
+#: timezones.h:744
+#, fuzzy
+msgid "Europe/Guernsey"
+msgstr "ევრობა/ათენი"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "ევროპა/ჰელსინკი"
+
+#: timezones.h:746
+#, fuzzy
+msgid "Europe/Isle_of_Man"
+msgstr "ევროპა/ოსლო"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "ევროპა/სტამბული"
+
+#: timezones.h:748
+#, fuzzy
+msgid "Europe/Jersey"
+msgstr "ევროპა/პარიზი"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "ევროპა/კალინინგრადი"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "ევროპა/კიევი"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "ევროპა/ლისაბონი"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "ევროპა/ლიუბლიანა"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "ევროპა/ლონდონი"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "ევროპა/ლუქსემბურგი"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "ევროპა/მადრიდი"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "ევროპა/მალტა"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr ""
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "ევროპა/მინსკი"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "ევროპა/მონაკო"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "ევროპა/მოსკოვი"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "ევროპა/ნიკოსია"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "ევროპა/ოსლო"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "ევროპა/პარიზი"
+
+#: timezones.h:774
+#, fuzzy
+msgid "Europe/Podgorica"
+msgstr "ევროპა/ანდორა"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "ევროპა/პრაღა"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "ევროპა/რიგა"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "ევროპა/რომი"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "ევროპა/სამარა"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "ევროპა/სან_მარინო"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "ევროპა/სარაევო"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "ევროპა/სიმფეროპოლი"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr ""
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "ევროპა/სოფია"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "ევროპა/სტოკჰოლმი"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "ევროპა/ტალინი"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr ""
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr ""
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr ""
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr ""
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "ევროპა/პატიკანი"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "ევროპა/ვენა"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "ევროპა/ვილნიუსი"
+
+#: timezones.h:799
+#, fuzzy
+msgid "Europe/Volgograd"
+msgstr "ევროპა/ბელგრადი"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "ევროპა/ვარშავა"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "ევროპა/ზაგრები"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "ევროპა/ზაპოროჟიე"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "ევროპა/ციურიხი"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr ""
+
+#: timezones.h:809
+msgid "GB"
+msgstr ""
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr ""
+
+#: timezones.h:811
+msgid "GMT"
+msgstr ""
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr ""
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr ""
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr ""
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "გრინვიჩი"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "ჰონგკონგი"
+
+#: timezones.h:817
+msgid "HST"
+msgstr ""
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "ისლანდია"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr ""
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr ""
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr ""
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr ""
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr ""
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr ""
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr ""
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr ""
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr ""
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr ""
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr ""
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "ირანი"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "ისრაელი"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "იამაიკა"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "იაპონია"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr ""
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "ლიბია"
+
+#: timezones.h:837
+msgid "MET"
+msgstr ""
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr ""
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr ""
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr ""
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr ""
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr ""
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr ""
+
+#: timezones.h:844
+msgid "MST"
+msgstr ""
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr ""
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr ""
+
+#: timezones.h:847
+msgid "NZ"
+msgstr ""
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr ""
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr ""
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr ""
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr ""
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr ""
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr ""
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr ""
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr ""
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr ""
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr ""
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr ""
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr ""
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr ""
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr ""
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr ""
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr ""
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr ""
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+#, fuzzy
+msgid "Hawaii"
+msgstr "აშშ/ჰავაი"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr ""
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr ""
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr ""
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+#, fuzzy
+msgid "Kosrae"
+msgstr "ისრაელი"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr ""
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr ""
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr ""
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr ""
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr ""
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr ""
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr ""
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr ""
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr ""
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr ""
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr ""
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr ""
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr ""
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr ""
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr ""
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr ""
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr ""
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr ""
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr ""
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr ""
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr ""
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr ""
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr ""
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr ""
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr ""
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "პოლონეთი"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "პორტუგალია"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr ""
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr ""
+
+#: timezones.h:934
+msgid "ROC"
+msgstr ""
+
+#: timezones.h:935
+msgid "ROK"
+msgstr ""
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "სინგაპური"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "თურქეთი"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr ""
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "უნივერსალური"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "აშშ/ალასკა"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr ""
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "აშშ/არიზონა"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "აშშ/ცენტრალური"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "აშშ/აღმოსავლეთი"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "აშშ/აღმ_ინდიანა"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "აშშ/ჰავაი"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr ""
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "აშშ/მიჩიგანი"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr ""
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr ""
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr ""
+
+#: timezones.h:952
+msgid "UTC"
+msgstr ""
+
+#: timezones.h:953
+msgid "WET"
+msgstr ""
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr ""
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "ზულუ"
diff --git a/panels/datetime/po-timezones/kn.po b/panels/datetime/po-timezones/kn.po
new file mode 100644
index 0000000..12d5e8f
--- /dev/null
+++ b/panels/datetime/po-timezones/kn.po
@@ -0,0 +1,3244 @@
+# translation of system-config-date.master-timezones.kn.po to Kannada
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# shankar Prasad <svenkate@redhat.com>, 2006.
+# Shankar Prasad <svenkate@redhat.com>, 2008, 2009, 2010.
+# Savitha, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: system-config-date.master-timezones.kn\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-12-07 10:52+0530\n"
+"Last-Translator: Savitha\n"
+"Language-Team: Kannada <kde-i18n-doc@kde.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: \n"
+"X-Generator: Lokalize 1.1\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"\n"
+"\n"
+"\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "ಆಫ್ರಿಕಾ/ಅಬಿಡ್ಜಾನ್"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "ಆಫ್ರಿಕಾ/ಅಕ್ರಾ"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "ಆಫ್ರಿಕಾ/ಆಡ್ಡಿಸ್_ಆಬಾಬಾ"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "ಆಫ್ರಿಕಾ/ಅಲ್ಗೈರಸ್"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "ಆಫ್ರಿಕಾ/ಅಸ್ಮೆರ"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "ಆಫ್ರಿಕಾ/ಅಸ್ಮೆರ"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "ಆಫ್ರಿಕಾ/ಬಮಾಕೊ"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "ಆಫ್ರಿಕಾ/ಬಾಂಗುಲಿ"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "ಆಫ್ರಿಕಾ/ಬಾಂಜುಲ್"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "ಆಫ್ರಿಕಾ/ಬಿಸ್ಸಾವು"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "ಆಫ್ರಿಕಾ/ಬ್ಲಾನ್ಟೈರ್"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "ಆಫ್ರಿಕಾ/ಬ್ರಝಾವಿಲ್ಲೆ"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "ಆಫ್ರಿಕಾ/ಬುಜುಂಬುರಾ"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "ಆಫ್ರಿಕಾ/ಕೈರೋ"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "ಆಫ್ರಿಕಾ/ಕಸ್ಸಾಬ್ಲಾಂಕಾ"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "ಆಫ್ರಿಕಾ/ಸಿಯೂಟಾ"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "ಸಿಯುಟಾ ಹಾಗು ಮೆಲಿಲಾ"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "ಆಫ್ರಿಕಾ/ಕೊನಾಕ್ರಿ"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "ಆಫ್ರಿಕಾ/ದಕಾರ್"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "ಆಫ್ರಿಕಾ/ದರ್_ಎ_ಸಲಾಮ್"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "ಆಫ್ರಿಕಾ/ಜಿಬೌಟಿ"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "ಆಫ್ರಿಕಾ/ಡೌಆಲಾ"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "ಆಫ್ರಿಕಾ/ಎಲ್_ಆಯುನ್"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "ಆಫ್ರಿಕಾ/ಫ್ರೀಟೌನ್"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "ಆಫ್ರಿಕಾ/ಗ್ಯಬೊರೊನೆ"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "ಆಫ್ರಿಕಾ/ಹರಾರೆ"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "ಆಫ್ರಿಕಾ/ಜೊಹಾನ್ಸ್ ಬರ್ಗ್"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "ಆಫ್ರಿಕಾ/ಕಂಪಾಲಾ"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "ಆಫ್ರಿಕಾ/ಖರ್ಟೌಮ್"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "ಆಫ್ರಿಕಾ/ಕಿಗಲಿ"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "ಆಫ್ರಿಕಾ/ಕಿನ್ಸಾಸ"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "ಪಶ್ಚಿಮ ಡೆಮೊ. ರಿಪ. ಆಫ್ ಕಾಂಗೊ"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "ಆಫ್ರಿಕಾ/ಲಗೋಸ್"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "ಆಫ್ರಿಕಾ/ಲಿಬ್ರೆವಿಲ್ಲೆ"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "ಆಫ್ರಿಕಾ/ಲೋಮ್"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "ಆಫ್ರಿಕಾ/ಲುವಾಂಡ"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "ಆಫ್ರಿಕಾ/ಲುಬುಂಬಾಶಿ"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "ಪೂರ್ವ ಡೆಮೊ. ರಿಪ. ಆಫ್ ಕಾಂಗೊ"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "ಆಫ್ರಿಕಾ/ಲುಸಾಕ"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "ಆಫ್ರಿಕಾ/ಮಲಾಬೊ"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "ಆಫ್ರಿಕಾ/ಮಪುಟೋ"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "ಆಫ್ರಿಕಾ/ಮಸೆರು"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "ಆಫ್ರಿಕಾ/ಬಬಾನೆ"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "ಆಫ್ರಿಕಾ/ಮೊಗಾದಿಶು"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "ಆಫ್ರಿಕಾ/ಮೊನ್ರೊವಿಯಾ"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "ಆಫ್ರಿಕಾ/ನೈರೋಬಿ"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "ಆಫ್ರಿಕಾ/ಜಮಿನಾ"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "ಆಫ್ರಿಕಾ/ನೈಮೆ"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "ಆಫ್ರಿಕಾ/ನೌಕ್ಚಾಟ್"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "ಆಫ್ರಿಕಾ/ಒಗಾದೊಗೊ"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "ಆಫ್ರಿಕಾ/ಪೋರ್ಟೊ-ನೊವೊ"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "ಆಫ್ರಿಕಾ/ಸಾವೊ-ಟೋಮೋ"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "ಆಫ್ರಿಕಾ/ಟಿಂಬುಕ್ತು"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "ಆಫ್ರಿಕಾ/ಟ್ರಿಪೋಲಿ"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "ಆಫ್ರಿಕಾ/ಟ್ಯುನಿಸ್"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "ಆಫ್ರಿಕಾ/ವಿಂದೊಎಕ್"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "ಅಮೆರಿಕ/ಅಡಾಕ್"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "ಅಲೂಶೀಯನ್ ದ್ವೀಪಗಳು"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "ಅಮೆರಿಕ/ಆಂಖೊರೇಜ್"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "ಅಲಸ್ಕಾ ಸಮಯ"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "ಅಮೆರಿಕ/ಅಂಗಿಲ್ಲಾ"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "ಅಮೆರಿಕ/ಆಂಟಿಗ್ಯುವಾ"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "ಅಮೆರಿಕ/ಅರ್ಗುಯಾನಾ"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "ಟೊಕಾಂಟಿನ್ಸ್"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "ಅಮೆರಿಕ/ಅರ್ಜೆಂಟೀನಾ/ಬ್ಯುನೋಸ್_ಏರೀಸ್"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "ಬ್ಯೂನೋಸ್ ಏರಿಸ್ (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "ಅಮೆರಿಕ/ಅರ್ಜೆಂಟೀನಾ/ಕ್ಯಾಟಮಾರ್ಕಾ"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "ಕಟಾಮಾರ್ಕಾ (CT), ಶುಬುಟ್ (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "ಅಮೆರಿಕ/ಅರ್ಜೆಂಟೀನಾ/ಕೊಮೊಡ್ ರಿವಾಡಾವಿಯಾ"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "ಅಮೆರಿಕ/ಅರ್ಜೆಂಟೀನಾ/ಕೊರ್ಡೋಬಾ"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "ಹೆಚ್ಚಿನ ಸ್ಥಳಗಳು (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "ಅಮೆರಿಕ/ಅರ್ಜೆಂಟೀನಾ/ಜುಜುಯ್"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "ಜುಜುಯ್ (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "ಅಮೆರಿಕ/ಅರ್ಜೆಂಟೀನಾ/ಲಾ_ರಿಯೋಜಾ"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "ಲಾ ರಿಯೋಜ (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "ಅಮೆರಿಕ/ಅರ್ಜೆಂಟೀನಾ/ಮೆಂಡೋಝಾ"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "ಮೆಂಡೋಝಾ (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "ಅಮೆರಿಕ/ಅರ್ಜೆಂಟೀನಾ/ರಿಯೋ_ಗೆಲ್ಲಾಗೊಸ್"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "ಸಾಂಟಾ ಕ್ರೂಝ್ (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "ಅಮೆರಿಕಾ/ಅರ್ಜೆಂಟೀನಾ/ಸಾಲ್ಟಾ"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "ಅಮೆರಿಕ/ಅರ್ಜೆಂಟೀನಾ/ಸಾನ್_ಜುವಾನ್"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "ಸ್ಯಾನ್ ಜುವಾನ್ (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "ಅಮೆರಿಕ/ಅರ್ಜೆಂಟೀನಾ/ಸಾನ್_ಲೂಯಿಸ್"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "ಸ್ಯಾನ್ ಲೂಯಿಸ್ (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "ಅಮೆರಿಕ/ಅರ್ಜೆಂಟೀನಾ/ಟುಕುಮಾನ್"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "ಟುಕುಮಾನ್ (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "ಅಮೆರಿಕ/ಅರ್ಜೆಂಟೀನಾ/ಉಶುಯಾಯಿ"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "ಟಿಯೆರಾ ಡೆಲ್ ಫ್ಯೂಗೊ (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "ಅಮೆರಿಕ/ಅರುಬಾ"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "ಅಮೆರಿಕ/ಅಸಂಕಿಯಾನ್"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "ಅಮೆರಿಕ/ಅಟಿಕೋಕನ್"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "ಪೂರ್ವ ಶಿಷ್ಟ ಸಮಯ - ಅಟಿಕೊಕನ್, ಒಂಟಾರಿಯೊ ಹಾಗು ಸೌತ್‌ಹ್ಯಾಂಪ್ಟನ್ ಐ, ನುನಾವುಟ್"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "ಅಮೆರಿಕ/ಅಟ್ಕಾ"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "ಅಮೆರಿಕ/ಬಹಿಯಾ"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "ಬಹಿಯಾ"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "ಅಮೆರಿಕ/ಬಹಿಯಾ_ಬಂಡೆರಾಸ್"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "ಮೆಕ್ಸಿಕನ್ ಮಧ್ಯ ಸಮಯ - ಬಹಿಯಾ ಡಿ ಬಂಡೆರಾಸ್"
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "ಅಮೆರಿಕ/ಬಾರ್ಬಡೋಸ್"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "ಅಮೆರಿಕ/ಬೆಲೆಮ್"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "ಅಮಾಪ, ಇ ಪಾರಾ"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "ಅಮೆರಿಕ/ಬೆಲೈಝ್"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "ಅಮೆರಿಕ/ಬ್ಲಾಂಕ್-ಸಾಬ್ಲೋನ್"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "ಅಟ್ಲಾಂಟಿಕ್ ಶಿಷ್ಟ ಸಮಯ - ಕ್ಯೂಬೆಕ್ - ಕೆಳ ಉತ್ತರ ತೀರ"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "ಅಮೆರಿಕ/ಬೊವ_ವಿಸ್ಟಾ"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "ರೊರೈಮಾ"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "ಅಮೆರಿಕ/ಬೊಗೊಟಾ"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "ಅಮೆರಿಕ/ಬೊಯ್ಸೆ"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "ಪರ್ವತ ಸಮಯ - ದಕ್ಷಿಣ ಇದಾಹೊ ಹಾಗು ಪೂರ್ವ ಒರೆಗಾನ್"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "ಅಮೆರಿಕ/ಬ್ಯೂನೋಸ್_ಏರಿಸ್"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "ಅಮೆರಿಕ/ಕೇಂಬ್ರಿಡ್ಜ್_ಬೇ"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "ಪರ್ವತ ಸಮಯ - ಪಶ್ಚಿಮ ನುನಾವುಟ್"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "ಅಮೆರಿಕ/ಕಾಂಪೋ_ಗ್ರಾಂಡೆ"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "ಮಾಟೊ ಗ್ರಾಸೊ ಡು ಸುಲ್"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "ಅಮೆರಿಕ/ಕ್ಯಾನ್ಕನ್"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "ಮಧ್ಯ ಸಮಯ - ಕ್ವಿಂಟಾನ ರೂ"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "ಅಮೆರಿಕ/ಕ್ಯಾರಾಕಾಸ್"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "ಅಮೆರಿಕ/ಕಟಾಮಾರ್ಕಾ"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "ಅಮೆರಿಕ/ಕಯೆನ್ನೆ"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "ಅಮೆರಿಕ/ಕಯ್ಮಾನ್"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "ಅಮೆರಿಕ/ಚಿಕಾಗೊ"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "ಮಧ್ಯ ಸಮಯ"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "ಅಮೆರಿಕ/ಚಿಹುವಾ"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "ಮೆಕ್ಸಿಕನ್ ಪರ್ವತ ಸಮಯ - ಯುಎಸ್ ಗಡಿಯ ಇನ್ನೊಂದು ಬದಿಯ ಚಿಹುವಾಹುವ"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "ಅಮೆರಿಕ/ಕೋರಲ್_ಹಾರ್ಬರ್"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "ಅಮೆರಿಕ/ಕಾರ್ಡೋಬಾ"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "ಅಮೆರಿಕ/ಕೋಸ್ಟಾ_ರಿಕಾ"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "ಅಮೆರಿಕ/ಕ್ಯುವಾಬಾ"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "ಮಟೊ ಗ್ರಾಸೊ"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "ಅಮೆರಿಕ/ಕ್ಯುರಾಕಾವ್"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "ಅಮೆರಿಕ/ಡನ್ಮಾರ್ಕಶಾವ್ನ"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "ಪೂರ್ವ ತೀರ, ಸ್ಕೋರ್ಸ್-ಬಿಸಂಡ್‌ನ ಉತ್ತರ"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "ಅಮೆರಿಕ/ಡಾವ್ಸನ್"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "ಪೆಸಿಫಿಕ್ ಸಮಯ - ಉತ್ತರ ಯುಕೊನ್"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "ಅಮೆರಿಕ/ಡಾವ್ಸನ್_ಕ್ರೀಕ್"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid "Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr "ಪರ್ವತ ಶಿಷ್ಟ ಸಮಯ - ಡಾಸನ್ ಕ್ರೀಕ್ ಹಾಗು ಫೋರ್ಟ್ ಸೇಂಟ್ ಜಾನ್, ಬ್ರಿಟೀಷ್ ಕೊಲಂಬಿಯಾ"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "ಅಮೆರಿಕ/ಡೆನ್ವೆರ್"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "ಪರ್ವತ ಸಮಯ"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "ಅಮೆರಿಕ/ಡೆಟ್ರಾಯಿಟ್"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "ಪೂರ್ವ ಸಮಯ - ಮಿಶಿಗನ್ - ಹೆಚ್ಚಿನ ಸಮಯಗಳು"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "ಅಮೆರಿಕ/ಡೊಮಿನಿಕಾ"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "ಅಮೆರಿಕ/ಎಡ್ಮೊಂಟನ್"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "ಪರ್ವತ ಸಮಯ - ಅಲ್ಬೆರ್ಟಾ, ಪೂರ್ವ ಬ್ರಿಟೀಷ್ ಕೊಲಂಬಿಯಾ ಹಾಗು ಪಶ್ಚಿಮ ಸಸ್ಕಾಶೆವಾನ್"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "ಅಮೆರಿಕ/ಐರುನೆಪೆ"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "ಪ ಅಮೆಝೊನಾಸ್"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "ಅಮೆರಿಕ/ಎಲ್_ಸಾಲ್ವೆಡಾರ್"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "ಅಮೆರಿಕ/ಎನ್ಸೆನಡಾ"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "ಅಮೆರಿಕ/ಫೊರ್ಟಾಲೆಝಾ"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "NE ಬ್ರಝಿಲ್ (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "ಅಮೆರಿಕ/ಫೋರ್ಟ್_ವಯ್ನೆ"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "ಅಮೆರಿಕ/ಗ್ಲೇಸ್_ಬೇ"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr "ಅಟ್ಲಾಂಟಿಕ್ ಸಮಯ - ನೋವಾ ಸ್ಕೋಟಿಯ - DST 1966-1971 ಯಲ್ಲಿ ಕಂಡುಬರದೆ ಇರುವ ಸ್ಥಳಗಳು"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "ಅಮೆರಿಕ/ಗೊಡ್ತಾಬ್"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "ಹೆಚ್ಚಿನ ಸ್ಥಳಗಳು"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "ಅಮೆರಿಕ/ಗೂಸ್_ಬೇ"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "ಅಟ್ಲಾಂಟಿಕ್ ಸಮಯ - ಲ್ಯಾಬ್ರೊಡಾರ್ - ಹೆಚ್ಚಿನ ಸ್ಥಳಗಳು"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "ಅಮೆರಿಕ/ಗ್ರಾಂಡ್_ಟರ್ಕ್"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "ಅಮೆರಿಕ/ಗ್ರೆನಡಾ"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "ಅಮೆರಿಕ/ಗುಯಾಡೆಲೌಪ್"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "ಅಮೆರಿಕ/ಗ್ವಾಟೆಮಾಲಾ"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "ಅಮೆರಿಕ/ಗಯಾಕಿಲ್"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "ಮೈನ್‌ಲ್ಯಾಂಡ್"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "ಅಮೆರಿಕ/ಗಯಾನಾ"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "ಅಮೆರಿಕ/ಹ್ಯಾಲಿಫಾಕ್ಸ್"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "ಅಟ್ಲಾಂಟಿಕ್ ಸಮಯ - ನೋವಾ ಸ್ಕಾಟಿಯ (ಹೆಚ್ಚಿನ ಸ್ಥಳಗಳು), PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "ಅಮೆರಿಕ/ಹವಾನಾ"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "ಅಮೆರಿಕ/ಹರ್ಮೆಸಿಲ್ಲೊ"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "ಪರ್ವತ ಶಿಷ್ಟ ಸಮಯ - ಸೊನೊರಾ"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "ಅಮೆರಿಕ/ಇಂಡಿಯಾನಾ/ಇಂಡಿಯಾನಾಪೊಲಿಸ್"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "ಪೂರ್ವ ಸಮಯ - ಇಂಡಿಯಾನ - ಹೆಚ್ಚಿನ ಸ್ಥಳಗಳು"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "ಅಮೆರಿಕ/ಇಂಡಿಯಾನಾ/ನಾಕ್ಸ್"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "ಮಧ್ಯ ಸಮಯ - ಇಂಡಿಯಾನ - ಸ್ಟಾರ್ಕ್ ಕೌಂಟಿ"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "ಅಮೆರಿಕ/ಇಂಡಿಯಾನಾ/ಮರೆಂಗೊ"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "ಪೂರ್ವ ಸಮಯ - ಇಂಡಿಯಾನ - ಕ್ರಾಫೋರ್ಡ್ ಕೌಂಟಿ"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "ಅಮೆರಿಕ/ಇಂಡಿಯಾನಾ/ಪೀಟರ್ಸ್ ಬರ್ಗ್"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "ಪೂರ್ವ ಸಮಯ - ಇಂಡಿಯಾನ - ಪೈಕ್ ಕೌಂಟಿ"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "ಅಮೆರಿಕ/ಇಂಡಿಯಾನಾಪೊಲಿಸ್"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "ಅಮೆರಿಕ/ಇಂಡಿಯಾನಾ/ಟೆಲ್_ಸಿಟಿ"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "ಮಧ್ಯ ಸಮಯ - ಇಂಡಿಯಾನ - ಪೆರಿ ಕೌಂಟಿ"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "ಅಮೆರಿಕ/ಇಂಡಿಯಾನಾ/ವೆವೆ"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "ಪೂರ್ವ ಸಮಯ - ಇಂಡಿಯಾನ - ಸ್ವಿಟ್ಜರ್ಲ್ಯಾಂಡ್ ಕೌಂಟಿ"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "ಅಮೆರಿಕ/ಇಂಡಿಯಾನಾ/ವಿನ್ಸೆನ್ನೆಸ್"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "ಪೂರ್ವ ಸಮಯ - ಇಂಡಿಯಾನ - ಡೇವಿಯಸ್, ಡುಬೊಯಿಸ್, ನಾಕ್ಸ್ ಹಾಗು ಮಾರ್ಟಿನ್ ಕೌಂಟಿಗಳು"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "ಅಮೆರಿಕ/ಇಂಡಿಯಾನಾ/ವಿನಾಮ್ಯಾಕ್"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "ಪೂರ್ವ ಸಮಯ - ಇಂಡಿಯಾನ - ಪುಲಾಸ್ಕಿ ಕೌಂಟಿ"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "ಅಮೆರಿಕ/ಇನುವಿಕ್"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "ಪರ್ವತ ಸಮಯ - ಪಶ್ಚಿಮ ಉತ್ತರಪಶ್ಚಿಮ ಟೆರಿಟರಿಗಳು"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "ಅಮೆರಿಕ/ಇಕ್ವಾಲಿಟ್"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "ಪೂರ್ವ ಸಮಯ - ಪೂರ್ವ ನುನಾವುಟ್ - ಹೆಚ್ಚಿನ ಸ್ಥಳಗಳು"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "ಅಮೆರಿಕ/ಜಮೈಕಾ"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "ಅಮೆರಿಕ/ಜುಜುಯ್"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "ಅಮೆರಿಕ/ಜುನೆಯಾ"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "ಅಲಾಸ್ಕಾ ಸಮಯ - ಅಲಾಸ್ಕಾ ಪ್ಯಾನ್‌ಹ್ಯಾಂಡಲ್"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "ಅಮೆರಿಕ/ಕೆಂಟುಕಿ/ಲೌಸ್ವಿಲ್ಲೆ"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "ಪೂರ್ವ ಸಮಯ - ಕೆಂಟುಕಿ - ಲೌಸ್ವಿಲ್ಲೆ ಪ್ರದೇಶ"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "ಅಮೆರಿಕ/ಕೆಂಟುಕಿ/ಮೊಂಟಿಸಿಲ್ಲೊ"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "ಪೂರ್ವ ಸಮಯ - ಕೆಂಟುಕಿ ವಯ್ನೆ ಕೌಂಟಿ"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "ಅಮೆರಿಕ/ಕ್ನೊಕ್ಸ್_ಇನ್"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "ಅಮೆರಿಕ/ಲಾ_ಪಾಝ್"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "ಅಮೆರಿಕ/ಲಿಮಾ"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "ಅಮೆರಿಕ/ಲಾಸ್_ಎಂಜೆಲೀಸ್"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "ಫೆಸಿಫಿಕ್ ಸಮಯ"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "ಅಮೆರಿಕ/ಲೌಸ್ವಿಲ್ಲೆ"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "ಅಮೆರಿಕ/ಮ್ಯಾಸಿಯೊ"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "ಅಲಗೋಸ್, ಸರ್ಗೀಪ್"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "ಅಮೆರಿಕ/ಮನಾಗುವಾ"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "ಅಮೆರಿಕ/ಮನಾವುಸ್"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "ಪೂ ಅಮೆಝೋನಾಸ್"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "ಅಮೆರಿಕ/ಮ್ಯಾರಿಗಾಟ್"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "ಅಮೆರಿಕ/ಮಾರ್ಟಿನಿಕ್ಯು"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "ಅಮೆರಿಕ/ಮಟಾಮೊರೊಸ್"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid "US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr "ಯುಎಸ್ ಮಧ್ಯ ಸಮಯ - ಯುಎಸ್ ಗಡಿಯ ಸಮೀಪದ ಕೊಹುಯಿಲಾ, ಡುರಾಂಗೊ, ನ್ಯುವೊ ಲಿಯೋನ್, ಟಮೌಲಿಪಾಸ್"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "ಅಮೆರಿಕ/ಮಝಾಟ್ಲಾನ್"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "ಪರ್ವತ ಸಮಯ - S ಬಾಜಾ, ನಯಾರಿಟ್, ಸಿನಾಲೊವಾ"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "ಅಮೆರಿಕ/ಮೆಂಡೊಝಾ"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "ಅಮೆರಿಕ/ಮೆನೋಮಿನೀ"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "ಮಧ್ಯ ಸಮಯ - ಮಿಶಿಗನ್, ಡಿಕಿನ್ಸನ್, ಗೊಗೆಬಿಕ್, ಐರನ್ ಹಾಗು ಮೆನೊಮಿನೀ ಕೌಂಟೀಸ್"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "ಅಮೆರಿಕ/ಮೆರಿಡಾ"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "ಮಧ್ಯ ಸಮಯ - ಕಂಪಾಚೆ, ಯುಕಾಟನ್"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "ಅಮೆರಿಕ/ಮೆಕ್ಸಿಕೊ_ಸಿಟಿ"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "ಮಧ್ಯ ಸಮಯ - ಹೆಚ್ಚಿನ ಸ್ಥಳಗಳು"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "ಅಮೆರಿಕ/ಮಿಕ್ಯುಲಾನ್"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "ಅಮೆರಿಕ/ಮಾಕ್ಟನ್"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "ಅಟ್ಲಾಂಟಿಕ್ ಸಮಯ - ನ್ಯೂ ಬ್ರುನ್ಸ್‌ವಿಕ್"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "ಅಮೆರಿಕ/ಮೊಂಟೆರ್ರಿ"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+"ಮೆಕ್ಸಿಕನ್ ಮಧ್ಯ ಸಮಯ - ಯುಎಸ್ ಗಡಿಯ ಇನ್ನೊಂದು ಬದಿಯ ಕೊಹುಯಿಲಾ, ಡುರಾಂಗೊ, ನ್ಯುವೊ ಲಿಯೋನ್, "
+"ಟಮೌಲಿಪಾಸ್"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "ಅಮೆರಿಕ/ಮೊಂನ್ಟೆವಿಡಿಯೊ"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "ಅಮೆರಿಕ/ಮೊಂಟ್ರೀಲ್"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "ಪೂರ್ವ ಸಮಯ - ಕ್ಯೂಬೆಕ್ - ಹೆಚ್ಚಿನ ಸ್ಥಳಗಳು"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "ಅಮೆರಿಕ/ಮೊಂಟ್ಸೆರ್ರಾಟ್ಸ್"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "ಅಮೆರಿಕ/ನಸ್ಸಾವು"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "ಅಮೆರಿಕ/ನ್ಯೂ_ಯೋರ್ಕ್"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "ಪೂರ್ವ ಸಮಯ"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "ಅಮೆರಿಕ/ನಿಪಿಗೋನ್"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid "Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr "ಪೂರ್ವ ಸಮಯ - ಒಂಟಾರಿಯೊ ಹಾಗು ಕ್ಯೂಬೆಕ್ - DST 1967-1973 ಯಲ್ಲಿ ಕಾಣಿಸದೆ ಇರುವ"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "ಅಮೆರಿಕ/ನೋಮ್"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "ಅಲಸ್ಕಾ ಸಮಯ - ಪಶ್ಚಿಮ ಅಲಸ್ಕಾ"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "ಅಮೆರಿಕ/ನೊರೊನ್ಹಾ"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "ಅಟ್ಲಾಂಟಿಕ್ ದ್ವೀಪಗಳು"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "ಅಮೆರಿಕ/ಉತ್ತರ_ಡಕೋಟ/ಮಧ್ಯ"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "ಮಧ್ಯ ಸಮಯ - ಉತ್ತರ ಡಕೊಟ - ಒಲಿವರ್ ಕೌಂಟಿ"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "ಅಮೆರಿಕ/ಉತ್ತರ_ಡಕೋಟ/ನ್ಯೂ_ಸಲೆಮ್"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "ಮಧ್ಯ ಸಮಯ - ದಕ್ಷಿಣ ಡಕೋಟ - ಮಾರ್ಟನ್ ಕೌಂಟಿ (ಮಂಡಾನ್ ಕ್ಷೇತ್ರವನ್ನು ಹೊರತುಪಡಿಸಿ)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "ಅಮೆರಿಕ/ಒಜಿನಾಗ"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "ಯುಎಸ್ ಪರ್ವತ ಸಮಯ - ಯುಎಸ್ ಗಡಿಯ ಸಮೀಪದ ಚಿಹುವಾಹುವ"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "ಅಮೆರಿಕ/ಪನಾಮ"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "ಅಮೆರಿಕ/ಪಂಗ್ನಿರ್ಟಂಗ್"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "ಪೂರ್ವ ಸಮಯ -ಪಂಗ್ನಿರ್ಟುಂಗ್, ನುನಾವುಟ್"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "ಅಮೆರಿಕ/ಪರಮಾರಿಬೊ"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "ಅಮೆರಿಕ/ಫೀನಿಕ್ಸ್"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "ಪರ್ವತ ಶಿಷ್ಟ ಸಮಯ - ಅರಿಝೋನ"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "ಅಮೆರಿಕ/ಪೋರ್ಟ್-ಅವ್-ಪ್ರಿನ್ಸ್"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "ಅಮೆರಿಕ/ಪೋರ್ಟೋ_ಏಕ್ರ್"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "ಅಮೆರಿಕ/ಪೋರ್ಟ್_ಆಫ್_ಸ್ಪೈನ್"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "ಅಮೆರಿಕ/ಪೋರ್ಟೋ_ವೆಲ್ಹೋ"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "ರೊಂಡೊನಿಯ"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "ಅಮೆರಿಕ/ಪೊರ್ಟೊ_ರಿಕೊ"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "ಅಮೆರಿಕ/ರೈನಿ_ರಿವರ್"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "ಮಧ್ಯ ಸಮಯ - ರೈನಿ ರಿವರ್ ಹಾಗು ಫೋರ್ಟ್ ಫ್ರಾನ್ಸ್, ಒಂಟಾರಿಯೊ"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "ಅಮೆರಿಕ/ರ್ಯಾಂಕಿನ್_ಇನ್ಲೆಟ್"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "ಮಧ್ಯ ಸಮಯ - ಮಧ್ಯ ನುನಾವುಟ್"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "ಅಮೆರಿಕ/ರೆಸಿಫೈ"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "ಪರ್ನ್ಯಾಂಬುಕೊ"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "ಅಮೆರಿಕ/ರೆಗಿನಾ"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "ಮಧ್ಯ ಶಿಷ್ಟ ಸಮಯ - ಸಸ್ಕಾಶೆವಾನ್ - ಹೆಚ್ಚಿನ ಸ್ಥಳಗಳು"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "ಅಮೆರಿಕ/ರೆಸಲ್ಯೂಟ್"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "ಪೂರ್ವ ಶಿಷ್ಟ ಸಮಯ - ರೆಸೊಲ್ಯೂಟ್, ನುನಾವುಟ್"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "ಅಮೆರಿಕ/ರಿಯೋ_ಬ್ರಾಂಕೋ"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "ಏಕರ್"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "ಅಮೆರಿಕ/ರೊಸಾರಿಯೋ"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "ಅಮೆರಿಕ/ಸ್ಯಾಂಟಾ_ಇಸಾಬೆಲ್"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "ಮೆಕ್ಸಿಕನ್ ಪೆಸಿಫಿಕ್ ಸಮಯ - ಯುಎಸ್ ಗಡಿಯ ಇನ್ನೊಂದು ಬದಿಯ ಬಾಜಾ ಕ್ಯಾಲಿಫೋರ್ನಿಯಾ"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "ಅಮೆರಿಕ/ಸ್ಯಾಂಟರೆಮ್"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "ಪ ಪಾರಾ"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "ಅಮೆರಿಕ/ಸ್ಯಾಂಟಿಗೋ"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "ಅಮೆರಿಕ/ಸ್ಯಾಂಟೊ_ಡೊಮಿಂಗೊ"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "ಅಮೆರಿಕ/ಸಾವೊ_ಪೌಲೊ"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "S & SE ಬ್ರಝಿಲ್ (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "ಅಮೆರಿಕ/ಸ್ಕೋರ್ಸ್ಬೈಸಂಡ್"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "ಸ್ಕೋರ್ಸ್-ಬಿಸಂಡ್‌ / ಇಟಿಕೊರ್ಟೂರ್ಮಿಟ್"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "ಅಮೆರಿಕ/ಶಿಪ್ರಾಕ್"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "ಪರ್ವತ ಸಮಯ - ನವಾಜೊ"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "ಅಮೆರಿಕ/ಸೈಂಟ್_ಬಾರ್ತಲ್ಮಿ"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "ಅಮೆರಿಕ/ಸೈಂಟ್_ಜಾನ್ಸ್"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "ನ್ಯೂಫೌಂಡ್‌ಲ್ಯಾಂಡ್‌ ಸಮಯ, SE ಲ್ಯಾಬ್ರಡಾರ್ ಅನ್ನೂ ಸಹ ಸೇರಿ"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "ಅಮೆರಿಕ/ಸೈಂಟ್_ಕಿಟ್ಸ್"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "ಅಮೆರಿಕ/ಸೈಂಟ್_ಲೂಸಿಯಾ"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "ಅಮೆರಿಕ/ಸೈಂಟ್_ಥಾಮಸ್"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "ಅಮೆರಿಕ/ಸೈಂಟ್_ವಿನ್ಸೆಂಟ್"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "ಅಮೆರಿಕ/ಸ್ವಿಫ್ಟ್_ಕರೆಂಟ್"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "ಮಧ್ಯ ಶಿಷ್ಟ ಸಮಯ - ಸಸ್ಕಾಶೆವಾನ್ - ಮಧ್ಯಪೂರ್ವ"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "ಅಮೆರಿಕ/ಟೆಗುಸಿಗಲಾಪ"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "ಅಮೆರಿಕ/ಥುಲೆ"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "ತುಲೆ / ಪಿಟ್‌ಫಿಕ್"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "ಅಮೆರಿಕ/ಥಂಡರ್_ಬೇ"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "ಪೂರ್ವ ಸಮಯ - ತಂಡರ್ ಬೇ, ಒಂಟಾರಿಯೊ"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "ಅಮೆರಿಕ/ಟಿಜುಯಾನ"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "ಯುಎಸ್ ಪೆಸಿಫಿಕ್ ಸಮಯ - ಯುಎಸ್ ಗಡಿಯ ಹತ್ತಿರದ ಬಾಜಾ ಕ್ಯಾಲಿಫೋರ್ನಿಯಾ"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "ಅಮೆರಿಕ/ಟೊರೆಂಟೊ"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "ಪೂರ್ವ ಸಮಯ - ಒಂಟಾರಿಯೊ - ಹೆಚ್ಚಿನ ಸ್ಥಳಗಳು"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "ಅಮೆರಿಕ/ಟೊರ್ಟೋಲ"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "ಅಮೆರಿಕ/ವ್ಯಾಂಕೊವೆರ್"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "ಪೆಸಿಫಿಕ್ ಸಮಯ - ಪಶ್ಚಿಮ ಬ್ರಿಟೀಷ್ ಕೊಲಂಬಿಯಾ"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "ಅಮೆರಿಕ/ವರ್ಜಿನ್"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "ಅಮೆರಿಕ/ವೈಟ್ ಹಾರ್ಸ್"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "ಪೆಸಿಫಿಕ್ ಸಮಯ - ದಕ್ಷಿಣ ಯುಕೊನ್"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "ಅಮೆರಿಕ/ವಿನ್ನಿಪೆಗ್"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "ಮಧ್ಯ ಸಮಯ - ಮಾನಿಟೋಬಾ ಹಾಗು ಪಶ್ಚಿಮ ಒಂಟಾರಿಯೊ"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "ಅಮೆರಿಕ/ಯಕುಟಾಟ್"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "ಅಲಸ್ಕಾ ಸಮಯ - ಅಲಸ್ಕಾ ಪ್ಯಾನ್‌ಹ್ಯಾಂಡಲ್ ನೆಕ್"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "ಅಮೆರಿಕ/ಯೆಲ್ಲೊನೈಫ್"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "ಪರ್ವತ ಸಮಯ - ಮಧ್ಯ ಉತ್ತರಪೂರ್ವ ಪ್ರದೇಶಗಳು"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "ಅಂಟಾರ್ಟಿಕ/ಕ್ಯಾಸೆ"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "ಕೇಸಿ ಸ್ಟೇಶನ್, ಬೇಲಿ ಪೆನಿನ್ಸುಲಾ"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "ಅಂಟಾರ್ಟಿಕ/ಡೇವಿಸ್"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "ಡೇವಿಸ್ ಸ್ಟೇಶನ್, ವೆಸ್ಟ್‌ಫೋಲ್ಡ್ ಹಿಲ್ಸ್"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "ಅಂಟಾರ್ಟಿಕ/ಡುಮೊಂಟ್ ಡಿ ಉರ್ವಿಲ್ಲೆ"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "ಡುಮೊಂಟ್, ಡಿ ಉರ್ವಿಲ್ ಸ್ಟೇಶನ್, ಟೆರಿ ಅಡಿಲಿ"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "ಅಂಟಾರ್ಟಿಕ/ಮಕ್ವಾರಿ"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "ಮಕ್ವಾರಿ ಐಲ್ಯಾಂಡ್ ಸ್ಟೇಶನ್, ಮಕ್ವಾರಿ ದ್ವೀಪ"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "ಅಂಟಾರ್ಟಿಕ/ಮಾವ್ಸಾನ್"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "ಮಾಸನ್ ಸ್ಟೇಶನ್, ಹೊಮ್ ಬೇ"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "ಅಂಟಾರ್ಟಿಕ/ಮ್ಯಾಕ್‌ಮುರ್ಡೊ"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "ಮ್ಯಾಕ್‌ಮುರ್ಡೊ ಸ್ಟೇಶನ್, ರಾಸ್ ದ್ವೀಪ"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "ಅಂಟಾರ್ಟಿಕ/ಪಾಮರ್"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "ಪಾಮರ್ ಸ್ಟೇಶನ್, ಆನ್ವರ್ಸ್ ದ್ವೀಪ"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "ಅಂಟಾರ್ಟಿಕ/ರೊಥೆರಾ"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "ರೊತೇರಾ ಸ್ಟೇಶನ್, ಅಡಿಲೇಡ್ ದ್ವೀಪ"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "ಅಂಟಾರ್ಟಿಕಾ/ದಕ್ಷಿಣ_ಧ್ರುವ"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "ಅಮುಂಡ್ಸನ್-ಸ್ಕಾಟ್ ಸ್ಟೇಶನ್, ದಕ್ಷಿಣ ಧ್ರುವ"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "ಅಂಟಾರ್ಟಿಕ/ಸ್ಯೋವಾ"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "ಸಿಯೋವಾ ಸ್ಟೇಶನ್, ಇ ಒಂಗುಲ್ ಐ"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "ಅಂಟಾರ್ಟಿಕ/ವೋಸ್ಟೋಕ್"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "ವೊಸ್ಟೊಕ್ ಸ್ಟೇಶನ್, S ಮ್ಯಾಗ್ನೆಟಿಕ್ ಪೋಲ್"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "ಆರ್ಕಟಿಕ್/ಲಾಂಗ್ಯಿರ್ ಬ್ಯೆನ್"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "ಏಷಿಯ/ಆಡೆನ್"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "ಏಷಿಯ/ಆಲ್ಮೆಟಿ"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "ಏಷಿಯ/ಅಮ್ಮಾನ್"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "ಏಷಿಯ/ಅನಾಡೈರ್"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "ಮಾಸ್ಕೊ+08 - ಬೆರಿಂಗ್ ಸಮುದ್ರ"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "ಏಷಿಯ/ಅಕ್ಟಾವು"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "ಅತ್ಯಾರು (ಅತಿರಾವು, ಗುರ್ಯೆವ್), ಮೆಂಗಾಹಿಸ್ಟಾವು (ಮಂಕಿಸ್ಟಾವು)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "ಏಷಿಯ/ಎಕ್ಟೋಬ್"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "ಅಕ್ಟೋಬ್"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "ಏಷಿಯ/ಎಶ್ಗಾಬ್ಯಾಟ್"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "ಏಷಿಯ/ಅಶ್ಕಾಬಾದ್"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "ಏಷಿಯ/ಬಾಗ್ದಾದ್"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "ಏಷಿಯ/ಬಹರೈನ್"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "ಏಷಿಯ/ಬಾಕು"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "ಏಷಿಯ/ಬ್ಯಾಂಕಾಕ್"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "ಏಷಿಯ/ಬೀರಟ್"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "ಏಷಿಯ/ಬಿಶ್ಕೆಕ್"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "ಏಷಿಯ/ಬ್ರೂನೈ"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "ಏಷಿಯ/ಕಲ್ಕತ್ತಾ"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "ಏಷಿಯ/ಕೊಯಿಬಾಲ್ಸಮ್"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "ಡೊರ್ನೊಡ್, ಸುಖ್‌ಬಾಟಾರ್"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "ಏಷಿಯ/ಚಾಂಗ್ಕಿಂಗ್"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "ಮಧ್ಯ ಚೈನಾ - ಸಿಶುವಾನ್, ಯುನಾನ್, ಗುವಾಂಗ್‌ಕ್ಸಿ, ಗುಝೌ, ಇತರೆ"
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "ಏಷಿಯ/ಚಂಗ್ಕಿಂಗ್"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "ಏಷಿಯ/ಕೊಲೊಂಬೋ"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "ಏಷಿಯ/ಡಕ್ಕಾ"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "ಏಷಿಯ/ಡಮಸ್ಕಸ್"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "ಏಷಿಯ/ಢಾಕಾ"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "ಏಷಿಯ/ಡಿಲಿ"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "ಏಷಿಯ/ದುಬೈ"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "ಏಷಿಯ/ದುಶಾನ್ಬೆ"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "ಏಷಿಯ/ಗಾಝಾ"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "ಏಷಿಯ/ಹರ್ಬಿನ್"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "ಹೀಲಾಂಗ್‌ಜಿಯಾಂಗ್ (ಮೊಹೆಯನ್ನು ಹೊರತುಪಡಿಸಿ), ಜಿಲಿನ್"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "ಏಷಿಯ/ಹೊ_ಚಿ-ಮಿನ್"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "ಏಷಿಯ/ಹಾಂಗ್_ಕಾಂಗ್"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "ಏಷಿಯ/ಹೋವ್ಡ್"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "ಬಯಾನ್-ಒಲ್ಗಿಯ್, ಗೋವಿ-ಅಲ್ಟಾಯಿ, ಹೋವ್ಡ್, ಉವ್ಸ್, ಸಾವ್ಕಾನ್"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "ಏಷಿಯ/ಇರ್ಕುಟ್ಸಕ್"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "ಮಾಸ್ಕೊ+05 - ಲೇಕ್ ಬೈಕಲ್"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "ಏಷಿಯ/ಇಸ್ತಾನ್ಬುಲ್"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "ಏಷಿಯ/ಜಕಾರ್ತ"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "ಜಾವಾ ಹಾಗು ಸುಮಾತ್ರ"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "ಏಷಿಯ/ಜಯಪುರ"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "ಇರಿಯನ್ ಜಯಾ ಹಾಗು ಮೊಲುಕಾಸ್"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "ಏಷಿಯ/ಜೆರುಸೆಲಂ"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "ಏಷಿಯ/ಕಾಬುಲ್"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "ಏಷಿಯ/ಕಾಂಚಟ್ಕಾ"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "ಮಾಸ್ಕೊ+08 - ಕಮಾಚಟ್ಕಾ"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "ಏಷಿಯ/ಕರಾಚಿ"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "ಏಷಿಯ/ಕಶ್ಗರ್"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "ಪಶ್ಚಿಮ ಟಿಬೆಟ್ ಹಾಗು ಕ್ಸಿಂಜಿಯಾಂಗ್"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "ಏಷಿಯ/ಕಠ್ಮಂಡು"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "ಏಷಿಯ/ಕಠ್ಮಂಡು"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "ಏಷಿಯ/ಕೋಲ್ಕತ್ತಾ"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "ಏಷಿಯ/ಕ್ರಸ್ನೋಯಾರ್ಸಕ್"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "ಮಾಸ್ಕೊ+04 - ಯೆನಿಸಿ ನದಿ"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "ಏಷಿಯ/ಕೌಲಾ_ಲುಂಪುರ್"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "ಪೆನಿನ್ಸುಲಾರ್ ಮಲೇಶಿಯಾ"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "ಏಷಿಯ/ಕುಚಿಂಗ್"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "ಸಬಾಹ್ ಹಾಗು ಸರಾವಾಕ್"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "ಏಷಿಯ/ಕುವೈತ್"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "ಏಷಿಯ/ಮಕಾವೊ"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "ಏಷಿಯ/ಮಕಾವ್"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "ಏಷಿಯ/ಮಗದನ್"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "ಮಾಸ್ಕೊ+08 - ಮಗಡಾನ್"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "ಏಷಿಯ/ಮಕಸ್ಸಾರ್"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "ಪೂರ್ವ ದಕ್ಷಿಣ ಬೊರ್ನಿಯೊ, ಸೆಲೆಬಸ್, ಬಾಲಿ, ನುಸಾ ಟೆಂಗಾರಾ, ಪಶ್ಚಿಮ ತಿಮೊರ್"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "ಏಷಿಯ/ಮೆನಿಲ್ಲಾ"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "ಏಷಿಯ/ಮಸ್ಕಟ್"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "ಏಷಿಯ/ನಿಕೋಶಿಯ"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "ಏಷಿಯ/ನೋವಾಕುಸ್ನೆಸ್ಕ್"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "ಮಾಸ್ಕೊ+03 - ನೊವೊಸಿಬಿರ್ಸಕ್"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "ಏಷಿಯ/ನೊವೊಸಿಬಿರ್ಸಕ್"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "ಮಾಸ್ಕೊ+03 - ನೊವೊಸಿಬಿರ್ಸಕ್"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "ಏಷಿಯ/ಓಮ್ಸಕ್"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "ಮಾಸ್ಕೊ+03 - ಪಶ್ಚಿಮ ಸೈಬೀರಿಯ"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "ಏಷಿಯ/ಓರಲ್"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "ಪಶ್ಚಿಮ ಕಝಕಿಸ್ತಾನ್"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "ಏಷಿಯ/ಫ್ನಾಮ್_ಪೆನ್ಹ್"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "ಏಷಿಯ/ಪೊಂಟಿಯಾನಕ್"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "ಪಶ್ಚಿಮ ಹಾಗು ಮಧ್ಯ ಬೊರ್ನಿಯೊ"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "ಏಷಿಯ/ಪ್ಯಾಂನ್ಗಿಯಾಂಗ್"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "ಏಷಿಯ/ಕತಾರ್"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "ಏಷಿಯ/ಕ್ವಿಝಿಲೊರ್ಡಾ"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "ಕಿಸಿಲೊರ್ಡಾ (ಕಿಸಿಲ್‌-ಓರ್ಡಾ)"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "ಏಷಿಯ/ರಂಗೂನ್"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "ಏಷಿಯ/ರಿಯಾದ್"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "ಏಷಿಯ/ರಿಯಾದ್೮೭"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "ಏಷಿಯ/ರಿಯಾದ್೮೮"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "ಏಷಿಯ/ರಿಯಾದ್೮೯"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "ಏಷಿಯ/ಸೈಗೂನ್"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "ಏಷಿಯ/ಸಖಾಲಿನ್"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "ಮಾಸ್ಕೊ+07 - ಸಕಾಲಿನ್ ದ್ವೀಪ"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "ಏಷಿಯ/ಸಮರಕಂಡ್"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "ಪಶ್ಚಿಮ ಉಝ್ಬೇಕಿಸ್ತಾನ್"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "ಏಷಿಯ/ಸಿಯೋಲ್"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "ಏಷಿಯ/ಶಾಂಗೈ"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "ಪೂರ್ವ ಚೈನಾ - ಬೀಜಿಂಗ್, ಗ್ವಾಂಡಾಂಗ್, ಶಾಂಗಾಯ್, ಇತರೆ"
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "ಏಷಿಯ/ಸಿಂಗಪೂರ್"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "ಏಷಿಯ/ತೈಪೆ"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "ಏಷಿಯ/ತಾಷ್ಕೆಂಟ್"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "ಪೂರ್ವ ಉಝ್ಬೇಕಿಸ್ತಾನ್"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "ಏಷಿಯ/ಬಿಲಿಸಿ"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "ಏಷಿಯ/ಟೆಹ್ರಾನ್"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "ಏಷಿಯ/ಟೆಲ್_ಎವಿವ್"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "ಏಷಿಯ/ಥಿಂಬು"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "ಏಷಿಯ/ಥಿಂಪು"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "ಏಷಿಯ/ಟೋಕಿಯೋ"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "ಏಷಿಯ/ಉಜಂಗ್_ಪಾಂಡಂಗ್"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "ಏಷಿಯ/ಉಲಾಂಬಾತರ್"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "ಏಷಿಯ/ಉಲಾನ್_ಬತಾರ್"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "ಏಷಿಯ/ಉರುಂಕಿ"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "ಟಿಬೆಟ್‌ ಹಾಗು ಕ್ಸಿಂಜಿಯಾಂಗ್‌ನ ಹೆಚ್ಚಿನ ಭಾಗ"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "ಏಷಿಯ/ವಿಯೆಂಟಿಯಾನೆ"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "ಏಷಿಯ/ವ್ಲಾಡಿವೊಸ್ಟೋಕ್"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "ಮಾಸ್ಕೊ+07 - ಅಮುರ್ ರಿವರ್"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "ಏಷಿಯ/ಯಕುಟ್ಸಕ್"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "ಮಾಸ್ಕೊ+06 - ಲೀನಾ ರಿವರ್"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "ಏಷಿಯ/ಯೆಕಟೆರಿನ್ಬರ್ಗ್"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "ಮಾಸ್ಕೊ+02 - ಉರಾಲ್ಸ್"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "ಏಷಿಯ/ಯೆರೆವಾನ್"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "ಅಟ್ಲಾಂಟಿಕ್/ಅಝೋರೆಸ್"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "ಅಝೋರಸ್"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "ಅಟ್ಲಾಂಟಿಕ್/ಬರ್ಮುಡಾ"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "ಅಟ್ಲಾಂಟಿಕ್/ಕೆನಾರಿ"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "ಕನಾರಿ ದ್ವೀಪಗಳು"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "ಅಟ್ಲಾಂಟಿಕ್/ಕೇಪ್_ವರ್ಡ್"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "ಅಟ್ಲಾಂಟಿಕ್/ಫೈರೋ"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "ಅಟ್ಲಾಂಟಿಕ್/ಫೆರೋ"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "ಅಟ್ಲಾಂಟಿಕ್/ಜಾನ್_ಮಯೆನ್"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "ಅಟ್ಲಾಂಟಿಕ್/ಮಡೆರಾ"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "ಮಡೀರಾ ದ್ವೀಪಗಳು"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "ಅಟ್ಲಾಂಟಿಕ್/ರೈಕ್ಜಾವಿಕ್"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "ಅಟ್ಲಾಂಟಿಕ್/ದಕ್ಷಿಣ_ಜಾರ್ಜಿಯಾ"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "ಅಟ್ಲಾಂಟಿಕ್/ಸ್ಟಾನ್ಲೆ"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "ಅಟ್ಲಾಂಟಿಕ್/ಸೈಂಟ್_ಹೆಲೆನಾ"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "ಆಸ್ಟ್ರೇಲಿಯಾ/ಎಸಿಟಿ"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "ಆಸ್ಟ್ರೇಲಿಯಾ/ಅಡಿಲೇಡ್"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "ದಕ್ಷಿಣ ಆಸ್ಟ್ರೇಲಿಯಾ"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "ಆಸ್ಟ್ರೇಲಿಯಾ/ಬ್ರಿಸ್ಬೇನ್"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "ಕ್ವೀನ್ಸ್‌ಲ್ಯಾಂಡ್ - ಹೆಚ್ಚಿನ ಪ್ರದೇಶಗಳು"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "ಆಸ್ಟ್ರೇಲಿಯಾ/ಬ್ರೋಕನ್_ಹಿಲ್"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "ನ್ಯೂ ಸೌತ್ ವೇಲ್ಸ್ - ಯಾಂಕೊವಿನಾ"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "ಆಸ್ಟ್ರೇಲಿಯಾ/ಕ್ಯಾನ್ಬೆರ್ರಾ"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "ಆಸ್ಟ್ರೇಲಿಯಾ/ಕ್ಯೂರ್ರಿ"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "ಟಾಸ್ಮೇನಿಯ - ಕಿಂಗ್ ದ್ವೀಪ"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "ಆಸ್ಟ್ರೇಲಿಯಾ/ಡಾರ್ವಿನ್"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "ಪೂರ್ವ ಟೆರಿಟರಿ"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "ಆಸ್ಟ್ರೇಲಿಯಾ/ಯೂಕ್ಲಾ"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "ಪಶ್ಚಿಮ ಆಸ್ಟ್ರೇಲಿಯಾ - ಯೂಕ್ಲಾ ಪ್ರದೇಶ"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "ಆಸ್ಟ್ರೇಲಿಯಾ/ಹೋಬರ್ಟ್"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "ಟಾಸ್ಮೇನಿಯ - ಹೆಚ್ಚಿನ ಸ್ಥಳಗಳು"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "ಆಸ್ಟ್ರೇಲಿಯಾ/ಎಲ್ ಎಚ್ ಐ"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "ಆಸ್ಟ್ರೇಲಿಯಾ/ಲಿಂಡೆಮಾನ್"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "ಕ್ವೀನ್ಸ್‌ಲ್ಯಾಂಡ್ - ಹಾಲಿಡೆ ದ್ವೀಪಗಳು"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "ಆಸ್ಟ್ರೇಲಿಯಾ/ಲಾರ್ಡ್_ಹೊವೆ"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "ಲೋರ್ಡ್ ಹೋವ್ ದ್ವೀಪ"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "ಆಸ್ಟ್ರೇಲಿಯಾ/ಮೆಲ್ಬೋರ್ನ್"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "ವಿಕ್ಟೋರಿಯಾ"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "ಆಸ್ಟ್ರೇಲಿಯಾ/ಉತ್ತರ"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "ಆಸ್ಟ್ರೇಲಿಯಾ/ಎನ್ ಎಸ್ ಡಬ್ಲ್ಯು"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "ಆಸ್ಟ್ರೇಲಿಯಾ/ಪರ್ತ್"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "ಪಶ್ಚಿಮ ಆಸ್ಟ್ರೇಲಿಯ -ಹೆಚ್ಚಿನ ಸ್ಥಳಗಳು"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "ಆಸ್ಟ್ರೇಲಿಯಾ/ಕ್ವೇನ್ಸ್ ಲ್ಯಾಂಡ್"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "ಆಸ್ಟ್ರೇಲಿಯಾ/ದಕ್ಷಿಣ"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "ಆಸ್ಟ್ರೇಲಿಯಾ/ಸಿಡ್ನಿ"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "ನ್ಯೂ ಸೌತ್ ವೇಲ್ಸ್ - ಹೆಚ್ಚಿನ ಸ್ಥಳಗಳು"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "ಆಸ್ಟ್ರೇಲಿಯಾ/ಟಾಸ್ಮಾನಿಯಾ"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "ಆಸ್ಟ್ರೇಲಿಯಾ/ವಿಕ್ಟೋರಿಯಾ"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "ಆಸ್ಟ್ರೇಲಿಯಾ/ಪಶ್ಚಿಮ"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "ಆಸ್ಟ್ರೇಲಿಯಾ/ಯಾಂಕೋವಿನಾ"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "ಬ್ರಝಿಲ್/ಏಕರ್"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "ಬ್ರಝಿಲ್/ಡಿನೊರೊನ್ಹ"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "ಬ್ರಝಿಲ್/ಪೂರ್ವ"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "ಬ್ರಝಿಲ್/ಪಶ್ಚಿಮ"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "ಕೆನಡ/ಅಟ್ಲಾಂಟಿಕ್"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "ಕೆನಡ/ಸೆಂಟ್ರಲ್"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "ಕೆನಡ/ಪೂರ್ವ"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "ಕೆನಡ/ಪೂರ್ವ-ಸಾಸ್ಕಾಟ್ಶೆವಾನ್"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "ಕೆನಡ/ಪರ್ವತ"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "ಕೆನಡ/ನ್ಯೂಫೌಂಡ್ ಲ್ಯಾಂಡ್"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "ಕೆನಡ/ಪೆಸಿಫಿಕ್"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "ಕೆನಡ/ಸಾಸ್ಕಾಟ್ಶೆವಾನ್"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "ಕೆನಡ/ಯುಕೊನ್"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "ಸಿಇಟಿ"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "ಚಿಲಿ/ಕಾಂಟಿನೆಂಟಲ್"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "ಚಿಲಿ/ಈಸ್ಟರ್ದ್ವೀಪ"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "ಸಿ ಎಸ್ ಟಿ೬ಡಿ ಎಸ್ ಟಿ"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "ಕ್ಯೂಬಾ"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "ಇಇಟಿ"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "ಈಜಿಪ್ಟ್"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "ಇರೆ"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "ಇ ಎಸ್ ಟಿ"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "ಇ ಎಸ್ ಟಿ ೫ ಇ ಡಿ ಟಿ"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ ೦"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ-೦"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ+೦"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ-೧"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ+೧"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ-೧೦"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ+೧೦"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ-೧೧"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ+೧೧"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ-೧೨"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ+೧೨"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ-೧೩"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ-೧೪"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ-೨"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ+೨"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ-೩"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ+೩"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ-೪"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ+೪"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ-೫"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ+೫"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ-೬"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ+೬"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ-೭"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ+೭"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ-೮"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ+೮"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ-೯"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಜಿ ಎಮ್ ಟಿ+೯"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಗ್ರೀನ್ವಿಚ್"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಯುಸಿಟಿ"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಯುನಿವರ್ಸಲ್"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಯುಸಿಟಿ"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "ಎಕ್ಸೆಟ್ರ/ಝುಲು"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "ಯುರೋಪ್/ಆಮ್ಸಟರ್ಡ್ಯಾಮ್"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "ಯುರೋಪ್/ಅಂಡೋರಾ"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "ಯುರೋಪ್/ಅಥೆನ್ಸ್"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "ಯುರೋಪ್/ಬೆಲ್ಫಾಸ್ಟ್"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "ಯುರೋಪ್/ಬೆಲ್ಗ್ರೇಡ್"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "ಯುರೋಪ್/ಬರ್ಲಿನ್"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "ಯುರೋಪ್/ಬ್ರಟಿಸ್ಲಾವಾ"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "ಯುರೋಪ್/ಬ್ರುಸೆಲ್ಸ್"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "ಯುರೋಪ್/ಬ್ಯುಕಾರೆಸ್ಟ್"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "ಯುರೋಪ್/ಬುಡಾಪೆಸ್ಟ್"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "ಯುರೋಪ್/ಚಿಸಿನೌ"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "ಯುರೋಪ್/ಕೊಪನ್ ಹೇಗನ್"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "ಯುರೋಪ್/ಡಬ್ಲಿನ್"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "ಯುರೋಪ್/ಗಿಬ್ರಾಲ್ಟರ್"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "ಯುರೋಪ್/ಗ್ಯುರ್ನೆಸಿ"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "ಯುರೋಪ್/ಹೆಲ್ಸಿಂಕಿ"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "ಯುರೋಪ್/ಐಸ್ಲ್_ಆಫ್_ಮ್ಯಾನ್"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "ಯುರೋಪ್/ಇಸ್ತಾಂಬುಲ್"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "ಯುರೋಪ್/ಜರ್ಸಿ"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "ಯುರೋಪ್/ಕಲಿನಿಂಗ್ರಾಡ್"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "ಮಾಸ್ಕೊ-01 - ಕಲಿನನ್‌ಗ್ರಾಡ್"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "ಯುರೋಪ್/ಕೀವ್"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "ಯುರೋಪ್/ಲಿಸ್ಬನ್"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "ಯುರೋಪ್/ಜುಬ್ಲಜಾನ"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "ಯುರೋಪ್/ಲಂಡನ್"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "ಯುರೋಪ್/ಲಕ್ಸೆಂಬರ್ಗ್"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "ಯುರೋಪ್/ಮ್ಯಾಡ್ರಿಡ್"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "ಯುರೋಪ್/ಮಾಲ್ಟಾ"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "ಯುರೋಪ್/ಮರೆಹಮ್"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "ಯುರೋಪ್/ಮಿಂಕ್ಸ್"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "ಯುರೋಪ್/ಮೊನಾಕೊ"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "ಯುರೋಪ್/ಮಾಸ್ಕೋ"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "ಮಾಸ್ಕೊ+00 - ಪಶ್ಚಿಮ ರಷ್ಯಾ"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "ಯುರೋಪ್/ನಿಕೋಸಿಯ"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "ಯುರೋಪ್/ಓಸ್ಲೊ"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "ಯುರೋಪ್/ಪ್ಯಾರಿಸ್"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "ಯುರೋಪ್/ಪೊಡ್ಗೋರಿಕಾ"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "ಯುರೋಪ್/ಪ್ರಾಗ್ಯು"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "ಯುರೋಪ್/ರಿಗಾ"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "ಯುರೋಪ್/ರೋಮ್"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "ಯುರೋಪ್/ಸಮಾರಾ"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "ಮಾಸ್ಕೊ - ಸಮಾರ, ಉಡ್ಮುರ್ಶಿಯ"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "ಯುರೋಪ್/ಸಾನ್_ಮಾರಿನೋ"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "ಯುರೋಪ್/ಸರ್ಜೆವೋ"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "ಯುರೋಪ್/ಸಿಮೆರೊಪೊಲ್"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "ಸೆಂಟ್ರಲ್ ಕ್ರಿಮೆಯ"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "ಯುರೋಪ್/ಸ್ಕೋಜೆ"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "ಯುರೋಪ್/ಸೋಫಿಯ"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "ಯುರೋಪ್/ಸ್ಟಾಕ್ ಹೊಂ"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "ಯುರೋಪ್/ಟಾಲ್ಲಿನ್"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "ಯುರೋಪ್/ಟಿರಾನೆ"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "ಯುರೋಪ್/ಟಿರಾಸ್ಪೊಲ್"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "ಯುರೋಪ್/ಉಝ್ಗುರೋಡ್"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "ರುತೇನಿಯ"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "ಯುರೋಪ್/ವಡುಝ್"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "ಯುರೋಪ್/ವ್ಯಾಟಿಕನ್"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "ಯುರೋಪ್/ವಿಯೆನ್ನಾ"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "ಯುರೋಪ್/ವಿಲ್ನಿಯಸ್"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "ಯುರೋಪ್/ವೊಲ್ಗೊಗ್ರಾಡ್"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "ಮಾಸ್ಕೊ+00 - ಕ್ಯಾಸ್ಪಿಯನ್ ಸಮುದ್ರ"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "ಯುರೋಪ್/ವರ್ಸಾವ್"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "ಯುರೋಪ್/ಝಗ್ರೆಬ್"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "ಯುರೋಪ್/ಝಪೊರೊಝೈ"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "ಸಪೊರೊಸೈ, ಪೂ ಲುಗಾನ್ಸ್ಕ್ / ಸಪೊರಿಸಿಯಾ, ಪೂ ಲುಹಾನ್ಸ್ಕ್"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "ಯುರೋಪ್/ಝ್ಯುರಿಚ್"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "ಫ್ಯಾಕ್ಟರಿ"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "ಜಿಬಿ"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "ಜಿಬಿ-ಇರೆ"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "ಜಿಎಂಟಿ"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "ಜಿಎಂಟಿ೦"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "ಜಿಎಂಟಿ-೦"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "ಜಿಎಂಟಿ+೦"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "ಗ್ರೀನ್ವಿಚ್"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "ಹಾಂಗ್ಕಾಂಗ್"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "ಹೆಚ್ ಎಸ್ ಟಿ"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "ದ್ವೀಪ"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "ಇಂಡಿಯನ್/ಅಂಟನಾನರಿವೊ"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "ಇಂಡಿಯನ್/ಚಾಗೋಸ್"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "ಇಂಡಿಯನ್/ಕ್ರಿಸ್ಮಸ್"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "ಇಂಡಿಯನ್/ಕೊಕೋಸ್"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "ಇಂಡಿಯನ್/ಕೊಮೊರೊ"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "ಇಂಡಿಯನ್/ಕೆರ್ಗುಲೆನ್"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "ಇಂಡಿಯನ್/ಮಾಹೆ"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "ಇಂಡಿಯನ್/ಮಾಲ್ಡೀವ್ಸ್"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "ಇಂಡಿಯನ್/ಮಾರಿಷಸ್"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "ಇಂಡಿಯನ್/ಮಯೊಟ್ಟೆ"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "ಇಂಡಿಯನ್/ರಿಯುನಿಯನ್"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "ಇರಾನ್"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "ಇಸ್ರೆಲ್"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "ಜಮೈಕಾ"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "ಜಪಾನ್"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "ಕ್ವಜಲೇನ್"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "ಲಿಬಿಯಾ"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "ಎಮ್ ಇ ಟಿ"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "ಮೆಕ್ಸಿಕೊ/ಬಜಾನೋರ್ಟೆ"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "ಮೆಕ್ಸಿಕೊ/ಬಜಾಸುರ್"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "ಮೆಕ್ಸಿಕೊ/ಜನರಲ್"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "ಮಧ್ಯಪೂರ್ವ/ರಿಯಾದ್೮೭"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "ಮಧ್ಯಪೂರ್ವ/ರಿಯಾದ್೮೮"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "ಮಧ್ಯಪೂರ್ವ/ರಿಯಾದ್೮೯"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "ಎಮ್ ಎಸ್ ಟಿ"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "ಎಮ್ ಎಸ್ ಟಿ ೭ ಎಮ್ ಡಿ ಟಿ"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "ನವಾಜೊ"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "ಎನ್ ಝಡ್"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "ಎನ್ ಝಡ್-ಸಿ ಎಚ್ ಎ ಟಿ"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "ಪೆಸಿಫಿಕ್/ಅಪಿಯಾ"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "ಪೆಸಿಫಿಕ್/ಆಕ್ ಲ್ಯಾಂಡ್"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "ಪೆಸಿಫಿಕ್/ಚತಾಮ್"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "ಚಾತಮ್ ದ್ವೀಪಗಳು"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "ಪೆಸಿಫಿಕ್/ಚೂಕ್"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "ಚೂಕ್ (ಟ್ರಕ್) ಹಾಗು ಯಾಪ್"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "ಪೆಸಿಫಿಕ್/ಈಸ್ಟರ್"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "ಈಸ್ಟರ್ ದ್ವೀಪ ಹಾಗು ಸಲಾ ವೈ ಗೊಮೆಝ್"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "ಪೆಸಿಫಿಕ್/ಇಫೇಟ್"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "ಪೆಸಿಫಿಕ್/ಎಂಡರ್ಬರ್ರಿ"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "ಫೀನಿಕ್ಸ್ ದ್ವೀಪಗಳು"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "ಪೆಸಿಫಿಕ್/ಫಕಾಫೊ"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "ಪೆಸಿಫಿಕ್/ಫಿಜಿ"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "ಪೆಸಿಫಿಕ್/ಫನಫುಟಿ"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "ಪೆಸಿಫಿಕ್/ಗಲಪ್ಯಾಗೊಸ್"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "ಗಾಲಪಗೋಸ್ ದ್ವೀಪಗಳು"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "ಪೆಸಿಫಿಕ್/ಗ್ಯಾಂಬಿರ್"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "ಗೇಂಬಿಯರ್ ದ್ವೀಪಗಳು"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "ಪೆಸಿಫಿಕ್/ಗ್ವಾಡೆಲ್ ಕೆನಾಲ್"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "ಪೆಸಿಫಿಕ್/ಗುವಾಮ್"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "ಪೆಸಿಫಿಕ್/ಹೊನಲುಲು"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "ಹವಾಯಿ"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "ಪೆಸಿಫಿಕ್/ಜಾನ್ಸಟನ್"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "ಜಾನ್‌ಸ್ಟನ್ ಎಟೊಲ್"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "ಪೆಸಿಫಿಕ್/ಕಿರಿಟಿಮ್ಯಾಟಿ"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "ಲೈನ್ ದ್ವೀಪಗಳು"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "ಪೆಸಿಫಿಕ್/ಕೊಸ್ರೆ"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "ಕೊಸ್ರೆ"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "ಪೆಸಿಫಿಕ್/ಕ್ವಾಜಾಲೇನ್"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "ಪೆಸಿಫಿಕ್/ಮಜುರೊ"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "ಪೆಸಿಫಿಕ್/ಮರ್ಕ್ಯಸಾಸ್"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "ಮಾರ್ಕೆಸಾಸ್ ದ್ವೀಪಗಳು"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "ಪೆಸಿಫಿಕ್/ಮಿಡ್ವೇ"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "ಮಿಡ್‌ವೆ ದ್ವೀಪಗಳು"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "ಪೆಸಿಫಿಕ್/ನೌರು"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "ಪೆಸಿಫಿಕ್/ನ್ಯು"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "ಪೆಸಿಫಿಕ್/ನಾರ್ಫೋಕ್"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "ಪೆಸಿಫಿಕ್/ನೌಮೆ"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "ಪೆಸಿಫಿಕ್/ಪ್ಯಾಗೊ_ಪ್ಯಾಗೊ"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "ಪೆಸಿಫಿಕ್/ಪಲವ್"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "ಪೆಸಿಫಿಕ್/ಪಿಟಿಕೇರ್ನ್"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "ಪೆಸಿಫಿಕ್/ಪೊನ್‌ಪೆ"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "ಪೊನ್‌ಪೆ (ಪೊಂಪೆ)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "ಪೆಸಿಫಿಕ್/ಪೊನಾಪೆ"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "ಪೆಸಿಫಿಕ್/ಪೊರ್ಟ್_ಮೋರ್ಸೆಬೈ"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "ಪೆಸಿಫಿಕ್/ರಾರೊಟೊಂಗಾ"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "ಪೆಸಿಫಿಕ್/ಸೈಪಾನ್"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "ಪೆಸಿಫಿಕ್/ಸಮೊವ"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "ಪೆಸಿಫಿಕ್/ತಾಹಿತಿ"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "ಸೊಸೈಟಿ ದ್ವೀಪಗಳು"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "ಪೆಸಿಫಿಕ್/ತರಾವಾ"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "ಗಿಲ್ಬರ್ಟ್ ದ್ವೀಪಗಳು"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "ಪೆಸಿಫಿಕ್/ಟೊಂಗಾಟಾಪು"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "ಪೆಸಿಫಿಕ್/ಟ್ರಕ್"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "ಪೆಸಿಫಿಕ್/ವೇಕ್"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "ವೇಕ್ ದ್ವೀಪಗಳು"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "ಪೆಸಿಫಿಕ್/ವಾಲ್ಲಿಸ್"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "ಪೆಸಿಫಿಕ್/ಯಾಪ್"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "ಪೋಲಾಂಡ್"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "ಪೋರ್ಚುಗಲ್"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "ಪಾಸಿಕ್ಸ್‌ರೂಲ್ಸ್"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "ಪಿ ಆರ್ ಸಿ"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "ಪಿ ಎಸ್ ಟಿ ೮ ಪಿ ಡಿ ಟಿ"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ಆರ್ ಒ ಸಿ"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ಆರ್ ಒ ಕೆ"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "ಸಿಂಗಪುರ್"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "ಟರ್ಕಿ"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "ಯುಸಿಟಿ"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "ಯುನಿವರ್ಸಲ್"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "ಯುಎಸ್/ಅಲಸ್ಕಾ"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "ಯುಎಸ್/ಅಲೇಶಿಯನ್"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "ಯುಎಸ್/ಅರಿಝೊನ"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "ಯುಎಸ್/ಸೆಂಟ್ರಲ್"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "ಯುಎಸ್/ಈಸ್ಟರ್ನ್"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "ಯುಎಸ್/ಪೂರ್ವ-ಇಂಡಿಯಾನ"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "ಯುಎಸ್/ಹವಾಯಿ"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "ಯುಎಸ್/ಇಂಡಿಯಾನ-ಸ್ಟಾರ್ಕ್"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "ಯುಎಸ್/ಮಿಚಿಗನ್"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "ಯುಎಸ್/ಪರ್ವತ"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "ಯುಎಸ್/ಪೆಸಿಫಿಕ್"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "ಯುಎಸ್/ಸಮೋವ"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "ಯು ಟಿ ಸಿ"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "ಡಬ್ಲುಇಟಿ"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "ಡಬ್ಲ್ಯು-ಎಸ್ ಯು"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "ಝುಲು"
+
diff --git a/panels/datetime/po-timezones/ko.po b/panels/datetime/po-timezones/ko.po
new file mode 100644
index 0000000..74c2622
--- /dev/null
+++ b/panels/datetime/po-timezones/ko.po
@@ -0,0 +1,3246 @@
+# translation of system-config-date.master-timezones.ko.po to
+# Michelle J Kim <mkim@redhat.com>, 2004.
+# Michelle Ji Yeen Kim <mkim@redhat.com>, 2006.
+# Eunju Kim <eukim@redhat.com>, 2006, 2008, 2009.
+# Hyunsok Oh<hoh@redhat.com>, 2010.
+# Eun-Ju Kim <eukim@redhat.com>, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: system-config-date.master-timezones.ko\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-12-07 15:24+1000\n"
+"Last-Translator: Eun-Ju Kim <eukim@redhat.com>\n"
+"Language-Team: <ko@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ko\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"\n"
+"\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "아프리카/아비장(Abidjan)"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "아프리카/아크라(Accra)"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "아프리카/아디스_아바바(Addis_Ababa)"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "아프리카/알제(Algiers)"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "아프리카/아스마라(Asmara)"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "아프리카/아스마라(Asmera)"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "아프리카/바마코(Bamako)"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "아프리카/방기(Bangui)"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "아프리카/반줄(Banjul)"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "아프리카/비소(Bissau)"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "아프리카/볼랑띠레(Blantyre)"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "아프리카/브라자빌(Brazzaville)"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "아프리카/부줌부라(Bujumbura)"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "아프리카/카이로(Cairo)"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "아프리카/카사블랑카(Casablanca)"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "아프리카/세우타(Ceuta)"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "세우타(Ceuta) & 멜리야 (Melilla) "
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "아프리카/코나크리(Conakry)"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "아프리카/다카르(Dakar)"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "아프리카/다르_에스_살람(Dar_es_Salaam)"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "아프리카/지부티(Djibouti)"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "아프리카/두알라(Douala)"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "아프리카/엘_아이운(El_Aaiun)"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "아프리카/프리타운(Freetown)"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "아프리카/가보로네(Gaborone)"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "아프리카/하라레(Harare)"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "아프리카/요하네스버그(Johannesburg)"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "아프리카/캄팔라(Kampala)"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "아프리카/카르툼(Khartoum)"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "아프리카/키갈리(Kigali)"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "아프리카/킨샤사(Kinshasa)"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "콩고 민주 공화국 서부 "
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "아프리카/라고스(Lagos)"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "아프리카/리브르빌(Libreville)"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "아프리카/로메(Lome)"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "아프리카/루안다(Luanda)"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "아프리카/루붐바시(Lubumbashi)"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "콩고 민주 공화국 동부 "
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "아프리카/루사카(Lusaka)"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "아프리카/말라보(Malabo)"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "아프리카/마푸토(Maputo)"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "아프리카/마세루(Maseru)"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "아프리카/음바바네(Mbabane)"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "아프리카/모가디슈(Mogadishu)"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "아프리카/먼로비아(Monrovia)"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "아프리카/나이로비(Nairobi)"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "아프리카/은자메나(Ndjamena)"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "아프리카/니아메이(Niamey)"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "아프리카/누악쇼트(Nouakchott)"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "아프리카/와가두구(Ouagadougou)"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "아프리카/포르토-노보(Porto-Novo)"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "아프리카/상_토메(Sao_Tome)"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "아프리카/팀북투(Timbuktu)"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "아프리카/트리폴리(Tripoli)"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "아프리카/튀니스(Tunis)"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "아프리카/빈트후크(Windhoek)"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "아메리카/에이닥(Adak)"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "알류샨 열도 (Aleutian Islands) "
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "아메리카/앵커리지(Anchorage)"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "알래스카 표준시 "
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "아메리카/앙귈라(Anguilla)"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "아메리카/안티구아(Antigua)"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "아메리카/아라구에이나(Araguaina)"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "토칸틴스 (Tocantins) "
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "아메리카/아르헨티나/부에노스_아이레스(Buenos_Aires)"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "부에노스 아이레스 (BA, CF) "
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "아메리카/아르헨티나/카타마르카(Catamarca)"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "카타마르카 (CT), 추부트 (CH) "
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "아메리카/아르헨티나/코모드리바다비아(ComodRivadavia)"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "아메리카/아르헨티나/코르도바(Cordoba)"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "대부분의 지역 (CB, CC, CN, ER, FM, MN, SE, SF) "
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "아메리카/아른헨티/후후이(Jujuy)"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "후후이 (JY) "
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "아메리카/아르헨티나/리오하(La_Rioja)"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "리오하 (LR) "
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "아메리카/아르헨티나/멘도사(Mendoza)"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "멘도사 (MZ) "
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "아메리카/아르헨티나/리오 가예고스(Rio_Gallegos)"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "산타쿠르즈 (SC) "
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "아메리카/아르헨티나/살타 "
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "아메리카/아르헨티나/산후안(San_Juan)"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "산후안 (SJ) "
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "아메리카/아르헨티나/산_루이스 "
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "산루이스 (SL) "
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "아메리카/아르헨티나/투쿠만(Tucuman)"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "투쿠만 (TM) "
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "아메리카/아르헨티나/우수아이아(Ushaia)"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "티에라델푸에고 (TF) "
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "아메리카/아루바(Aruba)"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "아메리카/아순시온(Asuncion)"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "아메리카/아티코칸(Atikokan)"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "동부 표준시 - 아티코칸, 온타리오 및 사우샘프톤, 누나부트 "
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "아메리카/아트카(Atka)"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "아메리카/바이아(Bahia) "
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "바이아(Bahia) "
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "아메리카/바이아 반데라스(Bahia_Banderas) "
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "멕시코 중부 표준시 - 바이아 데 반데라스 "
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "아메리카/바베이도스(Barbados)"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "아메리카/벨렘(Belem)"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "아마파 (Amapa) 파라 동부 (E Para) "
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "아메리카/벨리즈(Belize)"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "아메리카/블랑-사브론(Blanc-Sablon)"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "대서양 표준시 - 퀘벡 - 노스 쇼어 하단 "
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "아메리카/보아_비스타(Boa_Vista)"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "로라이마 (Roraima) "
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "아메리카/보고타(Bogota)"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "아메리카/보이스(Boise)"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "산지 표준시 - 아이다호 남부 & 오레곤 동부 "
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "아메리카/부에노스_아이레스(Buenos_Aires)"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "아메리카/캠브리지_베이(Cambridge_Bay)"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "산지 표준시 - 누나부트 서부 (west Nunavut) "
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "아메리카/캄푸그란데(Campo_Grande)"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "마투그로스드솔 (Mato Grosso do Sul) "
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "아메리카/칸쿤(Cancun)"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "중부 표준시 - 퀀타나 루 (Quintana Roo)"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "아메리카/카라카스(Caracas)"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "아메리카/카타마르카(Catamarca)"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "아메리카/카이엔(Cayenne)"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "아메리카/카이만(Cayman)"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "아메리카/시카고(Chicago)"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "중부 표준시 "
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "아메리카/치와와(Chihuahua)"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "멕시코 산지 표준시 - 미국 국경에서 먼 치와와 (Chihuahua) "
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "아메리카/코럴하버(Coral_Harbour)"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "아메리카/코르도바(Cordoba)"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "아메리카/코스타_리카(Costa_Rica)"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "아메리카/쿠이아바(Cuiaba)"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "마토 그로소 (Mato Grosso) "
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "아메리카/쿠라카오(Curacao)"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "아메리카/단마크샤븐(Danmarkshavn)"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "동부 해안, 스코스바이선드 북부 "
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "아메리카/도슨(Dawson)"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "태평양 표준시 - 유콘 북부 (north Yukon) "
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "아메리카/도슨_크릭(Dawson_Creek)"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid "Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr "산지 표준시 - 도슨 크릭 & 성요한 요새 (Fort Saint John), 브리티시 콜럼비아 "
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "아메리카/덴버(Denver)"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "산지 표준시 "
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "아메리카/디트로이트(Detroit)"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "동부 표준시 - 미시간 - 대부분의 지역 "
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "아메리카/도미니카(Dominica)"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "아메리카/에드몬톤(Edmonton)"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "산지 표준시 - 앨버타, 브리티시 콜럼비아 동부 & 사스케추안 서부 "
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "아메리카/에이루네프(Eirunepe)"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "아마존 서부 (W Amazonas) "
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "아메리카/엘_살바도르(El_Salvador)"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "아메리카/엔세나다(Ensenada)"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "아메리카/포르탈레자(Fortaleza)"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "브라질 북동부 (MA, PI, CE, RN, PB) "
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "아메리카/포르트_웨인(Fort_Wayne)"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "아메리카/글레이스_베이(Glace_Bay)"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr "대서양 표준시 - 노바스코샤 - 1966-1971년에 DST를 실시하지 않은 지역 "
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "아메리카/고드홉(Godthab)"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "대부분의 지역 "
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "아메리카/구스_베이(Goose_Bay)"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "대서양 표준시 - 래브라도 - 대부분의 지역 "
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "아메리카/그랜드_터크(Grand_Turk)"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "아메리카/그레나다(Grenada)"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "아메리카/과델루프(Guadeloupe)"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "아메리카/과테말라(Guatemala)"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "아메리카/과야킬(Guayaquil)"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "본토 "
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "아메리카/가이아나(Guyana)"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "아메리카/헬리팩스(Halifax)"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "대서양 표준시 - 노바스코샤 (대부분의 지역), PEI "
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "아메리카/아바나(Havana)"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "아메리카/에르모시요(Hermosillo)"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "산지 표준시 - 소노라 (Sonora) "
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "아메리카/인디애나/인디애나폴리스(Indianapolis)"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "동부 표준시 - 인디애나 - 대부분의 지역 "
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "아메리카/인디애나/녹스(Knox)"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "중부 표준시 - 인디애나 - 스타크 카운티 "
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "아메리카/인디애나/마렝고(Marengo)"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "동부 표준시 - 인디애나 - 크로퍼드 카운티 "
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "아메리카/인디애나/페테르스부르그(Petersburg)"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "동부 표준시 - 인디애나 - 파이크 카운티 "
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "아메리카/인디애나폴리스(Indianapolis)"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "아메리카/인디애나/텔_시티(Tell_City) "
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "중부 표준시 - 인디애나 - 페리 카운티 "
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "아메리카/인디애나/베베이(Vevay)"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "동부 표준시 - 인디애나 - 스위스 카운티 "
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "아메리카/인디애나/빈센느(Vincennes)"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "동부 표준시 - 인디애나 - 데이비스, 듀보이스, 녹스 & 마틴 카운티 "
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "아메리카/인디애나/워너맥(Winamac)"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "동부 표준시 - 인디애나 - 폴라스키 카운티 "
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "아메리카/이누빅(Inuvik)"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "산지 표준시 - 노스웨스트 테리토리 서부 (west Northwest Territories) "
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "아메리카/이칼루이트(Iqaluit)"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "동부 표준시 - 누나부트 동부 - 대부분의 지역 "
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "아메리카/자마이카(Jamaica)"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "아메리카/후후이(Jujuy)"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "아메리카/주노(Juneau)"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "알래스카 표준시 - 알래스카 팬핸들 (Alaska panhandle) "
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "아메리카/켄터키/루이스빌(Louisville)"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "동부 표준시 - 켄터키 - 루이스빌 지역 "
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "아메리카/켄터키/몬티첼로(Monticello)"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "동부 표준시 - 켄터키 - 웨인 카운티 "
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "아메리카/녹스_인(Knox_IN)"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "아메리카/라_파스(La_Paz)"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "아메리카/리마(Lima)"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "아메리카/로스_엔젤레스(Los_Angeles)"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "태평양 표준시 "
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "아메리카/루이스빌(Louisville)"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "아메리카/마세이오(Maceio)"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "알라고아스(Alagoas), 세르지페 (Sergipe) "
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "아메리카/마나구아(Managua)"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "아메리카/마나우스(Manaus)"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "아마존 동부 "
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "아메리카/마리곳(Marigot)"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "아메리카/마르티니크(Martinique)"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "아메리카/마나우스(Manaus)"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid "US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+"미국 중부 표준시 - 미국 국경에서 가까운 코아우일라, 듀랑고, 누에보레온, 타몰"
+"리파스"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "아메리카/마자틀란(Mazatlan)"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "산지 표준시 - S 바자, 나야릿, 시날로아 "
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "아메리카/멘도사(Mendoza)"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "아메리카/메노미니(Menominee)"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "중부 표준시 - 미시간 - 디킨슨, 고기빅, 아이언 & 메노미니 카운티 "
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "아메리카/메리다(Merida)"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "중부 표준시 - 캄페체, 유카탄 "
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "아메리카/멕시코_시티(Mexico_City)"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "중부 표준시 - 대부분의 지역 "
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "아메리카/미클롱(Miquelon)"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "아메리카/몽톤(Moncton)"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "대서양 표준시 - 뉴브런즈윅 (New Brunswick) "
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "아메리카/몬테레이(Monterrey)"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+"멕시코 중부 표준시 - 미국 국경에서 먼 코아우일라, 듀랑고, 누에보레온, 타몰리"
+"파스 "
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "아메리카/몬테비데오(Montevideo)"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "아메리카/몬트리올(Montreal)"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "동부 표준시 - 퀘벡 - 대부분의 지역 "
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "아메리카/몬트세라트(Montserrat)"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "아메리카/나소(Nassau)"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "아메리카/뉴_욕(New_York)"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "동부 표준시 "
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "아메리카/니피곤(Nipigon)"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid "Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr "동부 표준시 - 온타리오 & 퀘벡 - 1967-1973 년에 DST를 실시하지 않은 지역 "
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "아메리카/놈(Nome)"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "알래스카 표준시 - 알래스카 서부 "
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "아메리카/노롱야(Noronha)"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "대서양 제도 "
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "아메리카/북 다코타/중부"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "중부 표준시 - 노스 다코타 - 올리버 카운티 "
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "아메리카/북 다코타/뉴살렘(New_Salem)"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "중부 표준시 - 노스 다코타 - 모턴 카운티 (Mandan 지역 제외) "
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "아메리카/오히나가(Managua)"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "미국 산지 표준시 - 미국 국경에서 가까운 치와와 (Chihuahua) "
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "아메리카/파타마(Panama)"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "아메리카/팡니르텅(Pangnirtung)"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "동부 표준시 - 팡니르텅, 누나부트 "
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "아메리카/파라마리보(Paramaribo)"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "아메리카/피닉스(Phoenix)"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "산지 표준시 - 아리조나(Arizona) "
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "아메리카/포르-토-프랭스(Port-au-Prince)"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "아메리카/포르토_아크레(Porto_Acre)"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "아메리카/포트_오브_스페인(Port_of_Spain)"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "아메리카/포르토_벨로(Porto_Velho)"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "론도니아 (Rondonia) "
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "아메리카/푸에르토_리코(Puerto_Rico)"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "아메리카/레이니_리버(Rainy_River)"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "중부 표준시 - 레이니 리버 & 포트 프란시스, 온타리오 "
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "아메리카/란킨_인레트(Rankin_Inlet)"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "중부 표준시 - 누나부트 중부 "
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "아메리카/레시페(Recife)"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "페르남부코 (Pernambuco) "
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "아메리카/리자이나(Regina)"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "중부 표준시 - 사스케추안 - 대부분의 지역 "
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "아메리카/레졸루트(Resolute) "
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "동부 표준시 - 레졸루트, 누나부트 "
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "아메리카/리오_브랑코(Rio_Branco)"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "아크레 (Acre) "
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "아메리카/로사리오(Rosario)"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "아메리카/산타렘 이사벨(Santa Isabel)"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "멕시코 태평양 시간 - 국경에서 먼 바하 캘리포니아"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "아메리카/산타렘 (Santarem) "
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "파라 서부 (W Para) "
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "아메리카/산티아고(Santiago)"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "아메리카/산토_도밍고(Santo_Domingo)"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "아메리카/상_파울로(Sao_Paulo)"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "브라질 남부 및 남동부 (GO, DF, MG, ES, RJ, SP, PR, SC, RS) "
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "아메리카/스코스바이선드(Scoresbysund)"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "스코스바이선드 / 이토코르토르미우트 (Ittoqqortoormiit) "
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "아메리카/쉬프록(Shiprock)"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "산지 표준시 - 나바조 (Navajo) "
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "아메리카/세인트_바데레미(St_Barthelemy)"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "아메리카/세인트_존스(St_Johns)"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "뉴펀들랜드 표준시, SE 래브라도 포함 "
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "아메리카/세인트_키츠(St_Kitts)"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "아메리카/세인트_루시아(St_Lucia)"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "아메리카/세인트_토마스(St_Thomas)"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "아메리카/세인트_빈센트(St_Vincent)"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "아메리카/스위프트_커런트(Swift_Current)"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "중부 표준시 - 사스케추안 - 중서부 "
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "아메리카/테구시갈파(Tegucigalpa)"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "아메리카/툴레(Thule)"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "툴레 (Thule) / 피투픽(Pituffik) "
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "아메리카/썬더_베이(Thunder_Bay)"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "동부 표준시 - 썬더 베이, 온타리오 "
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "아메리카/티후아나(Tijuana)"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "미 태평양 시간 - 국경에 가까운 바하 캘리포니아"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "아메리카/토론토(Toronto)"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "동부 표준시 - 온타리오 - 대부분의 지역 "
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "아메리카/토르톨라(Tortola)"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "아메리카/밴쿠버(Vancouver)"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "태평양 표준시 - 브리티시 콜럼비아 서부 (west British Columbia) "
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "아메리카/버진(Virgin)"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "아메리카/화이트호스(Whitehorse)"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "태평양 표준시 - 유콘 남부 (south Yukon) "
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "아메리카/위니펙(Winnipeg)"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "중부 표준시 - 매니토바 & 온타리오 서부 "
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "아메리카/야쿠타트(Yakutat)"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "알래스카 표준시 - Alaska panhandle neck "
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "아메리카/옐로나이프(Yellowknife)"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "산지 표준시 - 노스웨스트 테리토리 중부 (central Northwest Territories) "
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "남극대륙/케이시(Casey)"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "케이시 기지 (Casey Station), 베일리 반도 (Bailey Peninsula) "
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "남극대륙/데이비스(Davis)"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "데이비스 기지 (Davis Station), 베스트폴드 힐즈 (Vestfold Hills) "
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "남극대륙/드몬두르빌(DumontDUrville)"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "드몬두르빌 기지 (Dumont-d'Urville Station), 테르 아델리 (Terre Adelie) "
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "남극대륙/맥쿼리(Macquarie)"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "맥쿼리섬 기지(Pacquarie Island Station), 맥쿼리 섬(Macquarie Island) "
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "남극대륙/모슨(Mawson)"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "모슨 기지 (Mawson Station), 홈스 베이 (Holme Bay) "
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "남극대륙/맥머도(McMurdo)"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "맥머도 기지(McMurdo Station), 로스섬 (Ross Island) "
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "남극대륙/팔머(Palmer)"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "팔머 기지(Palmer Station), 앙베스섬 (Anvers Island) "
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "남극대륙/로데라(Rothera)"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "로데라 기지(Rothera Station), 애들레이드섬 (Adelaide Island) "
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "남극대륙/남극(South_Pole)"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "아문센스콧 기지 (Amundsen-Scott Station), 남극 "
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "남극대륙/쇼와(Syowa)"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "쇼와 기지 (Syowa Station), 동부 옹굴 섬(E Ongul I) "
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "남극대륙/보스토크(Vostok)"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "보스토크 기지 (Vostok Station), 자남극 "
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "북극해/롱이어벤(Longyearbyen)"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "아시아/아덴(Aden)"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "아시아/알마티(Almaty)"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "아시아/암만(Amman)"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "아시아/아나디르(Anadyr)"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "모스크바+08 - 베링 해 (Bering Sea) "
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "아시아/아크타우(Aqtau)"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "아티라우 (Atirau, Gur'yev), Mangghystau (Mankistau) "
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "아시아/아크토베(Aqtobe)"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "아크토베 (Aktobe) "
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "아시아/아슈가바트(Ashgabat)"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "아시아/아슈하바드(Ashkhabad)"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "아시아/바그다드(Baghdad)"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "아시아/바레인(Bahrain)"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "아시아/바쿠(Baku)"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "아시아/방콕(Bangkok)"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "아시아/베이루트(Beirut)"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "아시아/비슈케크(Bishkek)"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "아시아/브루나이(Brunei)"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "아시아/캘커타(Calcutta)"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "아시아/초이발산(Choibalsan)"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "도르노드 (Dornod), 수흐바타르 (Sukhbaatar) "
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "아시아/충칭(Chongqing)"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "중국 중부 - 사천성, 윈난성, 광서 자치구, 산시성, 귀주성 등. "
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "아시아/충칭(Chungking)"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "아시아/콜롬보(Colombo)"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "아시아/다카(Dacca)"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "아시아/다마스커스(Damascus)"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "아시아/다카(Dhaka)"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "아시아/딜리(Dili)"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "아시아/두바이(Dubai)"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "아시아/두샨베(Dushanbe)"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "아시아/가자(Gaza)"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "아시아/하얼빈(Harbin)"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "흑룡강 (말갈 제외), 길림 "
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "아시아/호치민 (Ho_Chi_Minh) "
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "아시아/홍_콩(Hong_Kong)"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "아시아/홉드(Hovd)"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "바얀-오르기, 고비알타이, 홉드, Uvs, 자브항 "
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "아시아/이르쿠츠크(Irkutsk)"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "모스크바+05 - 바이칼 호수 (Lake Baikal) "
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "아시아/이스탄불(Istanbul)"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "아시아/자카르타(Jakarta)"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "자바 (Java) & 수마트라 (Sumatra) "
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "아시아/자야푸라(Jayapura)"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "이리안 자야 (Irian Jaya) & 몰루카 제도 (Moluccas) "
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "아시아/예루살렘(Jerusalem)"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "아시아/카불(Kabul)"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "아시아/캄차카(Kamchatka)"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "모스크바+08 - 캄차카(Kamchatka) "
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "아시아/카라치(Karachi)"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "아시아/카슈가르(Kashgar)"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "티벳 & 신강 서부 "
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "아시아/카트만두(Kathmandu) "
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "아시아/카트만두(Katmandu)"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "아시아/캘커타 (Kolkata) "
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "아시아/크라스노야르스크(Krasnoyarsk)"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "모스크바+04 - 예니세이강 (Yenisei River) "
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "아시아/쿠알라_룸푸르(Kuala_Lumpur)"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "말레이시아 반도 "
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "아시아/쿠칭(Kuching)"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "사바 (Sabah) & 사라와크 (Sarawak) "
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "아시아/쿠웨이트(Kuwait)"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "아시아/마카오(Macao)"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "아시아/마카우(Macau)"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "아시아/마가단(Magadan)"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "모스크바+08 - 마가단 (Magadan) "
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "아시아/마카사르(Makassar)"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "보르네오 동부 및 남부, 셀레베스, 발리, 누사틍가라, 동 티모르 "
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "아시아/마닐라(Manila)"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "아시아/무스카트(Muscat)"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "아시아/니코시아(Nicosia)"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "아시아/노보쿠즈네츠크(Novokuznetsk)"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "모스크바+03 - 노보쿠즈네츠크(Novokuznetsk)"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "아시아/노보시비르스크(Novosibirsk)"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "모스크바+03 - 노보시비르스크(Novosibirsk) "
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "아시아/옴스크(Omsk)"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "모스크바+03 - 시베리아 서부 "
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "아시아/오럴(Oral)"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "카자흐스탄 서부 "
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "아시아/프놈_펜(Phnom_Penh)"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "아시아/폰티아나크(Pontianak)"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "보르네오 (Borneo) 서부 및 중앙 "
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "아시아/평양(Pyongyang)"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "아시아/카타르(Qatar)"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "아시아/키질로르다(Qyzylorda)"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "키질로르다 (Kyzylorda, Kzyl-Orda) "
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "아시아/랑군(Rangoon)"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "아시아/리야드(Riyadh)"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "아시아/리야드87(Riyadh87)"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "아시아/리야드88(Riyadh88)"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "아시아/리야드89(Riyadh89)"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "아시아/사이공(Saigon)"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "아시아/사할린(Sakhalin)"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "모스크바+07 - 사할린 섬 (Sakhalin Island) "
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "아시아/사마르칸트(Samarkand)"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "우즈베키스탄 (Uzbekistan) 서부 "
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "아시아/서울(Seoul)"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "아시아/상하이(Shanghai)"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "중국 동부 - 베이징, 광동, 상하이 등. "
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "아시아/싱가포르(Singapore)"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "아시아/타이페이(Taipei)"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "아시아/타슈켄트(Tashkent)"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "우즈베키스탄 (Uzbekistan) 동부 "
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "아시아/트빌리시(Tbilisi)"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "아시아/테헤란(Tehran)"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "아시아/텔_아비브(Tel_Aviv)"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "아시아/팀부(Thimbu)"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "아시아/팀푸(Thimphu)"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "아시아/도쿄(Tokyo)"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "아시아/우중_판당(Ujung_Pandang)"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "아시아/울란바타르(Ulaanbaatar)"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "아시아/울란_바토르(Ulan_Bator)"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "아시아/우루무치(Urumqi)"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "티벳 (Tibet) & 신강 (Xinjiang)의 대부분 "
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "아시아/비엔티안(Vientiane)"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "아시아/블라디보스톡(Vladivostok)"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "모스코바+07 - 아무르강 (Amur River) "
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "아시아/야쿠츠크(Yakutsk)"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "모스코바+06 - 레나강 (Lena River) "
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "아시아/예카테린부르크(Yekaterinburg)"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "모스코바+02 - 우랄 (Urals) "
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "아시아/예레반(Yerevan)"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "대서양/아조레스(Azores)"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "아조레스(Azores) "
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "대서양/버뮤다(Bermuda)"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "대서양/카나리아(Canary)"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "카나리아 제도 (Canary Islands) "
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "대서양/카포_베르데(Cape_Verde)"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "대서양/페로(Faeroe)"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "대서양/페로(Faroe)"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "대서양/잔_메이엔(Jan_Mayen)"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "대서양/마데이라(Madeira)"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "마데이라 제도 (Madeira Islands) "
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "대서양/레이캬비크(Reykjavik)"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "대서양/남_조지아(South_Georgia)"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "대서양/스탠리(Stanley)"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "대서양/세인트_헬레나(St_Helena)"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "호주/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "호주/애들레이드(Adelaide)"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "호주 남부 "
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "호주/브리스베인(Brisbane)"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "퀸스랜드 - 대부분의 지역 "
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "호주/브로큰_힐(Broken_Hill)"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "뉴사우스 웨일즈 - 얀코위나 (Yancowinna) "
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "호주/캔버라(Canberra)"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "호주/커리(Currie)"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "태스마니아 - 킹 아일랜드 (King Island) "
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "호주/다윈(Darwin)"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "노던 테리토리 (Northern Territory) "
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "호주/유클라(Eucla)"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "호주 서부 - 유클라(Eucla) 지역 "
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "호주/호바트(Hobart)"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "태스마니아 - 대부분의 지역 "
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "호주/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "호주/린드만(Lindeman)"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "퀸스랜드 - 홀리데이 아일랜드 (Holiday Islands) "
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "호주/로드_하우(Lord_Howe)"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "로드 하우 섬(Lord Howe Island) "
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "호주/멜버른(Melbourne)"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "빅토리아(Victoria) "
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "호주/북부(North)"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "호주/뉴사우스웨일즈(NSW)"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "호주/퍼스(Perth)"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "호주 서부 - 대부분의 지역 "
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "호주/퀸스랜드(Queensland)"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "호주/남부(South)"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "호주/시드니(Sydney)"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "뉴사우스 웨일즈 - 대부분의 지역 "
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "호주/태스마니아(Tasmania)"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "호주/빅토리아(Victoria)"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "호주/서부(West)"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "호주/얀코위나(Yancowinna)"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "브라질/아크레(Acre)"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "브라질/데노론하(DeNoronha)"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "브라질/동부(East)"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "브라질/서부(West)"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "캐나다/아틀란틱(Atlantic)"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "캐나다/중부(Central)"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "캐나다/동부(Eastern)"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "캐나다/동-사스케추안(East-Saskatchewan)"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "캐나다/산맥(Mountain)"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "캐나다/뉴펀들랜드(Newfoundland)"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "캐나다/태평양(Pacific)"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "캐나다/사스케추안(Saskatchewan)"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "캐나다/유콘(Yukon)"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "칠레/전역(Continental)"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "칠레/이스터섬(EasterIsland)"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "쿠바(Cuba)"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "이집트(Egypt)"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "에이레(Eire)"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/그리니치(Greenwich)"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/국제시(Universal)"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/줄루(Zulu)"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "유럽/암스테르담(Amsterdam)"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "유럽/안도라(Andorra)"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "유럽/아테네(Athens)"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "유럽/벨파스트(Belfast)"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "유럽/벨그라드(Belgrade)"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "유럽/베를린(Berlin)"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "유럽/브라티슬라바(Bratislava)"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "유럽/브뤼셀(Brussels)"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "유럽/부카레스트(Bucharest)"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "유럽/부다페스트(Budapest)"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "유럽/치시나우(Chisinau)"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "유럽/코펜하겐(Copenhagen)"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "유럽/더블린(Dublin)"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "유럽/지브롤터(Gibraltar)"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "유럽/건지(Guernsey)"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "유럽/헬싱키(Helsinki)"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "유럽/맨섬(Isle_of_Man)"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "유럽/이스탄불(Istanbul)"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "유럽/저지(Jersey)"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "유럽/칼리닌그라드(Kaliningrad)"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "모스크바-01 - 칼리닌그라드(Kaliningrad) "
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "유럽/키예프(Kiev)"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "유럽/리스본(Lisbon)"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "유럽/류블리아나(Ljubljana)"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "유럽/런던(London)"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "유럽/룩셈부루크(Luxembourg)"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "유럽/마드리드(Madrid)"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "유럽/몰타(Malta)"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "유럽/마리함(Mariehamn)"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "유럽/민스크(Minsk)"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "유럽/모나코(Monaco)"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "유럽/모스크바(Moscow)"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "모스크바+00 - 러시아 서부 (west Russia) "
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "유럽/니코시아(Nicosia)"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "유럽/오슬로(Oslo)"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "유럽/파리(Paris)"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "유럽/포드고리차(Podgorica)"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "유럽/프라하(Prague)"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "유럽/리가(Riga)"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "유럽/로마(Rome)"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "유럽/사마라(Samara)"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "모스크바 - 사마라(Samara), 우드무르트 공화국(Udmurtia) "
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "유럽/산_마리노(San_Marino)"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "유럽/사라예보(Sarajevo)"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "유럽/심페로폴(Simferopol)"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "중앙 크림 반도 (central Crimea) "
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "유럽/스코프예(Skopje)"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "유럽/소피아(Sofia)"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "유럽/스톡홀름(Stockholm)"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "유럽/탈린(Tallinn)"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "유럽/티라나(Tirane)"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "유럽/티라스폴(Tiraspol)"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "유럽/우즈고로드(Uzhgorod)"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "루테니아 (Ruthenia) "
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "유럽/파두츠(Vaduz)"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "유럽/바티칸(Vatican)"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "유럽/비엔나(Vienna)"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "유럽/빌니우스(Vilnius)"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "유럽/볼고그라드(Volgograd)"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "모스크바+00 - 카스피 해(Caspian Sea) "
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "유럽/바르샤바(Warsaw)"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "유럽/자그레브(Zagreb)"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "유럽/자포로제(Zaporozhye)"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+"자포로제(Zaporozh'ye), 동 루간스크(E Lugansk) / 자포르지아(Zaporizhia), 동 루"
+"간스크(E Luhansk) "
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "유럽/취리히(Zurich)"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Factory"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-에이레(GB-Eire)"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "그리니치(Greenwich)"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "홍콩(Hongkong)"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "아이슬랜드(Iceland)"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "인도양/안타나나리보(Antananarivo)"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "인도양/차고스(Chagos)"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "인도양/크리스마스(Christmas)"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "인도양/코코스(Cocos)"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "인도양/코모로(Comoro)"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "인도양/케르구엘렌(Kerguelen)"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "인도양/마헤(Mahe)"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "인도양/몰디브(Maldives)"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "인도양/모리셔스(Mauritius)"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "인도양/마요트(Mayotte)"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "인도양/레위니옹(Reunion)"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "이란(Iran)"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "이스라엘(Israel)"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "자마이카(Jamaica)"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "일본(Japan)"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "콰잘레인(Kwajalein)"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "리비아(Libya)"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "멕시코/바자노르테(BajaNorte)"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "멕시코/바자수르(BajaSur)"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "멕시코/전역(General)"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "중동/리야드87(Riyadh87)"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "중동/리야드88(Riyadh88)"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "중동/리야드89(Riyadh89)"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "나바호(Navajo)"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "태평양/아피아(Apia)"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "태평양/오클랜드(Auckland)"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "태평양/채텀(Chatham) "
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "채텀 제도 (Chatham Islands) "
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "태평양/추우크(Chuuk) "
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "추우크 (트루크) 및 얍 "
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "태평양/이스터(Easter)"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "이스터 섬 (Easter Island) & 살라이고메즈 (Sala y Gomez) "
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "태평양/에파테(Efate)"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "태평양/엔더베리(Enderbury)"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "피닉스 제도 (Phoenix Islands) "
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "태평양/파카오포(Fakaofo)"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "태평양/피지(Fiji)"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "태평양/푸나푸티(Funafuti)"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "태평양/갈라파고스(Galapagos)"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "갈라파고스 제도 (Galapagos Islands) "
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "태평양/갬비어(Gambier)"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "갬비어 제도 (Gambier Islands) "
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "태평양/과달카날(Guadalcanal)"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "태평양/괌(Guam)"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "태평양/호놀룰루(Honolulu)"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "하와이(Hawaii) "
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "태평양/존스톤(Johnston)"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "존스톤 섬 (Johnston Atoll) "
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "태평양/키리티마티(Kiritimati)"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "라인 제도(Line Islands) "
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "태평양/코스레(Kosrae)"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "코스레(Kosrae) "
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "태평양/콰잘레인(Kwajalein)"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "태평양/마주로(Majuro)"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "태평양/마르퀘사스(Marquesas)"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "마르퀘사스 제도 (Marquesas Islands) "
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "태평양/미드웨이(Midway)"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "미드웨이 제도 (Midway Islands) "
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "태평양/나우루(Nauru)"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "태평양/니우에(Niue)"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "태평양/노르폭(Norfolk)"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "태평양/누메아(Noumea)"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "태평양/파고_파고(Pago_Pago)"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "태평양/팔라우(Palau)"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "태평양/피트케언(Pitcairn)"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "태평양/폰페이(Pohnpei) "
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "폰페이 (포나페) "
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "태평양/포나페(Ponape)"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "태평양/포트_모스비(Port_Moresby)"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "태평양/라로통가(Rarotonga)"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "태평양/사이판(Saipan)"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "태평양/사모아(Samoa)"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "태평양/타히티(Tahiti)"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "소시에테 제도 (Society Islands) "
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "태평양/타라와(Tarawa)"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "길버트 제도 (Gilbert Islands) "
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "태평양/통가타푸(Tongatapu)"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "태평양/트루크(Truk)"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "태평양/웨이크(Wake)"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "웨이크 섬 (Wake Island) "
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "태평양/월리스(Wallis)"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "태평양/얍(Yap)"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "폴란드(Poland)"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "포르투갈(Portugal)"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "대한민국(ROK)"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "싱가포르(Singapore)"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "터키(Turkey)"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "국제시(Universal)"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "미국/알래스카(Alaska)"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "미국/알류샨(Aleutian)"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "미국/아리조나(Arizona)"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "미국/중부(Central)"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "미국/동부(Eastern)"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "미국/동-인디애나(East-Indiana)"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "미국/하와이(Hawaii)"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "미국/인디애나-스타크(Indiana-Starke)"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "미국/미시간(Michigan)"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "미국/산맥(Mountain)"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "미국/태평양(Pacific)"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "미국/사모아(Samoa)"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "줄루(Zulu)"
+
diff --git a/panels/datetime/po-timezones/ku.po b/panels/datetime/po-timezones/ku.po
new file mode 100644
index 0000000..0cd6d1d
--- /dev/null
+++ b/panels/datetime/po-timezones/ku.po
@@ -0,0 +1,3237 @@
+# Kurdish translations for PACKAGE package.
+# Copyright (C) 2004 THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# Automatically generated, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2002-04-12 17:04-0400\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ASCII\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr ""
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr ""
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr ""
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr ""
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr ""
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr ""
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr ""
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr ""
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr ""
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr ""
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr ""
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr ""
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr ""
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr ""
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr ""
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr ""
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr ""
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr ""
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr ""
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr ""
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr ""
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr ""
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr ""
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr ""
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr ""
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr ""
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr ""
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr ""
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr ""
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr ""
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr ""
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr ""
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr ""
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr ""
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr ""
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr ""
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr ""
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr ""
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr ""
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr ""
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr ""
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr ""
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr ""
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr ""
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr ""
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr ""
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr ""
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr ""
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr ""
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr ""
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr ""
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr ""
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr ""
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr ""
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr ""
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr ""
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr ""
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr ""
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr ""
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr ""
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr ""
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr ""
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr ""
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr ""
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr ""
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr ""
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr ""
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr ""
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr ""
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr ""
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr ""
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr ""
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr ""
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr ""
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr ""
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr ""
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr ""
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr ""
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr ""
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr ""
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr ""
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr ""
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr ""
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr ""
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr ""
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr ""
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr ""
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr ""
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr ""
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr ""
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr ""
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr ""
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr ""
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr ""
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr ""
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr ""
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr ""
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr ""
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr ""
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr ""
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr ""
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr ""
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr ""
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr ""
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr ""
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr ""
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr ""
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr ""
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr ""
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr ""
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr ""
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr ""
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr ""
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr ""
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr ""
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr ""
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr ""
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr ""
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr ""
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr ""
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr ""
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr ""
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr ""
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr ""
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr ""
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr ""
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr ""
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr ""
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr ""
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr ""
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr ""
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr ""
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr ""
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr ""
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr ""
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr ""
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr ""
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr ""
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr ""
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr ""
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr ""
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr ""
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr ""
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr ""
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr ""
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr ""
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr ""
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr ""
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr ""
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr ""
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr ""
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr ""
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr ""
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr ""
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr ""
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr ""
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr ""
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr ""
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr ""
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr ""
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr ""
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr ""
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr ""
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr ""
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr ""
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr ""
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr ""
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr ""
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr ""
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr ""
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr ""
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr ""
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr ""
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr ""
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr ""
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr ""
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr ""
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr ""
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr ""
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr ""
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr ""
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr ""
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr ""
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr ""
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr ""
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr ""
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr ""
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr ""
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr ""
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr ""
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr ""
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr ""
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr ""
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr ""
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr ""
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr ""
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr ""
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr ""
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr ""
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr ""
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr ""
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr ""
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr ""
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr ""
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr ""
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr ""
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr ""
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr ""
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr ""
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr ""
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr ""
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr ""
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr ""
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr ""
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr ""
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr ""
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr ""
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr ""
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr ""
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr ""
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr ""
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr ""
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr ""
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr ""
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr ""
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr ""
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr ""
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr ""
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr ""
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr ""
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr ""
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr ""
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr ""
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr ""
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr ""
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr ""
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr ""
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr ""
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr ""
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr ""
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr ""
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr ""
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr ""
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr ""
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr ""
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr ""
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr ""
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr ""
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr ""
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr ""
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr ""
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr ""
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr ""
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr ""
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr ""
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr ""
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr ""
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr ""
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr ""
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr ""
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr ""
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr ""
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr ""
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr ""
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr ""
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr ""
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr ""
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr ""
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr ""
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr ""
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr ""
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr ""
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr ""
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr ""
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr ""
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr ""
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr ""
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr ""
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr ""
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr ""
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr ""
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr ""
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr ""
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr ""
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr ""
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr ""
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr ""
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr ""
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr ""
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr ""
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr ""
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr ""
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr ""
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr ""
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr ""
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr ""
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr ""
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr ""
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr ""
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr ""
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr ""
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr ""
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr ""
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr ""
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr ""
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr ""
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr ""
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr ""
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr ""
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr ""
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr ""
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr ""
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr ""
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr ""
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr ""
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr ""
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr ""
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr ""
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr ""
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr ""
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr ""
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr ""
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr ""
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr ""
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr ""
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr ""
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr ""
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr ""
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr ""
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr ""
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr ""
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr ""
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr ""
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr ""
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr ""
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr ""
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr ""
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr ""
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr ""
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr ""
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr ""
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr ""
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr ""
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr ""
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr ""
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr ""
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr ""
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr ""
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr ""
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr ""
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr ""
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr ""
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr ""
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr ""
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr ""
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr ""
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr ""
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr ""
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr ""
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr ""
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr ""
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr ""
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr ""
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr ""
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr ""
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr ""
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr ""
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr ""
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr ""
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr ""
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr ""
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr ""
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr ""
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr ""
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr ""
+
+#: timezones.h:685
+msgid "CET"
+msgstr ""
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr ""
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr ""
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr ""
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr ""
+
+#: timezones.h:690
+msgid "EET"
+msgstr ""
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr ""
+
+#: timezones.h:692
+msgid "Eire"
+msgstr ""
+
+#: timezones.h:693
+msgid "EST"
+msgstr ""
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr ""
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr ""
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr ""
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr ""
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr ""
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr ""
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr ""
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr ""
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr ""
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr ""
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr ""
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr ""
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr ""
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr ""
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr ""
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr ""
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr ""
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr ""
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr ""
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr ""
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr ""
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr ""
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr ""
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr ""
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr ""
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr ""
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr ""
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr ""
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr ""
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr ""
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr ""
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr ""
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr ""
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr ""
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr ""
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr ""
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr ""
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr ""
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr ""
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr ""
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr ""
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr ""
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr ""
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr ""
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr ""
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr ""
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr ""
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr ""
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr ""
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr ""
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr ""
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr ""
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr ""
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr ""
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr ""
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr ""
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr ""
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr ""
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr ""
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr ""
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr ""
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr ""
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr ""
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr ""
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr ""
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr ""
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr ""
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr ""
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr ""
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr ""
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr ""
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr ""
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr ""
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr ""
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr ""
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr ""
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr ""
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr ""
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr ""
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr ""
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr ""
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr ""
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr ""
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr ""
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr ""
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr ""
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr ""
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr ""
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr ""
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr ""
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr ""
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr ""
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr ""
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr ""
+
+#: timezones.h:808
+msgid "Factory"
+msgstr ""
+
+#: timezones.h:809
+msgid "GB"
+msgstr ""
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr ""
+
+#: timezones.h:811
+msgid "GMT"
+msgstr ""
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr ""
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr ""
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr ""
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr ""
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr ""
+
+#: timezones.h:817
+msgid "HST"
+msgstr ""
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr ""
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr ""
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr ""
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr ""
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr ""
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr ""
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr ""
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr ""
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr ""
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr ""
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr ""
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr ""
+
+#: timezones.h:830
+msgid "Iran"
+msgstr ""
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr ""
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr ""
+
+#: timezones.h:834
+msgid "Japan"
+msgstr ""
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr ""
+
+#: timezones.h:836
+msgid "Libya"
+msgstr ""
+
+#: timezones.h:837
+msgid "MET"
+msgstr ""
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr ""
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr ""
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr ""
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr ""
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr ""
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr ""
+
+#: timezones.h:844
+msgid "MST"
+msgstr ""
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr ""
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr ""
+
+#: timezones.h:847
+msgid "NZ"
+msgstr ""
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr ""
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr ""
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr ""
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr ""
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr ""
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr ""
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr ""
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr ""
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr ""
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr ""
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr ""
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr ""
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr ""
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr ""
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr ""
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr ""
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr ""
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr ""
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr ""
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr ""
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr ""
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr ""
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr ""
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr ""
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr ""
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr ""
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr ""
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr ""
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr ""
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr ""
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr ""
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr ""
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr ""
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr ""
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr ""
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr ""
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr ""
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr ""
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr ""
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr ""
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr ""
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr ""
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr ""
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr ""
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr ""
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr ""
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr ""
+
+#: timezones.h:929
+msgid "Poland"
+msgstr ""
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr ""
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr ""
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr ""
+
+#: timezones.h:934
+msgid "ROC"
+msgstr ""
+
+#: timezones.h:935
+msgid "ROK"
+msgstr ""
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr ""
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr ""
+
+#: timezones.h:938
+msgid "UCT"
+msgstr ""
+
+#: timezones.h:939
+msgid "Universal"
+msgstr ""
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr ""
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr ""
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr ""
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr ""
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr ""
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr ""
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr ""
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr ""
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr ""
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr ""
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr ""
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr ""
+
+#: timezones.h:952
+msgid "UTC"
+msgstr ""
+
+#: timezones.h:953
+msgid "WET"
+msgstr ""
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr ""
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr ""
diff --git a/panels/datetime/po-timezones/lo.po b/panels/datetime/po-timezones/lo.po
new file mode 100644
index 0000000..854ed50
--- /dev/null
+++ b/panels/datetime/po-timezones/lo.po
@@ -0,0 +1,3237 @@
+# Laotian translations for PACKAGE package.
+# Copyright (C) 2004 THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# Automatically generated, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: redhat-config-packages\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2002-04-12 17:04-0400\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr ""
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr ""
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr ""
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr ""
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr ""
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr ""
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr ""
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr ""
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr ""
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr ""
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr ""
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr ""
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr ""
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr ""
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr ""
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr ""
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr ""
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr ""
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr ""
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr ""
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr ""
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr ""
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr ""
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr ""
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr ""
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr ""
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr ""
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr ""
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr ""
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr ""
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr ""
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr ""
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr ""
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr ""
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr ""
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr ""
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr ""
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr ""
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr ""
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr ""
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr ""
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr ""
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr ""
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr ""
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr ""
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr ""
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr ""
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr ""
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr ""
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr ""
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr ""
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr ""
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr ""
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr ""
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr ""
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr ""
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr ""
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr ""
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr ""
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr ""
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr ""
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr ""
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr ""
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr ""
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr ""
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr ""
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr ""
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr ""
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr ""
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr ""
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr ""
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr ""
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr ""
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr ""
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr ""
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr ""
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr ""
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr ""
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr ""
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr ""
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr ""
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr ""
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr ""
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr ""
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr ""
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr ""
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr ""
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr ""
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr ""
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr ""
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr ""
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr ""
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr ""
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr ""
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr ""
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr ""
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr ""
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr ""
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr ""
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr ""
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr ""
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr ""
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr ""
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr ""
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr ""
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr ""
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr ""
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr ""
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr ""
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr ""
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr ""
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr ""
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr ""
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr ""
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr ""
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr ""
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr ""
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr ""
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr ""
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr ""
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr ""
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr ""
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr ""
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr ""
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr ""
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr ""
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr ""
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr ""
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr ""
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr ""
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr ""
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr ""
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr ""
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr ""
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr ""
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr ""
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr ""
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr ""
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr ""
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr ""
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr ""
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr ""
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr ""
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr ""
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr ""
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr ""
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr ""
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr ""
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr ""
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr ""
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr ""
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr ""
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr ""
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr ""
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr ""
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr ""
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr ""
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr ""
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr ""
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr ""
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr ""
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr ""
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr ""
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr ""
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr ""
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr ""
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr ""
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr ""
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr ""
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr ""
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr ""
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr ""
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr ""
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr ""
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr ""
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr ""
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr ""
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr ""
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr ""
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr ""
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr ""
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr ""
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr ""
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr ""
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr ""
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr ""
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr ""
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr ""
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr ""
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr ""
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr ""
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr ""
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr ""
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr ""
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr ""
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr ""
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr ""
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr ""
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr ""
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr ""
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr ""
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr ""
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr ""
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr ""
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr ""
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr ""
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr ""
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr ""
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr ""
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr ""
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr ""
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr ""
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr ""
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr ""
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr ""
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr ""
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr ""
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr ""
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr ""
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr ""
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr ""
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr ""
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr ""
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr ""
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr ""
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr ""
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr ""
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr ""
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr ""
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr ""
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr ""
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr ""
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr ""
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr ""
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr ""
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr ""
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr ""
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr ""
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr ""
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr ""
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr ""
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr ""
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr ""
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr ""
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr ""
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr ""
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr ""
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr ""
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr ""
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr ""
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr ""
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr ""
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr ""
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr ""
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr ""
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr ""
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr ""
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr ""
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr ""
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr ""
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr ""
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr ""
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr ""
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr ""
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr ""
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr ""
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr ""
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr ""
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr ""
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr ""
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr ""
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr ""
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr ""
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr ""
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr ""
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr ""
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr ""
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr ""
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr ""
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr ""
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr ""
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr ""
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr ""
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr ""
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr ""
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr ""
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr ""
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr ""
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr ""
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr ""
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr ""
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr ""
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr ""
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr ""
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr ""
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr ""
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr ""
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr ""
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr ""
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr ""
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr ""
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr ""
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr ""
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr ""
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr ""
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr ""
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr ""
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr ""
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr ""
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr ""
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr ""
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr ""
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr ""
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr ""
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr ""
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr ""
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr ""
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr ""
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr ""
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr ""
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr ""
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr ""
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr ""
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr ""
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr ""
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr ""
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr ""
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr ""
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr ""
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr ""
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr ""
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr ""
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr ""
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr ""
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr ""
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr ""
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr ""
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr ""
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr ""
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr ""
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr ""
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr ""
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr ""
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr ""
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr ""
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr ""
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr ""
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr ""
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr ""
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr ""
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr ""
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr ""
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr ""
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr ""
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr ""
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr ""
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr ""
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr ""
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr ""
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr ""
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr ""
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr ""
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr ""
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr ""
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr ""
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr ""
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr ""
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr ""
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr ""
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr ""
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr ""
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr ""
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr ""
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr ""
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr ""
+
+#: timezones.h:685
+msgid "CET"
+msgstr ""
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr ""
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr ""
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr ""
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr ""
+
+#: timezones.h:690
+msgid "EET"
+msgstr ""
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr ""
+
+#: timezones.h:692
+msgid "Eire"
+msgstr ""
+
+#: timezones.h:693
+msgid "EST"
+msgstr ""
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr ""
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr ""
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr ""
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr ""
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr ""
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr ""
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr ""
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr ""
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr ""
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr ""
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr ""
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr ""
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr ""
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr ""
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr ""
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr ""
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr ""
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr ""
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr ""
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr ""
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr ""
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr ""
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr ""
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr ""
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr ""
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr ""
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr ""
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr ""
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr ""
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr ""
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr ""
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr ""
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr ""
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr ""
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr ""
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr ""
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr ""
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr ""
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr ""
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr ""
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr ""
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr ""
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr ""
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr ""
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr ""
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr ""
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr ""
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr ""
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr ""
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr ""
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr ""
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr ""
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr ""
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr ""
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr ""
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr ""
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr ""
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr ""
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr ""
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr ""
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr ""
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr ""
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr ""
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr ""
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr ""
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr ""
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr ""
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr ""
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr ""
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr ""
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr ""
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr ""
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr ""
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr ""
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr ""
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr ""
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr ""
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr ""
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr ""
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr ""
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr ""
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr ""
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr ""
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr ""
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr ""
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr ""
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr ""
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr ""
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr ""
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr ""
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr ""
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr ""
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr ""
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr ""
+
+#: timezones.h:808
+msgid "Factory"
+msgstr ""
+
+#: timezones.h:809
+msgid "GB"
+msgstr ""
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr ""
+
+#: timezones.h:811
+msgid "GMT"
+msgstr ""
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr ""
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr ""
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr ""
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr ""
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr ""
+
+#: timezones.h:817
+msgid "HST"
+msgstr ""
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr ""
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr ""
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr ""
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr ""
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr ""
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr ""
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr ""
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr ""
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr ""
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr ""
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr ""
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr ""
+
+#: timezones.h:830
+msgid "Iran"
+msgstr ""
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr ""
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr ""
+
+#: timezones.h:834
+msgid "Japan"
+msgstr ""
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr ""
+
+#: timezones.h:836
+msgid "Libya"
+msgstr ""
+
+#: timezones.h:837
+msgid "MET"
+msgstr ""
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr ""
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr ""
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr ""
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr ""
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr ""
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr ""
+
+#: timezones.h:844
+msgid "MST"
+msgstr ""
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr ""
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr ""
+
+#: timezones.h:847
+msgid "NZ"
+msgstr ""
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr ""
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr ""
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr ""
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr ""
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr ""
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr ""
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr ""
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr ""
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr ""
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr ""
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr ""
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr ""
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr ""
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr ""
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr ""
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr ""
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr ""
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr ""
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr ""
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr ""
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr ""
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr ""
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr ""
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr ""
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr ""
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr ""
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr ""
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr ""
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr ""
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr ""
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr ""
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr ""
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr ""
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr ""
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr ""
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr ""
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr ""
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr ""
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr ""
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr ""
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr ""
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr ""
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr ""
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr ""
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr ""
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr ""
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr ""
+
+#: timezones.h:929
+msgid "Poland"
+msgstr ""
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr ""
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr ""
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr ""
+
+#: timezones.h:934
+msgid "ROC"
+msgstr ""
+
+#: timezones.h:935
+msgid "ROK"
+msgstr ""
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr ""
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr ""
+
+#: timezones.h:938
+msgid "UCT"
+msgstr ""
+
+#: timezones.h:939
+msgid "Universal"
+msgstr ""
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr ""
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr ""
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr ""
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr ""
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr ""
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr ""
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr ""
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr ""
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr ""
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr ""
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr ""
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr ""
+
+#: timezones.h:952
+msgid "UTC"
+msgstr ""
+
+#: timezones.h:953
+msgid "WET"
+msgstr ""
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr ""
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr ""
diff --git a/panels/datetime/po-timezones/lt.po b/panels/datetime/po-timezones/lt.po
new file mode 100644
index 0000000..0cf4c10
--- /dev/null
+++ b/panels/datetime/po-timezones/lt.po
@@ -0,0 +1,3351 @@
+# translation of lt.po to Lithuanian
+# translation of timezones.po to Lithuanian
+# This file is distributed under the same license as the PACKAGE package.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER.
+# Robertas Dereškevičius <roberto@mikrovisata.net>, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: lt\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2004-05-20 11:29+0300\n"
+"Last-Translator: Robertas Dereškevičius <roberto@mikrovisata.net>\n"
+"Language-Team: Lithuanian\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.3.1\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Afrika/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Afrika/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Afrika/Addis_Ababa"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Afrika/Algiers"
+
+#: timezones.h:5
+#, fuzzy
+msgid "Africa/Asmara"
+msgstr "Afrika/Asmera"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Afrika/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Afrika/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Afrika/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Afrika/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Afrika/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Afrika/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Afrika/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Afrika/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Afrika/Kairas"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Afrika/Kasablanka"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Afrika/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Afrika/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Afrika/Dakaras"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Afrika/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Afrika/Djibouti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Afrika/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Afrika/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Afrika/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Afrika/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Afrika/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Afrika/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Afrika/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Afrika/Khartoum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Afrika/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Afrika/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Afrika/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Afrika/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Afrika/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Afrika/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Afrika/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Afrika/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Afrika/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Afrika/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Afrika/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Afrika/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Afrika/Mogadishu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Afrika/Monrovija"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Afrika/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Afrika/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Afrika/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Afrika/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Afrika/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Afrika/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Afrika/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Afrika/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Afrika/Tripolis"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Afrika/Tunisas"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Afrika/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Amerika/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+#, fuzzy
+msgid "Aleutian Islands"
+msgstr "Australija/Queensland"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Amerika/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+#, fuzzy
+msgid "Alaska Time"
+msgstr "JAV/Alaska"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Amerika/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Amerika/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Amerika/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+#, fuzzy
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Amerika/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+#, fuzzy
+msgid "America/Argentina/Catamarca"
+msgstr "Amerika/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+#, fuzzy
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Amerika/Indiana/Indianapolis"
+
+#: timezones.h:78
+#, fuzzy
+msgid "America/Argentina/Cordoba"
+msgstr "Amerika/Cordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+#, fuzzy
+msgid "America/Argentina/Jujuy"
+msgstr "Amerika/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+#, fuzzy
+msgid "America/Argentina/La_Rioja"
+msgstr "Amerika/Araguaina"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+#, fuzzy
+msgid "America/Argentina/Mendoza"
+msgstr "Amerika/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+#, fuzzy
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Amerika/Indiana/Marengo"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+#, fuzzy
+msgid "America/Argentina/Salta"
+msgstr "Amerika/Antigua"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+#, fuzzy
+msgid "America/Argentina/San_Juan"
+msgstr "Amerika/Antigua"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+#, fuzzy
+msgid "America/Argentina/San_Luis"
+msgstr "Amerika/Antigua"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+#, fuzzy
+msgid "America/Argentina/Tucuman"
+msgstr "Amerika/Antigua"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+#, fuzzy
+msgid "America/Argentina/Ushuaia"
+msgstr "Amerika/Araguaina"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Amerika/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Amerika/Asuncion"
+
+#: timezones.h:110
+#, fuzzy
+msgid "America/Atikokan"
+msgstr "Amerika/Atka"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Amerika/Atka"
+
+#: timezones.h:114
+#, fuzzy
+msgid "America/Bahia"
+msgstr "Amerika/Boa_Vista"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "Amerika/Boa_Vista"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Amerika/Barbadosas"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Amerika/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Amerika/Belize"
+
+#: timezones.h:125
+#, fuzzy
+msgid "America/Blanc-Sablon"
+msgstr "Amerika/Cancun"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Amerika/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Amerika/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Amerika/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Amerika/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Amerika/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+#, fuzzy
+msgid "America/Campo_Grande"
+msgstr "Amerika/Cayman"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Amerika/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Amerika/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Amerika/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Amerika/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Amerika/Cayman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Amerika/Čikago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+#, fuzzy
+msgid "Central Time"
+msgstr "JAV/Central"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Amerika/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+#, fuzzy
+msgid "America/Coral_Harbour"
+msgstr "Amerika/Curacao"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Amerika/Cordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Amerika/Kosta_Rika"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Amerika/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Amerika/Curacao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Amerika/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Amerika/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Amerika/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Amerika/Denveris"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+#, fuzzy
+msgid "Mountain Time"
+msgstr "JAV/Mountain"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Amerika/Detroitas"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Amerika/Dominika"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Amerika/Edmontonas"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Amerika/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Amerika/El_Salvadoras"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Amerika/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Amerika/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Amerika/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Amerika/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Amerika/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Amerika/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Amerika/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Amerika/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Amerika/Guadeloupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Amerika/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Amerika/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Amerika/Guyana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Amerika/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Amerika/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Amerika/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Amerika/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Amerika/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Amerika/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+#, fuzzy
+msgid "America/Indiana/Petersburg"
+msgstr "Amerika/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Amerika/Indianapolis"
+
+#: timezones.h:227
+#, fuzzy
+msgid "America/Indiana/Tell_City"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+#, fuzzy
+msgid "America/Indiana/Vincennes"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+#, fuzzy
+msgid "America/Indiana/Winamac"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Amerika/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Amerika/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Amerika/Jamaika"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Amerika/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Amerika/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Amerika/Kentukis/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+#, fuzzy
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Amerika/Kentukis/Louisville"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Amerika/Kentukis/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Amerika/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Amerika/La_Pazas"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Amerika/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Amerika/Los_Andželas"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+#, fuzzy
+msgid "Pacific Time"
+msgstr "Pacific/Niue"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Amerika/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Amerika/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Amerika/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Amerika/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+#, fuzzy
+msgid "America/Marigot"
+msgstr "Amerika/Maceio"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Amerika/Martinique"
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "Amerika/Manaus"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Amerika/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Amerika/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Amerika/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Amerika/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Amerika/Mexico_City"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Amerika/Miquelon"
+
+#: timezones.h:289
+#, fuzzy
+msgid "America/Moncton"
+msgstr "Amerika/Edmontonas"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Amerika/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Amerika/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Amerika/Montrealis"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Amerika/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Amerika/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Amerika/Niu_Jorkas"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+#, fuzzy
+msgid "Eastern Time"
+msgstr "JAV/Eastern"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Amerika/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Amerika/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Amerika/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+#, fuzzy
+msgid "Atlantic islands"
+msgstr "Atlantika/Kanarai"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Amerika/Šiaurės_Dakota/Center"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+#, fuzzy
+msgid "America/North_Dakota/New_Salem"
+msgstr "Amerika/Šiaurės_Dakota/Center"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "Amerika/Managua"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Amerika/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Amerika/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Amerika/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Amerika/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Amerika/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Amerika/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Amerika/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Amerika/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Amerika/Puerto_Riko"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Amerika/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Amerika/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Amerika/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Amerika/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+#, fuzzy
+msgid "America/Resolute"
+msgstr "Amerika/Belem"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Amerika/Rio_Branko"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Amerika/Rosario"
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "Amerika/Santiago"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+#, fuzzy
+msgid "America/Santarem"
+msgstr "Amerika/Santiago"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Amerika/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Amerika/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Amerika/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Amerika/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Amerika/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+#, fuzzy
+msgid "America/St_Barthelemy"
+msgstr "Amerika/Belem"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Amerika/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Amerika/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Amerika/St_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Amerika/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Amerika/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Amerika/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Amerika/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Amerika/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Amerika/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Amerika/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+#, fuzzy
+msgid "America/Toronto"
+msgstr "Amerika/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Amerika/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Amerika/Vankuveris"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Amerika/Virdžinija"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Amerika/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Amerika/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Amerika/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Amerika/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antarktika/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antarktika/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antarktika/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+#, fuzzy
+msgid "Antarctica/Macquarie"
+msgstr "Antarktika/McMurdo"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antarktika/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antarktika/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antarktika/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+#, fuzzy
+msgid "Antarctica/Rothera"
+msgstr "Antarktika/South_Pole"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antarktika/South_Pole"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antarktika/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antarktika/Vostokas"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Arktika/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Azija/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Azija/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Azija/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Azija/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Azija/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Azija/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Azija/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Azija/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Azija/Bagdadas"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Azija/Bahrain"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Azija/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Azija/Bankokas"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Azija/Beirutas"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Azija/Biškekas"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Azija/Brunėjus"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Azija/Kalkuta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Azija/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Azija/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Azija/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Azija/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Azija/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Azija/Damaskas"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Azija/Dhaka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Azija/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Azija/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Azija/Dušanbė"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Azija/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Azija/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+#, fuzzy
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Azija/Chongqing"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Azija/Hong_Kongas"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Azija/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Azija/Irkutskas"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Azija/Stambulas"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Azija/Jakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Azija/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Azija/Jeruzalė"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Azija/Kabulas"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Azija/Kamčatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Azija/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Azija/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+#, fuzzy
+msgid "Asia/Kathmandu"
+msgstr "Azija/Katmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Azija/Katmandu"
+
+#: timezones.h:518
+#, fuzzy
+msgid "Asia/Kolkata"
+msgstr "Azija/Jakarta"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Azija/Krasnojarskas"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Azija/Kuala_Lumpuras"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Azija/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Azija/Kuveitas"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Azija/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Azija/Macau"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Azija/Magadanas"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Azija/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Azija/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Azija/Muskatas"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Azija/Nikozija"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "Azija/Irkutskas"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Azija/Novosibirskas"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Azija/Novosibirskas"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+#, fuzzy
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Azija/Novosibirskas"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Azija/Omskas"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Azija/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Azija/Phnom_Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Azika/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Azija/Pyongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Azija/Kataras"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Azija/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Azija/Rangoon"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Azija/Riyadh"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Azija/Riyadh87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Azija/Riyadh88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Azija/Riyadh89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Azija/Saigonas"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Azija/Sakhalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Azija/Samarkandas"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Azija/Seulas"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Azija/Šanhajus"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Azija/Singapūras"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Azija/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Azia/Taškentas"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Azija/Tbilisis"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Azija/Tehran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Azija/Tel_Avivas"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Azija/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Azija/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Azija/Tokijus"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Azija/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Azija/Ulaanbaatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Azija/Ulan_Batoras"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Azija/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Azija/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Azija/Vladivostokas"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Azija/Jakutskas"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Azija/Jekaterinburgas"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Azija/Jerevanas"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlantika/Azores"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlantika/Bermudai"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlantika/Kanarai"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlantika/Cape_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlantika/Faeroe"
+
+#: timezones.h:616
+#, fuzzy
+msgid "Atlantic/Faroe"
+msgstr "Atlantika/Faeroe"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlantika/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlantika/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlantika/Reikjavikas"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlantika/South_Georgia"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlantika/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlantika/St_Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Australija/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Australija/Adelaidė"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+#, fuzzy
+msgid "South Australia"
+msgstr "Australija/ACT"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Australija/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Australija/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Australija/Kanbera"
+
+#: timezones.h:636
+#, fuzzy
+msgid "Australia/Currie"
+msgstr "Australija/Kanbera"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Australija/Darvinas"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+#, fuzzy
+msgid "Australia/Eucla"
+msgstr "Australija/Queensland"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+#, fuzzy
+msgid "Western Australia - Eucla area"
+msgstr "Australija/Queensland"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Australija/Hobartas"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Australija/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Australija/Lindemanas"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Australija/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Australija/Melburnas"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+#, fuzzy
+msgid "Victoria"
+msgstr "Australija/Viktorija"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Australija/Šiaurė"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Australija/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Australija/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Australija/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Australija/Pietūs"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Australija/Sidnėjus"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Australija/Tasmanija"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Australija/Viktorija"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Australija/Vakarai"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Australija/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brazilija/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brazilija/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brazilija/Rytai"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brazilija/Vakarai"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Kanada/Atlantika"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Kanada/Centrinė"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Kanada/Rytinė"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Kanada/East-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Kanada/Mountain"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Kanada/Newfoundland"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Kanada/Pacific"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Kanada/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Kanada/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Čilė/Continental"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Čilė/EasterIsland"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Kuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Egiptas"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Eire"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Grinvičio"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universalus"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Europa/Amsterdamas"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Europa/Andora"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Europa/Atėnai"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Europa/Belfastas"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Europa/Belgradas"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Europa/Berlinas"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Europa/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Europa/Briuselis"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Europa/Buchareštas"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Europa/Budapeštas"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Europa/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Europa/Kopenhaga"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Europa/Dublinas"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Europa/Gibraltaras"
+
+#: timezones.h:744
+#, fuzzy
+msgid "Europe/Guernsey"
+msgstr "Europa/Atėnai"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Europa/Helsinkis"
+
+#: timezones.h:746
+#, fuzzy
+msgid "Europe/Isle_of_Man"
+msgstr "Europa/Oslas"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Europa/Stambulas"
+
+#: timezones.h:748
+#, fuzzy
+msgid "Europe/Jersey"
+msgstr "Europa/Paryžius"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Europa/Kaliningradas"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Europa/Kijevas"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Europa/Lisabona"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Europa/Liublijana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Europa/Londonas"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Europa/Luksemburgas"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Europa/Madridas"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Europa/Malta"
+
+#: timezones.h:765
+#, fuzzy
+msgid "Europe/Mariehamn"
+msgstr "Europa/Madridas"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Europa/Minskas"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Europa/Monako"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Europa/Maskva"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Europa/Nikozija"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Europa/Oslas"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Europa/Paryžius"
+
+#: timezones.h:774
+#, fuzzy
+msgid "Europe/Podgorica"
+msgstr "Europa/Andora"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Europa/Praha"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Europa/Ryga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Europa/Roma"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Europa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Europa/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Europa/Sarajevas"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Europa/Simferopolis"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Europa/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Europa/Sofija"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Europa/Stoholmas"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Europa/Talinas"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Europa/Tirane"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Europa/Tiraspolis"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Europas/Uzhgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Europa/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Europa/Vatikanas"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Europa/Viena"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Europe/Vilnius"
+
+#: timezones.h:799
+#, fuzzy
+msgid "Europe/Volgograd"
+msgstr "Europa/Belgradas"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Europa/Varšuva"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Europa/Zagrebas"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Europa/Zaporožė"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Europa/Ciurichas"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Factory"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Eire"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Grivičio"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkongas"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Islandija"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Indiana/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Indiana/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Indiana/Christmas"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Indiana/Cocos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Indiana/Comoro"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Indiana/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Indiana/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Indiana/Maldives"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Indiana/Mauritius"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Indiana/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Indiana/Reunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Iranas"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Izraelis"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamaika"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Japonija"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Libija"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Meksika/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Meksika/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Meksika/General"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Mideast/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Mideast/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Mideast/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Pacific/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Pacific/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Pacific/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+#, fuzzy
+msgid "Chatham Islands"
+msgstr "Čilė/EasterIsland"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "Pacific/Truk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+#, fuzzy
+msgid "Pacific/Easter"
+msgstr "Pacific/Easter"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Pacific/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Pacific/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Pacific/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Pacific/Fiji"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Pacific/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Pacific/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Pacific/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Pacific/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Pacific/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Pacific/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+#, fuzzy
+msgid "Hawaii"
+msgstr "JAV/Havajai"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Pacific/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Pacific/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Pacific/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+#, fuzzy
+msgid "Kosrae"
+msgstr "Izraelis"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Pacific/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Pacific/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Pacific/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Pacific/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Pacific/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Pacific/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Pacific/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Pacific/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Pacific/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Pacific/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Pacific/Pitcairn"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "Pacific/Ponape"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Pacific/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Pacific/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Pacific/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Pacific/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Pacific/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Pacific/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Pacific/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+#, fuzzy
+msgid "Gilbert Islands"
+msgstr "Čilė/EasterIsland"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Pacific/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Pacific/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Pacific/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Pacific/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Pacific/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Lenkija"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugalija"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapūras"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Turkija"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "JAV/Alaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "JAV/Aleutian"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "JAV/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "JAV/Central"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "JAV/Eastern"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "JAV/East-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "JAV/Havajai"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "JAV/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "JAV/Mičganas"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "JAV/Mountain"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "JAV/Pacific"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "JAV/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
+
+#, fuzzy
+#~ msgid "US/Pacific-New"
+#~ msgstr "JAV/Pacific"
+
+#~ msgid "SystemV/AST4"
+#~ msgstr "SystemV/AST4"
+
+#~ msgid "SystemV/AST4ADT"
+#~ msgstr "SystemV/AST4ADT"
+
+#~ msgid "SystemV/CST6"
+#~ msgstr "SystemV/CST6"
+
+#~ msgid "SystemV/CST6CDT"
+#~ msgstr "SystemV/CST6CDT"
+
+#~ msgid "SystemV/EST5"
+#~ msgstr "SystemV/EST5"
+
+#~ msgid "SystemV/EST5EDT"
+#~ msgstr "SystemV/EST5EDT"
+
+#~ msgid "SystemV/HST10"
+#~ msgstr "SystemV/HST10"
+
+#~ msgid "SystemV/MST7"
+#~ msgstr "SystemV/MST7"
+
+#~ msgid "SystemV/MST7MDT"
+#~ msgstr "SystemV/MST7MDT"
+
+#~ msgid "SystemV/PST8"
+#~ msgstr "SystemV/PST8"
+
+#~ msgid "SystemV/PST8PDT"
+#~ msgstr "SystemV/PST8PDT"
+
+#~ msgid "SystemV/YST9"
+#~ msgstr "SystemV/YST9"
+
+#~ msgid "SystemV/YST9YDT"
+#~ msgstr "SystemV/YST9YDT"
diff --git a/panels/datetime/po-timezones/lv.po b/panels/datetime/po-timezones/lv.po
new file mode 100644
index 0000000..413c451
--- /dev/null
+++ b/panels/datetime/po-timezones/lv.po
@@ -0,0 +1,3287 @@
+# translation of lv.po to Latvian
+# Andrew Martynov <andrewm@inventa.ru>, 2004.
+# Yuliya Poyarkova <ypoyarko@brisbane.redhat.com>, 2006.
+# Yulia Poyarkova <ypoyarko@redhat.com>, 2006.
+# Gatis Kalnins <gatis.kalnins@metatrons.lv>, 2006.
+# translation of ru.po to
+# translation of ru.po to
+# translation of ru.po to
+# translation of ru.po to
+# translation of ru.po to
+msgid ""
+msgstr ""
+"Project-Id-Version: lv\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2006-11-21 19:44+0200\n"
+"Last-Translator: Gatis Kalnins <gatis.kalnins@metatrons.lv>\n"
+"Language-Team: Latvian <locale@laka.lv>\n"
+"Language: lv\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.1\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Āfrika/Abidžana"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Āfrika/Akkra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Āfrika/Adis-Abeba"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Āfrika/Alžīra"
+
+#: timezones.h:5
+#, fuzzy
+msgid "Africa/Asmara"
+msgstr "Āfrika/Asmera"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Āfrika/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Āfrika/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Āfrika/Bangi"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Āfrika/Banžula"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Āfrika/Bisau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Āfrika/Blantaira"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Āfrika/Brazzavila"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Āfrika/Bužumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Āfrika/Kaira"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Āfrika/Kasablanka"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Āfrika/Seuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Āfrika/Konkari"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Āfrika/Dakāra"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Āfrika/Dar-es-Salama"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Āfrika/Džibuti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Āfrika/Duala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Āfrika/El Ajuna"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Āfrika/Frītauna"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Āfrika/Gaborona"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Āfrika/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Āfrika/Johanesburga"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Āfrika/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Āfrika/Hartuma"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Āfrika/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Āfrika/Kinšasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Āfrika/Lagosa"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Āfrika/Livervila"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Āfrika/Loma"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Āfrika/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Āfrika/Lubumbaši"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Āfrika/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Āfrika/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Āfrika/Maputu"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Āfrika/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Āfrika/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Āfrika/Mogadiša"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Āfrika/Monrovija"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Āfrika/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Āfrika/Ndžamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Āfrika/Niameja"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Āfrika/Nuakšota"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Āfrika/Uagadugu"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Āfrika/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Āfrika/Sao Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Āfrika/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Āfrika/Tripole"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Āfrika/Tunisa"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Āfrika/Vindhuka"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Amerika/Adaka"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+#, fuzzy
+msgid "Aleutian Islands"
+msgstr "Austrālija/Kvinslenda"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Amerika/Ankoridža"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+#, fuzzy
+msgid "Alaska Time"
+msgstr "ASV/Aļaska"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Amerika/Angila"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Amerika/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Amerika/Araguana"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Amerika/Argentīna/Buenosairesa"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Amerika/Argentīna/Katamarka"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Amerika/Argentīna/Komod-Rivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Amerika/Argentīna/Kordova"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Amerika/Argentīna/Žužuja"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Amerika/Argentīna/La Rioha"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Amerika/Argentīna/Mendosa"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Amerika/Argentīna/Rio Galegosa"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+#, fuzzy
+msgid "America/Argentina/Salta"
+msgstr "Amerika/Argentīna/San Huana"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Amerika/Argentīna/San Huana"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+#, fuzzy
+msgid "America/Argentina/San_Luis"
+msgstr "Amerika/Argentīna/San Huana"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Amerika/Argentīna/Tukumana"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Amerika/Argentīna/Ušuaja"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Amerika/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Amerika/Asunsjona"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Amerika/Atikokana"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Amerika/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Amerika/Baija"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "Amerika/Baija"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Amerika/Barbadosa"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Amerika/Belema"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Amerika/Beliza"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "Amerika/Blank-Sablona"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Amerika/Boa Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Amerika/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Amerika/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Amerika/Buenosairesa"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Amerika/Kembridž-Beja"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "Amerika/Kampo-Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Amerika/Kankuna"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Amerika/Karakasa"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Amerika/Katamarka"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Amerika/Kaijena"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Amerika/Kaimanas"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Amerika/Čikāga"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+#, fuzzy
+msgid "Central Time"
+msgstr "ASV/Centrs"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Amerika/Čihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "Amerika/Koralharbora"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Amerika/Kordova"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Amerika/Kostarika"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Amerika/Kujaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Amerika/Kjurasao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Amerika/Denmarkšavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Amerika/Dousona"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Amerika/Dausonkrīka"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Amerika/Denvera"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+#, fuzzy
+msgid "Mountain Time"
+msgstr "ASV/Kalni"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Amerika/Detroita"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Amerika/Dominika"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Amerika/Edmontona"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Amerika/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Amerika/Salvadora"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Amerika/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Amerika/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Amerika/Fortveina"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Amerika/Gleisbeja"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Amerika/Gothaba"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Amerika/Gusbeja"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Amerika/Grandturka"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Amerika/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Amerika/Gvadelupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Amerika/Gvatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Amerika/Gvajakila"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Amerika/Gvajana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Amerika/Halifaksa"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Amerika/Havanna"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Amerika/Hermosilo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Amerika/Indiāna/Inianapolisa"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Amerika/Indiāna/Knoksa"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Amerika/Indiāna/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "Amerika/Indiāna/Sankt-Pēterburga"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Amerika/Indiānapolisa"
+
+#: timezones.h:227
+#, fuzzy
+msgid "America/Indiana/Tell_City"
+msgstr "Amerika/Indiāna/Vevaja"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Amerika/Indiāna/Vevaja"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "Amerika/Indiāna/Vinsenesa"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+#, fuzzy
+msgid "America/Indiana/Winamac"
+msgstr "Amerika/Indiāna/Vinsenesa"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Amerika/Inuvīka"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Amerika/Ikaluita"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Amerika/Jamaika"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Amerika/Žužuja"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Amerika/Džuno"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Amerika/Kentuki/Lūisvilla"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+#, fuzzy
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Amerika/Kentuki/Lūisvilla"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Amerika/Kentuki/Montičello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Amerika/Knoks IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Amerika/La Pasa"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Amerika/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Amerika/Losandželosa"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+#, fuzzy
+msgid "Pacific Time"
+msgstr "Klusais okeāns/Niue"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Amerika/Lūisvilla"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Amerika/Maseijo"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Amerika/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Amerika/Manausa"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+#, fuzzy
+msgid "America/Marigot"
+msgstr "Amerika/Maseijo"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Amerika/Martinika"
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "Amerika/Manausa"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Amerika/Masatlana"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Amerika/Mendosa"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Amerika/Menomini"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Amerika/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Amerika/Mehiko"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Amerika/Mikelona"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "Amerika/Monktona"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Amerika/Montereja"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Amerika/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Amerika/Monreāla"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Amerika/Montserrata"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Amerika/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Amerika/Ņujorka"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+#, fuzzy
+msgid "Eastern Time"
+msgstr "ASV/Austrumi"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Amerika/Nipigona"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Amerika/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Amerika/Noronja"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+#, fuzzy
+msgid "Atlantic islands"
+msgstr "Atlantika/Kanāriju salas"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Amerika/Ziemeļdakota/Centrs"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "Amerika/Ziemeļdakota/Ņusalema"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "Amerika/Managua"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Amerika/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Amerika/Pangnirtunga"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Amerika/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Amerika/Fīniksa"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Amerika/Portoprensa"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Amerika/Portakra"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Amerika/Portofspeina"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Amerika/Portoveļju"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Amerika/Puertoriko"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Amerika/Reinirivera"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Amerika/Rankininleta"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Amerika/Resifi"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Amerika/Redžaina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+#, fuzzy
+msgid "America/Resolute"
+msgstr "Amerika/Belema"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Amerika/Riubranku"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Amerika/Rosario"
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "Amerika/Santjago"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+#, fuzzy
+msgid "America/Santarem"
+msgstr "Amerika/Santjago"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Amerika/Santjago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Amerika/Santo-Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Amerika/Sanpaulu"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Amerika/Skorsbisunna"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Amerika/Šiproka"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+#, fuzzy
+msgid "America/St_Barthelemy"
+msgstr "Amerika/Belema"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Amerika/Sentdžonsa"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Amerika/Sentkitsa"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Amerika/Sentlusija"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Amerika/Senttomasa"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Amerika/Sentvincenta"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Amerika/Sviftkarenta"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Amerika/Tegusigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Amerika/Tule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Amerika/Tanderbeja"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Amerika/Tihuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "Amerika/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Amerika/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Amerika/Vankuvera"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Amerika/Virdžīna"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Amerika/Vaithorsa"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Amerika/Vinnipega"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Amerika/Jakutata"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Amerika/Jellounaifa"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antarktika/Keisija"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antarktika/Deivisa"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antarktika/Djumondurvilla"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+#, fuzzy
+msgid "Antarctica/Macquarie"
+msgstr "Antarktika/Makmerdo"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antarktika/Mousona"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antarktika/Makmerdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antarktika/Palmera"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antarktika/Rotera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antarktika/Dienvidpols"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antarktika/Sjova"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antarktika/Vostoka"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Arktika/Longjerbjena"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Āzija/Adena"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Āzija/Almati"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Āzija/Ammana"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Āzija/Anadira"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Āzija/Aktava"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Āzija/Aktjubinska"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Āzija/Ašgabata"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Āzija/Ašhabada"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Āzija/Bagdāde"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Āzija/Bahreina"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Āzija/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Āzija/Bankoka"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Āzija/Beiruta"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Āzija/Biškeka"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Āzija/Bruneja"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Āzija/Kalkuta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Āzija/Čoibalsana"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Āzija/Čuncina"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Āzija/Čunkinga"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Āzija/Kolombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Āzija/Daka"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Āzija/Damaska"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Āzija/Dakka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Āzija/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Āzija/Dubaja"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Āzija/Dušanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Āzija/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Āzija/Harbina"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+#, fuzzy
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Āzija/Čuncina"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Āzija/Honkonga"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Āzija/Hovda"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Āzija/Irkutska"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Āzija/Stambula"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Āzija/Džakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Āzija/Džajapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Āzija/Jeruzaleme"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Āzija/Kabula"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Āzija/Kamčatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Āzija/Karači"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Āzija/Kašgara"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+#, fuzzy
+msgid "Asia/Kathmandu"
+msgstr "Āzija/Katmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Āzija/Katmandu"
+
+#: timezones.h:518
+#, fuzzy
+msgid "Asia/Kolkata"
+msgstr "Āzija/Džakarta"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Āzija/Krasnojarska"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Āzija/Kuala Lumpura"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Āzija/Kučinga"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Āzija/Kuveita"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Āzija/Makao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Āzija/Makao"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Āzija/Magadāna"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Āzija/Makassara"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Āzija/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Āzija/Maskata"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Āzija/Nikozija"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "Āzija/Irkutska"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Āzija/Novosibirska"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Āzija/Novosibirska"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+#, fuzzy
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Āzija/Novosibirska"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Āzija/Omska"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Āzija/Uraļska"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Āzija/Pnompeņa"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Āzija/Pontianaka"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Āzija/Phenjana"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Āzija/Katara"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Āzija/Kizil-Orda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Āzija/Ranguna"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Āzija/Rijadha"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Āzija/Rijadha87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Āzija/Rijadha88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Āzija/Rijadha89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Āzija/Saigona"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Āzija/Sahalina"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Āzija/Samarkanda"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Āzija/Seula"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Āzija/Šanhaja"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Āzija/Singapūra"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Āzija/Taipeja"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Āzija/Taškenta"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Āzija/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Āzija/Teherana"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Āzija/Telaviva"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Āzija/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Āzija/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Āzija/Tokija"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Āzija/Jung Pandanga"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Āzija/Ulan Batora"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Āzija/Ulan Batora"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Āzija/Urumči"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Āzija/Vjentjana"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Āzija/Vladivostoka"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Āzija/Jakutska"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Āzija/Jekaterinburga"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Āzija/Erevāna"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlantika/Azoru salas"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlantika/Bermudas"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlantika/Kanāriju salas"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlantika/Kape Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlantika/Fareru salas"
+
+#: timezones.h:616
+#, fuzzy
+msgid "Atlantic/Faroe"
+msgstr "Atlantika/Fareru salas"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlantika/Janmaijena"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlantika/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlantika/Reikjavika"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlantika/Dienviddžordžija"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlantika/Folklendu salas"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlantika/Sv.Helēnas sala"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Austrālija/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Austrālija/Adelaida"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+#, fuzzy
+msgid "South Australia"
+msgstr "Austrālija/ACT"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Austrālija/Brisbena"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Austrālija/Broken Hilla"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Austrālija/Kanberra"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Austrālija/Kernsa"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Austrālija/Darvina"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+#, fuzzy
+msgid "Australia/Eucla"
+msgstr "Austrālija/Kvinslenda"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+#, fuzzy
+msgid "Western Australia - Eucla area"
+msgstr "Austrālija/Kvinslenda"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Austrālija/Hobarta"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Austrālija/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Austrālija/Lindemana"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Austrālija/Lordhaua"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Austrālija/Melburna"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+#, fuzzy
+msgid "Victoria"
+msgstr "Austrālija/Viktorija"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Austrālija/Ziemeļi"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Austrālija/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Austrālija/Pērta"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Austrālija/Kvinslenda"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Austrālija/Dienvidi"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Austrālija/Sidneja"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Austrālija/Tasmānija"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Austrālija/Viktorija"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Austrālija/Rietumi"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Austrālija/Jankovina"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brazīlija/Akri"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brazīlija/Denoronja"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brazīlija/Rietumi"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brazīlija/Rietumi"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Kanāda/Atlantika"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Kanāda/Centrs"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Kanāda/Austrumi"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Kanāda/Austrumu Saskačevana"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Kanāda/Kalni"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Kanāda/Ņufaundlenda"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Kanāda/Klusais okeāns"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Kanāda/Saskačevana"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Kanāda/Jukona"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Čīle/Kontinents"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Čīle/Lieldienu salas"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Kuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Ēģipte"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Eire"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Grinviča"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Eiropa/Amsterdama"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Eiropa/Andorra"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Eiropa/Atēnas"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Eiropa/Belfāsta"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Eiropa/Belgrada"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Eiropa/Berlīne"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Eiropa/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Eiropa/Brisele"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Eiropa/Buhareste"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Eiropa/Budapešta"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Eiropa/Kišiņeva"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Eiropa/Kopenhāgena"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Eiropa/Dublina"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Eiropa/Gibraltārs"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Eiropa/Gernsija"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Eiropa/Helsinki"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Eiropa/Menas sala"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Eiropa/Stambula"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Eiropa/Džersija"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Eiropa/Kaļiņingrada"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Eiropa/Kijeva"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Eiropa/Lisabona"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Eiropa/Ļubļana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Eiropa/Londona"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Eiropa/Luksemburga"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Eiropa/Madride"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Eiropa/Malta"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Eiropa/Mariehamna"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Eiropa/Minska"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Eiropa/Monako"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Eiropa/Maskava"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Eiropa/Nikozija"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Eiropa/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Eiropa/Parīze"
+
+#: timezones.h:774
+#, fuzzy
+msgid "Europe/Podgorica"
+msgstr "Eiropa/Volgograda"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Eiropa/Prāga"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Eiropa/Rīga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Eiropa/Roma"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Eiropa/Samāra"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Eiropa/San Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Eiropa/Sarajeva"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Eiropa/Simferopole"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Eiropa/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Eiropa/Sofija"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Eiropa/Stokholma"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Eiropa/Tallina"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Eiropa/Tarana"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Eiropa/Tiraspole"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Eiropa/Užgoroda"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Eiropa/Vaduca"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Eiropa/Vatikāns"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Eiropa/Vīne"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Eiropa/Viļņa"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Eiropa/Volgograda"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Eiropa/Varšava"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Eiropa/Zagreba"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Eiropa/Zaporožje"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Eiropa/Cīrihe"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Factory"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Eire"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Grinviča"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Honkonga"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Islande"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Indija/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Indija/Čagosa"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Indija/Ziemassvētku salas"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Indija/Kokosu salas"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Indija/Komoro"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Indija/Kergelena"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Indija/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Indija/Maldivas"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Indija/Maurīcija"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Indija/Maijotta"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Indija/Rejunjona"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Irāna"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Izraēla"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamaika"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Japāna"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kvadžaleina"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Lībija"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Meksika/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Meksika/BajaSura"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Meksika/General"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Vidusāzija/Rijada87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Vidusāzija/Rijada88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Vidusāzija/Rijada89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Klusais okeāns/Apija"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Klusais okeāns/Oklenda"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Klusais okeāns/Čatema"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+#, fuzzy
+msgid "Chatham Islands"
+msgstr "Čīle/Lieldienu salas"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "Klusais okeāns/Truka"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+#, fuzzy
+msgid "Pacific/Easter"
+msgstr "Klusais okeāns/Lieldienu salas"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Klusais okeāns/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Klusais okeāns/Enderberija"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Klusais okeāns/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Klusais okeāns/Fudži"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Klusais okeāns/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Klusais okeāns/Galapagu salas"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Klusais okeāns/Gambje"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Klusais okeāns/Guadalkanala"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Klusais okeāns/Guama"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Klusais okeāns/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+#, fuzzy
+msgid "Hawaii"
+msgstr "ASV/Havaja"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Klusais okeāns/Džonstona"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Klusais okeāns/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Klusais okeāns/Kusaie"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+#, fuzzy
+msgid "Kosrae"
+msgstr "Izraēla"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Klusais okeāns/Kvadžaleina"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Klusais okeāns/Madžuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Klusais okeāns/Marķīzu salas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Klusais okeāns/Midueja"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Klusais okeāns/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Klusais okeāns/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Klusais okeāns/Norfolka"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Klusais okeāns/Numea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Klusais okeāns/Pago Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Klusais okeāns/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Klusais okeāns/Pitkerna salas"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "Klusais okeāns/Ponpejas"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Klusais okeāns/Ponpejas"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Klusais okeāns/Port Morsbija"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Klusais okeāns/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Klusais okeāns/Saipana"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Klusais okeāns/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Klusais okeāns/Taiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Klusais okeāns/Tarava"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+#, fuzzy
+msgid "Gilbert Islands"
+msgstr "Čīle/Lieldienu salas"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Klusais okeāns/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Klusais okeāns/Truka"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Klusais okeāns/Veika"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Klusais okeāns/Vollisa"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Klusais okeāns/Japa"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Polija"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugāle"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapūra"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Turcija"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "ASV/Aļaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "ASV/Aleutu salas"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "ASV/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "ASV/Centrs"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "ASV/Austrumi"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "ASV/Austrumindiāna"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "ASV/Havaja"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "ASV/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "ASV/Mičigana"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "ASV/Kalni"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "ASV/Klusais okeāns"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "ASV/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
+
+#~ msgid "US/Pacific-New"
+#~ msgstr "ASV/Klusais okeāns jaun."
diff --git a/panels/datetime/po-timezones/mai.po b/panels/datetime/po-timezones/mai.po
new file mode 100644
index 0000000..8a0baf2
--- /dev/null
+++ b/panels/datetime/po-timezones/mai.po
@@ -0,0 +1,3274 @@
+# translation of timezones.master.po to Maithili
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Sangeeta Kumari <sangeeta09@gmail.com>, 2009.
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones.master\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2009-02-24 21:51+0530\n"
+"Last-Translator: Sangeeta Kumari <sangeeta09@gmail.com>\n"
+"Language-Team: Maithili <maithili.sf.net>\n"
+"Language: mai\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: nplurals=2; plural=(n!=1);\n"
+"\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "अफ्रीका/अबीड्जन"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "अफ्रीका/अक्रा"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "अफ्रीका/एदिस_अबाबा"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "अफ्रीका/अलजियर्स"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "अफ्रीका/असमारा"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "अफ्रीका/असमेरा"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "अफ्रीका/बामाको"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "अफ्रीका/बंगुई"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "अफ्रीका/बंजल"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "अफ्रीका/बिसू"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "अफ्रीका/ब्लेनतरी"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "अफ्रीका/ब्राजाविल"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "अफ्रीका/बुजमबुरा"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "अफ्रीका/कैरो"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "अफ्रीका/कासाब्लांका"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "अफ्रीका/सियूटा"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "अफ्रीका/कोनाक्री"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "अफ्रीका/डकर"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "अफ्रीका/दार_एस_स्लेम"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "अफ्रीका/ड्जिबोटी"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "अफ्रीका/डूअला"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "अफ्रीका/एल_ऐन"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "अफ्रीका/फ्रीटाउन"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "अफ्रीका/गैब्रोन"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "अफ्रीका/हरिअररे"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "अफ्रीका/जोहांन्सबर्ग"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "अफ्रीका/कम्पाला"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "अफ्रीका/खार्तुम"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "अफ्रीका/किगाली"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "अफ्रीका/किंसासा"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "अफ्रीका/लागोस"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "अफ्रीका/लिबरविल"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "अफ्रीका/लोम"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "अफ्रीका/लुआंडा"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "अफ्रीका/लुबूंबशी"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "अफ्रीका/लुसाका"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "अफ्रीका/मलाबो"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "अफ्रीका/मपुतो"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "अफ्रीका/मैसेरु"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "अफ्रीका/मेबाबाने"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "अफ्रीका/मोगाडीशू"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "अफ्रीका/मोनरोविया"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "अफ्रीका/नैरोबी"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "अफ्रीका/नजेमेना"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "अफ्रीका/नेमै"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "अफ्रीका/नाकचाट"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "अफ्रीका/ऊगोदूगो"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "अफ्रीका/पोर्टो_नोवो"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "अफ्रीका/सावो टोम "
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "अफ्रीका/तिंबकटू"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "अफ्रीका/त्रिपोली"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "अफ्रीका/ट्यूनिस"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "अफ्रीका/विंडहाक"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "अमेरिका/अदक"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+#, fuzzy
+msgid "Aleutian Islands"
+msgstr "आस्ट्रेलिया/क्वींसलैंड"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "अमेरिका/एंकरेज"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+#, fuzzy
+msgid "Alaska Time"
+msgstr "US/अलास्का"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "अमेरिका/अंग्यूला"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "अमेरिका/एंटीगुआ"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "अमेरिका/अराग्वेना"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "अमेरिका/अर्जेंटीना/ब्युनसआयर्स"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "अमेरिका/अर्जेंटीना/कैटामारका"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "अमेरिका/अर्जेंटीना/कोमोडरिवाडाविया"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "अमेरिका/अर्जेंटीना/कारडोबा"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "अमेरिका/अर्जेंटीना/जुजै"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "अमेरिका/अर्जेंटीना/लारियोजा"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "अमेरिका/अर्जेंटीना/मेनडोजा"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "अमेरिका/अर्जेंटीना/रियो गैलियस"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+#, fuzzy
+msgid "America/Argentina/Salta"
+msgstr "अमेरिका/अर्जेंटीना/सान जुआन"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "अमेरिका/अर्जेंटीना/सान जुआन"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+#, fuzzy
+msgid "America/Argentina/San_Luis"
+msgstr "अमेरिका/अर्जेंटीना/सान जुआन"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "अमेरिका/अर्जेंटीना/टकमैन"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "अमेरिका/अर्जेंटीना/उशुआहिया"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "अमेरिका/अरुबा"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "अमेरिका/असनशियन"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "अमेरिका/एटिकोकान"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "अमेरिका/अटका"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "अमेरिका/विस्ता"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "अमेरिका/विस्ता"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "अमेरिका/बारबाडोस"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "अमेरिका/बेलेम"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "अमेरिका/बेलिज़"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "अमेरिका/ब्लांक-सैब्लान"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "अमेरिका/बोआ_विस्ता"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "अमेरिका/बोगोटा"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "अमेरिका/बोइस"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "अमेरिका/ब्युनसआयर्स"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "अमेरिका/कैम्बरीज़_बे"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "अमेरिका/कंपो ग्रैंड"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "अमेरिका/कानकुन"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "अमेरिका/कैराकस"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "अमेरिका/कैटामारका"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "अमेरिका/कैयेन"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "अमेरिका/कैमेन"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "अमेरिका/शिकागो"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+#, fuzzy
+msgid "Central Time"
+msgstr "US/केन्द्रीय"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "अमेरिका/चिहूआहुआ"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "अमेरिका/कोरल हार्बर"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "अमेरिका/कारडोबा"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "अमेरिका/कोस्टा_रिका"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "अमेरिका/क्यूबा"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "अमेरिका/कुराकाओ"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "अमेरिका/डेनमार्कशान"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "अमेरिका/डाशन"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "अमेरिका/डाशन_क्रीक"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "अमेरिका/डेनवर"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+#, fuzzy
+msgid "Mountain Time"
+msgstr "US/माउन्टेन"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "अमेरिका/डेट्रोइट"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "अमेरिका/डोमिनिका"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "अमेरिका/एड्मनटन"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "अमेरिका/युरीनएप"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "अमेरिका/एल_सेल्वाडोर"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "अमेरिका/एनसेनेडा"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "अमेरिका/फोर्टलेजा"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "अमेरिका/फोर्ट_वेन"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "अमेरिका/ग्लेस_बे"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "अमेरिका/गाडथब"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "अमेरिका/गूस_बे"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "अमेरिका/ग्रैंड_टर्क"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "अमेरिका/ग्रैंनेडा"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "अमेरिका/ग्वाडेलोपे"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "अमेरिका/ग्वाटेमाला"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "अमेरिका/गुआयाकिल"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "अमेरिका/गेलना"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "अमेरिका/हैलीफेक्स"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "अमेरिका/हवाना"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "अमेरिका/हरमोसिलो"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "अमेरिका/इंडियाना/इंडियानापोलिस"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "अमेरिका/इंडियाना/नाक्स"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "अमेरिका/इंडियाना/मेरेंगो"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "अमेरिका/इंडियाना/पीटर्सवर्ग"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "अमेरिका/इंडियानापोलिस"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "अमेरिका/इंडियाना/टेल_सिटी"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "अमेरिका/इंडियाना/वेवे"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "अमेरिका/इंडियाना/विंसिनेस"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "अमेरिका/इंडियाना/विनामेक"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "अमेरिका/इनुविक"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "अमेरिका/इकालूइत"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "अमेरिका/जमैका"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "अमेरिका/जुजै"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "अमेरिका/जूनो"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "अमेरिका/कैंटकी/लुईविल"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+#, fuzzy
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "अमेरिका/कैंटकी/लुईविल"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "अमेरिका/कैंटकी/मोनटिकलो"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "अमेरिका/नोक्सइन"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "अमेरिका/ला_पाज"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "अमेरिका/लिमा"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "अमेरिका/लास_एंजिल्स"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+#, fuzzy
+msgid "Pacific Time"
+msgstr "पैसीफिक/नीयू"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "अमेरिका/लुईविल"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "अमेरिका/मैसियो"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "अमेरिका/मेनेगुआ"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "अमेरिका/मैनास"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "अमेरिका/मैरिगोट"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "अमेरिका/मारटिनिक"
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "अमेरिका/मैनास"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "अमेरिका/मेजेटलेन"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "अमेरिका/मेनडोजा"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "अमेरिका/मेनोमिनी"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "अमेरिका/मेरीडा"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "अमेरिका/मैक्सिको_सिटी"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "अमेरिका/मिक्लान"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "अमेरिका/मोंकटन"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "अमेरिका/मांटेरी"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "अमेरिका/मांटेविडीयो"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "अमेरिका/मांट्रियल"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "अमेरिका/मांटेसेराट"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "अमेरिका/नसो"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "अमेरिका/न्यू_यार्क"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+#, fuzzy
+msgid "Eastern Time"
+msgstr "US/पूर्वी"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "अमेरिका/निपीगन"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "अमेरिका/नोम"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "अमेरिका/नोरोंहा"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+#, fuzzy
+msgid "Atlantic islands"
+msgstr "अटलांटिक/कैनेरी"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "अमेरिका/उत्तर_डकोटा/मध्य"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "अमेरिका/उत्तर_डकोटा/नव_सलेम"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "अमेरिका/मेनेगुआ"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "अमेरिका/पनामा"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "अमेरिका/पैंगनीरटंग"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "अमेरिका/पारामारीबो"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "अमेरिका/फिनिक्स"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "अमेरिका/पोर्ट_ओ_प्रिंस"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "अमेरिका/पोर्ट_एकर"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "अमेरिका/पोर्ट_आफ_स्पेन"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "अमेरिका/पोर्टो_वेलो"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "अमेरिका/प्यूरिटो_रिको"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "अमेरिका/रैनी_रिवर"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "अमेरिका/रेनकीन_इनलेट"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "अमेरिका/रिसीफ"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "अमेरिका/रेजीना"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "अमेरिका/रिजाल्यूट"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "अमेरिका/राये_ब्रानको"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "अमेरिका/रोसारियो"
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "अमेरिका/सेंटीयगो"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+#, fuzzy
+msgid "America/Santarem"
+msgstr "अमेरिका/सेंटीयगो"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "अमेरिका/सेंटीयगो"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "अमेरिका/सेंटो_डोमिंगो"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "अमेरिका/सावो_पोलो"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "अमेरिका/स्कोर्सबायसंड"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "अमेरिका/शिपराक"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "अमेरिका/सेंट_बार्थेलेमे"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "अमेरिका/सेंट_जाँस"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "अमेरिका/सेंट_किट्स"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "अमेरिका/सेंट_लुसिया"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "अमेरिका/सेंट_थामस"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "अमेरिका/सेंट_विंसेंट"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "अमेरिका/स्विफ्ट_करंट"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "अमेरिका/तेगुसीगालपा"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "अमेरिका/थुले"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "अमेरिका/थंडर_बे"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "अमेरिका/तीजुना"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "अमेरिका/टोरोंटो"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "अमेरिका/टोर्टोला"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "अमेरिका/वेंकोवेर"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "अमेरिका/वर्जिन"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "अमेरिका/व्हाइटहार्स"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "अमेरिका/विनीपेग"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "अमेरिका/यकुटेट"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "अमेरिका/यलोनाइफ"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "अंर्टाटिका/केसे"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "अंर्टाटिका/डेविस"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "अंर्टाटिका/डूमांटडरविल"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+#, fuzzy
+msgid "Antarctica/Macquarie"
+msgstr "अंर्टाटिका/मेकमुरडो"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "अंर्टाटिका/मोसन"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "अंर्टाटिका/मेकमुरडो"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "अंर्टाटिका/पामर "
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "अंर्टाटिका/रोथेरिया"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "अंर्टाटिका/साउथ_पोल"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "अंर्टाटिका/सय्वा"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "अंर्टाटिका/वोस्तोक"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "आर्टिक/लांगईयरबायेन"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "एशिया/अदन"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "एशिया/अलमटी"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "एशिया/अम्मान"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "एशिया/अनाडिर"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "एशिया/एकतो"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "एशिया/अकतूब"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "एशिया/अशगाबट"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "एशिया/अश्खाबाद"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "एशिया/बगदाद"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "एशिया/बहरीन"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "एशिया/बाकू"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "एशिया/बैंकाक"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "एशिया/बेरुट"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "एशिया/बिशकेक"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "एशिया/ब्रुनेई"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "एशिया/कोलकाता"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "एशिया/छोईबलसन"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "एशिया/चांगकिंग"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "एशिया/चुंगकिंग"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "एशिया/कोलोंबो"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "एशिया/डक्का"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "एशिया/डमस्कस"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "एशिया/ढाका "
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "एशिया/दिली"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "एशिया/दुबई"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "एशिया/दुसानबे"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "एशिया/गाजा"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "एशिया/हरबीन "
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+#, fuzzy
+msgid "Asia/Ho_Chi_Minh"
+msgstr "एशिया/चांगकिंग"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "एशिया/हांग_कांग"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "एशिया/हावड"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "एशिया/इरकुट्स्क"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "एशिया/इस्तांबुल"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "एशिया/जकार्ता"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "एशिया/जयपुर"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "एशिया/जेरुशलम"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "एशिया/काबूल"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "एशिया/कमचटका"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "एशिया/कराची"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "एशिया/केशगर"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+#, fuzzy
+msgid "Asia/Kathmandu"
+msgstr "एशिया/काठमांडू"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "एशिया/काठमांडू"
+
+#: timezones.h:518
+#, fuzzy
+msgid "Asia/Kolkata"
+msgstr "एशिया/जकार्ता"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "एशिया/क्रस्नोयास्क"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "एशिया/क्वालामपुर"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "एशिया/कुचिंग"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "एशिया/कुवैत"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "एशिया/मकाओ"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "एशिया/मकाउ"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "एशिया/मगाडन"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "एशिया/मकस्सर"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "एशिया/मनीला"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "एशिया/मस्कट"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "एशिया/निकोसिया"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "एशिया/इरकुट्स्क"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "एशिया/नोवोसिब्रिस्क"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "एशिया/नोवोसिब्रिस्क"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+#, fuzzy
+msgid "Moscow+03 - Novosibirsk"
+msgstr "एशिया/नोवोसिब्रिस्क"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "एशिया/ओमस्क"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "एशिया/ओरल"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "एशिया/नाम_पेन्ह"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "एशिया/पोनट्यानक"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "एशिया/प्योंगेलंग"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "एशिया/कतर"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "एशिया/कैजीलोरडा"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "एशिया/रंगून"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "एशिया/रियाद"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "एशिया/रियाद87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "एशिया/रियाद88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "एशिया/रियाद89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "एशिया/शैगांव"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "एशिया/साखालीन"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "एशिया/समरकंड"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "एशिया/सियोल"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "एशिया/शंघाई"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "एशिया/सिंगापुर"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "एशिया/ताईपे"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "एशिया/ताशकंद"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "एशिया/तबीलिसी"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "एशिया/तेहरिअरन"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "एशिया/तेल_अवीव"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "एशिया/तिमबू"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "एशिया/थिंफू"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "एशिया/टोक्यो"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "एशिया/ऊजूंग_पन्दांग"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "एशिया/उलानबतर"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "एशिया/उलन_बतोर"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "एशिया/उरुमकी"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "एशिया/वेटीयेन"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "एशिया/व्लाडीवास्टक"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "एशिया/यकुट्स्क"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "एशिया/येकातरीनबर्ग"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "एशिया/येराविन"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "अटलांटिक/अजोर्स"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "अटलांटिक/बरमुडा"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "अटलांटिक/कैनेरी"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "अटलांटिक/कैप_वर्द"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "अटलांटिक/फैरो"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "अटलांटिक/फराओ"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "अटलांटिक/जन_मयन"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "अटलांटिक/मेडिरा"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "अटलांटिक/रिकीज्विक"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "अटलांटिक/दक्षिण_जार्जिया"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "अटलांटिक/स्टेनली"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "अटलांटिक/सेंट_हेलेना"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "आस्ट्रेलिया/एसीटी"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "आस्ट्रेलिया/एडीलेड"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+#, fuzzy
+msgid "South Australia"
+msgstr "आस्ट्रेलिया/एसीटी"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "आस्ट्रेलिया/ब्रिसबेन"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "आस्ट्रेलिया/ब्रोकन_हिल"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "आस्ट्रेलिया/केनबेरा"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "आस्ट्रेलिया/क्यूरी"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "आस्ट्रेलिया/डारविन"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "आस्ट्रेलिया/यूक्ला"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+#, fuzzy
+msgid "Western Australia - Eucla area"
+msgstr "आस्ट्रेलिया/यूक्ला"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "आस्ट्रेलिया/होबर्ट"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "आस्ट्रेलिया/एलएचआई"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "आस्ट्रेलिया/लिंडेमेन"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "आस्ट्रेलिया/लार्ड_होव"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "आस्ट्रेलिया/मेलबार्न"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+#, fuzzy
+msgid "Victoria"
+msgstr "आस्ट्रेलिया/विक्टोरिया"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "आस्ट्रेलिया/उत्तर"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "आस्ट्रेलिया/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "आस्ट्रेलिया/पर्थ"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "आस्ट्रेलिया/क्वींसलैंड"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "आस्ट्रेलिया/दक्षिण"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "आस्ट्रेलिया/सिडनी"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "आस्ट्रेलिया/टस्मेनिया"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "आस्ट्रेलिया/विक्टोरिया"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "आस्ट्रेलिया/पश्चिम"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "आस्ट्रेलिया/यानकोविना"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "ब्राजिल/एक्रे"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "ब्राजिल/डेनोरोना"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "ब्राजिल/पूरब"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "ब्राजिल/पश्चिम"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "कोनेडा/अटलांटिक"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "कोनेडा/मध्य"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "कोनेडा/पूर्वी"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "कोनेडा/पूर्व-सस्कचवन"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "कोनेडा/माउन्टेन"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "कोनेडा/न्यूफोन्डलैंड"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "कोनेडा/पैसीफिक"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "कोनेडा/सस्कचवन"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "कोनेडा/यूकन"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "चिली/कान्टीनेन्टल"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "चिली/कोन्टीनेन्टल"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "क्यूबा"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "मिश्र"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "आयर"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/ग्रीनविच"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/यूनिवर्सल"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/ज़ुलू"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "यूरोप/एम्स्टरडेम"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "यूरोप/एंडोरा"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "यूरोप/एथेंस"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "यूरोप/बेलफास्ट"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "यूरोप/बेलग्रेड"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "यूरोप/बर्लिन"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "यूरोप/ब्रटिसलेवा"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "यूरोप/ब्रस्सेल्स"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "यूरोप/बुखारेस्ट"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "यूरोप/बुडापेस्ट"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "यूरोप/चीसीनो"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "यूरोप/कोपनहेगन"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "यूरोप/डब्लिन"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "यूरोप/जिब्राल्टर"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "यूरोप/गुयेर्न्से"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "यूरोप/हेलसिंकी"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "यूरोप/आइल_आफ_मैन"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "यूरोप/इस्तांबुल"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "यूरोप/जर्सी"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "यूरोप/कालिनीग्राड"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "यूरोप/कीव"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "यूरोप/लिसबन"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "यूरोप/लजुबलजएनाइ"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "यूरोप/लंदन"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "यूरोप/लेक्संबर्ग"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "यूरोप/मेड्रिड"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "यूरोप/माल्टा"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "यूरोप/मेरीहैम"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "यूरोप/मिंसक"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "यूरोप/मोनाको"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "यूरोप/मास्को"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "यूरोप/निकोसिया"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "यूरोप/ओसलो"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "यूरोप/पेरिस"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "यूरोप/पाडगोरिका"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "यूरोप/प्राग"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "यूरोप/रिगा"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "यूरोप/रोम"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "यूरोप/समारा"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "यूरोप/सेन_मरीनो"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "यूरोप/सराजेवो"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "यूरोप/सिमफेरोपोल"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "यूरोप/स्कपजे"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "यूरोप/सोफिया"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "यूरोप/स्टाकहोम"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "यूरोप/तालीन"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "यूरोप/तिरेन"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "यूरोप/तिरसपोल"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "यूरोप/उर्गोराड"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "यूरोप/वाडूज"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "यूरोप/वेटीकेन"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "यूरोप/वियेना"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "यूरोप/विलनियस"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "यूरोप/वोल्गोग्रैड"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "यूरोप/वारसो"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "यूरोप/जेगरीब"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "यूरोप/जपोरोजाई"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "यूरोप/ज्यूरिख"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "फैक्टरी"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-आइर"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "ग्रीनविच"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "हांगकाग"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "आइसलैंड"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "इंडियन/अंतानानरिवो"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "इंडियन/चागोस"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "इंडियन/क्रिसमस"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "इंडियन/कोकोस"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "इंडियन/कोमोरो"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "इंडियन/करगलन"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "इंडियन/माहे"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "इंडियन/मालदीव"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "इंडियन/मारीसस"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "इंडियन/मायोट"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "इंडियन/रियूनियन"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "इरान"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "इज़राइल"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "जमाईका"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "जापान"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "ख्वाजालेन"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "लीबिया"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "मैक्सिको/बजनोर्ट"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "मैक्सिको/बजासुर"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "मैक्सिको/जनरल"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "खाड़ी/रियाद87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "खाड़ी/रियाद88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "खाड़ी/रियाद89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "नवजो"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "पैसीफिक/एपिया"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "पैसीफिक/आकलैंड"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "पैसीफिक/चाथम"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+#, fuzzy
+msgid "Chatham Islands"
+msgstr "चिली/कोन्टीनेन्टल"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "पैसीफिक/त्रुक"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "प्रशांत/इस्टर"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "पैसीफिक/इफेट"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "पैसीफिक/इनडरबरी"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "पैसीफिक/फकाओफो"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "पैसीफिक/फिजी"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "पैसीफिक/फुनाफुटी"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "पैसीफिक/गलपगोस"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "पैसीफिक/गेम्बियर"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "पैसीफिक/गुवादलकनल"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "पैसीफिक/गुआम"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "पैसीफिक/होनोलूलू"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+#, fuzzy
+msgid "Hawaii"
+msgstr "US/हवाई"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "पैसीफिक/जांस्टन"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "पैसीफिक/किर्तीमति"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "पैसीफिक/कसरे"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+#, fuzzy
+msgid "Kosrae"
+msgstr "इज़राइल"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "पैसीफिक/क्वाजालेन"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "पैसीफिक/मजूरो"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "पैसीफिक/मार्कसास"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "पैसीफिक/मिडवे"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "पैसीफिक/नोरु"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "पैसीफिक/नीयू"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "पैसीफिक/नारफोक"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "पैसीफिक/नामिया"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "पैसीफिक/पैगो_पैगो"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "पैसीफिक/पलाउ"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "पैसीफिक/पिटकेरीन"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "पैसीफिक/पोनापे"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "पैसीफिक/पोनापे"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "पैसीफिक/पोर्ट_मोर्सबी"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "पैसीफिक/ररोतंगा"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "पैसीफिक/सैपेन"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "पैसीफिक/समोआ"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "पैसीफिक/ताहिटी"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "पैसीफिक/तारावा"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+#, fuzzy
+msgid "Gilbert Islands"
+msgstr "चिली/कोन्टीनेन्टल"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "पैसीफिक/टंगटपू"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "पैसीफिक/त्रुक"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "पैसीफिक/वेक"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "पैसीफिक/वालिस"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "पैसीफिक/याप"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "पोलंड"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "पुर्तगाल"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "सिंगापुर"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "तुर्की"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "यूनिवर्सल"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "US/अलास्का"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "US/एल्यूशन"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "US/एरीजोना"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "US/केन्द्रीय"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "US/पूर्वी"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "US/पूर्व-इंडियाना"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "US/हवाई"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "US/इंडियाना-स्टार्क"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "US/मिसिगन"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "US/माउन्टेन"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "US/पैसीफिक"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "US/समोवा"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "जुलु"
+
+#~ msgid "US/Pacific-New"
+#~ msgstr "US/प्रशांत-नव"
diff --git a/panels/datetime/po-timezones/meson.build b/panels/datetime/po-timezones/meson.build
new file mode 100644
index 0000000..b55fce7
--- /dev/null
+++ b/panels/datetime/po-timezones/meson.build
@@ -0,0 +1 @@
+i18n.gettext(control_center_gettext + '-timezones', preset: 'glib')
diff --git a/panels/datetime/po-timezones/mk.po b/panels/datetime/po-timezones/mk.po
new file mode 100644
index 0000000..5d7cb17
--- /dev/null
+++ b/panels/datetime/po-timezones/mk.po
@@ -0,0 +1,3350 @@
+# Macedonian translations for PACKAGE package.
+# Copyright (C) 2004 THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# Automatically generated, 2004.
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2004-07-23 01:24+0200\n"
+"Last-Translator: Tomislav <tome@users.ossm.org.mk>\n"
+"Language-Team: Macedonian <ossm-members@hedona.on.net.mk>\n"
+"Language: mk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Африка/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Африка/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Африка/Addis_Ababa"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Африка/Algiers"
+
+#: timezones.h:5
+#, fuzzy
+msgid "Africa/Asmara"
+msgstr "Африка/Asmera"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Африка/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Африка/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Африка/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Африка/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Африка/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Африка/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Африка/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Африка/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Африка/Cairo"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Африка/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Африка/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Африка/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Африка/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Африка/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Африка/Djibouti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Африка/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Африка/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Африка/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Африка/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Африка/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Африка/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Африка/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Африка/Khartoum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Африка/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Африка/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Африка/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Африка/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Африка/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Африка/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Африка/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Африка/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Африка/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Африка/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Африка/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Африка/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Африка/Mogadishu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Африка/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Африка/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Африка/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Африка/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Африка/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Африка/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Африка/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Африка/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Африка/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Африка/Tripoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Африка/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Африка/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Америка/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+#, fuzzy
+msgid "Aleutian Islands"
+msgstr "Австралија/Queensland"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Америка/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+#, fuzzy
+msgid "Alaska Time"
+msgstr "САД/Alaska"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Америка/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Америка/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Америка/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+#, fuzzy
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Америка/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+#, fuzzy
+msgid "America/Argentina/Catamarca"
+msgstr "Америка/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+#, fuzzy
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Америка/Indiana/Indianapolis"
+
+#: timezones.h:78
+#, fuzzy
+msgid "America/Argentina/Cordoba"
+msgstr "Америка/Cordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+#, fuzzy
+msgid "America/Argentina/Jujuy"
+msgstr "Америка/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+#, fuzzy
+msgid "America/Argentina/La_Rioja"
+msgstr "Америка/Araguaina"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+#, fuzzy
+msgid "America/Argentina/Mendoza"
+msgstr "Америка/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+#, fuzzy
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Америка/Indiana/Marengo"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+#, fuzzy
+msgid "America/Argentina/Salta"
+msgstr "Америка/Antigua"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+#, fuzzy
+msgid "America/Argentina/San_Juan"
+msgstr "Америка/Antigua"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+#, fuzzy
+msgid "America/Argentina/San_Luis"
+msgstr "Америка/Antigua"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+#, fuzzy
+msgid "America/Argentina/Tucuman"
+msgstr "Америка/Antigua"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+#, fuzzy
+msgid "America/Argentina/Ushuaia"
+msgstr "Америка/Araguaina"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Америка/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Америка/Asuncion"
+
+#: timezones.h:110
+#, fuzzy
+msgid "America/Atikokan"
+msgstr "Америка/Atka"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Америка/Atka"
+
+#: timezones.h:114
+#, fuzzy
+msgid "America/Bahia"
+msgstr "Америка/Boa_Vista"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "Америка/Boa_Vista"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Америка/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Америка/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Америка/Belize"
+
+#: timezones.h:125
+#, fuzzy
+msgid "America/Blanc-Sablon"
+msgstr "Америка/Cancun"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Америка/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Америка/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Америка/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Америка/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Америка/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+#, fuzzy
+msgid "America/Campo_Grande"
+msgstr "Америка/Cayman"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Америка/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Америка/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Америка/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Америка/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Америка/Cayman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Америка/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+#, fuzzy
+msgid "Central Time"
+msgstr "САД/Central"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Америка/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+#, fuzzy
+msgid "America/Coral_Harbour"
+msgstr "Америка/Curacao"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Америка/Cordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Америка/Costa_Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Америка/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Америка/Curacao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Америка/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Америка/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Америка/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Америка/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+#, fuzzy
+msgid "Mountain Time"
+msgstr "САД/Mountain"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Америка/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Америка/Dominica"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Америка/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Америка/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Америка/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Америка/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Америка/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Америка/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Америка/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Америка/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Америка/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Америка/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Америка/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Америка/Guadeloupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Америка/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Америка/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Америка/Guyana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Америка/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Америка/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Америка/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Америка/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Америка/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Америка/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+#, fuzzy
+msgid "America/Indiana/Petersburg"
+msgstr "Америка/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Америка/Indianapolis"
+
+#: timezones.h:227
+#, fuzzy
+msgid "America/Indiana/Tell_City"
+msgstr "Америка/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Америка/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+#, fuzzy
+msgid "America/Indiana/Vincennes"
+msgstr "Америка/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+#, fuzzy
+msgid "America/Indiana/Winamac"
+msgstr "Америка/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Америка/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Америка/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Америка/Jamaica"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Америка/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Америка/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Америка/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+#, fuzzy
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Америка/Kentucky/Louisville"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Америка/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Америка/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Америка/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Америка/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Америка/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+#, fuzzy
+msgid "Pacific Time"
+msgstr "Пацифик/Niue"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Америка/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Америка/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Америка/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Америка/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+#, fuzzy
+msgid "America/Marigot"
+msgstr "Америка/Maceio"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Америка/Martinique"
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "Америка/Manaus"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Америка/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Америка/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Америка/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Америка/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Америка/Mexico_City"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Америка/Miquelon"
+
+#: timezones.h:289
+#, fuzzy
+msgid "America/Moncton"
+msgstr "Америка/Edmonton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Америка/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Америка/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Америка/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Америка/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Америка/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Америка/New_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+#, fuzzy
+msgid "Eastern Time"
+msgstr "САД/Eastern"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Америка/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Америка/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Америка/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+#, fuzzy
+msgid "Atlantic islands"
+msgstr "Atlantic/Canary"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Америка/North_Dakota/Center"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+#, fuzzy
+msgid "America/North_Dakota/New_Salem"
+msgstr "Америка/North_Dakota/Center"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "Америка/Managua"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Америка/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Америка/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Америка/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Америка/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Америка/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Америка/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Америка/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Америка/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Америка/Puerto_Rico"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Америка/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Америка/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Америка/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Америка/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+#, fuzzy
+msgid "America/Resolute"
+msgstr "Америка/Belem"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Америка/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Америка/Rosario"
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "Америка/Santiago"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+#, fuzzy
+msgid "America/Santarem"
+msgstr "Америка/Santiago"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Америка/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Америка/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Америка/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Америка/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Америка/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+#, fuzzy
+msgid "America/St_Barthelemy"
+msgstr "Америка/Belem"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Америка/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Америка/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Америка/St_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Америка/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Америка/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Америка/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Америка/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Америка/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Америка/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Америка/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+#, fuzzy
+msgid "America/Toronto"
+msgstr "Америка/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Америка/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Америка/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Америка/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Америка/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Америка/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Америка/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Америка/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Антарктик/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Антарктик/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Антарктик/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+#, fuzzy
+msgid "Antarctica/Macquarie"
+msgstr "Антарктик/McMurdo"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Антарктик/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Антарктик/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Антарктик/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+#, fuzzy
+msgid "Antarctica/Rothera"
+msgstr "Антарктик/South_Pole"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Антарктик/South_Pole"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Антарктик/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Антарктик/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Arctic/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Азија/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Азија/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Азија/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Азија/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Азија/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Азија/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Азија/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Азија/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Азија/Baghdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Азија/Bahrain"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Азија/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Азија/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Азија/Beirut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Азија/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Азија/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Азија/Calcutta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Азија/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Азија/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Азија/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Азија/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Азија/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Азија/Damascus"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Азија/Dhaka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Азија/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Азија/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Азија/Dushanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Азија/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Азија/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+#, fuzzy
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Азија/Chongqing"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Азија/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Азија/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Азија/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Азија/Istanbul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Азија/Jakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Азија/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Азија/Jerusalem"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Азија/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Азија/Kamchatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Азија/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Азија/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+#, fuzzy
+msgid "Asia/Kathmandu"
+msgstr "Азија/Katmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Азија/Katmandu"
+
+#: timezones.h:518
+#, fuzzy
+msgid "Asia/Kolkata"
+msgstr "Азија/Jakarta"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Азија/Krasnoyarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Азија/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Азија/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Азија/Kuwait"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Азија/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Азија/Macau"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Азија/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Азија/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Азија/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Азија/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Азија/Nicosia"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "Азија/Irkutsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Азија/Novosibirsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Азија/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+#, fuzzy
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Азија/Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Азија/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Азија/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Азија/Phnom_Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Азија/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Азија/Pyongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Азија/Qatar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Азија/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Азија/Rangoon"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Азија/Riyadh"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Азија/Riyadh87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Азија/Riyadh88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Азија/Riyadh89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Азија/Saigon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Азија/Sakhalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Азија/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Азија/Seoul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Азија/Shanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Азија/Singapore"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Азија/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Азија/Tashkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Азија/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Азија/Tehran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Азија/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Азија/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Азија/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Азија/Tokyo"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Азија/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Азија/Ulaanbaatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Азија/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Азија/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Азија/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Азија/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Азија/Yakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Азија/Yekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Азија/Yerevan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlantic/Azores"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlantic/Bermuda"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlantic/Canary"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlantic/Cape_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlantic/Faeroe"
+
+#: timezones.h:616
+#, fuzzy
+msgid "Atlantic/Faroe"
+msgstr "Atlantic/Faeroe"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlantic/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlantic/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlantic/Reykjavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlantic/South_Georgia"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlantic/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlantic/St_Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Австралија/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Австралија/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+#, fuzzy
+msgid "South Australia"
+msgstr "Австралија/ACT"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Австралија/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Австралија/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Австралија/Canberra"
+
+#: timezones.h:636
+#, fuzzy
+msgid "Australia/Currie"
+msgstr "Австралија/Canberra"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Австралија/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+#, fuzzy
+msgid "Australia/Eucla"
+msgstr "Австралија/Queensland"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+#, fuzzy
+msgid "Western Australia - Eucla area"
+msgstr "Австралија/Queensland"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Австралија/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Австралија/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Австралија/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Австралија/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Австралија/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+#, fuzzy
+msgid "Victoria"
+msgstr "Австралија/Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Австралија/North"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Австралија/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Австралија/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Австралија/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Австралија/South"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Австралија/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Австралија/Tasmania"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Австралија/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Австралија/West"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Австралија/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brazil/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brazil/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brazil/East"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brazil/West"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Канада/Atlantic"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Канада/Central"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Канада/Eastern"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Канада/East-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Канада/Mountain"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Канада/Newfoundland"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Канада/Pacific"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Канада/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Канада/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Чиле/Continental"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Чиле/EasterIsland"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Cuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Egypt"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Eire"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Европа/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Европа/Andorra"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Европа/Athens"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Европа/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Европа/Belgrade"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Европа/Berlin"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Европа/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Европа/Brussels"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Европа/Bucharest"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Европа/Budapest"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Европа/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Европа/Copenhagen"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Европа/Dublin"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Европа/Gibraltar"
+
+#: timezones.h:744
+#, fuzzy
+msgid "Europe/Guernsey"
+msgstr "Европа/Athens"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Европа/Helsinki"
+
+#: timezones.h:746
+#, fuzzy
+msgid "Europe/Isle_of_Man"
+msgstr "Европа/Oslo"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Европа/Istanbul"
+
+#: timezones.h:748
+#, fuzzy
+msgid "Europe/Jersey"
+msgstr "Европа/Paris"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Европа/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Европа/Kiev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Европа/Lisbon"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Европа/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Европа/London"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Европа/Luxembourg"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Европа/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Европа/Malta"
+
+#: timezones.h:765
+#, fuzzy
+msgid "Europe/Mariehamn"
+msgstr "Европа/Madrid"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Европа/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Европа/Monaco"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Европа/Moscow"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Европа/Nicosia"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Европа/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Европа/Paris"
+
+#: timezones.h:774
+#, fuzzy
+msgid "Europe/Podgorica"
+msgstr "Европа/Andorra"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Европа/Prague"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Европа/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Европа/Rome"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Европа/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Европа/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Европа/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Европа/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Европа/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Европа/Sofia"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Европа/Stockholm"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Европа/Tallinn"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Европа/Tirane"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Европа/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Европа/Uzhgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Европа/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Европа/Vatican"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Европа/Vienna"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Европа/Vilnius"
+
+#: timezones.h:799
+#, fuzzy
+msgid "Europe/Volgograd"
+msgstr "Европа/Belgrade"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Европа/Warsaw"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Европа/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Европа/Zaporozhye"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Европа/Zurich"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Factory"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Eire"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Iceland"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Indian/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Indian/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Indian/Christmas"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Indian/Cocos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Indian/Comoro"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Indian/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Indian/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Indian/Maldives"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Indian/Mauritius"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Indian/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Indian/Reunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Iran"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Israel"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamaica"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Јапонија"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Libya"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Мексико/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Мексико/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Мексико/General"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Mideast/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Mideast/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Mideast/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Пацифик/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Пацифик/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Пацифик/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+#, fuzzy
+msgid "Chatham Islands"
+msgstr "Чиле/EasterIsland"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "Пацифик/Truk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+#, fuzzy
+msgid "Pacific/Easter"
+msgstr "Пацифик/Easter"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Пацифик/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Пацифик/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Пацифик/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Пацифик/Fiji"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Пацифик/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Пацифик/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Пацифик/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Пацифик/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Пацифик/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Пацифик/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+#, fuzzy
+msgid "Hawaii"
+msgstr "САД/Hawaii"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Пацифик/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Пацифик/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Пацифик/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+#, fuzzy
+msgid "Kosrae"
+msgstr "Israel"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Пацифик/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Пацифик/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Пацифик/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Пацифик/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Пацифик/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Пацифик/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Пацифик/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Пацифик/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Пацифик/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Пацифик/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Пацифик/Pitcairn"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "Пацифик/Ponape"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Пацифик/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Пацифик/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Пацифик/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Пацифик/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Пацифик/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Пацифик/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Пацифик/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+#, fuzzy
+msgid "Gilbert Islands"
+msgstr "Чиле/EasterIsland"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Пацифик/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Пацифик/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Пацифик/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Пацифик/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Пацифик/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Poland"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugal"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapore"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Турција"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "САД/Alaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "САД/Aleutian"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "САД/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "САД/Central"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "САД/Eastern"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "САД/East-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "САД/Hawaii"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "САД/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "САД/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "САД/Mountain"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "САД/Pacific"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "САД/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Зулу"
+
+#, fuzzy
+#~ msgid "US/Pacific-New"
+#~ msgstr "САД/Pacific"
+
+#~ msgid "SystemV/AST4"
+#~ msgstr "SystemV/AST4"
+
+#~ msgid "SystemV/AST4ADT"
+#~ msgstr "SystemV/AST4ADT"
+
+#~ msgid "SystemV/CST6"
+#~ msgstr "SystemV/CST6"
+
+#~ msgid "SystemV/CST6CDT"
+#~ msgstr "SystemV/CST6CDT"
+
+#~ msgid "SystemV/EST5"
+#~ msgstr "SystemV/EST5"
+
+#~ msgid "SystemV/EST5EDT"
+#~ msgstr "SystemV/EST5EDT"
+
+#~ msgid "SystemV/HST10"
+#~ msgstr "SystemV/HST10"
+
+#~ msgid "SystemV/MST7"
+#~ msgstr "SystemV/MST7"
+
+#~ msgid "SystemV/MST7MDT"
+#~ msgstr "SystemV/MST7MDT"
+
+#~ msgid "SystemV/PST8"
+#~ msgstr "SystemV/PST8"
+
+#~ msgid "SystemV/PST8PDT"
+#~ msgstr "SystemV/PST8PDT"
+
+#~ msgid "SystemV/YST9"
+#~ msgstr "SystemV/YST9"
+
+#~ msgid "SystemV/YST9YDT"
+#~ msgstr "SystemV/YST9YDT"
diff --git a/panels/datetime/po-timezones/ml.po b/panels/datetime/po-timezones/ml.po
new file mode 100644
index 0000000..8568c96
--- /dev/null
+++ b/panels/datetime/po-timezones/ml.po
@@ -0,0 +1,3240 @@
+# translation of system-config-date.master-timezones.ml.po to
+# translation of ml.po to
+# Ani Peter <apeter@redhat.com>, 2006, 2007.
+msgid ""
+msgstr ""
+"Project-Id-Version: system-config-date.master-timezones.ml\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-12-06 15:13+0530\n"
+"Last-Translator: \n"
+"Language-Team: <en@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: \n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"\n"
+"\n"
+"\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "ആഫ്രിക്ക/ആബിജാന്‍"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "ആഫ്രിക്ക/അക്ക്റാ"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "ആഫ്രിക്ക/അഡ്ഡിസ്സ്_അബാബാ"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "ആഫ്രിക്ക/അല്‍ജിയേഴ്സ്"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "ആഫ്രിക്ക/അസ്മാറാ"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "ആഫ്രിക്ക/അസ്മാറാ"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "ആഫ്രിക്ക/ബമാക്കോ"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "ആഫ്രിക്ക/ബാങെയ്"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "ആഫ്രിക്ക/ബാന്‍ജൂള്‍"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "ആഫ്രിക്ക/ബിസ്സൌ"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "ആഫ്രിക്ക/ബ്ളാന്‍ടൈര്‍ "
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "ആഫ്രിക്ക/ബ്രാസ്സെവില്‍"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "ആഫ്രിക്ക/ബുജംബൂറെ"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "ആഫ്രിക്ക/കെയ്റോ"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "ആഫ്രിക്ക/കസാബ്ളാന്‍ഖാ"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "ആഫ്രിക്ക/സ്യൂട്ടെ"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "സ്യൂട്ടാ & മെലീലാ"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "ആഫ്രിക്ക/കൊണാക്ക്രിി"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "ആഫ്രിക്ക/ഡക്കാര്‍"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "ആഫ്രിക്ക/ഡാര്‍_എസ്_സലാം"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "ആഫ്രിക്ക/ജിബോട്ടി"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "ആഫ്രിക്ക/ഡ്വാലാ"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "ആഫ്രിക്ക/എല്‍_ആയും"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "ആഫ്രിക്ക/ഫ്രീടൌണ്‍"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "ആഫ്രിക്ക/ഗബറോണീ"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "ആഫ്രിക്ക/ഹറാറെ"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "ആഫ്രിക്ക/ജോഹന്നസ്ബര്‍ഗ്"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "ആഫ്രിക്ക/കംപാലാ"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "ആഫ്രിക്ക/ഖാര്‍ഥും"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "ആഫ്രിക്ക/കിഗാളി"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "ആഫ്രിക്ക/കിന്‍ഷാസാ"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "പടിഞ്ഞാറന്‍ ഡെമോക്രാറ്റിക് ഓഫ് കോങ്കോ"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "ആഫ്രിക്ക/ലാഗോസ്"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "ആഫ്രിക്ക/ലിബ്രേവില്‍"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "ആഫ്രിക്ക/ലോമെ"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "ആഫ്രിക്ക/ലുവാന്‍ഡാ"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "ആഫ്രിക്ക/ലുബുംബാഷീ"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "കിഴക്കന്‍ ഡെമോക്രാറ്റിക് ഓഫ് കോങ്കോ"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "ആഫ്രിക്ക/ലുസാക്കാ"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "ആഫ്രിക്ക/മലാബൊ"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "ആഫ്രിക്ക/മപൂറ്റൊ"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "ആഫ്രിക്ക/മസേറു"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "ആഫ്രിക്ക/എംബാബാന്‍"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "ആഫ്രിക്ക/മൊഗാഡിഷു"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "ആഫ്രിക്ക/മൊണ്‍റോവ്യാ"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "ആഫ്രിക്ക/നൈറോബി"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "ആഫ്രിക്ക/എന്‍ജാമെനാ"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "ആഫ്രിക്ക/നിയാമെ"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "ആഫ്രിക്ക/ന്വാക്ഷോട്ട്"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "ആഫ്രിക്ക/വാഗഡൂഗൂ"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "ആഫ്രിക്ക/പോര്‍ട്ടോ -നോവോ"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "ആഫ്രിക്ക/സാവോ_റ്റോമെ"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "ആഫ്രിക്ക/റ്റിംബക്ക്റ്റൂ"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "ആഫ്രിക്ക/ട്രിപ്പോളി"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "ആഫ്രിക്ക/ട്യീണിസ്"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "ആഫ്രിക്ക/വിന്‍ഡ്ഹുക്ക്"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "അമേരിക്ക/എഡാക്ക്"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "അലൂഷ്യന്‍ ഐലന്‍ഡുകള്‍"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "അമേരിക്ക/ആഘറേജ്"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "അലാസ്ക്കാ സമയം"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "അമേരിക്ക/ആന്‍ഗ്വില"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "അമേരിക്ക/ആന്റിഗ്വാ"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "അമേരിക്ക/അരഗ്വൈന"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "ടോക്കാന്റിസ്"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "അമേരിക്ക/അര്‍ജന്റീന/ബ്വേനസ്_ആരീസ്"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "ബ്യൂണോസ് എയര്‍സ് (ബിഎ, സിഎഫ്)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "അമേരിക്ക/അര്‍ജന്റീന/കാറ്റാമാര്‍ക്ക"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "ക്യാറ്റമാര്‍കാ (CT), ക്യൂബട്ട് (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "അമേരിക്ക/അര്‍ജന്റീന/കൊമോട്രിവഡാവ്യാ"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "അമേരിക്ക/അര്‍ജന്റീന/കൊര്‍ഡോബ"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "മിക്ക് സ്ഥലങ്ങള്‍ (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "അമേരിക്ക/അര്‍ജന്റീന/ഹൂവീ"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "ജുജൂയ് (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "അമേരിക്ക/അര്‍ജന്റീന/ല_റിയോജ"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "ലാ റിയോജാ (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "അമേരിക്ക/അര്‍ജന്റീന/മെന്‍ഡോസ"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "മെന്‍ഡോസാ (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "അമേരിക്ക/അര്‍ജന്റീന/റിയോ_ഗല്ലെഗോസ്"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "സാന്റാ ക്രൂസ് (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "അമേരിക്ക/അര്‍ജന്റീന/സാല്‍ട്ടാ"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "അമേരിക്ക/അര്‍ജന്റീന/സാന്‍_വാന്‍"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "സാന്‍ ജുവാന്‍ (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "അമേരിക്ക/അര്‍ജന്റീന/സാന്‍_ലൂയിസ്"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "സാന്‍ ലൂയിസ് (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "അമേരിക്ക/അര്‍ജന്റീന/റ്റുക്കുമാന്‍"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "ടുക്കുമാന്‍ (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "അമേരിക്ക/അര്‍ജന്റീന/ഉഷ്വായാ"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "ടിയറാ ഡെല്‍ ഫ്യൂഗോ (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "അമേരിക്ക/അറൂബ"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "അമേരിക്ക/അസൂണ്‍സ്യോന്‍"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "അമേരിക്ക/അറ്റികോക്കന്‍"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "കിഴക്കന്‍ സ്റ്റാന്‍ഡേര്‍ഡ് സമയം - അറ്റിക്കോക്കന്‍, ഒന്‍ടാറിയോ, സൌത്താംപ്ടന്‍ ഐ, നുനാവത്"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "അമേരിക്ക/അട്ട്ക്ക"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "അമേരിക്ക/ബാഹ്യാ"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "ബാഹിയാ"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "അമേരിക്ക/ബാഹിയാ_ബാന്‍ഡെരാസ്"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "മെക്സിക്കന്‍ സെന്‍ട്രല്‍ സമയം - ബാഹിസാ ഡീ ബാന്‍ഡെരാസ്"
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "അമേരിക്ക/ബര്‍ബാഡോസ്"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "അമേരിക്ക/ബെലെം"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "അമാപാ, ഇ പാരാ"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "അമേരിക്ക/ബെലീസ്"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "അമേരിക്ക/ബ്ളാന്‍ക്-സാബ്ളോണ്‍"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "അറ്റ്ലാന്റിക് സ്റ്റാന്‍ഡേര്‍ഡ് സമയം - ക്യൂബെക് - ലോവര്‍ നോര്‍ത്ത് സ്റ്റോര്‍"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "അമേരിക്ക/ബ്വാ_വിസ്താ"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "റൊറൈമാ"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "അമേരിക്ക/ബൊഗോറ്റാ"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "അമേരിക്ക/ബൊയിസ്"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "മൌണ്ടന്‍ സമയം - തെക്ക് ഇഡാഹോ & കിഴക്ക് ഓര്‍ഗാനോ"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "അമേരിക്ക/ബ്വേനസ്_ആരീസ്"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "അമേരിക്ക/ക്കേബ്രിഡ്ജ്_ബെ"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "മൌണ്ടന്‍ സമയം - പടിഞ്ഞാറന്‍ നുനാവത്"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "അമേരിക്ക/ക്യാമ്പോ_ഗ്രാന്ഡേ"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "മാറ്റോ ഗ്രോസ്സോ ഡോ സുല്‍"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "അമേരിക്ക/ക്യാന്‍കൂണ്‍"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "സെന്‍ട്രല്‍ സമയം - ക്വിന്റാനാ റൂ"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "അമേരിക്ക/കാറക്കാസ്"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "അമേരിക്ക/കാറ്റാമാര്‍ക്ക"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "അമേരിക്ക/കയേന്‍"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "അമേരിക്ക/കെയ്മാന്‍"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "അമേരിക്ക/ഷിക്കാഗോ"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "സെന്‍ട്രല്‍ സമയം"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "അമേരിക്ക/ചിവാവാ"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "മെക്സിക്കന്‍ മൌണ്ടന്‍ സമയം - ചിഹ്വാഹ്വാ, യുഎസ് അതിര്‍ത്തിയില്‍ നിന്നും ദൂരെ"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "അമേരിക്ക/കോറല്‍_ഹാര്‍ബര്‍"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "അമേരിക്ക/കൊര്‍ഡോബ"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "അമേരിക്ക/കോസ്റ്റാ_റിക്കാ"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "അമേരിക്ക/കുയേബ"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "മാറ്റോ ഗ്രോസ്സോ"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "അമേരിക്ക/കുറേസൌ"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "അമേരിക്ക/ഡന്‍മാര്‍ക്ക്ഷാവന്‍"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "കിഴക്കന്‍ കോസ്റ്റ്, വടക്ക് സ്കോര്‍സ്ബൈസന്‍ഡ്"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "അമേരിക്ക/ഡോസന്‍"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "പസിഫിക് സമയം - വടക്ക് യൂക്കണ്‍"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "അമേരിക്ക/ഡോസന്‍_ക്രീക്ക്"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid "Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr "മൌണ്ടന്‍ സ്റ്റാന്‍ഡേര്‍ഡ് സമയം - ഡോസണ്‍ ക്രീക്ക് & ഫോര്‍ട്ട് സെയിന്റ് ജോണ്‍, ബ്രിട്ടിഷ് കൊളംബിയാ"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "അമേരിക്ക/ഡെന്‍വര്‍"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "മൌണ്ടന്‍ സമയം"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "അമേരിക്ക/ഡെട്രോയിറ്റ്"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "കിഴക്കന്‍ സമയം - മിച്ചിഗന്‍ - മിക്ക സ്ഥലങ്ങള്‍"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "അമേരിക്ക/ഡൊമെനിക്ക"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "അമേരിക്ക/എട്മണ്‍ട്ടണ്‍"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "മൌണ്ടന്‍ സമയം - ആല്‍ബേര്‍ട്ടാ, കിഴക്ക് ബ്രിട്ടിഷ് കൊളംബിയാ & പടിഞ്ഞാറന്‍ സാസ്കച്ചേവന്‍"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "അമേരിക്ക/യൂറിനെയ്പ്പ്"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "പടിഞ്ഞാറന്‍ അമേസോണാസ്"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "അമേരിക്ക/എല്‍_സാല്‍വഡോര്‍"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "അമേരിക്ക/എന്‍സെനാഡാ"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "അമേരിക്ക/ഫോര്‍ട്ടലെയ്സാ"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "തെക്ക് കിഴക്കന്‍ ബ്രസീല്‍ (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "അമേരിക്ക/ഫോര്‍ട്ട്_വെയ്ന്‍"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "അമേരിക്ക/ഗ്ളെയ്സ്_ബെ"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr "അറ്റ്ലാന്റിക് സമയം - നോവാ സ്കോട്ടിയാ - DST 1966-1971 പാലിയ്ക്കാത്ത സ്ഥലങ്ങള്‍"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "അമേരിക്ക/ഗോഡ്ഥാബ്"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "മിക്ക സ്ഥലങ്ങള്‍"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "അമേരിക്ക/ഗൂസ്_ബെ"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "അറ്റ്ലാന്റിക് സമയം - ലാബ്രഡോര്‍ - മിക്ക സ്ഥലങ്ങള്‍"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "അമേരിക്ക/ഗ്രാന്‍ഡ്_റ്റര്‍ക്ക്"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "അമേരിക്ക/ഗ്രനേഡാ"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "അമേരിക്ക/ഗ്വാഡ്ലോപ്പ്"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "അമേരിക്ക/ഗ്വാട്ടിമാല"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "അമേരിക്ക/ഗ്വായാക്കീല്‍"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "മെയിന്‍ലാന്‍ഡ്"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "അമേരിക്ക/ഗയാനാ"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "അമേരിക്ക/ഹാലിഫാക്സ്"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "അറ്റ്ലാന്റിക് സമയം - നോവാ സ്കോട്ടിയാ (മിക്ക് സ്ഥലങ്ങള്‍), PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "അമേരിക്ക/ഹവാനാ"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "അമേരിക്ക/ഹെര്‍മോസിലോ"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "മൌണ്ടന്‍ സ്റ്റാന്‍ഡേര്‍ഡ് സമയം - സൊണോറാ"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "അമേരിക്ക/ഇന്‍ഡ്യാന/ഇന്‍ഡ്യാനപോളിസ്"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "കിഴക്കന്‍ സമയം - ഇന്‍ഡ്യാനാ - മിക്ക സ്ഥലങ്ങള്‍"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "അമേരിക്ക/ഇന്‍ഡ്യാന/നോക്സ്"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "സെന്‍ട്രല്‍ സമയം - ഇന്‍ഡ്യാനാ - സ്റ്റാര്‍ക്ക് കൌണ്ടി"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "അമേരിക്ക/ഇന്‍ഡ്യാന/മാരെന്‍ഗോ"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "കിഴക്കന്‍ സമയം - ഇന്‍ഡ്യാനാ - ക്രൌഫോര്‍ഡ് കൌണ്ടി"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "അമേരിക്ക/ഇന്‍ഡ്യാനാ/പീറ്റേര്‍സ്ബര്‍ഗ്"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "കിഴക്കന്‍ സമയം - ഇന്‍ഡ്യാനാ - പൈക്ക് കൌണ്ടി"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "അമേരിക്ക/ഇന്‍ഡ്യാനപോളിസ്"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "അമേരിക്ക/ഇന്‍ഡ്യാന/ടെല്‍ _സിറ്റി"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "സെന്‍ട്രല്‍ സമയം - ഇന്‍ഡ്യാനാ - പെറി കൌണ്ടി"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "അമേരിക്ക/ഇന്‍ഡ്യാന/വെവായ്"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "കിഴക്കന്‍ സമയം - ഇന്‍ഡ്യാനാ - സ്വിറ്റ്സര്‍ലാന്‍ഡ് കൌണ്ടി"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "അമേരിക്ക/ഇന്‍ഡ്യാനാ/വിന്‍സെന്നസ്"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "കിഴക്കന്‍ സമയം - ഇന്‍ഡ്യാനാ - ഡേവിയസ്, ഡുബോയിസ്, നോക്സ് & മാര്‍ട്ടിന്‍ കൊണ്ടീസ്"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "അമേരിക്ക/ഇന്‍ഡ്യാനാ/വിനാമാക്"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "കിഴക്കന്‍ സമയം - ഇന്‍ഡ്യാനാ - പുലാസ്കി കൌണ്ടി"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "അമേരിക്ക/ഇനുവിക്ക്"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "മൌണ്ടന്‍ സമയം - പടിഞ്ഞാറ് വടക്ക് പടിഞ്ഞാറന്‍ ടെറിട്ടറികള്‍"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "അമേരിക്ക/ഇക്കലൂയിറ്റ്"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "കിഴക്കന്‍ സമയം - കിഴക്ക് നുനാവത് - മിക്ക സ്ഥലങ്ങള്‍"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "അമേരിക്ക/ജമെയ്ക്കാ"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "അമേരിക്ക/ഹൂവി"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "അമേരിക്ക/ജൂനൊ"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "അലാസ്കാ സമയം - അലാസ്കാ പാന്‍ഹാന്‍ഡില്‍"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "അമേരിക്ക/കെണ്‍ട്ടക്കി/ലൂയിവില്‍"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "കിഴക്കന്‍ സമയം - കെന്‍ട്ടക്കി - ലൂയിസ്‌വില്ലി "
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "അമേരിക്ക/കെണ്‍ട്ടക്കി/മോണ്‍ട്ടേഛിലോ"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "കിഴക്കന്‍ സമയം - കെണ്‍ട്ടക്കി - വായിന്‍ കൌണ്ടി"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "അമേരിക്ക/നോക്സ്_ഇന്‍"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "അമേരിക്ക/ലാ_പാസ്"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "അമേരിക്ക/ലിമാ"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "അമേരിക്ക/ലോസ്_ആന്ചലസ്"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "പസിഫിക്ക് സമയം"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "അമേരിക്ക/ലൂയിവില്‍"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "അമേരിക്ക/മാസെയോ"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "അലാഗോവാസ്, സെര്‍ഗൈപ്പ്"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "അമേരിക്ക/മനാഗ്വാ"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "അമേരിക്ക/മെനൌസ്"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "കിഴക്കന്‍ അമേസോണാസ്"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "അമേരിക്ക/മാരിഗോട്ട്"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "അമേരിക്ക/മാര്‍ട്ടിനെക്ക്"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "അമേരിക്ക/മറ്റമോറോസ്"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid "US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr "യുഎസ് സെന്‍ട്രല്‍ സമയം - കോവാഹ്യൂലാ, ഡുറാങ്കോ, ന്യൂവോ ലിയോണ്‍, ടമൌലിപാസ്, യുഎസ് അതിര്‍ത്തിയ്ക്കടുത്തു്"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "അമേരിക്ക/മാസറ്റ്ലാന്‍"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "മൌണ്ടന്‍ സമയം - തെക്കന്‍ ബാജാ, നായാറിത്ത്, സിനാലോവാ"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "അമേരിക്ക/മെന്‍‍ഡോസാ"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "അമേരിക്ക/മെനോമിനീ"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "സെന്‍ട്രല്‍ സമയം - മിച്ചിഗന്‍ - ഡിക്കിന്‍സണ്‍, ജോജെബിക്ക്, അയണ്‍ & മെനോമിനീ കൌണ്ടീസ്"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "അമേരിക്ക/മെറീഡാ"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "സെന്‍ട്രല്‍ സമയം - കാംപീച്ച്, യുകാറ്റാന്‍"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "അമേരിക്ക/മെക്സിക്കോ_സിറ്റി"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "സെന്‍ട്രല്‍ സമയം - മിക്ക സ്ഥലങ്ങള്‍"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "അമേരിക്ക/മിക്ക്വിലോണ്‍ "
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "അമേരിക്ക/മോന്‍ക്ട്ടണ്‍"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "അറ്റ്ലാന്റിക് സമയം - ന്യൂ ബ്രൂണ്‍സ്‌വിക്ക്"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "അമേരിക്ക/മോണ്‍ട്ടെറീ"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+"മെക്സിക്കന്‍ സെന്‍ട്രല്‍ സമയം - കോവാഹ്യൂലാ, ഡുറാങ്കോ, ന്യൂവോ ലിയോണ്‍, ടമൌലിപാസ്, യുഎസ് "
+"അതിര്‍ത്തിയില്‍ നിന്നും ദൂരെ"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "അമേരിക്ക/മോണ്‍ട്ടെവീഡിയോ"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "അമേരിക്ക/മോണ്ട്രിയല്‍"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "കിഴക്കന്‍ സമയം - ക്യൂബെക് - മിക്ക് സ്ഥലങ്ങള്‍"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "അമേരിക്ക/മോണ്‍ട്ട്സെറാറ്റ്"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "അമേരിക്ക/നാസ്സോ"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "അമേരിക്ക/ന്യൂ_യോര്‍ക്ക്"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "കിഴക്കന്‍ സമയം"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "അമേരിക്ക/നിപ്പിഗോണ്‍"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid "Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr "കിഴക്കന്‍ സമയം - ഒണ്‍ടാരിയോ & ക്യൂബെക് - DST 1967-1973 പാലിച്ചിട്ടില്ലാത്ത സ്ഥലങ്ങള്‍"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "അമേരിക്ക/നോം"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "അലാസ്കാ സമയം - പടിഞ്ഞാറന്‍ അലാസ്കാ"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "അമേരിക്ക/നൊറോണ"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "അറ്റ്ലാന്റിക് ഐലന്‍ഡുകള്‍"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "അമേരിക്ക/നോര്‍ത്ത്_ഡക്കോറ്റ/സെന്റര്‍"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "സെന്‍ട്രല്‍ സമയം - വടക്ക് ഡക്കോട്ടാ - ഒലിവര്‍ കൌണ്ടി"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "അമേരിക്ക/നോര്‍ത്ത്_ഡക്കോറ്റ/ന്യൂ_സലേം"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "സെന്‍ട്രല്‍ സമയം - വടക്ക് ഡക്കോട്ടാ - മോര്‍ട്ടണ്‍ കൌണ്ടി (മാന്‍ഡന്‍ ഒഴിച്ചു്)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "അമേരിക്ക/ഒജിനാഗാ"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "യുഎസ് മൌണ്ടന്‍ സമയം - ചിഹ്വാഹ്വാ, യുഎസ് അതിര്‍ത്തിയ്ക്കടുത്തു്"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "അമേരിക്ക/പനാമ"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "അമേരിക്ക/പാങ്നിര്‍ട്ടങ്"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "കിഴക്കന്‍ സമയം - പാങ്നിര്‍ട്ടങ്, നുനാവത്"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "അമേരിക്ക/പരാമാരിബോ"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "അമേരിക്ക/ഫീനിക്സ്"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "മൌണ്ടന്‍ സ്റ്റാന്‍ഡേര്‍ഡ് സമയം - അരിസോണാ"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "അമേരിക്ക/പോര്‍ട്ട്-ഔ-പ്രിന്‍സ്"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "അമേരിക്ക/പോര്‍ട്ടോ_ഏക്കര്‍"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "അമേരിക്ക/പോര്‍ട്ട്_ഓഫ്_സ്പയിന്‍"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "അമേരിക്ക/പോര്‍ട്ടോ_വെലോ"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "റോണ്ടിയാ"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "അമേരിക്ക/പ്യൂര്‍ട്ടോ_റിക്കോ"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "അമേരിക്ക/റെയ്നി_റിവര്‍"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "സെന്‍ട്രല്‍ സമയം - റെയിനി റിവര്‍ & ഫോര്‍ട്ട് ഫ്രാന്‍സസ്, ഒണ്‍ടാരിയോ"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "അമേരിക്ക/റാന്കിന്‍_ഇന്‍ലെറ്റ്"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "സെന്‍ട്രല്‍ സമയം - മദ്ധ്യ നുനാവത്"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "അമേരിക്ക/റെസീഫെ"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "പെര്‍നാബുക്കോ"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "അമേരിക്ക/റെജീന"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "സെന്‍ട്രല്‍ സ്റ്റാന്‍ഡേര്‍ഡ് സമയം - സസ്കാച്ചെവന്‍ - മിക്ക സ്ഥലങ്ങള്‍"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "അമേരിക്ക/റിസൊല്യൂട്ട്"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "കിഴക്കന്‍ സ്റ്റാന്‍ഡേര്‍ഡ് സമയം - റിസല്യൂട്ട്, നുനാവത്"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "അമേരിക്ക/റിയോ_ബ്രാന്‍ക്കോ"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "ഏക്കര്‍"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "അമേരിക്ക/റൊസാറിയോ"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "അമേരിക്ക/സാന്റാ_ഇസബെല്‍"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "മെക്സിക്കന്‍ പെസിഫിക് സമയം - ബാജാ കാലിഫോര്‍ണിയാ യുഎസ് അതിര്‍ത്തിയില്‍ നിന്നും ദൂരെ"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "അമേരിക്ക/സാന്‍ടറെം"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "പടിഞ്ഞാറന്‍ പാരാ"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "അമേരിക്ക/സാന്റിയാഗോ"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "അമേരിക്ക/സാന്റോ _ഡൊമിന്‍ഗോ"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "അമേരിക്ക/സാവോ_പൌലോ"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "S & SE ബ്രസീല്‍ (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "അമേരിക്ക/സ്ക്കോഴ്സ്ബൈസണ്‍ഡ്"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "സ്ക്കോര്‍സ്ബൈസന്‍ഡ് / ഇട്ടോക്കോര്‍ട്ടൂര്‍മിറ്റ്"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "അമേരിക്ക/ഷിപ്പ്‌റോക്ക്്"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "മൌണ്ടന്‍ സമയം - നാവാജോ"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "അമേരിക്ക/സെന്റ് _ബര്‍ഥലേമി"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "അമേരിക്ക/സെന്റ്_ജോണ്‍സ്"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "ന്യൂഫൌണ്ട്ലാന്‍ഡ് സമയം, SE ലാബ്രഡോര്‍ ഉള്‍പ്പടെ"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "അമേരിക്ക/സെന്റ്_കിറ്റ്സ്"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "അമേരിക്ക/സെന്റ്_ലീസിയാ"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "അമേരിക്ക/സെന്റ്_തോമസ്"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "അമേരിക്ക/സെന്റ്_വിന്‍സെന്റ്"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "അമേരിക്ക/സ്വിഫ്റ്റ്_കറണ്‍ട്ട്"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "സെന്‍ട്രല്‍ സ്റ്റാന്‍ഡേര്‍ഡ് സമയം - സാസ്കാച്ചെവാന്‍ - മിഡ്‌വെസ്റ്റ്"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "അമേരിക്ക/ടെഗൂസിഗല്‍പ്പ"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "അമേരിക്ക/തുലേ"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "തൂലേ / പിടുഫിക്ക്"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "അമേരിക്ക/തണ്‍ഡര്‍_ബെ"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "കിഴക്കന്‍ സമയം - തണ്ടര്‍ ബേ, ഒണ്‍ടാരിയോ"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "അമേരിക്ക/തിജ്വാനാ"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "യുഎസ് പസിഫിക് സമയം - ബാജാ കാലിഫോര്‍ണിയാ, യുഎസ് അതിര്‍ത്തിയിക്കടുത്തു്"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "അമേരിക്ക/ടൊറൊണ്‍ട്ടോ"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "കിഴക്കന്‍ സമയം - ഒണ്‍ടാരിയോ - മിക്ക സ്ഥലങ്ങള്‍"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "അമേരിക്ക/ടൊര്‍ട്ടോളാ"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "അമേരിക്ക/വാന്‍ക്കൂവര്‍"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "പസിഫിക് സമയം - പടിഞ്ഞാറന്‍ ബ്രിട്ടിഷ് കൊളംബിയാ"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "അമേരിക്ക/വെര്‍ജിന്‍"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "അമേരിക്ക/വൈറ്റ്ഹോഴ്സ്"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "പസിഫിക് സമയം - തെക്ക് യുക്കോണ്‍"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "അമേരിക്ക/വിന്നിപ്പെഗ്"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "സെന്‍ട്രല്‍ സമയം - മാനിറ്റോബാ & പടിഞ്ഞാറ് ഒണ്‍ടാരിയോ"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "അമേരിക്ക/യാക്കുറ്റാറ്റ്"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "അലാസ്കാ സമയം - അലാസ്കാ പാന്‍ഹാന്‍ഡില്‍ നെക്ക്"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "അമേരിക്ക/യെല്ലോനൈഫ്"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "മൌണ്ടന്‍ സമയം - മദ്ധ്യ വടക്ക് പടിഞ്ഞാറന്‍ ടെറിട്ടറികള്‍"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "അന്റാര്‍ട്ടിക്ക/റാര്‍ട്ടിത്/കാസ്സെയ്"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "സെസീ സ്റ്റേഷന്‍, ബെയിലീ പെനിന്‍സുലാ"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "അന്റാര്‍ട്ടിക്ക/ഡേവിസ്"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "ഡേവിസ് സ്റ്റേഷന്‍, വെസ്റ്റ്ഫോള്‍ഡ് ഹില്‍സ്"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "അന്റാര്‍ട്ടിക്ക/ഡുമോണ്‍ട്ടുര്‍വില്ലി"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "ഡ്യൂമോണ്ട്-ഡീ ഉര്‍വില്‍, ടെറേ അഡീലീ"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "അന്റാര്‍ട്ടിക്ക/മാക്വാരീ"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "മാക്വാരീ ഐലന്റ് സ്റ്റേഷന്‍, മാക്വാരീ ഐലന്‍ഡ്"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "അന്റാര്‍ട്ടിക്ക/മോസണ്‍"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "മോസണ്‍ സ്റ്റേഷന്‍, ഹോം ബേ"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "അന്റാര്‍ട്ടിക്ക/മാക്ക്മാര്‍ഡോ"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "മാക്‌മര്‍ഡോ സ്റ്റേഷന്‍, റോസ് ഐലന്‍ഡ്"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "അന്റാര്‍ട്ടിക്ക/പാമെര്‍"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "പാമര്‍ സ്റ്റേഷന്‍, അന്‍വര്‍സ് ഐലന്‍ഡ്"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "അന്റാര്‍ട്ടിക്ക/റൊഥേറാ"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "റോഥേറാ സ്റ്റേഷന്‍, അഡെലേയിഡ് ഐലന്‍ഡ്"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "അന്റാര്‍ട്ടിക്ക/സൌത്ത്_പോള്‍"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "അമണ്ട്സെന്‍-സ്കോട്ട് സ്റ്റേഷന്‍, സൌത്ത് പോള്‍"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "അന്റാര്‍ട്ടിക്ക/സ്യോവാ"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "സ്യോവാ സ്റ്റേഷന്‍, കിഴക്കന്‍ ഒങ്കുല്‍ ഐ"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "അന്റാര്‍ട്ടിക്ക/വോസ്ഥോക്ക്"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "വോസ്ടോക് സ്റ്റേഷന്‍, സൌത്ത് മാഗ്നെറ്റിക് പോള്‍"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "ആര്‍ട്ടിക്ക്/ലോങിയര്‍ബയന്‍"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "ഏഷ്യ/ഏഡന്‍"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "ഏഷ്യ/അല്‍മാട്ടി"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "ഏഷ്യ/അമ്മാന്‍"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "ഏഷ്യ/ആനെഡിര്‍"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "മോസ്കൌ+8 - ബെറിങ് സീ"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "ഏഷ്യ/ആക്ക്റ്റൌ"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "അറ്റിറൌ (അറ്റിറൌ, ഗുര്‍യെവ്), മാങ്കിസ്റ്റൌ (മാന്‍കിസ്റ്റൌ)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "ഏഷ്യ/അക്ക്റ്റോബെ"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "അക്ടോബ് "
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "ഏഷ്യ/അഷ്ഗാബാത്ത്"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "ഏഷ്യ/അഷ്കാബാദ്"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "ഏഷ്യ/ബാഗ്ദാദ്"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "ഏഷ്യ/ബെഹറിന്‍"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "ഏഷ്യ/ബാക്കു"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "ഏഷ്യ/ബാങ്കോക്ക്"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "ഏഷ്യ/ബെയ്റൂട്ട്"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "ഏഷ്യ/ബിഷ്കേക്ക്"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "ഏഷ്യ/ബ്രൂണെ"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "ഏഷ്യ/കല്‍ക്കത്ത"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "ഏഷ്യ/ഷൊയിബാല്‍സന്‍"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "ഡോര്‍നോഡ്, സുക്ബാത്തര്‍"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "ഏഷ്യ/ഷോങ്കിംങ്"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "സെന്‍ട്രല്‍ ചൈനാ - സിച്ചാന്‍, യുന്നാന്‍, ഗ്വാങ്സി, ഷാങ്സി, ഗ്യുസോ, എന്നിവ"
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "ഏഷ്യ/ഷങ്കിംങ്"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "ഏഷ്യ/കോളോബൊ"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "ഏഷ്യ/ഡാക്കാ"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "ഏഷ്യ/ഡമാസ്കസ്"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "ഏഷ്യ/ഡാക്കാ"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "ഏഷ്യ/ഡിലി"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "ഏഷ്യ/ദുബായ്"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "ഏഷ്യ/ദുഷാനബെ"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "ഏഷ്യ/ഗാസാ"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "ഏഷ്യ/ഹാര്‍ബിന്‍"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "ഹിലോങ്ജിയാങാ (മോഹെ ഒഴികെ), ജിലിന്‍"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "ഏഷ്യ/ഹോ_ചീ_മിന്‍ഹ്"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "ഏഷ്യ/ഹോങ്_കോങ്"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "ഏഷ്യ/ഹോവ്ഡ്"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "ബായാന്‍-ഒല്‍ജിയ്, ഗോവി-അല്‍ട്ടായി, ഹോവ്ഡ്, ഉവ്സ്, സാവ്ക്കാന്‍"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "ഏഷ്യ/ഐര്‍ക്കട്ട്സ്ക്ക്"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "മോസ്കൌ+05 - ലെയിക്ക് ബെയിക്കല്‍"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "ഏഷ്യ/ഇസ്ത്താന്‍ബുല്‍"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "ഏഷ്യ/ജക്കാര്‍ത്ത "
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "ജാവാ & സുമത്രാ"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "ഏഷ്യ/ജയപ്പുപ"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "ഇറിയാന്‍ ജയാ & മൊലുക്കസ്"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "ഏഷ്യ/ജേറുസലേം"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "ഏഷ്യ/കാബുള്‍"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "ഏഷ്യ/കംച്ചട്ട്ക്ക"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "മോസ്കൌ+08 - കാമ്ചട്ട്കാ"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "ഏഷ്യ/കറാച്ചി"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "ഏഷ്യ/കാഷ്ഗര്‍"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "പടഞ്ഞാറ് ടിബറ്റ് & ക്സിങ്ജിയാങ്"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "ഏഷ്യ/കാട്മണ്ടു"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "ഏഷ്യ/കാത്മണ്ടു"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "ഏഷ്യ/കോല്‍ക്കട്ട"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "ഏഷ്യ/ക്രാസ്നൊയാര്‍സ്ക്"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "മോസ്കൌ+04 - യെനിസീ റിവര്‍"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "ഏഷ്യ/ക്വാലാ_ലമ്പൂര്‍"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "പെനിന്‍സുലര്‍ മലേഷ്യാ"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "ഏഷ്യ/കച്ചിംങ്"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "സബാഹ് & സാറാവാക്"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "ഏഷ്യ/കുവൈത്ത്"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "ഏഷ്യ/മക്കൌ"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "ഏഷ്യ/മക്കാവു"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "ഏഷ്യ/മാഗഡന്‍"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "മോസ്കൌ+08 - മഗാഡാന്‍"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "ഏഷ്യ/മാക്കസ്സര്‍"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "കിഴക്ക്, തെക്ക് ബോര്‍ണിയോ, സെലബെസ്, ബാലി, ന്യൂസാ ടെങ്കേരാ, പടിഞ്ഞാറ് ടിമോര്‍"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "ഏഷ്യ/മാനില"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "ഏഷ്യ/മസ്ക്കറ്റ്"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "ഏഷ്യ/നിക്കോഷ്യാ"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "ഏഷ്യ/നോവോകസ്നെട്സ്ക്"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "മോസ്ക്കോ+03 - നൊവോകസ്നെട്സ്ക്"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "ഏഷ്യ/നൊവോസിബിര്‍സ്ക്"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "മോസ്ക്കോ+03 - നൊവോസിബിര്‍സ്ക്"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "ഏഷ്യ/ഓമ്സ്ക്ക്"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "മോസ്കൌ+03 - പടിഞ്ഞാറ് സൈബേരിയാ"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "ഏഷ്യ/ഒറാല്‍"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "പടിഞ്ഞാറന്‍ കസക്സ്ഥാന്‍"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "ഏഷ്യ/പെനോം_പെന്‍"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "ഏഷ്യ/പൊണ്‍ട്ടിയാനാക്ക്"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "പടിഞ്ഞാറന്‍ മദ്ധ്യ ബോര്‍ണിയോ"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "ഏഷ്യ/പ്യോംങ്ഗ്യാങ്"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "ഏഷ്യ/ഖത്തര്‍"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "ഏഷ്യ/ഖ്വിസിലോര്‍ഡാ"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "ഖിസിലോര്‍ഡാ "
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "ഏഷ്യ/രണ്‍ഗൂണ്‍"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "ഏഷ്യ/റിയാദ്"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "ഏഷ്യ/റിയാദ്87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "ഏഷ്യ/റിയാദ്88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "ഏഷ്യ/റിയാദ്89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "ഏഷ്യ/സയ്ഗോണ്‍"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "ഏഷ്യ/സാഖാലിന്‍"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "മോസ്കൌ+07 - സാഖാലിന്‍ ഐലന്‍ഡ്"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "ഏഷ്യ/സമര്‍ക്കണ്ഡ്"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "പടിഞ്ഞാറന്‍ ഉസ്ബെക്കിസ്ഥാന്‍"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "ഏഷ്യ/സോള്‍"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "ഏഷ്യ/ഷാന്‍ഗൈ"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "കിഴക്ക് ചൈനാ - ബെയിജിങ്, ഗ്വാങ്ഡോങ്, ഷാങ്കായി, എന്നിവ"
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "ഏഷ്യ/സിംഗപൂര്‍"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "ഏഷ്യ/ഥൈപെയ്"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "ഏഷ്യ/ഥഷ്ക്കെന്ത്"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "കിഴക്കന്‍ ഉസ്ബെക്കിസ്ഥാന്‍"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "ഏഷ്യ/ഥെബിലിസി"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "ഏഷ്യ/ടെഹ്രന്‍"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "ഏഷ്യ/ഥെല്‍_അവീവ്"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "ഏഷ്യ/ഥിംമ്പു"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "ഏഷ്യ/ഥിംമ്പു"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "ഏഷ്യ/ടോക്ക്യോ"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "ഏഷ്യ/ഉജംങ്_പാന്‍ഡങ്"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "ഏഷ്യ/ഉലാന്‍ബാത്തര്‍"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "ഏഷ്യ/ഉലാന്‍_ബാറ്റോര്‍"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "ഏഷ്യ/ഉറുംഖി"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "ടിബറ്റ്, ക്സിങ്ജാങ് എന്നിവടങ്ങളിലുള്ള മിക്ക സ്ഥലങ്ങള്‍"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "ഏഷ്യ/വിയന്റിയാന്‍"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "ഏഷ്യ/വ്ളാഡിവോസ്ഥോക്ക്"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "മോസ്കൌ+07 - അമൂര്‍ റിവര്‍"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "ഏഷ്യ/യെക്കൂട്ട്സ്ക്ക്"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "മോസ്കൌ+06 - ലെനാ റിവര്‍"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "ഏഷ്യ/യെക്കാത്തറിന്‍ബര്‍ഗ്"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "മോസ്കൌ+02 - ഉറല്‍സ്"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "ഏഷ്യ/യെറെവാന്‍"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "അറ്റ്ലാന്റിക്/അസോഴ്സ്"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "അസോര്‍സ്"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "അറ്റ്ലാന്റിക്/ബര്‍മൂഡാ"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "അറ്റ്ലാന്റിക്/കാനറി"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "കാനറി ഐലന്‍ഡുകള്‍"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "അറ്റ്ലാന്റിക്/കെയ്പ്പ്_വെര്‍ദി"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "അറ്റ്ലാന്റിക്/ഫെയ്റോ"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "അറ്റ്ലാന്റിക്/ഫെറോ"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "അറ്റ്ലാന്റിക്/ജാന്‍_മയന്‍"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "അറ്റ്ലാന്റിക്/മദീയ്റ"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "മഡയിറാ ഐലന്‍ഡുകള്‍"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "അറ്റ്ലാന്റിക്/റെഖ്യാവെക്ക്"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "അറ്റ്ലാന്റിക്/സൌത്ത്_ജോര്‍ജ്യാ"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "അറ്റ്ലാന്റിക്/സ്റ്റാന്‍ലി"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "അറ്റ്ലാന്റിക്/സെന്റര്‍_ഹെലെനാ"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "ഓസ്ട്രേലിയ/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "ഓസ്ട്രേലിയ/അഡെലേയ്ട്"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "തെക്കന്‍ ഓസ്ട്രേലിയാ"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "ഓസ്ട്രേലിയ/ബ്രിസ്ബന്‍"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "ക്വീന്‍സ്‌ലാന്‍ഡ് - മിക്ക് സ്ഥലങ്ങള്‍"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "ഓസ്ട്രേലിയ/ബ്രോക്കണ്‍_ഹില്‍"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "ന്യൂ സൌത്ത് വെയില്‍സ് - യാന്‍കോവിന്നാ"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "ഓസ്ട്രേലിയ/ക്യാന്‍ബെറാ"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "ഓസ്ട്രേലിയ/ക്യറീ"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "ടാസ്മാനിയാ - കിങ് ഐലന്‍ഡ്"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "ഓസ്ട്രേലിയ/ഡാര്‍വിന്‍"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "നോര്‍ത്തേണ്‍ ടെറിട്ടറി"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "ഓസ്ട്രേലിയ/യൂക്ലാ"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "പടിഞ്ഞാറാന്‍ ഓസ്ട്രേലിയാ - യൂക്ലാ"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "ഓസ്ട്രേലിയ/ഹൊബാര്‍ട്ട്"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "ടാസ്മാനിയാ - മിക്ക സ്ഥലങ്ങള്‍"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "ഓസ്ട്രേലിയ/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "ഓസ്ട്രേലിയ/ലിന്‍ട്മാന്‍"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "ക്വീന്‍സ്‌ലാന്‍ഡ് - ഹോളിഡേ ഐലന്‍ഡുകള്‍"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "ഓസ്ട്രേലിയ/ലോര്‍ഡ്_ഹോവ്"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "ലോര്‍ഡ് ഹോവ് ഐലന്‍ഡ്"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "ഓസ്ട്രേലിയ/മെല്‍ബോണ്‍"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "വിക്ടോറിയ"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "ഓസ്ട്രേലിയ/വടക്ക്"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "ഓസ്ട്രേലിയ/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "ഓസ്ട്രേലിയ/പെര്‍ത്ത്"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "പടിഞ്ഞാറന്‍ ഒസ്ട്രേലിയാ - മിക്ക് സ്ഥലങ്ങള്‍"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "ഓസ്ട്രേലിയ/ക്യീന്‍സ്ലാന്‍ഡ്"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "ഓസ്ട്രേലിയ/തെക്ക്"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "ഓസ്ട്രേലിയ/സിഡ്നി"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "ന്യൂ സൌത്ത് വെയില്‍സ് - മിക്ക സ്ഥലങ്ങള്‍"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "ഓസ്ട്രേലിയ/റ്റാസ്മാന്യ"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "ഓസ്ട്രേലിയ/വിക്ടോറിയ"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "ഓസ്ട്രേലിയ/പടിഞ്ഞാറ്"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "ഓസ്ട്രേലിയ/യാന്‍ക്കോവിന"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "ബ്രസീല്‍/ആക്ക്രെ"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "ബ്രസീല്‍/ഡെനൊറോണാ"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "ബ്രസീല്‍/കിഴക്ക്"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "ബ്രസീല്‍/പടിഞ്ഞാറ്"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "കാനഡ/അറ്റ്ലാന്റിക്"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "കാനഡ/സെന്‍ട്രല്‍"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "കാനഡ/കിഴക്കന്‍"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "കാനഡ/കിഴക്ക്-സാസ്ക്കച്ചേവാന്‍"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "കാനഡ/മൌണ്‍ടന്‍"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "കാനഡ/ന്യൂഫൌണ്‍ട്ലാന്‍ഡ്"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "കാനഡ/പസിഫിക്ക്"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "കാനഡ/സാസ്ക്കച്ചേവാന്‍"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "കാനഡ/യുക്കോണ്‍"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "ചിലി/കോണ്‍ട്ടിനെന്റല്‍"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "ചിലി/ഈസ്റ്റര്‍ഐലന്റ്"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "ക്യൂബ"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "ഈജിപ്റ്റ്"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "എയിര്‍"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/ഗ്രീന്‍വിച്ച്"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/യൂണിവേഴ്സല്‍"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/സുളു"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "യൂറോപ്പ്/ആമ്സറ്റര്‍‍ഡാം"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "യൂറോപ്പ്/ആന്‍ഡോറ"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "യൂറോപ്പ്/ഏഥന്‍സ്"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "യൂറോപ്പ്/ബെല്‍ഫാസ്റ്റ്"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "യൂറോപ്പ്/ബെല്‍ഗ്രേഡ്"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "യൂറോപ്പ്/ബെര്‍ലിന്‍"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "യൂറോപ്പ്/ബ്രാറ്റിസ്ലോവാ"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "യൂറോപ്പ്/ബ്രസ്സല്‍സ്"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "യൂറോപ്പ്/ബുക്കേറസ്റ്റ്"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "യൂറോപ്പ്/ബുഡാപെസ്റ്റ്"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "യൂറോപ്പ്/ഖിഷിനൌ"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "യൂറോപ്പ്/കൊപ്പെന്‍ഹാഗന്‍"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "യൂറോപ്പ്/ഡ്യൂബ്ളിന്‍"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "യൂറോപ്പ്/ഗിബ്രാല്റ്റര്‍"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "യൂറോപ്പ്/ജേര്‍ണ്സീ"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "യൂറോപ്പ്/ഹെല്‍സിന്‍ഖി"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "യൂറോപ്പ്/ഐല്‍ ഓഫ് മാന്‍"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "യൂറോപ്പ്/ഇസ്റ്റാന്‍ബുല്‍"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "യൂറോപ്പ്/ജേര്‍സീ"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "യൂറോപ്പ്/കലിനിന്‍ഗ്രാഡ്"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "മോസ്കൌ-01 - കാലിങ്ഗ്രാഡ്"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "യൂറോപ്പ്/കെയിവ്"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "യൂറോപ്പ്/ലിസ്ബണ്‍"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "യൂറോപ്പ്/ലുബ്ളെയാന"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "യൂറോപ്പ്/ലണ്ടന്‍"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "യൂറോപ്പ്/ലക്സംബര്‍ഗ്"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "യൂറോപ്പ്/മാഡ്രിഡ്"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "യൂറോപ്പ്/മാല്‍റ്റാ"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "യൂറോപ്പ്/മാരീഹം"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "യൂറോപ്പ്/മിന്‍സ്ക്ക്"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "യൂറോപ്പ്/മൊണാക്കൊ"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "യൂറോപ്പ്/മോസ്ക്കൊ"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "മോസ്കൌ+00 - പടിഞ്ഞാറന്‍ റഷ്യാ"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "യൂറോപ്പ്/നിക്കോഷ്യ"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "യൂറോപ്പ്/ഓസ്ലോ"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "യൂറോപ്പ്/പാരീസ്"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "യൂറോപ്പ്/പോഡ്ഗോറിക്കാ"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "യൂറോപ്പ്/പ്രാഗ്"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "യൂറോപ്പ്/റിഗ"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "യൂറോപ്പ്/റോം"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "യൂറോപ്പ്/സമേറ"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "മോസ്കൌ - സാമാറാ, ഉഡ്മര്‍ത്യാ"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "യൂറോപ്പ്/സാന്‍_മാറിനൊ"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "യൂറോപ്പ്/സരാജെവൊ"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "യൂറോപ്പ്/സിംഫെറോപ്പല്‍"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "സെന്‍ട്രല്‍ ക്രമിയാ"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "യൂറോപ്പ്/സ്ക്കോപ്പ്യെ"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "യൂറോപ്പ്/സോഫിയ"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "യൂറോപ്പ്/സ്റ്റോക്ക്ഹോം"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "യൂറോപ്പ്/റ്റാലിന്‍"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "യൂറോപ്പ്/റ്റിറാനെ"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "യൂറോപ്പ്/റ്റിറാസ്പ്പോള്‍"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "യൂറോപ്പ്/ഉസ്ഗൊറോഡ്"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "റൂഥേനിയാ"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "യൂറോപ്പ്/വാഡൂസ്"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "യൂറോപ്പ്/വത്തിക്കാന്‍"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "യൂറോപ്പ്/വിയെന്ന"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "യൂറോപ്പ്/വില്‍നെയസ്"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "യൂറോപ്പ്/വോള്‍ഗോഗ്രാഡ്"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "മോസ്കൌ+00 - കാസ്പിയന്‍ സീ"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "യൂറോപ്പ്/വാര്‍സൌ"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "യൂറോപ്പ്/സാഗ്രെബ്"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "യൂറോപ്പ്/സാപ്പൊറോസി"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "സാപോറോസ്യേ, കിഴക്കന്‍ ലുഗാന്‍സ്ക് / സാപോറിസിയാ, കിഴക്കന്‍ ലുഹാന്‍സ്ക്"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "യൂറോപ്പ്/സ്യൂറിക്ക്"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "ഫാക്ടറി"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-എയിര്‍"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "ഗ്രീന്‍വിച്ച്"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "ഹോങ്ക്കോങ്"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "ഐസ്ലാന്‍ഡ്"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "ഇഡ്യന്‍/ആന്റനാനാരിവൊ"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "ഇഡ്യന്‍/ഷാഗോസ്"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "ഇഡ്യന്‍/ക്രിസ്മസ്"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "ഇഡ്യന്‍/കൊക്കോസ്"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "ഇഡ്യന്‍/കൊമോറൊ"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "ഇഡ്യന്‍/കെര്‍ഗ്വേലന്‍"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "ഇഡ്യന്‍/മാഹെ"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "ഇഡ്യന്‍/മാല്‍ഡീവ്സ്"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "ഇഡ്യന്‍/മൊറീഷ്യസ്"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "ഇഡ്യന്‍/മയോട്ടെ"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "ഇഡ്യന്‍/റീയൂണ്യന്‍"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "ഇറാന്‍"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "ഇസ്രയേല്‍"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "ജമൈക്ക"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "ജപ്പാന്‍"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "ക്വാജലന്‍"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "ലിബ്യ"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "മെക്സിക്കൊ/ബജനോര്‍തെ"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "മെക്സിക്കൊ/ബാജാസുര്‍"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "മെക്സിക്കൊ/ജെനറല്‍"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "മിഡ്ഈസ്റ്റ്/റിയാദ്87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "മിഡ്ഈസ്റ്റ്/റിയാദ്88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "മിഡ്ഈസ്റ്റ്/റിയാദ്89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "നവാജൊ"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "പസിഫിക്ക്/ആപ്പിയ"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "പസിഫിക്ക്/ഓക്ക്ലാന്‍ഡ്"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "പസിഫിക്ക്/ചാഥാം"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "ചാഥം ഐലന്‍ഡുകള്‍"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "പസിഫിക്ക്/ചുക്ക്"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "ചുക്ക് (ട്രുക്ക്) ആന്‍ഡ് യാപ്"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "പസിഫിക്ക്/ഈസ്റ്റര്‍ "
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "ഈസ്റ്റര്‍ ഐലന്‍ഡ് & സാലാ വയി ഗോമസ്"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "പസിഫിക്ക്/എഫെയ്റ്റ്"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "പസിഫിക്ക്/എന്‍ഡര്‍ബ്യൂറി"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "ഫീണിക്സ് ഐലന്‍ഡുകള്‍"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "പസിഫിക്ക്/ഫക്കോഫൊ"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "പസിഫിക്ക്/ഫിജി"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "പസിഫിക്ക്/ഫുണാഫുത്തി"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "പസിഫിക്ക്/ഗലാപ്പാഗോസ്"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "ഗാലാപാഗോസ് ഐലന്‍ഡുകള്‍"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "പസിഫിക്ക്/ഗാംബിയര്‍"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "ഗാംബിയര്‍ ഐലന്‍ഡുകള്‍"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "പസിഫിക്ക്/ഗ്വഡാല്‍കനാല്‍"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "പസിഫിക്ക്/ഗ്വാം"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "പസിഫിക്ക്/ഹൊണോലുലു"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "ഹവായ്"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "പസിഫിക്ക്/ജോണ്‍സ്റ്റണ്‍"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "ജോണ്‍സ്റ്റണ്‍ അറ്റോള്‍"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "പസിഫിക്ക്/കെരിസ്മസ്"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "ലൈന്‍ ഐലന്‍ഡുകള്‍"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "പസിഫിക്ക്/കൊസ്രെ"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "കോസ്രേ"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "പസിഫിക്ക്/ക്വാജലന്‍"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "പസിഫിക്ക്/മജൂറോ"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "പസിഫിക്ക്/മാരക്ക്വെസാസ്"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "മാര്‍ക്വിസാസ് ഐലന്‍ഡുകള്‍"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "പസിഫിക്ക്/മിഡ്‌വേ"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "മിഡ്‌വേ ഐലന്‍ഡുകള്‍"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "പസിഫിക്ക്/നൌറൊ"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "പസിഫിക്ക്/നെയൂവെ"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "പസിഫിക്ക്/നോര്‍ഫോക്ക്"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "പസിഫിക്ക്/നവോമ്യ"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "പസിഫിക്ക്/പാഗോ_പാഗോ"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "പസിഫിക്ക്/പാലൌ"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "പസിഫിക്ക്/പിറ്റ്കെയിന്‍"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "പസിഫിക്ക്/പോന്‍പെയ്"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "പോന്‍പെയ് (പോണേപ്പ്)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "പസിഫിക്ക്/പൊനൈപ്പ്"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "പസിഫിക്ക്/പോര്‍ട്ട്_മോര്‍സ്ബീ"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "പസിഫിക്ക്/രരോട്ടൊന്‍ഗ"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "പസിഫിക്ക്/സായിപ്പാന്‍"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "പസിഫിക്ക്/സമോവ"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "പസിഫിക്ക്/തഹിത്തി"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "സൊസൈറ്റി ഐലന്‍ഡുകള്‍"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "പസിഫിക്ക്/തരാവാ"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "ഗില്‍ബേര്‍ട്ട് ഐലന്‍ഡുകള്‍"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "പസിഫിക്ക്/റ്റോങാറ്റപ്പു"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "പസിഫിക്ക്/ട്രക്ക്"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "പസിഫിക്ക്/വെയ്ക്ക്"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "വെയിക്ക് ഐലന്‍ഡ്"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "പസിഫിക്ക്/വാല്ലിസ്"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "പസിഫിക്ക്/യാപ്പ്"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "പോളണ്‍ട്"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "പോര്‍ച്ച്യുഗല്‍"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "സിംഗപ്പൂര്‍"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "തുര്‍ക്കി"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "യൂണിവേഴ്സല്‍"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "യു എസ്/അലാസ്ക്ക"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "യു എസ്/എലൂഷന്‍"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "യു എസ്/അരിസോണ"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "യു എസ്/സെന്‍ട്രല്‍"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "യു എസ്/കിഴക്കന്‍"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "യു എസ്/കിഴക്ക്-ഇഡ്യാന"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "യു എസ്/ഹവായ്"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "യു എസ്/ഇഡ്യാന-സ്റ്റാര്‍ക്ക്"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "യു എസ്/മിഷിഗന്‍"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "യു എസ്/മൌണ്‍ടന്‍"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "യു എസ്/പസിഫിക്ക്"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "യു എസ്/സമോവ"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "സുളു"
+
diff --git a/panels/datetime/po-timezones/mr.po b/panels/datetime/po-timezones/mr.po
new file mode 100644
index 0000000..ed4d7c0
--- /dev/null
+++ b/panels/datetime/po-timezones/mr.po
@@ -0,0 +1,3242 @@
+# translation of mr.po to Marathi
+# Marathi translations for PACKAGE package.
+# Copyright (C) 2004 THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Automatically generated, 2004.
+# Rahul Bhalerao <rbhalera@redhat.com>, 2006.
+# Rahul Bhalerao <b.rahul.pm@gmail.com>, 2006.
+# Sandeep Shedmake <sandeep.shedmake@gmail.com>, 2008.
+# Sandeep Shedmake <sshedmak@redhat.com>, 2009, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: mr\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-12-06 16:21+0530\n"
+"Last-Translator: Sandeep Shedmake <sshedmak@redhat.com>\n"
+"Language-Team: Marathi <fedora-trans-mr@redhat.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: mr\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: nplurals=2; plural=(n!=1);\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "आफ्रिका/अबिड्जन"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "आफ्रिका/अक्रा"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "आफ्रिका/एदिस_अबाबा"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "आफ्रिका/अलजियर्स"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "आफ्रिका/असमेरा"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "आफ्रिका/असमेरा"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "आफ्रिका/बामाको"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "आफ्रिका/बंगुई"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "आफ्रिका/बंजल"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "आफ्रिका/बिसू"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "आफ्रिका/ब्लेनतरी"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "आफ्रिका/ब्राजाविले"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "आफ्रिका/बुजमबुरा"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "आफ्रिका/कैरो"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "आफ्रिका/कासाब्लांका"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "आफ्रिका/सियूटा"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "सेउता & मेलिल्ला"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "आफ्रिका/कोनाक्री"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "आफ्रिका/डकर"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "आफ्रिका/दार_एस_स्लेम"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "आफ्रिका/ड्जिबोटी"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "आफ्रिका/डूअला"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "आफ्रिका//एल_ऐन"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "आफ्रिका/फ्रीटाउन"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "आफ्रिका/गैब्रोन"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "आफ्रिका/हरारे"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "आफ्रिका/जोहांन्सबर्ग"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "आफ्रिका/कम्पाला"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "आफ्रिका/खार्तुम"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "आफ्रिका/किगाली"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "आफ्रिका/किंसासा"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "पश्चिम डेमोक्रेटीक रिपब्लीक ऑफ काँगो"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "आफ्रिका/लागोस"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "आफ्रिका/लिबरविले"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "आफ्रिका/लोम"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "आफ्रिका/लुआंडा"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "आफ्रिका/लुबूंबशी"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "दक्षीण डेमोक्रेटीक रिपब्लीक ऑफ काँगो"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "आफ्रिका/लुसाका"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "आफ्रिका/मलाबो"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "आफ्रिका/मपुतो"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "आफ्रिका/मैसेरु"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "आफ्रिका/मेबाबाने"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "आफ्रिका/मोगाडीशू"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "आफ्रिका/मोनरोविया"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "आफ्रिका/नैरोबी"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "आफ्रिका/नजेमेना"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "आफ्रिका/नेमै"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "आफ्रिका/नाकचाट"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "आफ्रिका/ऊगोदूगो"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "आफ्रिका/पोर्टो-नोवो"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "आफ्रिका/सावो_टोम "
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "आफ्रिका/तिंबकटू"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "आफ्रिका/त्रिपोली"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "आफ्रिका/ट्यूनिस"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "आफ्रिका/विंडहॉक"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "अमेरिका/अदक"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "अल्यूशीयन द्वीप"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "अमेरिका/एंकरेज"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "अलास्का वेळ"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "अमेरिका/अंग्यूला"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "अमेरिका/एंटीगुआ"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "अमेरिका/अराग्वेना"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "टोकॅनटींस्"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "अमेरिका/अर्जेंटीना/ब्युनोज_आयर्स"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "ब्यूएनोज् आयरीज् (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "अमेरिका/अर्जेंटीना/कैटामारका"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "कटामार्का (CT), चुबुत (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "अमेरिका/अर्जेंटीना/कोमोडरिवाडाविया"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "अमेरिका/अर्जेंटीना/कारडोबा"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "बहुतांश ठिकाणं (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "अमेरिका/अर्जेंटीना/जुजै"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "जुजुय (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "अमेरिका/अर्जेंटीना/ला_रियोजा"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "ला रीओजा (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "अमेरिका/अर्जेंटीना/मेनडोजा"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "मेंडोजा (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "अमेरिका/अर्जेंटीना/रियो_गॅल्लेगोस्"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "सॅन्टा क्रुज (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "अमेरिका/अर्जेंटीना/साल्टा"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "अमेरिका/अर्जेंटीना/सॅन_जुआन"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "सॅन जुआन (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "अमेरिका/अर्जेंटीना/सॅन_लुइस"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "सॅन लुइस् (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "अमेरिका/अर्जेंटीना/टकमॅन"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "तुकुमॅन (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "अमेरिका/अर्जेंटीना/उशुआहिया"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "तैर्रा डेल फुएगो (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "अमेरिका/अरुबा"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "अमेरिका/असनशियन"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "अमेरिका/अटिकोकन"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "पूर्वीय मानक वेळ - अटीकोकन, ओंटारीयो व साऊथहॅम्पटन ई, नुनावुत"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "अमेरिका/अटका"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "अमेरिका/बहिया"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "बहीआ"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "अमेरिका/बहिया बंडेरास् (_B)"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "मेक्सिकन सेंट्रल टाईम - बाहिया डे बंडेरास्"
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "अमेरिका/बार्बाडोस"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "अमेरिका/बेलेम"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "अमापा, ए पारा"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "अमेरिका/बेलिज़"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "अमेरिका/ब्लांक-सॅब्लॉन"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "अटलँटीक मानक वेळ - क्यूबेक - लोवर उत्तरीय शोर"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "अमेरिका/बोआ_विस्ता"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "रोराइमा"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "अमेरिका/बोगोटा"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "अमेरिका/बोइस"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "माऊंटन वेळ - दक्षीण इदाहो & पूर्व ओरेगोन"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "अमेरिका/ब्युनोज_आयर्स"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "अमेरिका/कैम्बरीज_बे"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "माऊंटन वेळ - पश्चिम नुनावुत"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "अमेरिका/कंपो_ग्रैंड"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "माटो ग्रोस्सो डो सुल"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "अमेरिका/कानकुन"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "सेंट्रल वेळ - कुइंटाना रू"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "अमेरिका/कॅराकस"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "अमेरिका/कॅटामारका"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "अमेरिका/कैयेन"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "अमेरिका/कैमेन"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "अमेरिका/शिकागो"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "सेंट्रल वेळ"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "अमेरिका/चिहूआहुआ"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "मेक्सीकन माऊंटन वेळ - US बॉर्डर पासून चिहुआहुआ दूर आहे"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "अमेरिका/कोरल_हार्बर"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "अमेरिका/कारडोबा"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "अमेरिका/कोस्टा_रिका"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "अमेरिका/क्यूबा"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "मातो ग्रोस्सो"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "अमेरिका/कुराकाओ"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "अमेरिका/डेनमार्कशान"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "पूर्वीय तट, उत्तरीय स्कोर्सबायसुंड"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "अमेरिका/डॉशन"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "पॅसीफीक वेळ - उत्तर युकोन"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "अमेरिका/डॉशन_क्रीक"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid "Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr "माऊंटन मानक वेळ - दाव्सोन क्रिक & फोर्ट सैंट जॉन, ब्रिटीश कोल्मबीया"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "अमेरिका/डेनवर"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "माऊंटन वेळ"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "अमेरिका/डेट्रोइट"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "पूर्वीय वेळ - मिचीगन - बहुतांश ठिकाणे"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "अमेरिका/डोमिनिका"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "अमेरिका/एड्मनटन"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "माऊंटन वेळ - अल्बेर्टा, पूर्वीय ब्रिटीश कोल्मबीया व पश्चिम स्कात्चेवान"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "अमेरिका/युरीनएप"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "W अमजोनास्"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "अमेरिका/एल_सेल्वाडोर"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "अमेरिका/एनसेनेडा"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "अमेरिका/फोर्टलेजा"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "NE ब्राझील (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "अमेरिका/फोर्ट_वेन"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "अमेरिका/ग्लेस_बे"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr "अटलँटीक वेळ - नोवा स्कोटीया - DST 1966-1971 लागू न करणारे ठिकाणे"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "अमेरिका/गॉडथब"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "बहुतांश ठिकाण"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "अमेरिका/गूस_बे"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "अटलँटीक वेळ - लॅब्रडोर - बहुतांश ठिकाण"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "अमेरिका/ग्रँड_टर्क"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "अमेरिका/ग्रेनेडा"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "अमेरिका/ग्वाडेलोपे"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "अमेरिका/ग्वाटेमाला"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "अमेरिका/गुआयाकिल"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "मैनलँड"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "अमेरिका/गयाना"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "अमेरिका/हॅलीफेक्स"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "अटलँटीक वेळ - नोवा स्कोटीया (बहुतांश स्थळं), PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "अमेरिका/हवाना"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "अमेरिका/हर्मोसिलो"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "माऊंटन मानक वेळ - सोनोरा"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "अमेरिका/इंडियाना/इंडियानापोलिस"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "पूर्वीय वेळ - इंडीयाना - बहुतांश ठिकाण"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "अमेरिका/इंडियाना/नॉक्स"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "सेंट्रल वेळ - इंडीयाना - स्टार्के देश"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "अमेरिका/इंडियाना/मेरेंगो"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "पूर्वीय वेळ - इंडीयाना - क्रॉव्फोर्ड देश"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "अमेरिका/इंडियाना/पीटर्सबर्ग"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "पूर्वीय वेळ - इंडीयाना - पाईक देश "
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "अमेरिका/इंडियानापोलिस"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "अमेरिका/इंडियाना/टेल_शहर"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "सेंट्रल वेळ - इंडीयाना - पेर्री देश"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "अमेरिका/इंडियाना/वेवे"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "पूर्वीय वेळ - इंडीयाना - स्वीट्जरलँड देश"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "अमेरिका/इंडियाना/विन्सेनेस"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "पूर्वीय वेळ - इंडीआना- डावीएस्, डुबौस्, क्नोक्स् व मार्टीन देश"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "अमेरिका/इंडियाना/विनामॅक"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "पूर्वीय वेळ - इंडीआना - पुलास्की देश"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "अमेरिका/इनुविक"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "माऊंटन वेळ - उत्तरपश्चिम प्रांत"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "अमेरिका/इकालूइत"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "पूर्वीय वेळ - पश्चिम नुनावुत - बहुतांश ठिकाण"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "अमेरिका/जमैका"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "अमेरिका/जुजै"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "अमेरिका/जूनो"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "अलास्का वेळ - अलास्का पॅनहॅन्डल्"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "अमेरिका/कैंटकी/लुईसविले"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "पूर्वीय वेळ - केंटक्की - लुइसविल्ली क्षेत्र"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "अमेरिका/कैंटकी/मॉन्टिकलो"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "पूर्वीय वेळ - केंटक्की - वेय्न देश"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "अमेरिका/नोक्स_इन"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "अमेरिका/ला_पाज"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "अमेरिका/लिमा"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "अमेरिका/लॉस_एंजिल्स"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "पॅसीफिक वेळ"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "अमेरिका/लुईसविल"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "अमेरिका/मैसियो"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "अल्गोआस्, सेर्गीपे"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "अमेरिका/मेनेगुआ"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "अमेरिका/मैनास"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "E अमाजोनास्"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "अमेरिका/मॅरीगोट"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "अमेरिका/मॉर्टिनिक"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "अमेरिका/मॅटामोरोज्"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid "US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr "US सेंट्रल वेळ - कोहुइला, डुरांगो, नुएवो लीओन, तमौलीपास् US बॉर्डर जवळ आहे"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "अमेरिका/मेजेटलेन"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "माऊंटन वेळ - S बजा, नयारीत, सिनालोआ"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "अमेरिका/मेन्डोजा"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "अमेरिका/मेनोमिनी"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "सेंट्रल वेळ - मिचीगन - डिकींसन, गोगेबीक, आर्न व मेनोमिनी देश"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "अमेरिका/मेरीडा"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "सेंट्रल वेळ - कॅपेचे, युकॅटन"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "अमेरिका/मेक्सिको_सिटी"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "सेंट्रल वेळ - बहुतांश ठिकाण"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "अमेरिका/मिक्लॉन"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "अमेरिका/मॉन्कटॉन"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "अटलँटीक वेळ - नवीन ब्रुंस्वीक"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "अमेरिका/माँटेर्री"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr "मेक्सीकन सेंट्रल वेळ - कोहुइला, डुरांगो, नुएवो लीओन, तमौलीपास् US बॉर्डर पासून दूर आहे"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "अमेरिका/मॉन्टेविडीयो"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "अमेरिका/मॉन्ट्रियल"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "पूर्वीय वेळ - क्यूबेक - बहुतांश ठिकाणे"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "अमेरिका/मॉन्टेसेराट"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "अमेरिका/नसो"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "अमेरिका/न्यू_यॉर्क"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "पूर्वीय वेळ"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "अमेरिका/निपीगन"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid "Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr "पूर्वीय वेळ - ओंटारीयो व कुबेक - ठिकाणे जे DST 1967-1973 लागू करत नाही"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "अमेरिका/नोम"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "अलास्का वेळ - पश्चिम अलास्का"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "अमेरिका/नोरोंहा"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "अटलांटिक द्वीप"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "अमेरिका/उत्तर_डकोटा/मध्य"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "सेंट्रल वेळ - उत्तरीय डकोटा - ओलीव्हर कंट्री"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "अमेरिका/उत्तर_डकोटा/न्यू_सालेम"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "सेंट्रल वेळ - उत्तरीय डकोटा - मोर्टन कंट्री (मंदान क्षेत्राला वगळून)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "अमेरिका/ओजीनगा"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "US माऊंटन वेळ - चिहुआहुआ US बॉर्डर जवळ आहे"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "अमेरिका/पनामा"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "अमेरिका/पँगनीरटंग"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "पूर्वीय वेळ - पांग्नीर्तुंग, नुनावुत"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "अमेरिका/पारामारीबो"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "अमेरिका/फिनिक्स"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "माऊंटन मानक वेळ - एरीझोना"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "अमेरिका/पोर्ट-ओ-प्रिंस"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "अमेरिका/पोर्ट_एकर"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "अमेरिका/पोर्ट_ऑफ_स्पेन"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "अमेरिका/पोर्टो_वेलो"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "रोंडोनीया"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "अमेरिका/प्यूरिटो_रिको"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "अमेरिका/रेनी_रिवर"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "सेंट्रल वेळ - रैनी रिव्हर & फोर्ट फ्रांसेस्, ओंटारीयो"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "अमेरिका/रॅनकीन_इनलेट"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "सेंट्रल वेळ - सेंट्रल नुनावुट"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "अमेरिका/रिसीफ"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "पेर्नाम्बुको"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "अमेरिका/रेजीना"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "सेंट्रल मानक वेळ - सास्कात्चेवान - बहुतांश ठिकाण"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "अमेरिका/रीजोल्युट"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "पूर्वीय मानक वेळ - रेसोल्यूट, नुनावुट"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "अमेरिका/रीयो_ब्रान्को"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "अक्रे"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "अमेरिका/रोसारियो"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "अमेरिका/सँटा इजाबेल (_I)"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "मेक्सीकन पॅसीफीक वेळ - बाजा कॅलीफोर्नीया US बॉर्डर पासून दूर आहे"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "अमेरिका/सँटारेम"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "W पॅरा"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "अमेरिका/सेंटीयगो"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "अमेरिका/सेंटो_डोमिंगो"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "अमेरिका/सावो_पोलो"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "S व SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "अमेरिका/स्कोर्सबायसंड"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "स्कोर्सबीसुंड / इट्टोक्कोर्तूर्मीत्"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "अमेरिका/शिपरॉक"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "माऊंटन वेळ - नवाजो"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "अमेरिका/सैंट_बर्थलेमी"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "अमेरिका/सेंट_जॉन्स"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "नवीनफाऊंडलँड वेळ - दक्षीणपूर्वीय लॅब्रडोर"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "अमेरिका/सेंट_किट्स"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "अमेरिका/सेंट_लुसिया"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "अमेरिका/सेंट_थॉमस"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "अमेरिका/सेंट_विंसेंट"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "अमेरिका/स्विफ्ट_करंट"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "सेंट्रल मानक वेळ - सास्कात्चेवान - मध्यपश्चिम"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "अमेरिका/तेगुसीगालपा"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "अमेरिका/थ्यूल"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "थुले / पीटुफ्फीक्"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "अमेरिका/थंडर_बे"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "पूर्वीय वेळ - थंडर बे, ओंटारीयो"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "अमेरिका/तीजुवाना"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "US पॅसीफीक वेळ - बाजा कॅलीफोर्निया US बॉर्डरच्या जवळ"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "अमेरिका/टोरोंटो"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "पूर्वीय वेळ - ओन्टारीयो - बहुतांश ठिकाण"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "अमेरिका/टोर्टोला"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "अमेरिका/वेंकोवेर"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "पॅसीफीक वेळ - पश्चिम ब्रिटीश कोल्बीया"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "अमेरिका/वर्जिन"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "अमेरिका/व्हाइटहॉर्स"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "पॅसीफीक वेळ - दक्षीण युकोन"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "अमेरिका/विनीपेग"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "सेंट्रल वेळ - मनीटोबा व पश्चिम ओन्टारीयो"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "अमेरिका/यकुटेट"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "अलास्का वेळ - अलास्का पॅनहॅन्डल् नेक्"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "अमेरिका/यलोनाइफ"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "माऊंटन वेळ - सेंट्रल उत्तरपश्चिमी प्रांत"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "अंटार्टिका/कॅसे"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "केसी स्टेशन, बैले पेनींसुला"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "अंटार्टिका/डेविस"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "डेवीस स्टेशन, वेस्टफोल्ड हिल्स्"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "अंटार्टिका/डूमांटडरविल"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "ड्युमोंट-डऊर्वील्ले स्टेशन, टेर्रे अडीलै"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "अंटार्टिका/मेककैरी"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "मॅककैरी द्विप स्टेशन, मॅककैरी द्विप"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "अंटार्टिका/मॉसन"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "मव्सोन स्टेशन, होल्म बे"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "अंटार्टिका/मेकमुरडो"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "मॅकमुर्डो स्टेशन, रॉस् द्वीप"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "अंटार्टिका/पामर "
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "पाल्मर स्टेशन, अंवेर्स् द्वीप"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "अंटार्टिका/रोथेरिया"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "रोथेरा स्टेशन, अडेलैड द्वीप"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "अंटार्टिका/साउथ_पोल"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "अमुंड्सेन-स्कॉट् स्टेशन, दक्षीण पोल्"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "अंटार्टिका/सय्वा"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "स्योवा स्टेशन, ए ओंगुल इ"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "अंटार्टिका/वोस्तोक"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "वोस्टोक स्टेशन, दक्षीण मॅगनेटीक पोल्"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "आर्टिक/लाँगईयरबायेन"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "आशिया/अदन"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "आशिया/अलमटी"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "आशिया/अम्मान"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "आशिया/अनाडिर"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "मॉस्को+08 - बेरिंग समुद्र"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "आशिया/एकतो"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "अत्यरौ (अतीरौ, गुर्येव), मंघ्घीस्तौ (मनकीस्तौ)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "आशिया/अकतूब"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "अक्तोबे (अक्तोबे)"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "आशिया/अशगाबट"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "आशिया/अश्खाबाद"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "आशिया/बगदाद"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "आशिया/बहरीन"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "आशिया/बाकू"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "आशिया/बँकॉक"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "आशिया/बेरुट"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "आशिया/बिशकेक"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "आशिया/ब्रुनेई"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "आशिया/कोलकाता"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "आशिया/छोईबलसन"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "डोर्नोड, सुखबातर"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "आशिया/चांगकिंग"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "सेंट्रल चाइना - सीचुआन, युनान, गुआंग्सी, शान्सी, गुइझौ, इत्या."
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "आशिया/चुंगकिंग"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "आशिया/कोलोंबो"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "आशिया/डक्का"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "आशिया/डमस्कस"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "आशिया/ढाका "
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "आशिया/दिली"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "आशिया/दुबई"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "आशिया/दुसानबे"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "आशिया/गाजा"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "आशिया/हरबीन "
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "हैलोंजीआंग (मोहेला वगळून), जीलीन"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "आशिया/हो_छी_मिंह"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "आशिया/हाँग_काँग"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "आशिया/हावड"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "बयान-ओल्गी, गोवी-अल्तै, होव्ड्, उव्स्, झव्खान"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "आशिया/इरकुट्स्क"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "मॉस्को+05 - बैकल तलाव"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "आशिया/इस्तांबुल"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "आशिया/जकार्ता"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "जावा व सुमत्रा"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "आशिया/जयपुर"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "इरियन जया व द मोलुक्कास्"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "आशिया/जेरुसलेम"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "आशिया/काबूल"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "आशिया/कमचटका"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "मॉस्को+08 - कमचत्का"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "आशिया/कराची"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "आशिया/केशगर"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "पश्चिम तीबेट & क्सींजीआंगचे"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "आशिया/कठमंडू"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "आशिया/काठमांडू"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "आशिया/कोलकाता"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "आशिया/क्रस्नोयास्क"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "मॉस्को+04 - येनीसै नदी"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "आशिया/क्वाला_लम्पुर"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "पेनींस्युलार मलेशीया"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "आशिया/कुचिंग"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "सबाह & सरवाक"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "आशिया/कुवैत"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "आशिया/मकाओ"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "आशिया/मकाउ"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "आशिया/मगाडन"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "मॉस्को+08 - मगदान"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "आशिया/मकस्सर"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "पूर्व & दक्षिण बोर्नीओ, सेलेबेज्, बाली, नुसा टेंगार्रा, पश्चिम तीमोर"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "आशिया/मनीला"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "आशिया/मस्कत"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "आशिया/निकोसिया"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "आशिया/नोवोकुझ्नेत्स्क"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "मॉस्को+03 - नोवोकुझ्नेत्स्क"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "आशिया/नोवोसिब्रिस्क"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "मॉस्को+03 - नोवोसिबिर्स्क्"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "आशिया/ओमस्क"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "मॉस्को+03 - पश्चिम सायबेरिया"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "आशिया/ओरल"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "पश्चिम कझाखस्तान"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "आशिया/नॉम_पेन्ह"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "आशिया/पोनट्यानक"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "पूर्व & सेंट्रल बोर्नीओ"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "आशिया/प्योंगयांग"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "आशिया/कतार"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "आशिया/कैजीलोरडा"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "क्जीलोर्डा (कायजीलोर्डा, क्जील-ओर्डा)"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "आशिया/रंगून"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "आशिया/रियाद"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "आशिया/रियाद87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "आशिया/रियाद88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "आशिया/रियाद89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "आशिया/शैगांव"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "आशिया/साखालीन"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "मॉस्को+07 - सक्हालीन द्वीप"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "आशिया/समरकंड"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "पूर्वीय उझ्बेकिस्तान"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "आशिया/सियोल"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "आशिया/शंघाई"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "पूर्वीय चाइना - बैजींग, गुआंगडोंग, शांघाई, इत्या."
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "आशिया/सिंगापुर"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "आशिया/ताईपे"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "आशिया/ताशकंद"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "पूर्व उझ्बेकिस्तान"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "आशिया/तबीलिसी"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "आशिया/तेहरान"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "आशिया/तेल_अवीव"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "आशिया/तिमबू"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "आशिया/थिंफू"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "आशिया/टोक्यो"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "आशिया/ऊजूंग_पन्दांग"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "आशिया/उलानबतर"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "आशिया/उलन_बतोर"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "आशिया/उरुमकी"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "तीबेट & क्सींजीआंगचे बहुतांश भाग"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "आशिया/वेंटीयेन"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "आशिया/व्लाडीवोस्टोक"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "मॉस्को+07 - अमूर नदी"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "आशिया/यकुट्स्क"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "मॉस्को+06 - लेना नदी"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "आशिया/येकातरीनबर्ग"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "मॉस्को+02 - यूरल्स्"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "आशिया/येराविन"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "अटलांटिक/अजोर्स"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "अझोरेज्"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "अटलांटिक/बर्म्यूडा"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "अटलांटिक/कॅनेरी"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "कनॅरी द्वीप"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "अटलांटिक/केप_वर्दे"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "अटलांटिक/फैरो"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "अटलांटिक/फैरो"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "अटलांटिक/जन_मयन"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "अटलांटिक/मेडिरा"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "मडैरा द्वीप"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "अटलांटिक/रिकजाविक"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "अटलांटिक/दक्षिण_जॉर्जिया"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "अटलांटिक/स्टेनली"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "अटलांटिक/सेंट_हेलेना"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "ऑस्ट्रेलिया/एसीटी"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "ऑस्ट्रेलिया/एडीलेड"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "दक्षिण ऑस्ट्रेलिया"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "ऑस्ट्रेलिया/ब्रिसबेन"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "क्वीन्सलँड - बहुतांश ठिकाण"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "ऑस्ट्रेलिया/ब्रोकन_हिल"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "नवीन दक्षीण वेल्स् - यांकोविंन्ना"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "ऑस्ट्रेलिया/केनबेरा"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "ऑस्ट्रेलिया/क्यूरी"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "तास्मानीया - किंग द्वीप"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "ऑस्ट्रेलिया/डार्विन"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "उत्तरीय प्रांत"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "ऑस्ट्रेलिया/एक्ला"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "पूर्वीय ऑस्ट्रेलिया - यूक्ला क्षेत्र"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "ऑस्ट्रेलिया/होबर्ट"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "तस्मानीया - बहुतांश ठिकाण"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "ऑस्ट्रेलिया/एलएचआय"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "ऑस्ट्रेलिया/लिंडेमेन"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "क्वीन्सलँड - हॉलीडे द्वीप"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "ऑस्ट्रेलिया/लॉर्ड_होव"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "लार्ड होव्हे द्वीप"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "ऑस्ट्रेलिया/मेलबॉर्न"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "विक्टोरिया"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "ऑस्ट्रेलिया/उत्तर"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "ऑस्ट्रेलिया/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "ऑस्ट्रेलिया/पर्थ"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "पश्चिम ऑस्ट्रेलिया - बहुतांश ठिकाण"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "ऑस्ट्रेलिया/क्वींसलँड"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "ऑस्ट्रेलिया/दक्षिण"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "ऑस्ट्रेलिया/सिडनी"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "नवीन दक्षिण वेल्स् - बहुतांश ठिकाणे"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "ऑस्ट्रेलिया/टास्मानिया"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "ऑस्ट्रेलिया/विक्टोरिया"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "ऑस्ट्रेलिया/पश्चिम"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "ऑस्ट्रेलिया/यान्कोविना"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "ब्राझिल/एकर"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "ब्राझिल/डेनोरोना"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "ब्राझिल/पूर्व"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "ब्राझिल/पश्चिम"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "कॅनडा/अटलांटिक"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "कॅनडा/मध्य"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "कॅनडा/पूर्वीय"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "कॅनडा/पूर्व-सस्कचवन"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "कॅनडा/माउन्टेन"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "कॅनडा/न्यूफाउंडलँड"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "कॅनडा/पॅसीफिक"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "कॅनडा/सस्कचवन"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "कॅनडा/यूकोन"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "चिली/कॉन्टीनेन्टल"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "चिली/इस्टरआयलंड"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "क्यूबा"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "इजिप्त"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "आयर"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr " Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/ग्रीनविच"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/यूनिवर्सल"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/झुलू"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "यूरोप/एम्स्टरडॅम"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "यूरोप/एंडोरा"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "यूरोप/अथेंस"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "यूरोप/बेलफास्ट"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "यूरोप/बेलग्रेड"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "यूरोप/बर्लिन"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "यूरोप/ब्रटिस्लावा"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "यूरोप/ब्रस्सेल्स"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "यूरोप/बुखारेस्ट"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "यूरोप/बुडापेस्ट"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "यूरोप/चीसीनो"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "यूरोप/कोपनहेगन"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "यूरोप/डब्लीन"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "यूरोप/जिब्राल्टर"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "यूरोप/गर्नेसी"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "यूरोप/हेलसिंकी"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "यूरोप/इस्ले_ऑफ_मॅन"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "यूरोप/इस्तांबुल"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "यूरोप/जर्सी"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "यूरोप/कालिनीग्राड"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "मॉस्को+01 - कलीनींग्रॅड"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "यूरोप/कीव"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "यूरोप/लिस्बन"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "यूरोप/लजुबलजाना"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "यूरोप/लंडन"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "यूरोप/लेक्झंबर्ग"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "यूरोप/मेड्रिड"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "यूरोप/माल्टा"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "यूरोप/मेरीहैम"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "यूरोप/मिंस्क"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "यूरोप/मोनॅको"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "यूरोप/मॉस्को"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "मॉस्को+01 - पश्चिम रशीया"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "यूरोप/निकोसिया"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "यूरोप/ओसलो"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "यूरोप/पॅरिस"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "यूरोप/पॉडगोरिका"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "यूरोप/प्राग"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "यूरोप/रिगा"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "यूरोप/रोम"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "यूरोप/समारा"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "मॉस्क - समारा, उद्मुर्तीया"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "यूरोप/सॅन_मरीनो"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "यूरोप/सराजेवो"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "यूरोप/सिमफेरोपोल"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "सेंट्रल क्रिमे"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "यूरोप/स्कोप्जे"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "यूरोप/सोफिया"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "यूरोप/स्टॉकहोम"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "यूरोप/टॅलीन"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "यूरोप/तिरेन"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "यूरोप/तिरसपोल"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "यूरोप/उज्गोराड"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "रूथेनीया"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "यूरोप/वाडूज"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "यूरोप/वॅटीकेन"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "यूरोप/वियेना"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "यूरोप/विलनियस"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "यूरोप/वोल्गोग्राड"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "मॉस्क+00 - कास्पीयन सी"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "यूरोप/वारसो"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "यूरोप/जेगरीब"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "यूरोप/जपोरोझाई"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "झापोरोझ्ये, ए लुगांस्क / झापोरिझीया, ए लुहांस्क"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "यूरोप/ज्यूरिख"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "फॅक्टरी"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-आइर"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "ग्रीनविच"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "हाँगकाँग"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "आइसलँड"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "इंडियन/अंतानानरिवो"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "इंडियन/चागोस"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "इंडियन/ख्रिसमस"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "इंडियन/कोकोस"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "इंडियन/कोमोरो"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "इंडियन/करगलन"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "इंडियन/माहे"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "इंडियन/मालदीव"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "इंडियन/मॉरीशस"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "इंडियन/मायोटे"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "इंडियन/रियूनियन"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "इरान"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "इस्राइल"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "जमैका"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "जपान"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "क्वाजालिन"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "लीबिया"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "मेक्झिको/बजनोर्ट"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "मेक्झिको/बजासुर"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "मेक्झिको/जनरल"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "मिडईस्ट/रियाद87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "मिडईस्ट/रियाद88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "मिडईस्ट/रियाद89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "नवजो"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "पॅसीफिक/एपिया"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "पॅसीफिक/ऑकलँड"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "पॅसीफिक/चाथम"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "छाथम द्वीप"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "पॅसीफिक/छूक"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "छूक (ट्रूक) व यॅप"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "पॅसीफिक/इस्टर"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "इस्टर द्वीप & साला वाय गोमेज्"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "पॅसीफिक/इफेट"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "पॅसीफिक/इनडरबरी"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "फिनीक्स् द्वीप"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "पॅसीफिक/फकाओफो"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "पॅसीफिक/फिजी"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "पॅसीफिक/फुनाफुटी"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "पॅसीफिक/गलपगोस"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "गालापागोस् द्वीप"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "पॅसीफिक/गेम्बियर"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "गॅम्बैर द्वीप"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "पॅसीफिक/गुवादलकनल"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "पॅसीफिक/गुआम"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "पॅसीफिक/होनोलूलू"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "हवाई"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "पॅसीफिक/जॉनस्टन"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "जॉनस्टोन एटोल्ल"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "पसीफिक/किरीतिमति"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "लीने द्वीप"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "पॅसीफिक/कोस्रे"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "कोस्रे"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "पॅसीफिक/क्वाजालेन"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "पॅसीफिक/मजूरो"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "पॅसीफिक/मार्कसास"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "मार्क्यूसास द्वीप"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "पॅसीफिक/मिडवे"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "मिडवे आयलँडस्"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "पॅसीफिक/नोरु"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "पॅसीफिक/नीयू"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "पॅसीफिक/नारफोक"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "पॅसीफिक/नामिया"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "पॅसीफिक/पॅगो_पॅगो"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "पॅसीफिक/पलाउ"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "पॅसीफिक/पिटकेरीन"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "पॅसीफिक/पोन्पै"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "पोन्पै (पोन्पे)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "पॅसीफिक/पोनापे"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "पॅसीफिक/पोर्ट_मोर्सबी"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "पॅसीफिक/ररोतंगा"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "पॅसीफिक/सैपेन"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "पॅसीफिक/समोआ"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "पॅसीफिक/ताहिटी"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "सोसायटी द्वीप"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "पॅसीफिक/तारावा"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "गिल्बर्ट द्वीप"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "पॅसीफिक/टंगटपू"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "पॅसीफिक/त्रुक"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "पॅसीफिक/वेक"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "वेक द्वीप"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "पॅसीफीक/वालीस्"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "पॅसीफिक/याप"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "पोलंड"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "पुर्तगाल"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "सिंगापुर"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "तुर्की"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "यूनिवर्सल"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "US/अलास्का"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "US/एल्यूशन"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "US/एरीजोना"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "US/केन्द्रीय"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "US/पूर्वीय"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "US/पूर्व-इंडियाना"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "US/हवाई"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "US/इंडियाना-स्टार्क"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "US/मिसिगन"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "US/माउन्टेन"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "US/पॅसीफिक"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "US/समोवा"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "झुलू"
+
diff --git a/panels/datetime/po-timezones/ms.po b/panels/datetime/po-timezones/ms.po
new file mode 100644
index 0000000..3117fd9
--- /dev/null
+++ b/panels/datetime/po-timezones/ms.po
@@ -0,0 +1,3277 @@
+# Malay translation of timezone
+# Copyright (C) 2003 Hasbullah Bin Pit
+# Hasbullah Bin Pit <sebol@ikhlas.com> 2003
+msgid ""
+msgstr ""
+"Project-Id-Version: system-config-date\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2007-05-13 00:27+0800\n"
+"Last-Translator: Sharuzzaman Ahmat Raslan <sharuzzaman@myrealbox.com>\n"
+"Language-Team: Malay <gabai-penyumbang@lists.sf.net>\n"
+"Language: ms\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Afrika/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Afrika/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Afrika/Addis_Ababa"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Afrika/Algiers"
+
+#: timezones.h:5
+#, fuzzy
+msgid "Africa/Asmara"
+msgstr "Afrika/Asmera"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Afrika/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Afrika/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Afrika/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Afrika/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Afrika/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Afrika/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Afrika/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Afrika/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Afrika/Kaherah"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Afrika/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Afrika/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Afrika/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Afrika/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Afrika/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Afrika/Djibouti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Afrika/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Afrika/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Afrika/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Afrika/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Afrika/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Afrika/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Afrika/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Afrika/Khartoum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Afrika/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Afrika/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Afrika/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Afrika/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Afrika/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Afrika/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Afrika/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Afrika/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Afrika/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Afrika/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Afrika/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Afrika/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Afrika/Mogadishu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Afrika/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Afrika/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Afrika/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Afrika/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Afrika/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Afrika/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Afrika/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Afrika/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Afrika/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Afrika/Tripoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Afrika/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Afrika/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Amerika/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+#, fuzzy
+msgid "Aleutian Islands"
+msgstr "Australia/Queensland"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Amerika/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+#, fuzzy
+msgid "Alaska Time"
+msgstr "US/Alaska"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Amerika/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Amerika/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Amerika/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Amerika/Argentina/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Amerika/Argentina/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Amerika/Argentina/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Amerika/Argentina/Cordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Amerika/Argentina/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Amerika/Argentina/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Amerika/Argentina/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Amerika/Argentina/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+#, fuzzy
+msgid "America/Argentina/Salta"
+msgstr "Amerika/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Amerika/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+#, fuzzy
+msgid "America/Argentina/San_Luis"
+msgstr "Amerika/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Amerika/Argentina/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Amerika/Argentina/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Amerika/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Amerika/Asuncion"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Amerika/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Amerika/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Amerika/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "Amerika/Bahia"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Amerika/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Amerika/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Amerika/Belize"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "Amerika/Blanc-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Amerika/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Amerika/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Amerika/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Amerika/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Amerika/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "Amerika/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Amerika/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Amerika/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Amerika/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Amerika/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Amerika/Cayman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Amerika/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+#, fuzzy
+msgid "Central Time"
+msgstr "US/Central"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Amerika/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "Amerika/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Amerika/Cordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Amerika/Costa_Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Amerika/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Amerika/Curacao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Amerika/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Amerika/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Amerika/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Amerika/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+#, fuzzy
+msgid "Mountain Time"
+msgstr "US/Mountain"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Amerika/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Amerika/Dominica"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Amerika/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Amerika/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Amerika/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Amerika/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Amerika/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Amerika/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Amerika/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Amerika/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Amerika/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Amerika/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Amerika/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Amerika/Guadeloupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Amerika/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Amerika/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Amerika/Guyana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Amerika/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Amerika/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Amerika/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Amerika/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Amerika/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Amerika/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "Amerika/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Amerika/Indianapolis"
+
+#: timezones.h:227
+#, fuzzy
+msgid "America/Indiana/Tell_City"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "Amerika/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+#, fuzzy
+msgid "America/Indiana/Winamac"
+msgstr "Amerika/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Amerika/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Amerika/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Amerika/Jamaica"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Amerika/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Amerika/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Amerika/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+#, fuzzy
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Amerika/Kentucky/Louisville"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Amerika/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Amerika/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Amerika/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Amerika/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Amerika/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+#, fuzzy
+msgid "Pacific Time"
+msgstr "Pasifik/Niue"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Amerika/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Amerika/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Amerika/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Amerika/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+#, fuzzy
+msgid "America/Marigot"
+msgstr "Amerika/Maceio"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Amerika/Martinique"
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "Amerika/Manaus"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Amerika/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Amerika/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Amerika/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Amerika/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Amerika/Mexico_City"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Amerika/Miquelon"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "Amerika/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Amerika/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Amerika/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Amerika/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Amerika/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Amerika/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Amerika/New_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+#, fuzzy
+msgid "Eastern Time"
+msgstr "US/Eastern"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Amerika/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Amerika/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Amerika/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+#, fuzzy
+msgid "Atlantic islands"
+msgstr "Atlantik/Canary"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Amerika/North_Dakota/Center"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "Amerika/North_Dakota/New_Salem"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "Amerika/Managua"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Amerika/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Amerika/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Amerika/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Amerika/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Amerika/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Amerika/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Amerika/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Amerika/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Amerika/Puerto_Rico"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Amerika/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Amerika/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Amerika/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Amerika/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+#, fuzzy
+msgid "America/Resolute"
+msgstr "Amerika/Belem"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Amerika/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Amerika/Rosario"
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "Amerika/Santiago"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+#, fuzzy
+msgid "America/Santarem"
+msgstr "Amerika/Santiago"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Amerika/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Amerika/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Amerika/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Amerika/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Amerika/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+#, fuzzy
+msgid "America/St_Barthelemy"
+msgstr "Amerika/Belem"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Amerika/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Amerika/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Amerika/St_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Amerika/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Amerika/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Amerika/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Amerika/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Amerika/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Amerika/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Amerika/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "Amerika/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Amerika/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Amerika/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Amerika/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Amerika/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Amerika/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Amerika/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Amerika/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antartika/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antartika/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antartika/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+#, fuzzy
+msgid "Antarctica/Macquarie"
+msgstr "Antartika/McMurdo"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antartika/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antartika/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antartika/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antartika/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antartika/Kutub_Selatan"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antartika/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antartika/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Artik/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Asia/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Asia/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Asia/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Asia/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Asia/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Asia/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Asia/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Asia/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Asia/Baghdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Asia/Bahrain"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Asia/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Asia/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Asia/Beirut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Asia/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Asia/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Asia/Calcutta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Asia/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Asia/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Asia/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Asia/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Asia/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Asia/Damascus"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Asia/Dhaka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Asia/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Asia/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Asia/Dushanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Asia/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Asia/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+#, fuzzy
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Asia/Chongqing"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Asia/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Asia/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Asia/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Asia/Istanbul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Asia/Jakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Asia/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Asia/Jerusalem"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Asia/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Asia/Kamchatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Asia/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Asia/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+#, fuzzy
+msgid "Asia/Kathmandu"
+msgstr "Asia/Katmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Asia/Katmandu"
+
+#: timezones.h:518
+#, fuzzy
+msgid "Asia/Kolkata"
+msgstr "Asia/Jakarta"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Asia/Krasnoyarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Asia/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Asia/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Asia/Kuwait"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Asia/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Asia/Macau"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Asia/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Asia/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Asia/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Asia/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Asia/Nicosia"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "Asia/Irkutsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Asia/Novosibirsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Asia/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+#, fuzzy
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Asia/Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Asia/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Asia/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Asia/Phnom_Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Asia/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Asia/Pyongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Asia/Qatar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Asia/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Asia/Rangoon"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Asia/Riyadh"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Asia/Riyadh87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Asia/Riyadh88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Asia/Riyadh89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Asia/Saigon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Asia/Sakhalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Asia/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Asia/Seoul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Asia/Shanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Asia/Singapura"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Asia/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Asia/Tashkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Asia/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Asia/Tehran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Asia/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Asia/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Asia/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Asia/Tokyo"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Asia/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Asia/Ulaanbaatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Asia/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Asia/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Asia/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Asia/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Asia/Yakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Asia/Yekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Asia/Yerevan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlantik/Azores"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlantik/Bermuda"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlantik/Canary"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlantik/Cape_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlantik/Faeroe"
+
+#: timezones.h:616
+#, fuzzy
+msgid "Atlantic/Faroe"
+msgstr "Atlantik/Faeroe"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlantik/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlantik/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlantik/Reykjavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlantik/South_Georgia"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlantik/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlantik/St_Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Australia/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Australia/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+#, fuzzy
+msgid "South Australia"
+msgstr "Australia/ACT"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Australia/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Australia/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Australia/Canberra"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Australia/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Australia/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+#, fuzzy
+msgid "Australia/Eucla"
+msgstr "Australia/Queensland"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+#, fuzzy
+msgid "Western Australia - Eucla area"
+msgstr "Australia/Queensland"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Australia/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Australia/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Australia/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Australia/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Australia/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+#, fuzzy
+msgid "Victoria"
+msgstr "Australia/Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Australia/Utara"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Australia/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Australia/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Australia/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Australia/South"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Australia/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Australia/Tasmania"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Australia/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Australia/Barat"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Australia/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brazil/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brazil/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brazil/Timur"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brazil/Barat"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Kanada/Atlantik"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Kanada/Tengah"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Kanada/Timur"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Kanada/East-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Kanada/Mountain"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Kanada/Newfoundland"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Kanada/Pasifik"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Kanada/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Kanada/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Chile/Continental"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Chile/EasterIsland"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Cuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Mesir"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Eire"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Eropah/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Eropah/Andorra"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Eropah/Athens"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Eropah/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Eropah/Belgrade"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Eropah/Berlin"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Eropah/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Eropah/Brussels"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Eropah/Bucharest"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Eropah/Budapest"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Eropah/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Eropah/Copenhagen"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Eropah/Dublin"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Eropah/Gibraltar"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Eropah/Guernsey"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Eropah/Helsinki"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Eropah/Isle_of_Man"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Eropah/Istanbul"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Eropah/Jersey"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Eropah/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Eropah/Kiev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Eropah/Lisbon"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Eropah/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Eropah/London"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Eropah/Luxembourg"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Eropah/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Eropah/Malta"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Eropah/Mariehamn"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Eropah/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Eropah/Monaco"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Eropah/Moskow"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Eropah/Nicosia"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Eropah/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Eropah/Paris"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Eropah/Podgorica"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Eropah/Prague"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Eropah/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Eropah/Rom"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Eropah/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Eropah/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Eropah/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Eropah/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Eropah/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Eropah/Sofia"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Eropah/Stockholm"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Eropah/Tallinn"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Eropah/Tirane"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Eropah/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Eropah/Uzhgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Eropah/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Eropah/Vatican"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Eropah/Vienna"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Eropah/Vilnius"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Eropah/Volgograd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Eropah/Warsaw"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Eropah/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Eropah/Zaporozhye"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Eropah/Zurich"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Kilang"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Eire"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Iceland"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "India/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "India/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "India/Christmas"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "India/Cocos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "India/Comoro"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "India/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "India/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "India/Maldives"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "India/Mauritius"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "India/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "India/Reunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Iran"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Israel"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamaica"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Jepun"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Libya"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Mexico/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Mexico/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Mexico/General"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Timurtengah/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Timurtengah/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Timurtengah/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Pasifik/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Pasifik/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Pasifik/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+#, fuzzy
+msgid "Chatham Islands"
+msgstr "Chile/EasterIsland"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "Pasifik/Truk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Pasifik/Easter"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Pasifik/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Pasifik/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Pasifik/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Pasifik/Fiji"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Pasifik/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Pasifik/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Pasifik/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Pasifik/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Pasifik/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Pasifik/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+#, fuzzy
+msgid "Hawaii"
+msgstr "US/Hawaii"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Pasifik/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Pasifik/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Pasifik/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+#, fuzzy
+msgid "Kosrae"
+msgstr "Israel"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Pasifik/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Pasifik/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Pasifik/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Pasifik/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Pasifik/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Pasifik/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Pasifik/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Pasifik/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Pasifik/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Pasifik/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Pasifik/Pitcairn"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "Pasifik/Ponape"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Pasifik/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Pasifik/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Pasifik/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Pasifik/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Pasifik/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Pasifik/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Pasifik/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+#, fuzzy
+msgid "Gilbert Islands"
+msgstr "Chile/EasterIsland"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Pasifik/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Pasifik/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Pasifik/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Pasifik/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Pasifik/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Poland"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugal"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapura"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Turki"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "US/Alaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "US/Aleutian"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "US/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "US/Central"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "US/Eastern"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "US/East-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "US/Hawaii"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "US/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "US/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "US/Mountain"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "US/Pacific"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "US/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
+
+#~ msgid "US/Pacific-New"
+#~ msgstr "US/Pasifik-Baru"
diff --git a/panels/datetime/po-timezones/nb.po b/panels/datetime/po-timezones/nb.po
new file mode 100644
index 0000000..831e4fc
--- /dev/null
+++ b/panels/datetime/po-timezones/nb.po
@@ -0,0 +1,3234 @@
+# Kjartan Maraas <kmaraas@gnome.org>, 2006-2010.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones 3.0.13\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-10-31 15:14+0100\n"
+"Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n"
+"Language-Team: Norwegian/Bokmaal <i18n-nb@lister.ping.uio.no>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: \n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Afrika/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Afrika/Akra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Afrika/Addis_Abeba"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Afrika/Algerie"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "Afrika/Asmara"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Afrika/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Afrika/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Afrika/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Afrika/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Afrika/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Afrika/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Afrika/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Afrika/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Afrika/Kairo"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Afrika/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Afrika/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "Ceuta & Melilla"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Afrika/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Afrika/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Afrika/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Afrika/Djibouti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Afrika/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Afrika/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Afrika/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Afrika/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Afrika/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Afrika/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Afrika/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Afrika/Khartoum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Afrika/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Afrika/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Afrika/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Afrika/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Afrika/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Afrika/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Afrika/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Afrika/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Afrika/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Afrika/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Afrika/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Afrika/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Afrika/Mogadishu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Afrika/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Afrika/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Afrika/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Afrika/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Afrika/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Afrika/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Afrika/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Afrika/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Afrika/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Afrika/Tripoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Afrika/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Afrika/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Amerika/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Aleutiske øyer"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Amerika/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Alaska-tid"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Amerika/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Amerika/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Amerika/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "Tocantins"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Amerika/Argentina/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Buenos Aires (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Amerika/Argentina/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "Catamarca (CT), Chubut (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Amerika/Argentina/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Amerika/Argentina/Cordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "de fleste lokasjoner (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Amerika/Argentina/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Jujuy (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Amerika/Argentina/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "La Rioja (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Amerika/Argentina/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "Mendoza (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Amerika/Argentina/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "Santa Cruz (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "Amerika/Argentina/Salta"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Amerika/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "San Juan (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "Amerika/Argentina/San_Luis"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "San Luis (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Amerika/Argentina/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "Tucuman (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Amerika/Argentina/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "Tierra del Fuego (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Amerika/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Amerika/Asuncion"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Amerika/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Amerika/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Amerika/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "Bahia"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "Amerika/Bahia_Banderas"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "Meksikansk sentraltid - Bahia de Banderas"
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Amerika/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Amerika/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "Amapa, E Para"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Amerika/Belize"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "Amerika/Blanc-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "Atlantisk standardtid - Quebec - nedre nordlige kyst"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Amerika/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "Roraima"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Amerika/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Amerika/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Amerika/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Amerika/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "Fjelltid - vest-Nunavut"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "Amerika/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "Mato Grosso do Sul"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Amerika/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "Sentraltid - Quintana Roo"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Amerika/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Amerika/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Amerika/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Amerika/Cayman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Amerika/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "Sentral tid"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Amerika/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "Fjell-tid - Chihuahua"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "Amerika/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Amerika/Cordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Amerika/Costa_Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Amerika/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "Mato Grosso"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Amerika/Curacao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Amerika/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "østkysten, nord for Scresbysund"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Amerika/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "Stillehavstid - nordre Yukon"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Amerika/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Amerika/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "Fjelltid"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Amerika/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "Østlig tid - Michigan - de fleste lokasjoner"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Amerika/Dominica"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Amerika/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Amerika/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "Vestlige Amazonas"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Amerika/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Amerika/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Amerika/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "noen "
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Amerika/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Amerika/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Amerika/Kapp_det_gode_håp"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "de fleste lokasjoner"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Amerika/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Amerika/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Amerika/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Amerika/Guadeloupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Amerika/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Amerika/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "hovedlandet"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Amerika/Guyana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Amerika/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "Atlanterhavstid - Nova Scotia (de fleste steder), PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Amerika/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Amerika/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Amerika/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "Østlig tid - Indiana - de fleste lokasjoner"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Amerika/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "Sentraltid - Indiana - Starke fylke"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Amerika/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "Amerika/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Amerika/Indianapolis"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "Amerika/Indiana/Tell City"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "Amerika/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "Amerika/Indiana/Winamac"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Amerika/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Amerika/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Amerika/Jamaica"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Amerika/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Amerika/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "Alaska-tid - Alaska panhandle"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Amerika/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Østlig tid - Kentucky - Louisville området"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Amerika/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "Østlig tid - Kentucky - Wayne County"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Amerika/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Amerika/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Amerika/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Amerika/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "Stillehavstid"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Amerika/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Amerika/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "Alagoas, Sergipe"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Amerika/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Amerika/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "Østlige Amazonas"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "Amerika/Marigot"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Amerika/Martinique"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "Amerika/Matamoros"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Amerika/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Amerika/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Amerika/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Amerika/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "Sentral tid - Campeche, Yucatan"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Amerika/Mexico_by"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "Sentral tid - de fleste lokasjoner"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Amerika/Miquelon"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "Amerika/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "Atlantisk tid - New Brunswick"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Amerika/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Amerika/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Amerika/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Amerika/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Amerika/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Amerika/New_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "Østlig tid"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Amerika/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Amerika/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "Alaska-tid - vest-Alaska"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Amerika/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "Øyer i atlanterhavet"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Amerika/North_Dakota/Sentrum"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "Amerika/North_Dakota/New_Salem"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "Amerika/Ojinaga"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "USA Fjell-tid - Chihuahua nær den amerikanske grensen"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Amerika/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Amerika/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "Østlig tid - Pangnirtung, Nunavut"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Amerika/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Amerika/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "Standard fjelltid - Arizona"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Amerika/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Amerika/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Amerika/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Amerika/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "Rondonia"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Amerika/Puerto_Rico"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Amerika/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Amerika/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "Sentraltid - sentrale Nunavut"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Amerika/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "Pernambuco"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Amerika/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "Amerika/Resolute"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "Østlig standardtid - Resolute, Nunavut"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Amerika/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "Acre"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Amerika/Rosario"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "Amerika/Santa_Isabel"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "Amerika/Santarem"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "Ruthenia"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Amerika/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Amerika/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Amerika/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Amerika/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "Scoresbysund / Ittoqqortoormiit"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Amerika/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "Fjelltid - Navajo"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "Amerika/St_Barthelemy"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Amerika/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Amerika/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Amerika/St_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Amerika/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Amerika/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Amerika/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "Sentral standardtid - Saskatchewan - midtvesten"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Amerika/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Amerika/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "Thule / Pituffik"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Amerika/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Amerika/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "Amerika/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Amerika/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Amerika/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Amerika/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Amerika/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Amerika/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Amerika/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Amerika/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antarktis/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "Casey Station, Bailey Peninsula"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antarktis/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "Davis Station, Vestfold Hills"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antarktis/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "Dumont-d'Urville Station, Terre Adelie"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "Antarktis/Macquarie"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "Macquarie Island Station, Macquarie Island"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antarktis/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "Mawson Station, Holme Bay"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antarktis/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "McMurdo Station, Ross Island"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antarktis/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "Palmer Station, Anvers Island"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antarktis/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "Rothera Station, Adelaide Island"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antarktis/Sydpolen"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "Amundsen-Scott-stasjonen, sydpolen"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antarktis/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "Syowa Station, E Ongul I"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antarktis/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "Vostok Station, S magnetiske pol"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Antarktis/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Asia/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Asia/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Asia/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Asia/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "Moskva+08 - Beringhavet"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Asia/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Asia/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "Aqtobe (Aktobe)"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Asia/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Asia/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Asia/Bagdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Asia/Bahrain"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Asia/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Asia/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Asia/Beirut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Asia/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Asia/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Asia/Calcutta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Asia/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "Dornod, Sukhbaatar"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Asia/Chongging"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Asia/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Asia/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Asia/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Asia/Damaskus"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Asia/Dhaka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Asia/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Asia/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Asia/Dushanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Asia/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Asia/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Asia/Ho_Chi_Minh"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Asia/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Asia/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Asia/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Moskva+05 - Baikalsjøen"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Asia/Istanbul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Asia/Jakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "Java & Sumatra"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Asia/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Asia/Jerusalem"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Asia/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Asia/Kamchatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "Moskva+08 - Kamchatka"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Asia/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Asia/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "vest-tibet & Xinjiang"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "Asia/Katmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Asia/Katmandu"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "Asia/Kolkata"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Asia/Krasnoyarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "Moskva+04 - Yenisei-elven"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Asia/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Asia/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "Sabah & Sarawak"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Asia/Kuwait"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Asia/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Asia/Macao"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Asia/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "Moskva+08 - Magadan"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Asia/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Asia/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Asia/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Asia/Nikosia"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "Asia/Novokuznetsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Moskva+03 - Novokuznetsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Asia/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Moskva+03 - Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Asia/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "Moskva+03 - vest-Sibir"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Asia/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "Vest-Kasakhstan"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Asia/Phnom_Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Asia/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "vestlige og sentrale Borneo"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Asia/Pyongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Asia/Qatar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Asia/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Asia/Rangoon"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Asia/Riyadh"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Asia/Riyadh87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Asia/Riyadh88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Asia/Riyadh89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Asia/Saigon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Asia/Sakhalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "Moskva+07 - Sakhalin-øya"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Asia/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "vest-Usbekistan"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Asia/Seoul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Asia/Shanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "Øst-Kina - Beijing, Guangdong, Shanghai, etc."
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Asia/Singapore"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Asia/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Asia/Tashkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "Øst-Usbekistan"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Asia/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Asia/Tehran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Asia/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Asia/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Asia/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Asia/Tokyo"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Asia/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Asia/Ulaanbaatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Asia/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Asia/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "det meste av Tibet & Xinjiang"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Asia/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Asia/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "Moskva+07 - Amurelven"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Asia/Yakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "Moskva+06 - Elven Lena"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Asia/Yekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "Moskva+02 - Uralfjellene"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Asia/Yerevan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlanterhavet/Azorene"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "Azorene"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlanterhavet/Bermuda"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlanterhavet/Kanariøyene"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "Kanariøyene"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlanterhavet/Kapp_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlanterhavet/Færøyene"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "Atlanterhavet/Færøyene"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlanterhavet/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlanterhavet/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "Madeira"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlanterhavet/Reykjavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlanterhavet/Syd_Georgia"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlanterhavet/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlanterhavet/St_Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Australia/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Australia/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "Syd-Australia"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Australia/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "Queensland - de fleste lokasjoner"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Australia/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "New South Wales - Yancowinna"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Australia/Canberra"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Australia/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "Tasmania - King Island"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Australia/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "Nordterritoriet"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "Australia/Eucla"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "Vest-Australia - Eucla-området"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Australia/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "Tasmania - de fleste lokasjoner"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Australia/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Australia/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "Queensland - Holiday Islands"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Australia/Lord_Howe-øya"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "Lord Howe Island"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Australia/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Australia/Nord"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Australia/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Australia/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "Vest-Australia - de fleste lokasjoner"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Australia/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Australia/Syd"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Australia/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "New South Wales - de fleste lokasjoner"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Australia/Tasmania"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Australia/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Australia/Vest"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Australia/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brasil/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brasil/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brasil/Øst"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brasil/Vest"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Canada/Atlantisk"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Canada/Sentral"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Canada/Østlig"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Canada/Øst-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Canada/Mountain"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Canada/Newfoundland"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Canada/Stillehavet"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Canada/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Canada/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Chile/Kontinental"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Chile/Påskeøya"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Cuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Egypt"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Irland"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universell"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Europa/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Europa/Andorra"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Europa/Aten"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Europa/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Europa/Beograd"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Europa/Berlin"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Europa/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Europa/Brussel"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Europa/Bukuresti"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Europa/Budapest"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Europa/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Europa/København"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Europa/Dublin"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Europa/Gibraltar"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Europa/Guernsey"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Europa/Helsinki"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Europa/Man"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Europa/Istanbul"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Europa/Jersey"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Europa/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Moskva-01 - Kaliningrad"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Europa/Kiev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Europa/Lisboa"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Europa/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Europa/London"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Europa/Luxemburg"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Europa/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Europa/Malta"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Europa/Mariehamn"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Europa/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Europa/Monaco"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Europa/Moskva"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "Moskva+00 - vest-russland"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Europa/Nicosia"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Europa/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Europa/Paris"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Europa/Podgorica"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Europa/Praha"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Europa/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Europa/Roma"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Europa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Moskva - Samara, Udmurtia"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Europa/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Europa/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Europa/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "Sentrale Krim"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Europa/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Europa/Sofia"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Europa/Stockholm"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Europa/Tallinn"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Europa/Tirana"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Europa/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Europa/Uzhgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "Ruthenia"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Europa/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Europa/Vatikanstaten"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Europa/Wien"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Europa/Vilnius"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Europa/Volgograd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "Moskva+00 - det kaspiske hav"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Europa/Warshawa"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Europa/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Europa/Zaporozje"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Europa/Zurich"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Factory"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Eire"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Island"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Indiahavet/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Indiahavet/Chagosøyene"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Indiahavet/Christmasøya"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Indiahavet/Kokosøyene"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Indiahavet/Komorene"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Indiahavet/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Indiahavet/Mahé"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Indiahavet/Maldivene"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Indiahavet/Mauritius"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Indiahavet/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Indiahavet/Réunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Iran"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Israel"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamaica"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Japan"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Libya"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Mexico/Baja_California_Norte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Mexico/Baja_California_Sur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Mexico/Generell"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Midt-østen/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Midt-østen/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Midt-østen/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Stillehavet/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Stillehavet/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Stillehavet/Chathamøyene"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "Chatham-øyene"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "Stillehavet/Chuuk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "Chuuk (Truk) og Yap"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Stillehavet/Påskeøya"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "Påskeøya & Sala y Gomez"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Stillehavet/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Stillehavet/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "Phoenix-øyene"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Stillehavet/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Stillehavet/Fiji"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Stillehavet/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Stillehavet/Galápagosøyene"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "Galapagos-øyene"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Stillehavet/Gambierøyene"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "Gambier-øyene"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Stillehavet/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Stillehavet/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Stillehavet/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "Hawaii"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Stillehavet/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "Johnston-atollen"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Stillehavet/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "Line-øyene"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Stillehavet/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "Kosrae"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Stillehavet/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Stillehavet/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Stillehavet/Marquesasøyene"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "Marquesas-øyene"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Stillehavet/Midwayøyene"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "Midway-øyene"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Stillehavet/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Stillehavet/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Stillehavet/Norfolkøya"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Stillehavet/Nouméa"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Stillehavet/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Stillehavet/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Stillehavet/Pitcairn"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "Stillehavet/Pohnpei"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "Pohnpei (Ponape)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Stillehavet/Pohnpei"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Stillehavet/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Stillehavet/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Stillehavet/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Stillehavet/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Stillehavet/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "Society-øyene"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Stillehavet/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "Gilbert-øyene"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Stillehavet/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Stillehavet/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Stillehavet/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "Wake-øya"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Stillehavet/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Stillehavet/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Polen"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugal"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapore"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Tyrkia"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universell"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "US/Alaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "US/Aleutene"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "US/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "US/Sentral"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "US/Øst"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "US/Øst-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "US/Hawaii"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "US/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "US/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "US/Mountain"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "US/Stillehavet"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "US/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
diff --git a/panels/datetime/po-timezones/nds.po b/panels/datetime/po-timezones/nds.po
new file mode 100644
index 0000000..2986327
--- /dev/null
+++ b/panels/datetime/po-timezones/nds.po
@@ -0,0 +1,3725 @@
+# translation of system-config-date.master-timezones.po to
+# translation of system-config-date.master-timezones.nds.po to
+# Low German translation of system-config-date.timezones
+# Copyright (C) 2004 Red Hat, Inc.
+# This file is distributed under the same license as the system-config-date package.
+#
+#
+# Automatically generated, 2004.
+# Nils-Christoph Fiedler <ncfiedler@fedoraproject.org>, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: system-config-date.master-timezones\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-08-16 14:09+0100\n"
+"Last-Translator: Nils Philippsen <nils@redhat.com>\n"
+"Language-Team: Fedora Low German <nds-lowgerman@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: nds\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Low German\n"
+"X-Generator: vim\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Afrika/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Afrika/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Afrika/Addis_Abeba"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Afrika/Algier"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "Afrika/Asmera"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Afrika/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Afrika/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Afrika/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Afrika/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Afrika/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Afrika/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Afrika/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Afrika/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Afrika/Kairo"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Afrika/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Afrika/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "Ceuta & Melilla"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Afrika/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Afrika/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Afrika/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Afrika/Dschibuti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Afrika/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Afrika/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Afrika/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Afrika/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Afrika/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Afrika/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Afrika/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Afrika/Khartum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Afrika/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Afrika/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "Westl. Dem. Rep. Kongo"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Afrika/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Afrika/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Afrika/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Afrika/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Afrika/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "Östl. Dem. Rep. Kongo"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Afrika/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Afrika/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Afrika/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Afrika/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Afrika/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Afrika/Mogadischu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Afrika/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Afrika/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Afrika/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Afrika/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Afrika/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Afrika/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Afrika/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Afrika/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Afrika/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Afrika/Tripolis"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Afrika/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Afrika/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Amerika/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Aleuten Inseln"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Amerika/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Alaska-Zeit"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Amerika/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Amerika/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Amerika/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "Tocantins"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Amerika/Argentinien/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Buenos Aires (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Amerika/Argentinien/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "Catamarca (CT), Chubut (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Amerika/Argentinien/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Amerika/Argentinien/Cordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "fast alle Orte (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Amerika/Argentinien/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Jujuy (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Amerika/Argentinien/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "La Rioja (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Amerika/Argentinien/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "Mendoza (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Amerika/Argentinien/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "Santa Cruz (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "Amerika/Argentinien/Salta"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Amerika/Argentinien/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "San Juan (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "Amerika/Argentinien/San_Luis"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "San Luis (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Amerika/Argentinien/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "Tucuman (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Amerika/Argentinien/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "Feuerland (Tierra del Fuego, TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Amerika/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Amerika/Asuncion"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Amerika/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+"Eastern Standard Time - Atikokan, Ontario und Southampton Insel, Nunavut"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Amerika/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Amerika/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "Bahia"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "Amerika/Bahia_Banderas"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "Mexican Central Time - Bahia de Banderas"
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Amerika/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Amerika/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "Amapa, E Para"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Amerika/Belize"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "Amerika/Blanc-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "Atlantic Standard Time - Quebec - Untere Nordküste"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Amerika/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "Roraima"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Amerika/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Amerika/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "Mountain Time - Süd-Idaho & Ost-Oregon"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Amerika/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Amerika/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "Mountain Time - West-Nunavut"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "Amerika/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "Mato Grosso do Sul"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Amerika/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "Central Time - Quintana Roo"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Amerika/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Amerika/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Amerika/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Amerika/Cayman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Amerika/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "Central Time"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Amerika/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "Mexican Mountain Time - Chihuahua fern der US-Grenze"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "Amerika/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Amerika/Cordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Amerika/Costa_Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Amerika/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "Mato Grosso"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Amerika/Curacao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Amerika/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "Ostküste, im Norden von Scoresbysund"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Amerika/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "Pacific Time - Nord Yukon"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Amerika/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Amerika/Denver"
+
+#
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "Mountain Time"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Amerika/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "Eastern Time - Michigan - fast alle Orte"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Amerika/Dominica"
+
+#
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Amerika/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "Mountain Time - Alberta, östl. British-Columbia & westl. Saskatchewan"
+
+#
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Amerika/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "Westl. Amazonas"
+
+#
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Amerika/El_Salvador"
+
+#
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Amerika/Ensenada"
+
+#
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Amerika/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "Nordöstl. Brasilien (MA, PI, CE, RN, PB)"
+
+#
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Amerika/Fort_Wayne"
+
+#
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Amerika/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+"Atlantic Time - Nova Scotia - Orte, die der DST (Sommerzeit) 1966-1971 nicht "
+"folgten"
+
+#
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Amerika/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "fast alle Orte"
+
+#
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Amerika/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "Atlantic Time - Labrador - fast alle Orte"
+
+#
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Amerika/Grand_Turk"
+
+#
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Amerika/Grenada"
+
+#
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Amerika/Guadeloupe"
+
+#
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Amerika/Guatemala"
+
+#
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Amerika/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "Festland"
+
+#
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Amerika/Guyana"
+
+#
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Amerika/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "Atlantic Time - Nova Scotia (fast alle Orte), PEI"
+
+#
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Amerika/Havanna"
+
+#
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Amerika/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "Mountain Standard Time - Sonora"
+
+#
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Amerika/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "Eastern Time - Indiana - fast alle Orte"
+
+#
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Amerika/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "Central Time - Indiana - Starke County"
+
+#
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Amerika/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "Eastern Time - Indiana - Crawford County"
+
+#
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "Amerika/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "Eastern Time - Indiana - Pike County"
+
+#
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Amerika/Indianapolis"
+
+#
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "Amerika/Indiana/Tell_City"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "Central Time - Indiana - Perry County"
+
+#
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "Eastern Time - Indiana - Switzerland County"
+
+#
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "Amerika/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+
+#
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "Amerika/Indiana/Winamac"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "Eastern Time - Indiana - Pulaski County"
+
+#
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Amerika/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "Mountain Time - westliche Northwest Territories"
+
+#
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Amerika/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "Eastern Time - Ost-Nunavut - fast alle Orte"
+
+#
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Amerika/Jamaika"
+
+#
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Amerika/Jujuy"
+
+#
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Amerika/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "Alaska Time - Alaska Panhandle"
+
+#
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Amerika/Kentucky/Louisville"
+
+#
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Amerika/Kentucky/Louisville"
+
+#
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Amerika/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "Eastern Time - Kentucky - Wayne County"
+
+#
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Amerika/Knox_IN"
+
+#
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Amerika/La_Paz"
+
+#
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Amerika/Lima"
+
+#
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Amerika/Los_Angeles"
+
+#
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "Pacific Time"
+
+#
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Amerika/Louisville"
+
+#
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Amerika/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "Alagoas"
+
+#
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Amerika/Managua"
+
+#
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Amerika/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "Östl. Amazonas"
+
+#
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "Amerika/Marigot"
+
+#
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Amerika/Martinique"
+
+#
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "Amerika/Matamoros"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas nahe der US-"
+"Grenze"
+
+#
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Amerika/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "Mountain Time - Südl. Baja, Nayarit, Sinaloa"
+
+#
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Amerika/Mendoza"
+
+#
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Amerika/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+"Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+
+#
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Amerika/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "Central Time - Campeche, Yucatan"
+
+#
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Amerika/Mexiko_Stadt"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "Central Time - fast alle Orte"
+
+#
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Amerika/Miquelon"
+
+#
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "Amerika/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "Atlantic Time - New Brunswick"
+
+#
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Amerika/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas fern der US-"
+"Grenze"
+
+#
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Amerika/Montevideo"
+
+#
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Amerika/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "Eastern Time - Quebec - fast alle Orte"
+
+#
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Amerika/Montserrat"
+
+#
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Amerika/Nassau"
+
+#
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Amerika/New_York"
+
+#
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "Eastern Time"
+
+#
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Amerika/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+"Eastern Time - Ontario & Quebec - Orte, die der DST (Sommerzeit) 1967-1973 "
+"nicht folgten"
+
+#
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Amerika/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "Alaska Time - West-Alaska"
+
+#
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Amerika/Noronha"
+
+#
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "Atlantische Inseln"
+
+#
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Amerika/North_Dakota/Zentrum"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "Central Time - North Dakota - Oliver County"
+
+#
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "Amerika/North_Dakota/New_Salem"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "Central Time - North Dakota - Morton County (außer Mandan-Region)"
+
+#
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "Amerika/Ojinaga"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "US Mountain Time - Chihuahua nahe der US-Grenze"
+
+#
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Amerika/Panama"
+
+#
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Amerika/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "Eastern Time - Pangnirtung, Nunavut"
+
+#
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Amerika/Paramaribo"
+
+#
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Amerika/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "Mountain Standard Time - Arizona"
+
+#
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Amerika/Port-au-Prince"
+
+#
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Amerika/Porto_Acre"
+
+#
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Amerika/Port_of_Spain"
+
+#
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Amerika/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "Rondonia"
+
+#
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Amerika/Puerto_Rico"
+
+#
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Amerika/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "Central Time - Rainy River & Fort Frances, Ontario"
+
+#
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Amerika/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "Central Time - Zentral-Nunavut"
+
+#
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Amerika/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "Pernambuco"
+
+#
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Amerika/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "Central Standard Time - Saskatchewan - fast alle Orte"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "Amerika/Resolute"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "Eastern Standard Time - Resolute, Nunavut"
+
+#
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Amerika/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "Acre"
+
+#
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Amerika/Rosario"
+
+#
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "Amerika/Santa_Isabel"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "Mexican Pacific Time - Baja California fern der US-Grenze"
+
+#
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "Amerika/Santarem"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "Westl. Para"
+
+#
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Amerika/Santiago"
+
+#
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Amerika/Santo_Domingo"
+
+#
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Amerika/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "Südl. & Südöstl. Brasilien (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Amerika/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "Scoresbysund / Ittoqqortoormiit"
+
+#
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Amerika/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "Mountain Time - Navajo"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "Amerika/St_Barthelemy"
+
+#
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Amerika/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "Newfoundland Time, einschließlich südöstl. Labrador"
+
+#
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Amerika/St_Kitts"
+
+#
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Amerika/St_Lucia"
+
+#
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Amerika/St_Thomas"
+
+#
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Amerika/St_Vincent"
+
+#
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Amerika/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "Central Standard Time - Saskatchewan - Mittlerer Westen"
+
+#
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Amerika/Tegucigalpa"
+
+#
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Amerika/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "Thule / Pituffik"
+
+#
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Amerika/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "Eastern Time - Thunder Bay, Ontario"
+
+#
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Amerika/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "US Pacific Time - Baja California nahe der US-Grenze"
+
+#
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "Amerika/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "Eastern Time - Ontario - fast alle Orte"
+
+#
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Amerika/Tortola"
+
+#
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Amerika/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "Pacific Time - Westliches British Columbia"
+
+#
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Amerika/Virgin"
+
+#
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Amerika/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "Pacific Time - Süd-Yukon"
+
+#
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Amerika/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "Central Time - Manitoba & West-Ontario"
+
+#
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Amerika/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "Alaska Time - Alaska Panhandle"
+
+#
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Amerika/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "Mountain Time - zentrale Northwest Territories"
+
+#
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antarktis/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "Casey Station, Bailey Peninsula"
+
+#
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antarktis/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "Davis Station, Vestfold Hills"
+
+#
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antarktis/Dumont d'Urville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "Dumont-d'Urville Station, Terre Adelie"
+
+#
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "Antarktis/Macquarie"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "Macquarie-Insel Station, Macquarie-Insel"
+
+#
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antarktis/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "Mawson Station, Holme Bay"
+
+#
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antarktis/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "McMurdo Station, Ross Island"
+
+#
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antarktis/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "Palmer Station, Anvers Island"
+
+#
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antarktis/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "Rothera Station, Adelaide Island"
+
+#
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antarktis/Südpol"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "Amundsen-Scott Station, South Pole"
+
+#
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antarktis/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "Syowa Station, östl. Ongul Insel"
+
+#
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antarktis/Wostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "Vostok Station, magnetischer Südpol"
+
+#
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Arktis/Longyearbyen"
+
+#
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Asien/Aden"
+
+#
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Asien/Almaty"
+
+#
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Asien/Amman"
+
+#
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Asien/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "Moskau+08 - Beringsee"
+
+#
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Asien/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+
+#
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Asien/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "Aqtobe (Aktobe)"
+
+#
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Asien/Ashgabat"
+
+#
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Asien/Ashkhabad"
+
+#
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Asien/Bagdad"
+
+#
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Asien/Bahrain"
+
+#
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Asien/Baku"
+
+#
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Asien/Bangkok"
+
+#
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Asien/Beirut"
+
+#
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Asien/Bishkek"
+
+#
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Asien/Brunei"
+
+#
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Asien/Kalkutta"
+
+#
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Asien/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "Dornod, Sukhbaatar"
+
+#
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Asien/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "Zentral-China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, usw."
+
+#
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Asien/Chungking"
+
+#
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Asien/Colombo"
+
+#
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Asien/Dacca"
+
+#
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Asien/Damaskus"
+
+#
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Asien/Dhaka"
+
+#
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Asien/Dili"
+
+#
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Asien/Dubai"
+
+#
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Asien/Duschanbe"
+
+#
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Asien/Gaza"
+
+#
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Asien/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "Heilongjiang (außer Mohe), Jilin"
+
+#
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Asien/Ho_Chi_Minh_Stadt"
+
+#
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Asien/Hong_Kong"
+
+#
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Asien/Chowd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "Bajan-Ölgii, Gobi-Altai, Chowd, Uws, Zawchan"
+
+#
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Asien/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Moskau+05 - Baikal-See"
+
+#
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Asien/Istanbul"
+
+#
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Asien/Jakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "Java & Sumatra"
+
+#
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Asien/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "Irian Jaya & die Molukken"
+
+#
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Asien/Jerusalem"
+
+#
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Asien/Kabul"
+
+#
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Asien/Kamtschatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "Moskau+08 - Kamtschatka"
+
+#
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Asien/Karachi"
+
+#
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Asien/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "West-Tibet & Xinjiang"
+
+#
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "Asien/Kathmandu"
+
+#
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Asien/Katmandu"
+
+#
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "Asien/Kalkutta"
+
+#
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Asien/Krasnojarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "Moskau+04 - Jenissei Fluss"
+
+#
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Asien/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "Halbinsel Malaysia"
+
+#
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Asien/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "Sabah & Sarawak"
+
+#
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Asien/Kuwait"
+
+#
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Asien/Macao"
+
+#
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Asien/Macau"
+
+#
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Asien/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "Moskau+08 - Magadan"
+
+#
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Asien/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "Ost- & Süd-Borneo, Sulawesi, Bali, Kleine Sunda-Inseln, West-Timor"
+
+#
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Asien/Manila"
+
+#
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Asien/Maskat"
+
+#
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Asien/Nikosia"
+
+#
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "Asien/Nowokusnezk"
+
+#
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Moskau+03 - Nowokusnezk"
+
+#
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Asien/Nowosibirsk"
+
+#
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Moskau+03 - Nowosibirsk"
+
+#
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Asien/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "Moskau+03 - Westl. Sibirien"
+
+#
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Asien/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "Westl. Kasachstan"
+
+#
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Asien/Phnom_Penh"
+
+#
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Asien/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "West- & Zentral-Borneo"
+
+#
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Asien/Pjöngjang"
+
+#
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Asien/Katar"
+
+#
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Asien/Qysylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "Qysylorda (Kysyl-Orda, Ksyl-Orda)"
+
+#
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Asien/Rangun"
+
+#
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Asien/Riad"
+
+#
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Asien/Riad87"
+
+#
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Asien/Riad88"
+
+#
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Asien/Riad89"
+
+#
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Asien/Saigon"
+
+#
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Asien/Sachalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "Moskau+07 - Sachalin Inseln"
+
+#
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Asien/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "Westliches Usbekistan"
+
+#
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Asien/Seoul"
+
+#
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Asien/Shanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "Östl. China - Peking, Guangdong, Shanghai, etc."
+
+#
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Asien/Singapur"
+
+#
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Asien/Taipei"
+
+#
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Asien/Taschkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "Östl. Usbekistan"
+
+#
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Asien/Tiflis"
+
+#
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Asien/Teheran"
+
+#
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Asien/Tel_Aviv"
+
+#
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Asien/Thimbu"
+
+#
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Asien/Thimphu"
+
+#
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Asien/Tokio"
+
+#
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Asien/Ujung_Pandang"
+
+#
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Asien/Ulaanbaatar"
+
+#
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Asien/Ulan_Bator"
+
+#
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Asien/Ürümqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "Große Teile von Tibet & Xinjiang"
+
+#
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Asien/Vientiane"
+
+#
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Asien/Wladiwostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "Moskau+07 - Amur Fluss"
+
+#
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Asien/Jakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "Moskau+06 - Lena Fluss"
+
+#
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Asien/Jekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "Moskau+02 - Ural"
+
+#
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Asien/Eriwan"
+
+#
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlantik/Azoren"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "Azoren"
+
+#
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlantik/Bermuda"
+
+#
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlantik/Kanaren"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "Kanarische Inseln"
+
+#
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlantik/Kap_Verde"
+
+#
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlantik/Färöer"
+
+#
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "Atlantik/Färöer"
+
+#
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlantik/Jan_Mayen"
+
+#
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlantik/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "Madeira Inseln"
+
+#
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlantik/Reykjavik"
+
+#
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlantik/Südgeorgien"
+
+#
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlantik/Stanley"
+
+#
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlantik/St._Helena"
+
+#
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Australien/ACT"
+
+#
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Australien/Adelaide"
+
+#
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "Südaustralien"
+
+#
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Australien/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "Queensland - fast alle Orte"
+
+#
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Australien/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "Neusüdwales - Yancowinna"
+
+#
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Australien/Canberra"
+
+#
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Australien/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "Tasmanien - King Island"
+
+#
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Australien/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "Nordterritorium"
+
+#
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "Australien/Eucla"
+
+#
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "Westaustralien - Eucla-Gebiet"
+
+#
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Australien/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "Tasmanien - fast alle Orte"
+
+#
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Australien/LHI"
+
+#
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Australien/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "Queensland - Holiday Islands"
+
+#
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Australien/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "Lord-Howe-Insel"
+
+#
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Australien/Melbourne"
+
+#
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "Viktoria"
+
+#
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Australien/Nord"
+
+#
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Australien/NSW"
+
+#
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Australien/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "Westaustralien - fast alle Orte"
+
+#
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Australien/Queensland"
+
+#
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Australien/Süd"
+
+#
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Australien/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "Neusüdwales - fast alle Orte"
+
+#
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Australien/Tasmanien"
+
+#
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Australien/Viktoria"
+
+#
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Australien/West"
+
+#
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Australien/Yancowinna"
+
+#
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brasilien/Acre"
+
+#
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brasilien/DeNoronha"
+
+#
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brasilien/Ost"
+
+#
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brasilien/West"
+
+#
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Kanada/Atlantik"
+
+#
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Kanada/Zentral"
+
+#
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Kanada/Ost"
+
+#
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Kanada/Ost-Saskatchewan"
+
+#
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Kanada/Mountain"
+
+#
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Kanada/Neufundland"
+
+#
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Kanada/Pazifik"
+
+#
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Kanada/Saskatchewan"
+
+#
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Kanada/Yukon"
+
+#
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Chile/Kontinental"
+
+#
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Chile/Osterinsel"
+
+#
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Kuba"
+
+#
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Ägypten"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Irland"
+
+#
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulu"
+
+#
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Europa/Amsterdam"
+
+#
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Europa/Andorra"
+
+#
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Europa/Athen"
+
+#
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Europa/Belfast"
+
+#
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Europa/Belgrad"
+
+#
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Europa/Berlin"
+
+#
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Europa/Bratislava"
+
+#
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Europa/Brüssel"
+
+#
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Europa/Bukarest"
+
+#
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Europa/Budapest"
+
+#
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Europa/Chişinău"
+
+#
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Europa/Kopenhagen"
+
+#
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Europa/Dublin"
+
+#
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Europa/Gibraltar"
+
+#
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Europa/Guernsey"
+
+#
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Europa/Helsinki"
+
+#
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Europa/Isle_of_Man"
+
+#
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Europa/Istanbul"
+
+#
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Europa/Jersey"
+
+#
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Europa/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Moskau-01 - Kaliningrad"
+
+#
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Europa/Kiew"
+
+#
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Europa/Lissabon"
+
+#
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Europa/Ljubljana"
+
+#
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Europa/London"
+
+#
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Europa/Luxemburg"
+
+#
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Europa/Madrid"
+
+#
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Europa/Malta"
+
+#
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Europa/Mariehamn"
+
+#
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Europa/Minsk"
+
+#
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Europa/Monaco"
+
+#
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Europa/Moskau"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "Moskau+00 - Westliches Russland"
+
+#
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Europa/Nikosia"
+
+#
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Europa/Oslo"
+
+#
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Europa/Paris"
+
+#
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Europa/Podgorica"
+
+#
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Europa/Prag"
+
+#
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Europa/Riga"
+
+#
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Europa/Rom"
+
+#
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Europa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Moskau - Samara, Udmurtia"
+
+#
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Europa/San_Marino"
+
+#
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Europa/Sarajevo"
+
+#
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Europa/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "Zentral-Crimea"
+
+#
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Europa/Skopje"
+
+#
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Europa/Sofia"
+
+#
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Europa/Stockholm"
+
+#
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Europa/Tallinn"
+
+#
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Europa/Tirana"
+
+#
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Europa/Tiraspol"
+
+#
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Europa/Uschhorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "Ruthenien"
+
+#
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Europa/Vaduz"
+
+#
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Europa/Vatikan"
+
+#
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Europa/Wien"
+
+#
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Europa/Vilnius"
+
+#
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Europa/Wolgograd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "Moskau+00 - Kaspisches Meer"
+
+#
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Europa/Warschau"
+
+#
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Europa/Zagreb"
+
+#
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Europa/Saporischschja"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "Saporoschje, östl. Lugansk / Saporischschja, östl. Luhansk"
+
+#
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Europa/Zürich"
+
+#
+#: timezones.h:808
+msgid "Factory"
+msgstr "Factory"
+
+#
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Irland"
+
+#
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Island"
+
+#
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Indischer Ozean/Antananarivo"
+
+#
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Indischer Ozean/Chagos"
+
+#
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Indischer Ozean/Weihnachtsinseln"
+
+#
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Indischer Ozean/Kokosinseln"
+
+#
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Indischer Ozean/Komoren"
+
+#
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Indischer Ozean/Kerguelen"
+
+#
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Indischer Ozean/Mahe"
+
+#
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Indischer Ozean/Malediven"
+
+#
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Indischer Ozean/Mauritius"
+
+#
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Indischer Ozean/Mayotte"
+
+#
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Indischer Ozean/Réunion"
+
+#
+#: timezones.h:830
+msgid "Iran"
+msgstr "Iran"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#
+#: timezones.h:832
+msgid "Israel"
+msgstr "Israel"
+
+#
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamaika"
+
+#
+#: timezones.h:834
+msgid "Japan"
+msgstr "Japan"
+
+#
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Libyen"
+
+#
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Mexiko/BajaNorte"
+
+#
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Mexiko/BajaSur"
+
+#
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Mexiko/General"
+
+#
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Mittlerer Osten/Riad87"
+
+#
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Mittlerer Osten/Riad88"
+
+#
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Mittlerer Osten/Riad89"
+
+#
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Pazifik/Apia"
+
+#
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Pazifik/Auckland"
+
+#
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Pazifik/Chatham"
+
+#
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "Chatham Inseln"
+
+#
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "Pazifik/Chuuk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "Chuuk (Truk) und Yap"
+
+#
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Pazifik/Osterinsel"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "Osterinseln & Sala y Gomez"
+
+#
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Pazifik/Efate"
+
+#
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Pazifik/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "Phoenixinseln"
+
+#
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Pazifik/Fakaofo"
+
+#
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Pazifik/Fidschi"
+
+#
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Pazifik/Funafuti"
+
+#
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Pazifik/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "Galapagos-Inseln"
+
+#
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Pazifik/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "Gambier Inseln"
+
+#
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Pazifik/Guadalcanal"
+
+#
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Pazifik/Guam"
+
+#
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Pazifik/Honolulu"
+
+#
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "Hawaii"
+
+#
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Pazifik/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "Johnston-Atoll"
+
+#
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Pazifik/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "Line-Inseln"
+
+#
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Pazifik/Kosrae"
+
+#
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "Kosrae"
+
+#
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Pazifik/Kwajalein"
+
+#
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Pazifik/Majuro"
+
+#
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Pazifik/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "Marquesas-Inseln"
+
+#
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Pazifik/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "Midway-Inseln"
+
+#
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Pazifik/Nauru"
+
+#
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Pazifik/Niue"
+
+#
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Pazifik/Norfolk"
+
+#
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Pazifik/Noumea"
+
+#
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Pazifik/Pago_Pago"
+
+#
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Pazifik/Palau"
+
+#
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Pazifik/Pitcairn"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "Pazifik/Pohnpei"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "Pohnpei (Ponape)"
+
+#
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Pazifik/Ponape"
+
+#
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Pazifik/Port_Moresby"
+
+#
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Pazifik/Rarotonga"
+
+#
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Pazifik/Saipan"
+
+#
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Pazifik/Samoa"
+
+#
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Pazifik/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "Gesellschaftsinseln"
+
+#
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Pazifik/Tarawa"
+
+#
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "Gilbert-Inseln"
+
+#
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Pazifik/Tongatapu"
+
+#
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Pazifik/Truk"
+
+#
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Pazifik/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "Wake Island"
+
+#
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Pazifik/Wallis"
+
+#
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Pazifik/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Polen"
+
+#
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugal"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapur"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Türkei"
+
+#
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "US/Alaska"
+
+#
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "US/Aleutian"
+
+#
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "US/Arizona"
+
+#
+#: timezones.h:943
+msgid "US/Central"
+msgstr "US/Central"
+
+#
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "US/Eastern"
+
+#
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "US/Ost-Indiana"
+
+#
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "US/Hawaii"
+
+#
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "US/Indiana-Starke"
+
+#
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "US/Michigan"
+
+#
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "US/Mountain"
+
+#
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "US/Pacific"
+
+#
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "US/Samoa"
+
+#
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
diff --git a/panels/datetime/po-timezones/nl.po b/panels/datetime/po-timezones/nl.po
new file mode 100644
index 0000000..e83d57f
--- /dev/null
+++ b/panels/datetime/po-timezones/nl.po
@@ -0,0 +1,3288 @@
+# Dutch translation of timezones.
+# Copyright (c) 2003 The free software foundation, inc.
+# This file is distributed under the same license as the timezones package.
+# Tino Meinen <a.t.meinen@chello.nl>, 2003.
+# Peter van Egdom <p.van.egdom@gmail.com>, 2006, 2007, 2008.
+# Geert Warrink <geert.warrink@onsnet.nu>, 2009, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-08-25 14:12+0200\n"
+"Last-Translator: Geert Warrink <geert.warrink@onsnet.nu>\n"
+"Language-Team: Fedora\n"
+"Language: nl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Virtaal 0.6.1\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Afrika/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Afrika/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Afrika/Addis_Ababa"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Afrika/Algiers"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "Afrika/Asmara"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Afrika/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Afrika/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Afrika/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Afrika/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Afrika/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Afrika/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Afrika/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Afrika/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Afrika/Caïro"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Afrika/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Afrika/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "Ceuta & Melilla"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Afrika/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Afrika/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Afrika/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Afrika/Djibouti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Afrika/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Afrika/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Afrika/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Afrika/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Afrika/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Afrika/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Afrika/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Afrika/Khartoem"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Afrika/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Afrika/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "west Dem. Rep. Congo"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Afrika/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Afrika/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Afrika/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Afrika/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Afrika/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "oost Dem. Rep. Congo"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Afrika/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Afrika/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Afrika/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Afrika/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Afrika/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Afrika/Mogadishu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Afrika/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Afrika/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Afrika/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Afrika/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Afrika/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Afrika/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Afrika/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Afrika/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Afrika/Timboektoe"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Afrika/Tripoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Afrika/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Afrika/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Amerika/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Aleoeten"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Amerika/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Alaska tijd"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Amerika/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Amerika/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Amerika/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "Tocantins"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Amerika/Argentinië/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Buenos Aires (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Amerika/Argentinië/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "Catamarca (CT), Chubut (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Amerika/Argentinië/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Amerika/Argentinië/Cordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "meeste locaties (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Amerika/Argentinië/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Jujuy (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Amerika/Argentinië/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "La Rioja (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Amerika/Argentinië/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "Mendoza (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Amerika/Argentinië/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "Santa Cruz (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "Amerika/Argentinië/Salta"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Amerika/Argentinië/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "San Juan (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "Amerika/Argentinië/San_Luis"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "San Luis (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Amerika/Argentinië/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "Tucuman (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Amerika/Argentinië/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "Vuurland (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Amerika/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Amerika/Asunción"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Amerika/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Amerika/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Amerika/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "Bahia"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "Amerika/Bahia_Banderas"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "Mexican Central Time - Bahia de Banderas"
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Amerika/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Amerika/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "Amapa, E Para"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Amerika/Belize"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "Amerika/Blanc-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "Atlantic Standard Time - Quebec - Lower North Shore"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Amerika/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "Roraima"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Amerika/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Amerika/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "Mountain Time - zuid Idaho & oost Oregon"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Amerika/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Amerika/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "Mountain Time - west Nunavut"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "Amerika/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "Mato Grosso do Sul"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Amerika/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "Central Time - Quintana Roo"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Amerika/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Amerika/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Amerika/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Amerika/Caymaneilanden"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Amerika/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "Central Time"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Amerika/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "Mexico Mountain Time - Chihuahua of afstand van de VS grens"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "Amerika/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Amerika/Cordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Amerika/Costa_Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Amerika/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "Mato Grosso"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Amerika/Curaçao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Amerika/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "oost kust, ten noorden van Scoresbysund"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Amerika/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "Pacific Time - noord Yukon"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Amerika/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, Brits-Columbia"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Amerika/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "Mountain Time"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Amerika/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "Eastern Time - Michigan - meeste locaties"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Amerika/Dominica"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Amerika/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "Mountain Time - Alberta, oost Brits-Columbia & west Saskatchewan"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Amerika/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "W Amazonas"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Amerika/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Amerika/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Amerika/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "NO Brazilïe (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Amerika/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Amerika/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr "Atlantic Time - Nova Scotia - plaatsen die DST 1966-1971 niet naleven"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Amerika/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "meeste locaties"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Amerika/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "Atlantic Time - Labrador - meeste locaties"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Amerika/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Amerika/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Amerika/Guadeloupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Amerika/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Amerika/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "vasteland"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Amerika/Guyana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Amerika/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "Atlantic Time - Nova Scotia (meeste plaatsen), PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Amerika/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Amerika/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "Mountain Standard Time - Sonora"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Amerika/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "Eastern Time - Indiana - meeste locaties"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Amerika/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "Central Time - Indiana - Starke County"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Amerika/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "Eastern Time - Indiana - Crawford County"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "Amerika/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "Eastern Time - Indiana - Pike County"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Amerika/Indianapolis"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "Amerika/Indiana/Tell_City"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "Central Time - Indiana - Perry County"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "Eastern Time - Indiana - Switzerland County"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "Amerika/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "Amerika/Indiana/Winamac"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "Eastern Time - Indiana - Pulaski County"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Amerika/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "Mountain Time - west Northwest Territories"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Amerika/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "Eastern Time - oost Nunavut - meeste locaties"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Amerika/Jamaica"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Amerika/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Amerika/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "Alaska Time - Alaska Panhandle"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Amerika/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Eastern Time - Kentucky - Louisville gebied"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Amerika/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "Eastern Time - Kentucky - Wayne County"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Amerika/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Amerika/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Amerika/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Amerika/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "Pacific Time"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Amerika/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Amerika/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "Alagoas, Sergipe"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Amerika/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Amerika/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "E Amazonas"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "Amerika/Marigot"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Amerika/Martinique"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "Amerika/Matamoros"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+"VS Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas bij VS grens"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Amerika/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "Mountain Time - S Baja, Nayarit, Sinaloa"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Amerika/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Amerika/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+"Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Amerika/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "Central Time - Campeche, Yucatan"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Amerika/Mexico_City"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "Central Time - meeste locaties"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Amerika/Miquelon"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "Amerika/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "Atlantic Time - New Brunswick"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Amerika/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+"Mexico Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas weg van de "
+"VS grens"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Amerika/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Amerika/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "Eastern Time - Quebec - meeste locaties"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Amerika/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Amerika/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Amerika/New_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "Eastern Time"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Amerika/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+"Eastern Time - Ontario & Quebec - plaatsen die DST 1967-1973 niet naleven"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Amerika/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "Alaska Time - west Alaska"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Amerika/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "Atlantische eilanden"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Amerika/North_Dakota/Center"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "Central Time - North Dakota - Oliver County"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "Amerika/North_Dakota/New_Salem"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "Central Time - North Dakota - Morton County (behalve Mandan gebied)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "Amerika/Ojinaga"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "VS Mountain Time - Chihuahua bij de VS grens"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Amerika/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Amerika/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "Eastern Time - Pangnirtung, Nunavut"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Amerika/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Amerika/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "Mountain Standard Time - Arizona"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Amerika/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Amerika/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Amerika/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Amerika/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "Rondonia"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Amerika/Puerto_Rico"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Amerika/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "Central Time - Rainy River & Fort Frances, Ontario"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Amerika/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "Central Time - centraal Nunavut"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Amerika/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "Pernambuco"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Amerika/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "Central Standard Time - Saskatchewan - meeste locaties"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "Amerika/Resolute"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "Eastern Standard Time - Resolute, Nunavut"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Amerika/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "Acre"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Amerika/Rosario"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "Amerika/Santa_Isabel"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "Mexico Pacific Time - Baja California weg vanaf VS grens"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "Amerika/Santarem"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "W Para"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Amerika/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Amerika/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Amerika/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "Z & ZO Brazilïe (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Amerika/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "Scoresbysund / Ittoqqortoormiit"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Amerika/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "Mountain Time - Navajo"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "Amerika/St_Barthelemy"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Amerika/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "Newfoundland Time, inclusief ZO Labrador"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Amerika/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Amerika/St_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Amerika/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Amerika/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Amerika/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "Central Standard Time - Saskatchewan - middenwesten"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Amerika/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Amerika/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "Thule / Pituffik"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Amerika/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "Eastern Time - Thunder Bay, Ontario"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Amerika/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "VS Pacific Time - Baja California bij de VS grens"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "Amerika/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "Eastern Time - Ontario - meeste locaties"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Amerika/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Amerika/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "Pacific Time - west Brits-Columbia"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Amerika/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Amerika/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "Pacific Time - zuid Yukon"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Amerika/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "Central Time - Manitoba & west Ontario"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Amerika/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "Alaska Time - Alaska Panhandle neck"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Amerika/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "Mountain Time - centraal Northwest Territories"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antarctica/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "Casey Station, Bailey Peninsula"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antarctica/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "Davis Station, Vestfold Hills"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antarctica/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "Dumont-d'Urville Station, Terre Adelie"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "Antarctica/Macquarie"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "Macquarie Island Station, Macquarie Island"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antarctica/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "Mawson Station, Holme Bay"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antarctica/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "McMurdo Station, Ross Island"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antarctica/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "Palmer Station, Anvers Island"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antarctica/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "Rothera Station, Adelaide Island"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antarctica/South_Pole"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "Amundsen-Scott Station, Zuidpool"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antarctica/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "Syowa Station, O Ongul I"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antarctica/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "Vostok Station, Z Magnetic Pole"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Arctic/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Azië/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Azië/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Azië/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Azië/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "Moskou+08 - Bering Zee"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Azië/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Azië/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "Aqtobe (Aktobe)"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Azië/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Azië/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Azië/Bagdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Azië/Bahrein"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Azië/Bakoe"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Azië/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Azië/Beiroet"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Azië/Bisjkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Azië/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Azië/Calcutta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Azië/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "Dornod, Sukhbaatar"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Azië/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "centraal China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, enz."
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Azië/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Azië/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Azië/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Azië/Damascus"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Azië/Dhaka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Azië/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Azië/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Azië/Dushanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Azië/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Azië/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "Heilongjiang (behalve Mohe), Jilin"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Azië/Ho_Chi_Minh"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Azië/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Azië/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Azië/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Moskou+05 - Baikalmeer"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Azië/Istanbul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Azië/Jakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "Java & Sumatra"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Azië/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "Papoea & de Molukken"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Azië/Jeruzalem"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Azië/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Azië/Kamchatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "Moskou+08 - Kamchatka"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Azië/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Azië/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "west Tibet & Xinjiang"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "Azië/Kathmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Azië/Katmandu"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "Azië/Calcutta"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Azië/Krasnoyarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "Moskou+04 - Jenisej"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Azië/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "schiereiland Maleisië"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Azië/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "Sabah & Sarawak"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Azië/Kuwait"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Azië/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Azië/Macau"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Azië/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "Moskou+08 - Magadan"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Azië/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "oost & zuid Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Azië/Manilla"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Azië/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Azië/Nicosia"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "Azië/Novokuznetsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Moskou+03 - Novokuznetsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Azië/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Moskou+03 - Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Azië/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "Moskou+03 - west Siberië"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Azië/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "West Kazachstan"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Azië/Phnom_Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Azië/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "west & centraal Borneo"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Azië/Pyongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Azië/Qatar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Azië/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Azië/Rangoon"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Azië/Riyadh"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Azië/Riyadh87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Azië/Riyadh88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Azië/Riyadh89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Azië/Saigon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Azië/Sakhalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "Moskou+07 - Sachalin eilanden"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Azië/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "west Oezbekistan"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Azië/Seoel"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Azië/Shanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "oost China - Beijing, Guangdong, Shanghai, enz."
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Azië/Singapore"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Azië/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Azië/Tashkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "oost Oezbekistan"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Azië/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Azië/Teheran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Azië/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Azië/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Azië/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Azië/Tokio"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Azië/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Azië/Ulaanbaatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Azië/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Azië/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "merendeel van Tibet & Xinjiang"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Azië/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Azië/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "Moskou+07 - Amoer rivier"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Azië/Yakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "Moskou+06 - Lena rivier"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Azië/Yekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "Moskou+02 - Oeral"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Azië/Yerevan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlantisch/Azoren"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "Azoren"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlantisch/Bermuda"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlantisch/Canarisch"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "Canarische Eilanden"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlantisch/Kaap_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlantisch/Faeroe"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "Atlantisch/Faroe"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlantisch/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlantisch/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "Madeira eilanden"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlantisch/Reykjavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlantisch/South_Georgia"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlantisch/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlantisch/St_Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Australië/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Australië/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "Zuid Australië"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Australië/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "Queensland - meeste locaties"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Australië/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "Nieuw-Zuid-Wales - Yancowinna"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Australië/Canberra"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Australië/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "Tasmanië - King Island"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Australië/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "Noordelijk Territorium"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "Australië/Eucla"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "West Australië - Eucla gebied"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Australië/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "Tasmanië - meeste locaties"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Australië/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Australië/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "Queensland - Holiday Islands"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Australië/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "Lord Howe Island"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Australië/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Australië/North"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Australië/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Australië/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "West-Australië - meeste locaties"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Australië/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Australië/South"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Australië/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "Nieuw-Zuid-Wales - meeste locaties"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Australië/Tasmanië"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Australië/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Australië/West"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Australië/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brazilië/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brazilië/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brazilië/Oost"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brazilië/West"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Canada/Atlantic"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Canada/Centraal"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Canada/Oost"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Canada/East-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Canada/Mountain"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Canada/Newfoundland"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Canada/Pacific"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Canada/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Canada/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Chili/Continentaal"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Chili/Paaseiland"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Cuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Egypte"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Eire"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Europa/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Europa/Andorra"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Europa/Athene"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Europa/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Europa/Belgrado"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Europa/Berlijn"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Europa/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Europa/Brussel"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Europa/Boekarest"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Europa/Boedapest"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Europa/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Europa/Kopenhagen"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Europa/Dublin"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Europa/Gibraltar"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Europa/Guernsey"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Europa/Helsinki"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Europa/Isle_of_Man"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Europa/Istanbul"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Europa/Jersey"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Europa/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Moskou-01 - Kaliningrad"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Europa/Kiev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Europa/Lissabon"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Europa/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Europa/Londen"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Europa/Luxemburg"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Europa/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Europa/Malta"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Europa/Mariehamn"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Europa/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Europa/Monaco"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Europa/Moskou"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "Moskou+00 - west Rusland"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Europa/Nicosia"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Europa/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Europa/Parijs"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Europa/Podgorica"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Europa/Praag"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Europa/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Europa/Rome"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Europa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Moskou - Samara, Udmurtia"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Europa/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Europa/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Europa/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "centraal Krimrepubliek"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Europa/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Europa/Sofia"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Europa/Stockholm"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Europa/Tallinn"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Europa/Tirane"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Europa/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Europa/Uzhgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "Roethenië"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Europa/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Europa/Vaticaan"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Europa/Wenen"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Europa/Vilnius"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Europa/Volgograd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "Moskou+00 - Kaspische Zee"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Europa/Warschau"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Europa/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Europa/Zaporozhye"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "Zaporozh'ye, O Lugansk / Zaporizhia, O Luhansk"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Europa/Zürich"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Factory"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Eire"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Ijsland"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Indian/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Indian/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Indian/Christmas"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Indian/Cocos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Indian/Comoro"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Indian/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Indian/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Indian/Maldives"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Indian/Mauritius"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Indian/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Indian/Reunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Iran"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Israël"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamaica"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Japan"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Libya"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Mexico/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Mexico/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Mexico/General"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Middenoosten/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Middenoosten/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Middenoosten/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Pacific/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Pacific/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Pacific/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "Chathameilanden"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "Pacific/Chuuk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "Chuuk (Truk) en Yap"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Pacific/Paaseiland"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "Paaseiland & Sala y Gomez"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Pacific/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Pacific/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "Phoenixeilanden"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Pacific/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Pacific/Fiji"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Pacific/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Pacific/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "Galapagoseilanden"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Pacific/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "Gambiereilanden"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Pacific/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Pacific/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Pacific/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "Hawaï"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Pacific/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "Johnston Atol"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Pacific/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "Line-eilanden"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Pacific/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "Kosrae"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Pacific/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Pacific/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Pacific/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "Marquesaseilanden"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Pacific/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "Midway-eilanden"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Pacific/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Pacific/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Pacific/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Pacific/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Pacific/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Pacific/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Pacific/Pitcairn"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "Pacific/Pohnpei"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "Pohnpei (Ponape)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Pacific/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Pacific/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Pacific/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Pacific/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Pacific/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Pacific/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "Genootschapseilanden"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Pacific/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "Gilberteilanden"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Pacific/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Pacific/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Pacific/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "Wake"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Pacific/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Pacific/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Polen"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugal"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapore"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Turkije"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "US/Alaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "US/Aleutian"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "US/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "US/Central"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "US/Eastern"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "US/East-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "US/Hawaii"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "US/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "US/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "US/Mountain"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "US/Pacific"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "US/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
+
+#~ msgid "US/Pacific-New"
+#~ msgstr "US/Pacific-New"
+
+#~ msgid "SystemV/AST4"
+#~ msgstr "SystemV/AST4"
+
+#~ msgid "SystemV/AST4ADT"
+#~ msgstr "SystemV/AST4ADT"
+
+#~ msgid "SystemV/CST6"
+#~ msgstr "SystemV/CST6"
+
+#~ msgid "SystemV/CST6CDT"
+#~ msgstr "SystemV/CST6CDT"
+
+#~ msgid "SystemV/EST5"
+#~ msgstr "SystemV/EST5"
+
+#~ msgid "SystemV/EST5EDT"
+#~ msgstr "SystemV/EST5EDT"
+
+#~ msgid "SystemV/HST10"
+#~ msgstr "SystemV/HST10"
+
+#~ msgid "SystemV/MST7"
+#~ msgstr "SystemV/MST7"
+
+#~ msgid "SystemV/MST7MDT"
+#~ msgstr "SystemV/MST7MDT"
+
+#~ msgid "SystemV/PST8"
+#~ msgstr "SystemV/PST8"
+
+#~ msgid "SystemV/PST8PDT"
+#~ msgstr "SystemV/PST8PDT"
+
+#~ msgid "SystemV/YST9"
+#~ msgstr "SystemV/YST9"
+
+#~ msgid "SystemV/YST9YDT"
+#~ msgstr "SystemV/YST9YDT"
diff --git a/panels/datetime/po-timezones/nn.po b/panels/datetime/po-timezones/nn.po
new file mode 100644
index 0000000..b5b5c5c
--- /dev/null
+++ b/panels/datetime/po-timezones/nn.po
@@ -0,0 +1,3238 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: Fri Jul 20 18:10:01 2001\n"
+"Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n"
+"Language-Team: Norwegian\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8-bit\n"
+"Generated-By: pygettext.py 1.1\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr ""
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr ""
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr ""
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr ""
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr ""
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr ""
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr ""
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr ""
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr ""
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr ""
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr ""
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr ""
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr ""
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr ""
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr ""
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr ""
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr ""
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr ""
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr ""
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr ""
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr ""
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr ""
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr ""
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr ""
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr ""
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr ""
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr ""
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr ""
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr ""
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr ""
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr ""
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr ""
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr ""
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr ""
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr ""
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr ""
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr ""
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr ""
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr ""
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr ""
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr ""
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr ""
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr ""
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr ""
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr ""
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr ""
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr ""
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr ""
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr ""
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr ""
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr ""
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr ""
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr ""
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr ""
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr ""
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr ""
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr ""
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr ""
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr ""
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr ""
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr ""
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr ""
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr ""
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr ""
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr ""
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr ""
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr ""
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr ""
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr ""
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr ""
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr ""
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr ""
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr ""
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr ""
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr ""
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr ""
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr ""
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr ""
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr ""
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr ""
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr ""
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr ""
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr ""
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr ""
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr ""
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr ""
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr ""
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr ""
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr ""
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr ""
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr ""
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr ""
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr ""
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr ""
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr ""
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr ""
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr ""
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr ""
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr ""
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr ""
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr ""
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr ""
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr ""
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr ""
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr ""
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr ""
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr ""
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr ""
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr ""
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr ""
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr ""
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr ""
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr ""
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr ""
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr ""
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr ""
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr ""
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr ""
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr ""
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr ""
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr ""
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr ""
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr ""
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr ""
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr ""
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr ""
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr ""
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr ""
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr ""
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr ""
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr ""
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr ""
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr ""
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr ""
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr ""
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr ""
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr ""
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr ""
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr ""
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr ""
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr ""
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr ""
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr ""
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr ""
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr ""
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr ""
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr ""
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr ""
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr ""
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr ""
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr ""
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr ""
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr ""
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr ""
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr ""
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr ""
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr ""
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr ""
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr ""
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr ""
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr ""
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr ""
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr ""
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr ""
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr ""
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr ""
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr ""
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr ""
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr ""
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr ""
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr ""
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr ""
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr ""
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr ""
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr ""
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr ""
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr ""
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr ""
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr ""
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr ""
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr ""
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr ""
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr ""
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr ""
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr ""
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr ""
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr ""
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr ""
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr ""
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr ""
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr ""
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr ""
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr ""
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr ""
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr ""
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr ""
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr ""
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr ""
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr ""
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr ""
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr ""
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr ""
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr ""
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr ""
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr ""
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr ""
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr ""
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr ""
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr ""
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr ""
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr ""
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr ""
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr ""
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr ""
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr ""
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr ""
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr ""
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr ""
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr ""
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr ""
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr ""
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr ""
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr ""
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr ""
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr ""
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr ""
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr ""
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr ""
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr ""
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr ""
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr ""
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr ""
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr ""
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr ""
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr ""
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr ""
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr ""
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr ""
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr ""
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr ""
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr ""
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr ""
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr ""
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr ""
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr ""
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr ""
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr ""
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr ""
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr ""
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr ""
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr ""
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr ""
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr ""
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr ""
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr ""
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr ""
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr ""
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr ""
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr ""
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr ""
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr ""
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr ""
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr ""
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr ""
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr ""
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr ""
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr ""
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr ""
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr ""
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr ""
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr ""
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr ""
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr ""
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr ""
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr ""
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr ""
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr ""
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr ""
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr ""
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr ""
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr ""
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr ""
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr ""
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr ""
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr ""
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr ""
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr ""
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr ""
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr ""
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr ""
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr ""
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr ""
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr ""
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr ""
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr ""
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr ""
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr ""
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr ""
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr ""
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr ""
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr ""
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr ""
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr ""
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr ""
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr ""
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr ""
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr ""
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr ""
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr ""
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr ""
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr ""
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr ""
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr ""
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr ""
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr ""
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr ""
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr ""
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr ""
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr ""
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr ""
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr ""
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr ""
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr ""
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr ""
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr ""
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr ""
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr ""
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr ""
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr ""
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr ""
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr ""
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr ""
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr ""
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr ""
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr ""
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr ""
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr ""
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr ""
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr ""
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr ""
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr ""
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr ""
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr ""
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr ""
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr ""
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr ""
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr ""
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr ""
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr ""
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr ""
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr ""
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr ""
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr ""
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr ""
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr ""
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr ""
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr ""
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr ""
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr ""
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr ""
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr ""
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr ""
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr ""
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr ""
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr ""
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr ""
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr ""
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr ""
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr ""
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr ""
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr ""
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr ""
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr ""
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr ""
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr ""
+
+#: timezones.h:685
+msgid "CET"
+msgstr ""
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr ""
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr ""
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr ""
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr ""
+
+#: timezones.h:690
+msgid "EET"
+msgstr ""
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr ""
+
+#: timezones.h:692
+msgid "Eire"
+msgstr ""
+
+#: timezones.h:693
+msgid "EST"
+msgstr ""
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr ""
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr ""
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr ""
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr ""
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr ""
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr ""
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr ""
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr ""
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr ""
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr ""
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr ""
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr ""
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr ""
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr ""
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr ""
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr ""
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr ""
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr ""
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr ""
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr ""
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr ""
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr ""
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr ""
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr ""
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr ""
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr ""
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr ""
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr ""
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr ""
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr ""
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr ""
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr ""
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr ""
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr ""
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr ""
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr ""
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr ""
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr ""
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr ""
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr ""
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr ""
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr ""
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr ""
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr ""
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr ""
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr ""
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr ""
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr ""
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr ""
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr ""
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr ""
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr ""
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr ""
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr ""
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr ""
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr ""
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr ""
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr ""
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr ""
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr ""
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr ""
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr ""
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr ""
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr ""
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr ""
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr ""
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr ""
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr ""
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr ""
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr ""
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr ""
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr ""
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr ""
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr ""
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr ""
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr ""
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr ""
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr ""
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr ""
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr ""
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr ""
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr ""
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr ""
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr ""
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr ""
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr ""
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr ""
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr ""
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr ""
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr ""
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr ""
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr ""
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr ""
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr ""
+
+#: timezones.h:808
+msgid "Factory"
+msgstr ""
+
+#: timezones.h:809
+msgid "GB"
+msgstr ""
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr ""
+
+#: timezones.h:811
+msgid "GMT"
+msgstr ""
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr ""
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr ""
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr ""
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr ""
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr ""
+
+#: timezones.h:817
+msgid "HST"
+msgstr ""
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr ""
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr ""
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr ""
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr ""
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr ""
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr ""
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr ""
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr ""
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr ""
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr ""
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr ""
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr ""
+
+#: timezones.h:830
+msgid "Iran"
+msgstr ""
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr ""
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr ""
+
+#: timezones.h:834
+msgid "Japan"
+msgstr ""
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr ""
+
+#: timezones.h:836
+msgid "Libya"
+msgstr ""
+
+#: timezones.h:837
+msgid "MET"
+msgstr ""
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr ""
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr ""
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr ""
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr ""
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr ""
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr ""
+
+#: timezones.h:844
+msgid "MST"
+msgstr ""
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr ""
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr ""
+
+#: timezones.h:847
+msgid "NZ"
+msgstr ""
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr ""
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr ""
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr ""
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr ""
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr ""
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr ""
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr ""
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr ""
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr ""
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr ""
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr ""
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr ""
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr ""
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr ""
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr ""
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr ""
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr ""
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr ""
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr ""
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr ""
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr ""
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr ""
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr ""
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr ""
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr ""
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr ""
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr ""
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr ""
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr ""
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr ""
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr ""
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr ""
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr ""
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr ""
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr ""
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr ""
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr ""
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr ""
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr ""
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr ""
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr ""
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr ""
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr ""
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr ""
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr ""
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr ""
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr ""
+
+#: timezones.h:929
+msgid "Poland"
+msgstr ""
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr ""
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr ""
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr ""
+
+#: timezones.h:934
+msgid "ROC"
+msgstr ""
+
+#: timezones.h:935
+msgid "ROK"
+msgstr ""
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr ""
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr ""
+
+#: timezones.h:938
+msgid "UCT"
+msgstr ""
+
+#: timezones.h:939
+msgid "Universal"
+msgstr ""
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr ""
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr ""
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr ""
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr ""
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr ""
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr ""
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr ""
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr ""
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr ""
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr ""
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr ""
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr ""
+
+#: timezones.h:952
+msgid "UTC"
+msgstr ""
+
+#: timezones.h:953
+msgid "WET"
+msgstr ""
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr ""
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr ""
diff --git a/panels/datetime/po-timezones/or.po b/panels/datetime/po-timezones/or.po
new file mode 100644
index 0000000..c0b341e
--- /dev/null
+++ b/panels/datetime/po-timezones/or.po
@@ -0,0 +1,3250 @@
+# translation of or.po to Oriya
+# This file is distributed under the same license as the PACKAGE package.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER.
+#
+# Subhransu Behera <sbehera@redhat.com>, 2006.
+# Subhransu Behera <arya_subhransu@yahoo.co.in>, 2007.
+# saroj kumar padhy <saroz.kumar@gmail.com>, 2008.
+# Manoj Kumar Giri <mgiri@redhat.com>, 2009, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: or\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-12-06 15:28+0530\n"
+"Last-Translator: \n"
+"Language-Team: Oriya <Translation-team-or@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: or\n"
+"X-Generator: Lokalize 1.1\n"
+"Plural-Forms: nplurals=2; plural=(n!=1);\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "ଆଫ୍ରୀକା/ଅବୀଡଜନ"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "ଆଫ୍ରୀକା/ଅକ୍ରା"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "ଆଫ୍ରୀକା/ଏଦିସ_ଅବାବା"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "ଆଫ୍ରୀକା/ଅଲଜିୟର୍ସ"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "ଆଫ୍ରୀକା/ଅସମେରା"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "ଆଫ୍ରୀକା/ଅସମେରା"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "ଆଫ୍ରୀକା/ବାମାକୋ"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "ଆଫ୍ରୀକା/ବଂଙ୍ଗୁଈ"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "ଆଫ୍ରୀକା/ବଂଜଲ"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "ଆଫ୍ରୀକା/ବିସୂ"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "ଆଫ୍ରୀକା/ବ୍ଲେନଟରୀ"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "ଆଫ୍ରୀକା/ବ୍ରାଜାବିଲ"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "ଆଫ୍ରୀକା/ବୁଜମବୁରା"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "ଆଫ୍ରୀକା/କାଇରୋ"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "ଆଫ୍ରୀକା/କାସାବ୍ଲାଙ୍କା"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "ଆଫ୍ରୀକା/ସିୟୁଟା"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "ସ୍ବେଟା ଏବଂ ମେଲିଲା"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "ଆଫ୍ରୀକା/କୋନାକ୍ରୀ"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "ଆଫ୍ରୀକା/ଡାକର"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "ଆଫ୍ରୀକା/ଡାର_ଏସ_ସ୍ଲେମ"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "ଆଫ୍ରୀକା/ଡ୍ଜିବୋଟି"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "ଆଫ୍ରୀକା/ଡୂଅଲା"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "ଆଫ୍ରୀକା/ଏଲ_ଐନ"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "ଆଫ୍ରୀକା/ଫ୍ରୀଟାଓନ"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "ଆଫ୍ରୀକା/ଗୈବ୍ରୋନ"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "ଆଫ୍ରୀକା/ହରାରେ"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "ଆଫ୍ରୀକା/ଜୋହାଂନ୍ସବର୍ଗ"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "ଆଫ୍ରୀକା/କମ୍ପାଲା"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "ଆଫ୍ରୀକା/ଖାର୍ତୁମ"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "ଆଫ୍ରୀକା/କିଗାଲୀ"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "ଆଫ୍ରୀକା/କିଂସାସା"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "ପଶ୍ଚିମ କୋଙ୍ଗୋ ର ଲୋକତାନ୍ତ୍ରିକ ଗଣରାଜ୍ଯ"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "ଆଫ୍ରୀକା/ଲାଗୋସ"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "ଆଫ୍ରୀକା/ଲିବରଭିଲ"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "ଆଫ୍ରୀକା/ଲୋମ"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "ଆଫ୍ରୀକା/ଲୁଆଣ୍ଡା"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "ଆଫ୍ରୀକା/ଲୁବୂଂବଶୀ"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "ପୂର୍ବ କୋଙ୍ଗୋ ଲୋକତାନ୍ତ୍ରିକ ଗଣରାଜ୍ଯ"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "ଆଫ୍ରୀକା/ଲୁସାକା"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "ଆଫ୍ରୀକା/ମଲାବୋ"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "ଆଫ୍ରୀକା/ମାପୁତୋ"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "ଆଫ୍ରୀକା/ମୈସେରୁ"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "ଆଫ୍ରୀକା/ମ୍ବେବାନେ"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "ଆଫ୍ରୀକା/ମୋଗାଡୀଶୂ"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "ଆଫ୍ରୀକା/ମୋନରୋବିୟା"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "ଆଫ୍ରୀକା/ନାଇରୋବୀ"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "ଆଫ୍ରୀକା/ନଜେମେନା"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "ଆଫ୍ରୀକା/ନିୟାମେ"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "ଆଫ୍ରୀକା/ନୌକଚୋଟ"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "ଆଫ୍ରୀକା/ଔଗାଦୂଗୋ"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "ଆଫ୍ରୀକା/ପୋର୍ଟୋ_ନୋଭୋ"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "ଆଫ୍ରୀକା/ସାଓ_ଟୋମ"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "ଆଫ୍ରୀକା/ତିଂବକଟୂ"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "ଆଫ୍ରୀକା/ତ୍ରିପୋଲୀ"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "ଆଫ୍ରୀକା/ଟ୍ଯୂନିସ"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "ଆଫ୍ରୀକା/ୱିଣ୍ଡହୋକ"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "ଆମେରିକା/ଅଦାକ"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "ଏଲ୍ଯୁସିୟାନ ଦ୍ବୀପ"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "ଆମେରିକା/ଏଙ୍କରେଜ"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "ଆଲାସ୍କା ସମୟ"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "ଆମେରିକା/ଏଙ୍ଗୁଲା"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "ଆମେରିକା/ଏଣ୍ଟିଗୁଆ"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "ଆମେରିକା/ଅରାଗ୍ବେନା"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "ତୋକାଣ୍ଟିନସ"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "ଆମେରିକା/ଆର୍ଜେଣ୍ଟୀନା/ବ୍ଯୁନସ_ଆୟର୍ସ"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "ବ୍ଯୁନସ ଆୟର୍ସ (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "ଆମେରିକା/ଆର୍ଜେଣ୍ଟୀନା/କୈଟାମାର୍କା"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "କାଟାମାର୍କା (CT), ଚୁବୁତ (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "ଆମେରିକା/ଆର୍ଜେଣ୍ଟୀନା/କୋମୋଡରିଭାଡାଭିଆ"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "ଆମେରିକା/ଆର୍ଜେଣ୍ଟୀନା/କୋରଡୋଭା"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "ଅଧିକାଂଶ ସ୍ଥାନଗୁଡ଼ିକ (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "ଆମେରିକା/ଆର୍ଜେଣ୍ଟୀନା/ଜୁଜୈ"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "ଜୁଜୈ (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "ଆମେରିକା/ଆର୍ଜେଣ୍ଟୀନା/ଲା_ରିୟୋଜା"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "ଲା ରିୟୋଜା (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "ଆମେରିକା/ଆର୍ଜେଣ୍ଟୀନା/ମୋନଡୋଜା"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "ମେଣ୍ଡୋଜା (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "ଆମେରିକା/ଆର୍ଜେଣ୍ଟୀନା/ରିୟୋ_ଗୈଲିୟସ"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "ସାନ୍ତା କ୍ରୁଜ (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "ଆମେରିକା/ଆର୍ଜେଣ୍ଟୀନା/ସାଲଟା"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "ଆମେରିକା/ଆର୍ଜେଣ୍ଟୀନା/ସାନ_ଜୁଆନ"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "ସାନ ଜୁଆନ (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "ଆମେରିକା/ଆର୍ଜେଣ୍ଟୀନା/ସାନ_ଲୁଇସ"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "ସାନ ଲୁଇସ (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "ଆମେରିକା/ଆର୍ଜେଣ୍ଟୀନା/ଟକମୈନ"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "ଟୁକୁମାନ (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "ଆମେରିକା/ଆର୍ଜେଣ୍ଟୀନା/ଓଶୁଆହିୟା"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "ତିୟେରା ଡେଲ ଫୁୟେଗୋ (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "ଆମେରିକା/ଅରୁବା"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "ଆମେରିକା/ଅସନଶିୟନ"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "ଆମେରିକା/ଅଟିକୋକାନ"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "ପୂର୍ବୀ ମାନକ ସମୟ - ଏଟିକୋକାନ, ଓଣ୍ଟାରିଓ ଏବଂ ସାଉଥାମ୍ପଟୋନ ଆଇ, ନୁନାଭଟ"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "ଆମେରିକା/ଅଟକା"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "ଆମେରିକା/ବିସ୍ତା"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "ବାହିଆ"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "ଆମେରିକା/ବାହିଆ_ବାନ୍ଦେରାସ"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "ମେକ୍ସିକାନ ମଧ୍ଯ ସମୟ - ବାହିଆ ଦେ ବାନ୍ଦେରାସ"
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "ଆମେରିକା/ବାର୍ବାଡୋସ"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "ଆମେରିକା/ବେଲେମ"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "ଆମାପା, ପୂର୍ବ ପାରା"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "ଆମେରିକା/ବେଲିଜ"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "ଆମେରିକା/ବ୍ଲାଙ୍କ-ସାବ୍ଲୋନ"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "ଆଟଲାଣ୍ଟିକ ମାନକ ସମୟ - କ୍ଯୁବେକ - ନିମ୍ନ ଉତ୍ତର ଉପକୂଳ"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "ଆମେରିକା/ବୋଆ_ଭିସ୍ଟା"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "ରୋରାଇମା"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "ଆମେରିକା/ବୋଗୋଟା"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "ଆମେରିକା/ବୋଇସ"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "ପର୍ବତୀୟ ସମୟ - ଦକ୍ଷିଣ ଇଦାହୋ ଏବଂ ପୂର୍ବ ଓରେଗୋନ"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "ଆମେରିକା/ବ୍ଯୁନୋଶ_ଆୟର୍ସ"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "ଆମେରିକା/କୈମ୍ବରୀଜ_ବେ"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "ପର୍ବତ ସମୟ - ପଶ୍ଚିମ ନୁନାଭଟ"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "ଆମେରିକା/କମ୍ପୋ_ଗ୍ରେଣ୍ଡ"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "ମାତୋ ଗ୍ରସୋ ଦୋ ସୁଲ"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "ଆମେରିକା/କାନକୁନ"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "କେନ୍ଦ୍ରୀୟ ସମୟ - କ୍ବିନଣ୍ଟାନା ରୁ"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "ଆମେରିକା/କୈରାକସ"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "ଆମେରିକା/କୈଟାମାର୍କା"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "ଆମେରିକା/କୈୟେନ"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "ଆମେରିକା/କୈମେନ"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "ଆମେରିକା/ଚିକାଗୋ"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "ମଧ୍ଯବର୍ତ୍ତୀ ସମୟ"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "ଆମେରିକା/ଚିହୁଆହୁଆ"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "ମେକ୍ସିକାନ ପର୍ବତ ସମୟ - ଚିହ୍ୟୁହେ US ସୀମାରୁ ଦୂରରେ"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "ଆମେରିକା/କୋରଲ_ହାର୍ବର"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "ଆମେରିକା/କୋର୍ଡୋବା"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "ଆମେରିକା/କୋଷ୍ଟା_ରିକା"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "ଆମେରିକା/କ୍ଯୁୟିବା"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "ମାତୋ ଗ୍ରସୋ"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "ଆମେରିକା/କୁରାକାଓ"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "ଆମେରିକା/ଡେନମାର୍କଶାନ"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "ପୂର୍ବ ଚଟସ୍ଥ, ସ୍କୋରର୍ସ୍ବାୟସଣ୍ଡ ର ଉତ୍ତର"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "ଆମେରିକା/ଡାଓଶନ"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "ପ୍ରଶାନ୍ତ ସମୟ - ଉତ୍ତର ୟୁକୋନ"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "ଆମେରିକା/ଡାଓଶନ_କ୍ରୀକ"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid "Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr "ପର୍ବତୀୟ ମାନକ ସମୟ - ଡାଉସନ କ୍ରୀକ ଏବଂ ସେଣ୍ଟ ଜୋନ ଦୁର୍ଗ, ବ୍ରିଟିଶ କୋଲମ୍ବିୟା"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "ଆମେରିକା/ଡେନଭର"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "ମାଉଣ୍ଟେନ ସମୟ"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "ଆମେରିକା/ଡୋଟ୍ରୋଇଟ"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "ପୂର୍ବୀ ସମୟ - ମିଚିଗାନ - ଅଧିକାଂଶ ଅଞ୍ଚଳ"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "ଆମେରିକା/ଡୋମିନିକା"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "ଆମେରିକା/ଏଡମୋଣ୍ଟୋନ"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "ପର୍ବତୀୟ ସମୟ - ଅଲବେର୍ଟା, ପୂର୍ବ ବ୍ରିଟିଶ କୋଲମ୍ବିୟା ଏବଂ ପଶ୍ଚିମ ସାସକେଚୱାନ"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "ଆମେରିକା/ୟୁରୀନଏପ"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "ପଶ୍ଚିମୀ ଆମାଜୋନସ୍"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "ଆମେରିକା/ଏଲ_ସେଲଭାଡୋର"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "ଆମେରିକା/ଏନସେନେଡା"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "ଆମେରିକା/ଫୋର୍ଟଲେଜା"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "ଉତ୍ତରପୂର୍ବ ବ୍ରାଜିଲ (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "ଆମେରିକା/ଫୋର୍ଟ_ୱେନ"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "ଆମେରିକା/ଗ୍ଲେସ_ବେ"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr "ଆଟଲାଣ୍ଟିକ ସମୟ - ନୋଭା ସ୍କୋଟିୟା - ଅଞ୍ଚଳ ଯାହାକି DST 1966-1971 କୁ ଦେଖେ ନାହିଁ"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "ଆମେରିକା/ଗଡ୍ଥବ"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "ଅଧିକାଂଶ ଅଞ୍ଚଳ"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "ଆମେରିକା/ଗୂସ_ବେ"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "ଆଟଲାଣ୍ଟିକ ସମୟ - ଲାବ୍ରାଡୋର - ଅଧିକାଂଶ ଅଞ୍ଚଳ"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "ଆମେରିକା/ଗ୍ରାଣ୍ଡ_ତୁର୍କ"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "ଆମେରିକା/ଗ୍ରୈନେଡା"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "ଆମେରିକା/ଗ୍ବାଡେଲୋପେ"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "ଆମେରିକା/ଗ୍ବାଟେମାଲା"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "ଆମେରିକା/ଗୁଆୟାକିଲ"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "ମେନଲ୍ଯାଣ୍ଡ"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "ଆମେରିକା/ଗୁଆନା"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "ଆମେରିକା/ହେଲିଫେକ୍ସ"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "ଆଟଲାଣ୍ଟିକ ସମୟ - ନୋଭା ସ୍କୋଟିୟା (ଅଧିକାଂଶ ଅଞ୍ଚଳ), PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "ଆମେରିକା/ହଭାନା"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "ଆମେରିକା/ହର୍ମୋସିଲୋ"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "ପର୍ବତୀୟ ମାନକ ସମୟ - ସୋନୋରା"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "ଆମେରିକା/ଇଣ୍ଡିୟାନା/ଇଣ୍ଡିୟାନାପୋଲିସ"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "ପୂର୍ବୀ ସମୟ - ଇଣ୍ଡିୟାନା - ଅଧିକାଂଶ ଅଞ୍ଚଳ"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "ଆମେରିକା/ଇଣ୍ଡିୟାନା/ନକ୍ସ"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "ମଧ୍ଯବର୍ତ୍ତୀ ସମୟ - ଭାରତୀୟ - ଷ୍ଟାର୍କ ଦେଶ"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "ଆମେରିକା/ଇଣ୍ଡିୟାନା/ମାରେଙ୍ଗୋ"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "ପୂର୍ବୀ ସମୟ - ଇଣ୍ଡିୟାନା - କ୍ରୋଫୋର୍ଡ କାଉଣ୍ଟୀ"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "ଆମେରିକା/ଇଣ୍ଡିୟାନା/ପିଟର୍ସବର୍ଗ"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "ପୂର୍ବୀ ସମୟ - ଇଣ୍ଡିୟାନା - ପାଇକ କାଉଣ୍ଟୀ"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "ଆମେରିକା/ଇଣ୍ଡିୟାନାପୋଲିସ"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "ଆମେରିକା/ଇଣ୍ଡିୟାନା/ଟେଲ୍_ସିଟି"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "କେନ୍ଦ୍ରୀୟ ସମୟ - ଇଣ୍ଡିୟାନା - ପେରୀ କାଉଣ୍ଟୀ"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "ଆମେରିକା/ଇଣ୍ଡିୟାନା/ଭିଭେ"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "ପୂର୍ବୀ ସମୟ - ଇଣ୍ଡିୟାନା - ସ୍ବିଜରଲ୍ଯାଣ୍ଡ କାଉଣ୍ଟୀ"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "ଆମେରିକା/ଇଣ୍ଡିୟାନା/ଭିନସେନ୍ସ"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "ପୂର୍ବ ସମୟ - ଇଣ୍ଡିୟାନା - ଡେଭିସ, ଡ୍ଯୁବୋଇସ, ନୋକ୍ସ & ମାର୍ଟିନ କାଉଣ୍ଟୀ"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "ଆମେରିକା/ଇଣ୍ଡିୟାନା/ୱିନାମେକ୍"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "ପୂର୍ବୀ ସମୟ - ଇଣ୍ଡିୟାନା - ପୋଲସ୍କି କାଉଣ୍ଟୀ"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "ଆମେରିକା/ଇନୁବିକ"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "ପର୍ବତୀୟ ସମୟ - ପଶ୍ଚିମ ଉତ୍ତରପଶ୍ଚିମ ପ୍ରଦେଶ"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "ଆମେରିକା/ଇକାଲୁଇତ"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "ପୂର୍ବୀ ସମୟ - ପୂର୍ବୀ ନୁନାଭଟ - ଅଧିକାଂଶ ଅଞ୍ଚଳ"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "ଆମେରିକା/ଜାମାଇକା"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "ଆମେରିକା/ଜୁଜୈ"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "ଆମେରିକା/ଜୂନୋ"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "ଆଲାସ୍କା ସମୟ - ଆଲାସ୍କା ପାନହ୍ଯାଣ୍ଡେଲ"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "ଆମେରିକା/କେଣ୍ଟୁକୀ/ଲୁଈବିଲ"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "ପୂର୍ବୀ ସମୟ - କେଣ୍ଟୁକୀ - ଲୋଉସଭିଲ୍ଲା କ୍ଷେତ୍ର"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "ଆମେରିକା/କେଣ୍ଟୁକୀ/ମୋଣ୍ଟିକଲେ"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "ପୂର୍ବୀ ସମୟ - କେଣ୍ଟୁକୀ - ୱେନ କାଉଣ୍ଟୀ"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "ଆମେରିକା/ନକ୍ସଇନ"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "ଆମେରିକା/ଲା_ପାଜ"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "ଆମେରିକା/ଲିମା"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "ଆମେରିକା/ଲୋସ_ଏନ୍ଜେଲସ"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "ସ୍ଥିର ସମୟ"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "ଆମେରିକା/ଲୁଈବିଲ"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "ଆମେରିକା/ମୈସିୟୋ"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "ଆଲାଗାଓସ, ସର୍ଜିପ"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "ଆମେରିକା/ମେନେଗୁଆ"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "ଆମେରିକା/ମୈନାସ"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "ପୂର୍ବ ଆମାଜୋନସ"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "ଆମେରିକା/ମେରିଗଟ୍"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "ଆମେରିକା/ମୋରଟିନିକ"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "ଆମେରିକା/ମେଟାମୋରୋସ"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid "US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr "US କେନ୍ଦ୍ରୀୟ ସମୟ - କୋହୁଲା, ଦୁରାଙ୍ଗୋ, ନ୍ଯୁଭୋ ଲିଓନ, US ସୀମା ନିକଟବର୍ତ୍ତୀ ତାମାଓଲିପାସ"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "ଆମେରିକା/ମେଜେଟଲେନ"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "ପର୍ବତୀୟ ସମୟ - ଦକ୍ଷିଣ ବାଜା, ନାୟାରିତ, ସିନାଲୋଆ"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "ଆମେରିକା/ମେନଡୋଜା"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "ଆମେରିକା/ମେନୋମିନୀ"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "କେନ୍ଦ୍ରୀୟ ସମୟ - ମିଚୀଗାନ - ଡିକିସୋନ, ଗୋଗେବିକ, ଆଇରୋନ ଏବଂ ମେନୋମିନୀ କାଉଣ୍ଟିଜ"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "ଆମେରିକା/ମେରୀଡା"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "କେନ୍ଦ୍ରୀୟ ସମୟ - କାମପୈଜ, ୟୁକାଟନ"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "ଆମେରିକା/ମେକ୍ସିକୋ_ସହର"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "କେନ୍ଦ୍ରୀୟ ସମୟ - ଅଧିକାଂଶ ଅଞ୍ଚଳ"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "ଆମେରିକା/ମିକ୍ଲୋନ"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "ଆମେରିକା/ମୋଙ୍କଟୋନ"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "ଆଟଲାଣ୍ଟିକ ସମୟ - ନୂତନ ବ୍ରୁନସ୍ବିକ"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "ଆମେରିକା/ମାଣ୍ଟୋରୀ"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+"ମେକ୍ସିକାନ କେନ୍ଦ୍ରୀୟ ସମୟ - କୋହୁଲା, ଦୁରାଙ୍ଗୋ, ନ୍ଯୁଭୋ ଲିଓନ, US ସୀମା ଦୂରବର୍ତ୍ତୀ ତାମାଓଲିପାସ"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "ଆମେରିକା/ମାଣ୍ଟେଭିଡିଓ"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "ଆମେରିକା/ମାଣ୍ଟେୟଲ"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "ପୂର୍ବୀ ସମୟ - କ୍ଯୁବେକ - ଅଧିକାଂଶ ଅଞ୍ଚଳ"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "ଆମେରିକା/ମାଣ୍ଟେସେରାଟ"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "ଆମେରିକା/ନସୋ"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "ଆମେରିକା/ନ୍ଯୁ_ୟର୍କ"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "ପୂର୍ବୀ ସମୟ"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "ଆମେରିକା/ନିପୀଗନ"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid "Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr "ପୂର୍ବୀ ସମୟ - ଓଣ୍ଟାରିୟୋ ଏବଂ କ୍ଯୁବେକ - ଅଞ୍ଚଳ ଯେଉଁ ଗୁଡିକ DST 1967-1973 କୁ ଦେଖନ୍ତି ନାହିଁ"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "ଆମେରିକା/ନୋମ"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "ଆଲାସ୍କା ସମୟ - ପଶ୍ଚିମ ଆଲାସ୍କା"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "ଆମେରିକା/ନୋରୋଂହା"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "ଆଟଲାଣ୍ଟିକ ଦ୍ବୀପ"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "ଆମେରିକା/ଉତ୍ତର_ଡକୋଟା/ମଦ୍ଦ୍ଯ"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "କେନ୍ଦ୍ରୀୟ ସମୟ - ଉତ୍ତର ଡାକୋଟା - ଓଲିଭର କାଉଣ୍ଟୀ"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "ଆମେରିକା/ଉତ୍ତର_ଡକୋଟା/ନ୍ଯୁ_ସାଲେମ"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "କେନ୍ଦ୍ରୀୟ ସମୟ - ଉତ୍ତର ଡାକୋଟା - ମୋର୍ଟୋନ କାଉଣ୍ଟୀ (ମାନଡାନ କ୍ଷେତ୍ର ବ୍ଯତୀଥ)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "ଆମେରିକା/ଓଜିନାଗା"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "US ପର୍ବତୀୟ ସମୟ - US ସୀମା ନିକଟବର୍ତ୍ତୀ ଚୀହୁବାହୁବା"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "ଆମେରିକା/ପାନାମା"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "ଆମେରିକା/ପେଙ୍ଗନୀରଟଙ୍ଗ"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "ପୂର୍ବୀ ସମୟ - ପାଙ୍ଗନିର୍ଟଙ୍ଗ, ନୁନାଭଟ"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "ଆମେରିକା/ପାରାମାରୀବୋ"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "ଆମେରିକା/ଫୋନିକ୍ସ"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "ପର୍ବତୀୟ ମାନକ ସମୟ - ଏରିଜୋନା"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "ଆମେରିକା/ପୋର୍ଟ_ଓ_ପ୍ରିନ୍ସ"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "ଆମେରିକା/ପୋର୍ଟ_ଏକର"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "ଆମେରିକା/ପୋର୍ଟ_ଅଫ_ସ୍ପେନ"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "ଆମେରିକା/ପୋର୍ଟୋ_ଭେଲୋ"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "ରୋଣ୍ଡୋନିୟା"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "ଆମେରିକା/ପ୍ଯୁରିଟୋ_ରିକୋ"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "ଆମେରିକା/ରୈନୀ_ରିଭର"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "କେନ୍ଦ୍ରୀୟ ସମୟ - ରେନୀ ନଦୀ ଏବଂ ଫ୍ରାନ୍ସିସ ଦୁର୍ଗ, ଓଣ୍ଟାରିୟୋ"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "ଆମେରିକା/ରେନକୀନ_ଇନଲେଟ"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "କେନ୍ଦ୍ରୀୟ ସମୟ - କେନ୍ଦ୍ରୀୟ ନୁନାଭଟ"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "ଆମେରିକା/ରିସୀଫ"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "ପାର୍ନାମବୁକୋ"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "ଆମେରିକା/ରେଜୀନା"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "କେନ୍ଦ୍ରୀୟ ମାନକ ସମୟ - ସାସକଚୱାନ - ଅଧିକାଂଶ ଅଞ୍ଚଳ"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "ଆମେରିକା/ରିଜୋଲ୍ଯୁଟ୍"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "ପୂର୍ବୀ ମାନକ ସମୟ - ରିଜୋଲ୍ୟୁଟ, ନୁନାଭୁତ"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "ଆମେରିକା/ରିଓ_ବ୍ରାଙ୍କୋ"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "ଅକ୍ରେ"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "ଆମେରିକା/ରୋସାରିୟୋ"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "ଆମେରିକା/ସେଣ୍ଟା_ ଇସାବେଲ"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "ମେକ୍ସିକାନ ପ୍ରସାନ୍ତ ମହାସାଗର ସମୟ - US ସୀମା ଦୂରବର୍ତ୍ତ ବାଜା କାଲିଫର୍ନିୟା"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "ଆମେରିକା/ସେଣ୍ଟାରେମ"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "W ପାରା"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "ଆମେରିକା/ସେଣ୍ଟିୟାଗୋ"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "ଆମେରିକା/ସେଣ୍ଟୋ_ଡୋମିଙ୍ଗୋ"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "ଆମେରିକା/ସାଓ_ପୋଲୋ"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "ଦ ଏବଂ ଦପ ବ୍ରାଜିଲ (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "ଆମେରିକା/ସ୍କୋର୍ସବାୟସଂଡ"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "ସ୍କୋରର୍ସ୍ବାୟସଣ୍ଡ / ଇଟ୍ଟୋଖୋରଟୁରମିଟ"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "ଆମେରିକା/ଶିପରୋକ"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "ପର୍ବତୀୟ ସମୟ - ନଭାଜୋ"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "ଆମେରିକା/ସେଇଣ୍ଟ୍_ବାର୍ଥେଲେମୀ"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "ଆମେରିକା/ସେଣ୍ଟ_ଜୋନ୍ସ"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "ନ୍ଯୁଫାଉଣ୍ଡଲ୍ଯାଣ୍ଡ ସମୟ, ଦକ୍ଷିଣ ପୂର୍ବ ଲାବ୍ରାଡୋର ସହିତ"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "ଆମେରିକା/ସେଣ୍ଟ_କିଟ୍ସ"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "ଆମେରିକା/ସେଣ୍ଟ_ଲୁସିୟା"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "ଆମେରିକା/ସେଣ୍ଟ_ଥୋମାସ"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "ଆମେରିକା/ସେଣ୍ଟ_ଭିନସେଣ୍ଟ"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "ଆମେରିକା/ସ୍ବିଫ୍ଟ_କରେଣ୍ଟ"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "କେନ୍ଦ୍ରୀୟ ମାନକ ସମୟ - ସାସକଚୱାନ - ମଧ୍ଯପଶ୍ଚିମୀ"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "ଆମେରିକା/ତେଗୁସୀଗାଲପା"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "ଆମେରିକା/ଥୁଲେ"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "ଥୁଲେ / ପିଟୁଫିକ"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "ଆମେରିକା/ଥଣ୍ଡର_ବେ"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "ପୂର୍ବୀ ସମୟ - ଥଣ୍ଡର ବେ, ଓଣ୍ଟାରିୟୋ"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "ଆମେରିକା/ତୀଜୁନା"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "US ପ୍ରସାନ୍ତ ମହାସାଗର ସମୟ - US ସୀମା ନିକଟବର୍ତ୍ତୀ ବାଜା କାଲିଫର୍ନିୟା"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "ଆମେରିକା/ଟୋରୋଣ୍ଟୋ"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "ପୂର୍ବୀ ସମୟ - ଓଣ୍ଟାରିୟୋ - ଅଧିକାଂଶ ଅଞ୍ଚଳ"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "ଆମେରିକା/ଟୋର୍ଟୋଲା"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "ଆମେରିକା/ଭାଙ୍କୋବେର"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "ପ୍ରଶାନ୍ତ ସମୟ - ପଶ୍ଚିମ ବ୍ରିଟୀଶ କୋଲମ୍ବିୟା"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "ଆମେରିକା/ଭର୍ଜିନ"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "ଆମେରିକା/ହ୍ବାଇଟହୋର୍ସ"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "ପ୍ରଶାନ୍ତ ସମୟ - ଦକ୍ଷିଣ ୟୁକୋନ"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "ଆମେରିକା/ୱିନୀପେଗ"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "କେନ୍ଦ୍ରୀୟ ସମୟ - ମେନିଟୋବା ଏବଂ ପଶ୍ଚିମ ଓଣ୍ଟାରିୟୋ"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "ଆମେରିକା/ୟକୁଟେଟ"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "ଆଲାସ୍କା ସମୟ - ଆଲାସ୍କା ପାନହ୍ଯାଣ୍ଡେଲ ନେକ"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "ଆମେରିକା/ୟଲୋନାଇଫ"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "ପର୍ବତୀୟ ସମୟ - କେନ୍ଦ୍ରୀୟ ଉତ୍ତରପଶ୍ଚିମୀ ପ୍ରଦେଶ"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "ଆଣ୍ଟାର୍କଟିକା/କେସେ"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "କାସେ ଷ୍ଟେସନ, ବୈଲି ପେନିଞ୍ଜୁଲା"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "ଆଣ୍ଟାର୍କଟିକା/ଡେଭିସ"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "ଡେଭିସ ଷ୍ଟେସନ, ଭେଷ୍ଟଫୋଲ୍ଡ ପର୍ବତମାଳା"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "ଆଣ୍ଟାର୍କଟିକା/ଡୂମାଣ୍ଟଡରବିଲ"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "ଡ୍ଯୁମୋଣ୍ଟ-ଡି'ଆରଭିଲ୍ଲେ ଆଧାର, ଟେରେ ଏଡିଲୀ"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "ଆଣ୍ଟାର୍କଟିକା/ମେକ୍ୟୁରୀ"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "ମେକ୍ୟୁରୀ ଦ୍ୱୀପ ଷ୍ଟେସନ, ମେକ୍ୟୁରୀ ଦ୍ୱୀପ"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "ଆଣ୍ଟାର୍କଟିକା/ମୋସନ"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "ମାଓସନ ଷ୍ଟେମନ, ହୋମ ବେ"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "ଆଣ୍ଟାର୍କଟିକା/ମେକମୁରଡୋ"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "ମେକମୁରଡୋ ଷ୍ଟେସନ, ରୋସ ଦ୍ବୀପ"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "ଆଣ୍ଟାର୍କଟିକା/ପାମର"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "ପାମର ଷ୍ଟେସନ, ଆନଭର୍ସ ଦ୍ବୀପ"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "ଆଣ୍ଟାର୍କଟିକା/ରୋଥେରିୟା"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "ରୋଥେରା ଷ୍ଟେସନ, ଏଡିଲେଡ ଦ୍ବୀପ"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "ଆଣ୍ଟାର୍କଟିକା/ସାଉଥ_ପୋଲ"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "ଆମୁଣ୍ଡସେନ-ସ୍କଟ ଷ୍ଟେସନ, କୁମେରୁ"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "ଆଣ୍ଟାର୍କଟିକା/ସ୍ଯୋୱା"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "ସ୍ଯୋୱା ଷ୍ଟେସନ, ଇ ଓଙ୍ଗୁଲ ଆଇ"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "ଆଣ୍ଟାର୍କଟିକା/ବୋସ୍ତୋକ"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "ଭୋଷ୍ଟୋକ ଷ୍ଟେସନ, ଦ ଚୁମ୍ବକୀୟ ମେରୁ"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "ଆର୍କଟିକ/ଲଙ୍ଗଈୟରବ୍ଯେନ"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "ଏସିଆ/ଏଡେନ"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "ଏସିଆ/ଅଲମଟୀ"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "ଏସିଆ/ଅମ୍ମାନ"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "ଏସିଆ/ଅନାଡିର"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "ମୋସ୍କୋ+08 - ବେରିଙ୍ଗ ସମୁଦ୍ର"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "ଏସିଆ/ଏକତୋ"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "ଅଟ୍ଯିରାଓ (ଅଟିରାଓ, ଗୁରୟେବ), ମାଙ୍ଘିସ୍ତାଓ (ମାଙ୍କିସ୍ତାଓ)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "ଏସିଆ/ଅକତୂବ"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "ଅକ୍ଟୋବ (ଅକ୍ଟୋବ)"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "ଏସିଆ/ଅଶଗାବଟ"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "ଏସିଆ/ଅସ୍ଖାବାଦ"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "ଏସିଆ/ବାଗଦାଦ"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "ଏସିଆ/ବାହରୀନ"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "ଏସିଆ/ବାକୂ"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "ଏସିଆ/ବେଙ୍ଗକୋକ"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "ଏସିଆ/ବେରୁଟ"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "ଏସିଆ/ବିଶକେକ"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "ଏସିଆ/ବ୍ରୁନେଈ"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "ଏସିଆ/କୋଲକାତା"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "ଏସିଆ/ଛୋଈବଲସନ"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "ଡୋରନୋଡ, ସୁଖବାତର"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "ଏସିଆ/ଚାଙ୍ଗକିଙ୍ଗ"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "କେନ୍ଦ୍ରୀୟ ଚୀନ - ସିଚୁଆନ, ୟୁନାନ, ଗୁଆଙ୍ଗକ୍ସି, ଶାନକ୍ସି, ଗୁଇଝୌ, ଇତ୍ଯାଦି।"
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "ଏସିଆ/ଚୁଙ୍ଗକିଙ୍ଗ"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "ଏସିଆ/କୋଲୋମ୍ବୋ"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "ଏସିଆ/ଡକ୍କା"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "ଏସିଆ/ଡମସ୍କସ"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "ଏସିଆ/ଢାକା"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "ଏସିଆ/ଦିଲ୍ଲୀ"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "ଏସିଆ/ଦୁବାଈ"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "ଏସିଆ/ଦୁସାନବେ"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "ଏସିଆ/ଗାଜା"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "ଏସିଆ/ହରବୀନ"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "ହେଲୋଙ୍ଗଜିଆଙ୍ଗ (ମୋହେ ବ୍ଯତୀଥ), ଜିଲିନ"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "ଏସିଆ/ହୋ_ଚି_ମିନ"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "ଏସିଆ/ହଙ୍ଗକଙ୍ଗ"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "ଏସିଆ/ହାବଡ"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "ବାୟନ-ଓଲଜୀ, ଗୋଭି-ଆଲତାଇ, ହୋବ୍ଡ, ୟୁବ୍ସ, ଜାଭଖନ"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "ଏସିଆ/ଇରକୁଟ୍ସ୍କ"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "ମୋସ୍କୋ+05 - ବୈକାଲ ନଦୀ"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "ଏସିଆ/ଇସ୍ତାନବୁଲ"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "ଏସିଆ/ଜାକର୍ତା"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "ଜାଭା ଏବଂ ସୁମାତ୍ରା"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "ଏସିଆ/ଜୟପୁରା"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "ଆଇରିୟାନ ଜାୟା ଏବଂ ମୋଲୁକାସ"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "ଏସିଆ/ଜେରୁଜେଲମ"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "ଏସିଆ/କାବୂଲ"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "ଏସିଆ/କାମଚଟକା"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "ମୋସ୍କୋ+08 - କାମଚଟକା"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "ଏସିଆ/କରାଚୀ"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "ଏସିଆ/କେଶଗର"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "ତିବ୍ବତ ଏବଂ ଜିନଜିୟାଙ୍ଗ ୟୁଗୋହର ର ଅଧିକାଂଶ ଅଞ୍ଚଳ"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "ଏସିଆ/କାଠମାଣ୍ଡୁ"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "ଏସିଆ/କାଠମାଣ୍ଡୁ"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "ଏସିଆ/କଲିକତା"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "ଏସିଆ/କ୍ରସ୍ନୋୟାସ୍କ"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "ମୋସ୍କୋ+04 - ୟେନିସୀ ନଦୀ"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "ଏସିଆ/କ୍ବାଲାଲାମପୁର"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "ମଲେଶିୟା ଉପଦ୍ବୀପ"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "ଏସିଆ/କୁଚିଙ୍ଗ"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "ସାବାହ ଏବଂ ସାରୱାକ"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "ଏସିଆ/କୁଏତ"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "ଏସିଆ/ମକାଓ"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "ଏସିଆ/ମକାଉ"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "ଏସିଆ/ମଗାଦନ"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "ମୋସ୍କୋ+08 - ମାଗାଦନ"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "ଏସିଆ/ମକସ୍ସର"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "ପୂର୍ବ ଏବଂ ଦକ୍ଷିଣ ବୋର୍ନିୟୋ, ସେଲେବିସ, ବାଲି, ନୁସା ତେନଗେରା, ପଶ୍ଚିମ ଟିମୋର"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "ଏସିଆ/ମନୀଲା"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "ଏସିଆ/ମାସ୍କଟ"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "ଏସିଆ/ନିକୋସିୟା"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "ଏସିଆ/ନୋଭୋକୁନେଚ"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "ମୋସ୍କୋ+03 - ନୋଭୋକୁନେଚ"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "ଏସିଆ/ନୋଭୋସିବ୍ରିସ୍କ"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "ମୋସ୍କୋ+03 - ନୋଭୋସିବ୍ରିସ୍କ"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "ଏସିଆ/ଓମସ୍କ"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "ମୋସ୍କୋ+03 - ପଶ୍ଚିମ ସାଇବେରିୟା"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "ଏସିଆ/ଓରାଲ"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "ପଶ୍ଚିମ କାଜାଖସ୍ତାନ"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "ଏସିଆ/ନୋମ_ପେନ୍ହ"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "ଏସିଆ/ପୋଣ୍ଟିୟାନକ"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "ପଶ୍ଚିମ ଏବଂ କେନ୍ଦ୍ର ବୋର୍ନିୟୋ"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "ଏସିଆ/ପ୍ଯୋଙ୍ଗୟାଙ୍ଗ"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "ଏସିଆ/କାତର"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "ଏସିଆ/କୈଜୀଲୋରଡା"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "ଖିଜିଲୋରଡା (କିଜିଲୋରଡା, କିଜିଲ-ଓରଡା)"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "ଏସିଆ/ରେଙ୍ଗୁନ"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "ଏସିଆ/ରିୟାଦ"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "ଏସିଆ/ରିୟାଦ87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "ଏସିଆ/ରିୟାଦ88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "ଏସିଆ/ରିୟାଦ89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "ଏସିଆ/ଶୈଗୋନ"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "ଏସିଆ/ସାଖାଲୀନ"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "ମୋସ୍କୋ+07 - ସାଖାଲିନ ଦ୍ବୀପ"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "ଏସିଆ/ସମରକଣ୍ଡ"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "ପଶ୍ଚିମ ଉଜବେକିସ୍ତାନ"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "ଏସିଆ/ସିୟୋଲ"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "ଏସିଆ/ସାଙ୍ଘାଈ"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "ପୂର୍ବ ଚୀନ - ବେଜିଙ୍ଗ, ଗୁଆଙ୍ଗଡୋଙ୍ଗ, ସାଙ୍ଘାଈ, ଇତ୍ଯାଦି।"
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "ଏସିଆ/ସିଙ୍ଗାପୁର"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "ଏସିଆ/ତାଈପେଇ"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "ଏସିଆ/ତାଶକେଂଟ"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "ପୂର୍ବ ଉଜବେକିସ୍ତାନ"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "ଏସିଆ/ତବୀଲିସୀ"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "ଏସିଆ/ତେହରାନ"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "ଏସିଆ/ତେଲ_ଅଭିବ"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "ଏସିଆ/ଥିମବୁ"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "ଏସିଆ/ଥିମ୍ପୁ"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "ଏସିଆ/ଟୋକିୟୋ"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "ଏସିଆ/ଊଜୁଙ୍ଗ_ପନ୍ଦାଙ୍ଗ"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "ଏସିଆ/ଉଲାନବାତର"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "ଏସିଆ/ଉଲାନ_ବାତୋର"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "ଏସିଆ/ଉଋମକୀ"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "ତିବ୍ବତ ଏବଂ ଜିନଜିୟାଙ୍ଗ ର ଅଧିକାଂଶ ଅଞ୍ଚଳ"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "ଏସିଆ/ଭେଟୀୟେନ"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "ଏସିଆ/ଭ୍ଲାଡିବାଷ୍ଟକ"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "ମୋସ୍କୋ+07 - ଅମୁର ନଦୀ"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "ଏସିଆ/ୟକୁଟସ୍କ"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "ମୋସ୍କୋ+06 - ଲୀନା ନଦୀ"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "ଏସିଆ/ୟେକାତରୀନବର୍ଗ"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "ମୋସ୍କୋ+02 - ୟୁରାଲ"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "ଏସିଆ/ୟେରୀଭାନ"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "ଆଟଲାଣ୍ଟିକ/ଅଜୋର୍ସ"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "ଆଜୋରସ"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "ଆଟଲାଣ୍ଟିକ/ବର୍ମୁଡା"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "ଆଟଲାଣ୍ଟିକ/କୈନେରୀ"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "କାନାରୀ ଦ୍ବୀପ"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "ଆଟଲାଣ୍ଟିକ/କେପ_ଭର୍ଦେ"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "ଆଟଲାଣ୍ଟିକ/ଫୈରୋ"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "ଆଟଲାଣ୍ଟିକ/ଫେରୋ"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "ଆଟଲାଣ୍ଟିକ/ଜାନ_ମୟେନ"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "ଆଟଲାଣ୍ଟିକ/ମାଡିରା"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "ମାଡେରା ଦ୍ବୀପ"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "ଆଟଲାଣ୍ଟିକ/ରେକ୍ଜାଭିକ"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "ଆଟଲାଣ୍ଟିକ/ଦକ୍ଷିଣ_ଜେର୍ଜିୟା"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "ଆଟଲାଣ୍ଟିକ/ଷ୍ଟେନଲୀ"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "ଆଟଲାଣ୍ଟିକ/ସେଣ୍ଟ_ହେଲେନା"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "ଆଟଲାଣ୍ଟିକ/ଏ.ସୀ.ଟୀ."
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "ଅଷ୍ଟ୍ରେଲିୟା/ଏଡୀଲେଡ"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "ଦକ୍ଷିଣ ଅଷ୍ଟ୍ରେଲିଆ"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "ଅଷ୍ଟ୍ରେଲିୟା/ବ୍ରିସବେନ"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "କୁଇନ୍ସଲ୍ଯାଣ୍ଡ - ଅଧିକାଂଶ ଅଞ୍ଚଳ"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "ଅଷ୍ଟ୍ରେଲିୟା/ବ୍ରୋକେନ_ହିଲ"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "ନୂତନ ଦକ୍ଷିଣ ୱାଲସ - ୟାନକୋୱିନା"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "ଅଷ୍ଟ୍ରେଲିୟା/କାନବେରା"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "ଅଷ୍ଟ୍ରେଲିୟା/କ୍ଯୁରୀ"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "ତାସ୍ମାନିୟା - କିଙ୍ଗ ଦ୍ବୀପ"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "ଅଷ୍ଟ୍ରେଲିୟା/ଡାରୱିନ"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "ଉତ୍ତରୀୟ ପ୍ରଦେଶ"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "ଅଷ୍ଟ୍ରେଲିୟା/ଇଉକ୍ଲା"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "ପଶ୍ଚିମୀ ଅଷ୍ଟ୍ରେଲିୟା - ଇଉକ୍ଲା ଅଞ୍ଚଳ"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "ଅଷ୍ଟ୍ରେଲିୟା/ହୋବର୍ଟ"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "ତାସ୍ମାନିୟା - ଅଧିକାଂଶ ଅଞ୍ଚଳ"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "ଅଷ୍ଟ୍ରେଲିୟା/ଏଲ.ଏଚ.ଆଇ."
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "ଅଷ୍ଟ୍ରେଲିୟା/ଲିଣ୍ଡେମ୍ଯାନ"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "କୁଇନ୍ସଲ୍ଯାଣ୍ଡ - ହୋଲିଡେ ଦ୍ବୀପ"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "ଅଷ୍ଟ୍ରେଲିୟା/ଲୋର୍ଡ_ହୋଏ"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "ଲର୍ଡ ହାଵ ଦ୍ବୀପ"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "ଅଷ୍ଟ୍ରେଲିୟା/ମେଲବୋର୍ନ"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "ଭିକ୍ଟୋରିୟା"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "ଅଷ୍ଟ୍ରେଲିୟା/ଉତ୍ତର"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "ଅଷ୍ଟ୍ରେଲିୟା/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "ଅଷ୍ଟ୍ରେଲିୟା/ପର୍ଥ"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "ପଶ୍ଚିମି ଅଷ୍ଟ୍ରେଲିଆ - ଅଧିକାଂଶ ଅଞ୍ଚଳ"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "ଅଷ୍ଟ୍ରେଲିୟା/କୁଇନ୍ସଲ୍ଯାଣ୍ଡ"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "ଅଷ୍ଟ୍ରେଲିୟା/ଦକ୍ଷିଣ"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "ଅଷ୍ଟ୍ରେଲିୟା/ସିଡନୀ"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "ନୂତନ ଦକ୍ଷିଣ ୱାଲସ - ଅଧିକାଂଶ ଅଞ୍ଚଳ"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "ଅଷ୍ଟ୍ରେଲିୟା/ତସ୍ମେନିୟା"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "ଅଷ୍ଟ୍ରେଲିୟା/ଭିକ୍ଟୋରିୟା"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "ଅଷ୍ଟ୍ରେଲିୟା/ପଶ୍ଚିମ"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "ଅଷ୍ଟ୍ରେଲିୟା/ୟାନକୋୱିନ୍ନା"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "ବ୍ରାଜିଲ/ଆକ୍ରେ"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "ବ୍ରାଜିଲ/ଡିନୋରୋନା"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "ବ୍ରାଜିଲ/ପୂର୍ବ"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "ବ୍ରାଜିଲ/ପଶ୍ଚିମ"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "କାନାଡା/ଆଟଲାଣ୍ଟିକ"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "କାନାଡା/ମଧ୍ଯ"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "କାନାଡା/ପୂର୍ବୀ"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "କାନାଡା/ପୂର୍ବ-ସାସ୍କଚେବାନ"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "କାନାଡା/ମାଉଣ୍ଟେନ"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "କାନାଡା/ନ୍ଯୁଫାଉଣ୍ଡଲ୍ଯାଣ୍ଡ"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "କାନାଡା/ପେସୀଫିକ"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "କାନାଡା/ସାସ୍କଚେବାନ"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "କାନାଡା/ୟୁକୋନ"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "ଚିଲୀ/କୋଣ୍ଟୀନେଣ୍ଟାଲ"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "ଚିଲୀ/ଇଷ୍ଟରଦ୍ବୀପ"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "କ୍ଯୁବା"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "ମିଶର"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "ଆୟର"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/ଗ୍ରୀନୱିଚ"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/ୟୁନିଭର୍ସଲ"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/ଜୁଲୁ"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "ୟୁରୋପ/ଆମଷ୍ଟରଡାମ"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "ୟୁରୋପ/ଆଣ୍ଡୋରା"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "ୟୁରୋପ/ଏଥେନ୍ସ"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "ୟୁରୋପ/ବେଲଫାଷ୍ଟ"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "ୟୁରୋପ/ବେଲଗ୍ରେଡ"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "ୟୁରୋପ/ବର୍ଲିନ"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "ୟୁରୋପ/ବ୍ରାଟିଶଲୋଭା"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "ୟୁରୋପ/ବୃସେଲ୍ସ"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "ୟୁରୋପ/ବୁଖାରେଷ୍ଟ"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "ୟୁରୋପ/ବୁଡାପେଷ୍ଟ"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "ୟୁରୋପ/ଚିସୀନୋ"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "ୟୁରୋପ/କୋପନହେଗନ"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "ୟୁରୋପ/ଡବ୍ଲିନ"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "ୟୁରୋପ/ଜିବ୍ରାଲ୍ଟର"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "ୟୁରୋପ/ଗୁୟେର୍ନସୀ"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "ୟୁରୋପ/ହେଲସିଙ୍କୀ"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "ୟୁରୋପ/ଇସଲେ_ଅଫ_ମେନ"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "ୟୁରୋପ/ଇସ୍ତାଂବୁଲ"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "ୟୁରୋପ/ଜର୍ସୀ"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "ୟୁରୋପ/କାଲିନୀଗ୍ରାଡ"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "ମୋସ୍କୋ+01 - କାଲୀନିନଗ୍ରାଡ"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "ୟୁରୋପ/କୀବ"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "ୟୁରୋପ/ଲିସବନ"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "ୟୁରୋପ/ଲଜୁବଲଜାନା"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "ୟୁରୋପ/ଲଣ୍ଡନ"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "ୟୁରୋପ/ଲେକ୍ସଂବର୍ଗ"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "ୟୁରୋପ/ମାଦ୍ରିଦ"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "ୟୁରୋପ/ମାଲ୍ଟା"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "ୟୁରୋପ/ମେରୀହାମ"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "ୟୁରୋପ/ମିନସ୍କ"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "ୟୁରୋପ/ମୋନାକୋ"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "ୟୁରୋପ/ମୋସ୍କୋ"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "ମୋସ୍କୋ+00 - ପଶ୍ଚିମ ରୁଷ"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "ୟୁରୋପ/ନିକୋସିୟା"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "ୟୁରୋପ/ଓସଲୋ"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "ୟୁରୋପ/ପାରିସ"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "ୟୁରୋପ/ପୋଡଗୋରିକା"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "ୟୁରୋପ/ପ୍ରାଗ"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "ୟୁରୋପ/ରିଗା"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "ୟୁରୋପ/ରୋମ"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "ୟୁରୋପ/ସାମାରା"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "ମୋସ୍କୋ - ସାମରା, ଉଡମୁର୍ଟିଆ"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "ୟୁରୋପ/ସେନ_ମରୀନୋ"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "ୟୁରୋପ/ସରାଜେଭୋ"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "ୟୁରୋପ/ସିମଫେରୋପୋଲ"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "କେନ୍ଦ୍ରୀୟ କ୍ରୀମିଆ"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "ୟୁରୋପ/ସ୍କପଜେ"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "ୟୁରୋପ/ସୋଫିୟା"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "ୟୁରୋପ/ଷ୍ଟୋକହୋମ"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "ୟୁରୋପ/ତାଲୀନ"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "ୟୁରୋପ/ତିରେନ"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "ୟୁରୋପ/ତିରାସପୋଲ"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "ୟୁରୋପ/ଓଜଗୋରୋଡ"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "ରୁଥେନିୟା"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "ୟୁରୋପ/ବାଡୁଜ"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "ୟୁରୋପ/ଭାଟୀକେନ"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "ୟୁରୋପ/ଭିୟେନା"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "ୟୁରୋପ/ଭିଲନିୟସ"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "ୟୁରୋପ/ଭୋଲ୍ଗୋଗ୍ରାଡ"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "ମୋସ୍କୋ+00 - କାସ୍ପିୟାନ ସାଗର"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "ୟୁରୋପ/ୱିରସୋ"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "ୟୁରୋପ/ଜେଗରୀବ"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "ୟୁରୋପ/ଜପୋରୋଜାଈ"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "ଜାପ୍ରୋଝାୟ, ଇ ଲୁଙ୍ଗାସ୍କ / ଜାପୋରିଝିଆ, ଇ ଲୁହାନସ୍କ"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "ୟୁରୋପ/ଜ୍ଯୁରିଖ"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "କାରଖାନା"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "ଗିଗା-ବାଇଟ"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "ଗିଗା-ବାଇଟ-ଆଇର"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "ଗ୍ରୀନୱିଚ"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "ହଙ୍ଗକଙ୍ଗ"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "ଆଇସଲ୍ଯାଣ୍ଡ"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "ଇଣ୍ଡିଆନ/ଅନ୍ତନାନାରିଭୋ"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "ଇଣ୍ଡିଆନ/ଚାଗୋସ"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "ଇଣ୍ଡିଆନ/କ୍ରିଷ୍ଟମାସ"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "ଇଣ୍ଡିଆନ/କୋକୋସ"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "ଇଣ୍ଡିଆନ/କୋମୋରୋ"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "ଇଣ୍ଡିଆନ/କର୍ଗ୍ଯୁଲେନ"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "ଇଣ୍ଡିଆନ/ମାହେ"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "ଇଣ୍ଡିଆନ/ମାଲଦୀବ"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "ଇଣ୍ଡିଆନ/ମରୀସିୟସ"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "ଇଣ୍ଡିଆନ/ମାୟୋଟ"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "ଇଣ୍ଡିଆନ/ରିୟୁନିୟନ"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "ଇରାନ"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "ଇସ୍ରାଇଲ"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "ଜାମାଈକା"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "ଜାପାନ"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "ଖ୍ବାଜାଲେନ"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "ଲୀବିୟା"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "ମେକ୍ସିକୋ/ବଜନୋର୍ଟ"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "ମେକ୍ସିକୋ/ବଜାସୁର"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "ମେକ୍ସିକୋ/ଜେନେରାଲ"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "ଖାଡୀ/ରିୟାଦ87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "ଖାଡୀ/ରିୟାଦ88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "ଖାଡୀ/ରିୟାଦ89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "ନଭାଜୋ"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "ପେସୀଫିକ/ଏପିୟା"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "ପେସୀଫିକ/ଅକଲ୍ଯାଣ୍ଡ"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "ପେସୀଫିକ/ଚାଥମ"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "ଚାଥାମ ଦ୍ବୀପ"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "ପେସୀଫିକ/ଚୁକ"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "ଚୁକ (ତ୍ରୁକ) ଏବଂ ୟାପ"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "ପେସିଫିକ/ଇଷ୍ଟର"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "ଇଷ୍ଟର ଦ୍ବୀପ ଏବଂ ସାଲା ୟେ ଗୋମିଜ"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "ପେସୀଫିକ/ଇଫେଟ"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "ପେସୀଫିକ/ଇଣ୍ଡରବରୀ"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "ଫୋଏନିକ୍ସ ଦ୍ବୀପ"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "ପେସୀଫିକ/ଫକାଓଫୋ"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "ପେସୀଫିକ/ଫିଜୀ"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "ପେସୀଫିକ/ଫୁନାଫୁଟୀ"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "ପେସୀଫିକ/ଗଲାପଗୋସ"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "ଗାଲାପାଗୋସ ଦ୍ବୀପପୁଞ୍ଜ"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "ପେସୀଫିକ/ଗେମ୍ବିୟର"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "ଗେମ୍ବିଏର ଦ୍ବୀପ"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "ପେସୀଫିକ/ଗୁଆଦଲକାନଲ"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "ପେସୀଫିକ/ଗୁଆମ"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "ପେସୀଫିକ/ହୋନୋଲୁଲୁ"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "ହାୱାଇ"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "ପେସୀଫିକ/ଜନଷ୍ଟୋନ"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "ଜୋନଷ୍ଟୋନ ଆଟୋଲ"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "ପେସୀଫିକ/କିର୍ତୀମତି"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "ଲାଇନ ଦ୍ବୀପପୁଞ୍ଜ"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "ପେସୀଫିକ/କୋସରେ"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "କୋସରେ"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "ପେସୀଫିକ/କ୍ବାଜାଲେନ"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "ପେସୀଫିକ/ମଜୂରା"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "ପେସୀଫିକ/ମାର୍କସାସ"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "ମାର୍କ୍ୟୁସାସ ଦ୍ବୀପ"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "ପେସୀଫିକ/ମିଡୱେ"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "ମିଡୱେ ଦ୍ବୀପ"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "ପେସୀଫିକ/ନୋରୁ"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "ପେସୀଫିକ/ନୀୟୁ"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "ପେସୀଫିକ/ନାରଫୋକ"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "ପେସୀଫିକ/ନାମିୟା"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "ପେସୀଫିକ/ପୈଗୋ_ପୈଗୋ"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "ପେସୀଫିକ/ପଲାଓ"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "ପେସୀଫିକ/ପିଟକେରୀନ"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "ପେସୀଫିକ/ପୋନପେ"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "ପୋନାପେ (ପୋହନାପୀ)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "ପେସୀଫିକ/ପୋନପେ"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "ପେସୀଫିକ/ପର୍ଟ_ମୋର୍ସବୀ"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "ପେସୀଫିକ/ରାରୋତଙ୍ଗା"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "ପେସୀଫିକ/ସାଇପେନ"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "ପେସୀଫିକ/ସମୋଆ"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "ପେସୀଫିକ/ତାହିଟୀ"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "ସୋସାଇଟୀ ଦ୍ବୀପ"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "ପେସୀଫିକ/ତାରାବା"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "ଗିଲବର୍ଟ ଦ୍ବୀପ"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "ପେସୀଫିକ/ଟଙ୍ଗାଟାପୁ"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "ପେସୀଫିକ/ତ୍ରୁକ"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "ପେସୀଫିକ/ୱେକ"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "ଓ୍ବେକ ଦ୍ବୀପ"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "ପେସୀଫିକ/ୱାଲିସ"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "ପେସୀଫିକ/ୟାପ"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "ପୋଲାଣ୍ଡ"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "ପର୍ତୁଗାଲ"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "ପୋସିକ୍ସରୁଲସ"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "ସିଙ୍ଗାପୁର"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "ତୁର୍କୀ"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "ୟୁନିଭର୍ସଲ"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "ଯୁକ୍ତରାଷ୍ଟ୍ର/ଆଲାସ୍କା"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "ଯୁକ୍ତରାଷ୍ଟ୍ର/ଏଲ୍ଯୁସିୟାନ"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "ଯୁକ୍ତରାଷ୍ଟ୍ର/ଏରୀଜୋନା"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "ଯୁକ୍ତରାଷ୍ଟ୍ର/କେନ୍ଦ୍ରୀୟ"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "ଯୁକ୍ତରାଷ୍ଟ୍ର/ପୂର୍ବୀ"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "ଯୁକ୍ତରାଷ୍ଟ୍ର/ପୂର୍ବ-ଇଣ୍ଡିୟାନା"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "ଯୁକ୍ତରାଷ୍ଟ୍ର/ହାୱାଈ"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "ଯୁକ୍ତରାଷ୍ଟ୍ର/ଇଣ୍ଡିୟାନା-ଷ୍ଟାର୍କ"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "ଯୁକ୍ତରାଷ୍ଟ୍ର/ମିସିଗନ"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "ଯୁକ୍ତରାଷ୍ଟ୍ର/ମାଉଣ୍ଟେନ"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "ଯୁକ୍ତରାଷ୍ଟ୍ର/ପେସୀଫିକ"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "ଯୁକ୍ତରାଷ୍ଟ୍ର/ସମୋଆ"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "ଜୁଲୁ"
+
+
diff --git a/panels/datetime/po-timezones/pa.po b/panels/datetime/po-timezones/pa.po
new file mode 100644
index 0000000..dd77004
--- /dev/null
+++ b/panels/datetime/po-timezones/pa.po
@@ -0,0 +1,3239 @@
+# translation of system-config-date.master-timezones.pa.po to Punjabi
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Jaswinder Singh <jsingh@redhat.com>, 2008, 2009, 2010.
+# A S Alam <aalam@users.sf.net>, 2009.
+msgid ""
+msgstr ""
+"Project-Id-Version: system-config-date.master-timezones.pa\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-12-07 10:08+0530\n"
+"Last-Translator: Jaswinder Singh <jsingh@redhat.com>\n"
+"Language-Team: Punjabi/Panjabi <kde-i18n-doc@kde.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: pa\n"
+"X-Generator: Lokalize 1.1\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "ਅਫਰੀਕਾ/ਅਬੀਡਜਾਨ"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "ਅਫਰੀਕਾ/ਅਸੱਰਾ"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "ਅਫਰੀਕਾ/ਅਡੀਸ ਅਬਾਬਾ"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "ਅਫਰੀਕਾ/ਅਲਜੀਰੀਸ"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "ਅਫਰੀਕਾ/ਅਸਮਾਰਾ"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "ਅਫਰੀਕਾ/ਅਸਮੀਰਾ"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "ਅਫਰੀਕਾ/ਬਾਕਾਮੋ"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "ਅਫਰੀਕਾ/ਬਾਨਗੂਈ"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "ਅਫਰੀਕਾ/ਬਿਨਜੂਲ"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "ਅਫਰੀਕਾ/ਬਿਸੱਊ"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "ਅਫਰੀਕਾ/ਬਲਾਨਟਰੀ"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "ਅਫਰੀਕਾ/ਬਰਾਜ਼ਾਵੀਲੀ"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "ਅਫਰੀਕਾ/ਬੂਜ਼ੂਮਬੂਰਾ"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "ਅਫਰੀਕਾ/ਕੀਰੋ"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "ਅਫਰੀਕਾ/ਕਾਸਾਬਲਾਨਾਸਾ"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "ਅਫਰੀਕਾ/ਕੀਊਟਾ"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "ਸੀਊਟਾ ਤੇ ਮੇਲਿਲਾ"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "ਅਫਰੀਕਾ/ਕੋਨਕਰੀ"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "ਅਫਰੀਕਾ/ਡਾਕਾਰ"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "ਅਫਰੀਕਾ/ਡਾਰੀਸ ਅਸ ਸਲਾਮ"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "ਅਫਰੀਕਾ/ਡਜ਼ੀਬੂਅਟੀ"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "ਅਫਰੀਕਾ/ਡੂਊਲਾ"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "ਅਫਰੀਕਾ/ਈਲਆਊਨ"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "ਅਫਰੀਕਾ/ਫਰੀਟਾਉਨ"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "ਅਫਰੀਕਾ/ਗਾਬੋਰੋਨੀ"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "ਅਫਰੀਕਾ/ਹਾਰਾਰੇ"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "ਅਫਰੀਕਾ/ਜਹਾਨਸਬਰਗ"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "ਅਫਰੀਕਾ/ਕੰਪਾਲਾ"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "ਅਫਰੀਕਾ/ਖਰਟੋਮ"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "ਅਫਰੀਕਾ/ਕੀਗਲੀ"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "ਅਫਰੀਕਾ/ਕੀਨਸ਼ਾਸਾ"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "ਪੱਛਮੀ ਡੈਮੋਕਰੇਟਿਕ ਰੀਪਬਲਿਕ ਆਫ ਕੌਂਗੋ"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "ਅਫਰੀਕਾ/ਲਾਗੋਸ"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "ਅਫਰੀਕਾ/ਲੀਬਰੀਵੀਲੀ"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "ਅਫਰੀਕਾ/ਲੋਮੀ"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "ਅਫਰੀਕਾ/ਲੂਡਾ"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "ਅਫਰੀਕਾ/ਲੂਬੂਮਬਸੀ"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "ਪੂਰਬੀ ਡੈਮੋਕਰੇਟਿਕ ਰੀਪਬਲਿਕ ਆਫ ਕੌਂਗੋ"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "ਅਫਰੀਕਾ/ਲੂਸਾਕਾ"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "ਅਫਰੀਕਾ/ਮਾਲਾਬੋ"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "ਅਫਰੀਕਾ/ਮਾਪੂਟੋ"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "ਅਫਰੀਕਾ/ਮਾਸੀਰੂ"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "ਅਫਰੀਕਾ/ਮਬਾਬਾਨੀ"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "ਅਫਰੀਕਾ/ਮੋਗਾਡੀਸ਼ੂ"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "ਅਫਰੀਕਾ/ਮੋਨਰੋਵੀਆ"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "ਅਫਰੀਕਾ/ਨੈਰੋਬੀ"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "ਅਫਰੀਕਾ/ਨਡਜਾਮੀਨਾ"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "ਅਫਰੀਕਾ/ਨਾਮੀ"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "ਅਫਰੀਕਾ/ਨੂਊਕਚੋਟ"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "ਅਫਰੀਕਾ/ਊਗਾਡੋਗੋਊ"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "ਅਫਰੀਕਾ/ਪੋਰਟੋ-ਨੋਵੋ"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "ਅਫਰੀਕਾ/ਸਾਓਟੋਮੀ"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "ਅਫਰੀਕਾ/ਟੀਮਬੂਕਟੂ"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "ਅਫਰੀਕਾ/ਟਰੀਪੋਲੀ"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "ਅਫਰੀਕਾ/ਟੂਨਿਸ਼"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "ਅਫਰੀਕਾ/ਵਿਨਹੋਇਕ"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "ਅਮਰੀਕਾ/ਅਡਾਕ"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "ਅਲੀਊਟੀਅਨ ਆਈਸਲੈਂਡ"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "ਅਮਰੀਕਾ/ਅਨਚੋਰਜ਼ੀ"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "ਅਲਾਸਕਾ ਟਾਈਮ"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "ਅਮਰੀਕਾ/ਅੰਗੋਲਾ"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "ਅਮਰੀਕਾ/ਅੰਟੀਗੁਆ"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "ਅਮਰੀਕਾ/ਆਰਗੂਮੀਆ"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "ਟੋਕਾਨਟਿਨਸ"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "ਅਮਰੀਕਾ/ਅਰਜਨਟੀਨਾ/ਬੂਈਨੋਸ ਏਅਰਸ"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "ਬੂਏਨੋਸ ਏਅਰੀਸ (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "ਅਮਰੀਕਾ/ਅਰਜਨਟੀਨਾ/ਕਾਟਾਮਾਰਸਾ"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "ਕੈਟਾਮਾਰਕਾ (CT), ਚੂਬੂਟ (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "ਅਮਰੀਕਾ/ਅਰਜਨਟੀਨਾ/ਕੋਮੋਡ ਰਿਵਾਡਵੀਆਆਨਾਪੋਲੀਸ"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "ਅਮਰੀਕਾ/ਅਰਜਨਟੀਨਾ/ਕੋਰਡੋਬਾ"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "ਵਧੇਰੇ ਸਥਿਤੀਆਂ (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "ਅਮਰੀਕਾ/ਅਰਜਨਟੀਨਾ/ਜੂਜਈ"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "ਜੂਜੂਏ (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "ਅਮਰੀਕਾ/ਅਰਜਨਟੀਨਾ/ਲਾਰਿਓਜਾੀਆ"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "ਲਾ ਰਿਓਜਾ (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "ਅਮਰੀਕਾ/ਅਰਜਨਟੀਨਾ/ਮਾਨਡੋਜ਼ਾ"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "ਮੈਨਡੋਜ਼ਾ (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "ਅਮਰੀਕਾ/ਅਰਜਨਟੀਨਾ/ਰੀਓ ਗੈਲੀਗੋਸਰੀਨਗੋ"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "ਸਾਂਟਾ ਕਰੂਜ਼ (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "ਅਮਰੀਕਾ/ਅਰਜਨਟੀਨਾ/ਸਾਲਟਾ"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "ਅਮਰੀਕਾ/ਅਰਜਨਟੀਨਾ/ਸੈਨ ਜਾਓਨਗੁਆ"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "ਸੇਨ ਜੂਆਨ (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "ਅਮਰੀਕਾ/ਅਰਜਨਟੀਨਾ/ਸੈਨ_ਲੂਇਸ"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "ਸੈਨ ਲੂਇਸ (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "ਅਮਰੀਕਾ/ਅਰਜਨਟੀਨਾ/ਟੂਕੁਮਾਨਗੁਆ"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "ਟੂਕੂਮੈਨ (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "ਅਮਰੀਕਾ/ਅਰਜਨਟੀਨਾ/ਉਸ਼ੂਈਆੀਆ"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "ਟੀਏਰਾ ਡੇਲ ਫੂਏਗੋ (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "ਅਮਰੀਕਾ/ਅਰੂਬਾ"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "ਅਮਰੀਕਾ/ਅਸੁਨਸੀਨ"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "ਅਮਰੀਕਾ/ਅਟੀਕੋਕਾਨ"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "ਪੂਰਬੀ ਸਟੈਂਡਰਡ ਟਾਈਮ - ਅਟੀਕੋਕਾਨ, ਓਨਟਾਰੀਓ ਅਤੇ ਦੱਖਣ-ਐਮਪਟਨ I, ਨੂਨਾਵੂਟ"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "ਅਮਰੀਕਾ/ਅਟਕਾ"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "ਅਮਰੀਕਾ/ਬਾਹੀਆਸਟਾ"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "ਬਾਹੀਆ"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "ਅਮਰੀਕਾ/ਬਾਹੀਆ_ਬਾਂਡਰਾਸ"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "ਮੈਕਸੀਕਨ ਸੈਂਟਰਲ ਟਾਈਮ - ਬਾਹੀਆ ਡੇ ਬਾਂਡਰਾਸ"
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "ਅਮਰੀਕਾ/ਬਾਰਬਾਡੋਸ"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "ਅਮਰੀਕਾ/ਬੀਲੀਮ"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "ਅਮਾਪਾ, E ਪਾਰਾ"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "ਅਮਰੀਕਾ/ਬੀਲਿਜ਼ੀ"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "ਅਮਰੀਕਾ/ਬਲਾਂਸ-ਸਾਬਲੋਨ"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "ਅਟਲਾਂਟਿਕ ਸਟੈਂਡਰਡ ਟਾਈਮ - ਕੂਈਬੇਕ - ਹੇਠਲਾ ਉੱਤਰੀ ਸ਼ੋਰ"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "ਅਮਰੀਕਾ/ਬੋਵੀਸਟਾ"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "ਰੋਰਾਇਮਾ"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "ਅਮਰੀਕਾ/ਬੋਗੋਟਾ"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "ਅਮਰੀਕਾ/ਬੋਸੀ"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "ਮਾਊਂਨਟੇਨ ਟਾਈਮ - ਦੱਖਣੀ ਇਡਾਹੋ ਤੇ ਪੂਰਬੀ ਓਰੀਗੋਨ"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "ਅਮਰੀਕਾ/ਬੂਈਨੋਸ ਏਅਰਸ"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "ਅਮਰੀਕਾ/ਕਮਬਿਰਿਜ਼ ਖਾੜੀ"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "ਮਾਊਨਟੇਨ ਟਾਈਮ - ਪੱਛਮੀ ਨੂਨਾਵੂਟ"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "ਅਮਰੀਕਾ/ਕੈਂਪੋ ਗਰਾਂਡਾਨ"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "ਮੈਟੋ ਗਰੋਸੋ ਡੂ ਸੂਲ"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "ਅਮਰੀਕਾ/ਕਾਨਕੂਨ"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "ਸੈਂਟਰਲ ਟਾਈਮ - ਕੂਇਨਟਾਨਾ ਰੂ"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "ਅਮਰੀਕਾ/ਕਾਰਾਕਸ"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "ਅਮਰੀਕਾ/ਕਾਟਾਮਾਰਸਾ"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "ਅਮਰੀਕਾ/ਕਾਯੀਨੀ"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "ਅਮਰੀਕਾ/ਕਾਯਮਾਨ"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "ਅਮਰੀਕਾ/ਸ਼ਿਕਾਗੋ"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "ਸੈਂਟਰਲ ਟਾਈਮ"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "ਅਮਰੀਕਾ/ਸ਼ਿਹੂਆਹੂਆ"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "ਮੈਕਸੀਕਨ ਮਾਊਨਟੇਨ ਟਾਈਮ - ਚਿਹੂਆਹੂਆ ਯੂ ਐਸ ਸੀਮਾ ਤੋਂ ਦੂਰ"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "ਅਮਰੀਕਾ/ਕੋਰਲ ਹਾਰਬਰਾਕੋ"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "ਅਮਰੀਕਾ/ਕੋਰਡੋਬਾ"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "ਅਮਰੀਕਾ/ਕੋਸਟਾ ਰੀਸਾ"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "ਅਮਰੀਕਾ/ਕਿਊਬਾ"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "ਮੈਟੋ ਗਰੋਸੋ"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "ਅਮਰੀਕਾ/ਕੂਰਾਕੋ"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "ਅਮਰੀਕਾ/ਡਮਾਰਕਸ਼ਨ"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "ਪੂਰਬੀ ਕੋਆਸਟ, Scoresbysund ਦਾ ਉੱਤਰੀ"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "ਅਮਰੀਕਾ/ਡਾਵਸਨ"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "ਪੈਸੀਫਿਕ ਟਾਈਮ - ਉੱਤਰੀ ਯੂਕੋਨ"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "ਅਮਰੀਕਾ/ਡਾਵਸਨ ਕਰੀਕ"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid "Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr "ਮਾਊਨਟੇਨ ਸਟੈਂਡਰਡ ਟਾਈਮ - ਡਾਵਸਨ ਕਰੀਕ ਤੇ ਫੋਰਟ ਸੇਂਟ ਜੌਹਨ, ਬਰਿਟਸ਼ ਕੋਲੰਬੀਆ"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "ਅਮਰੀਕਾ/ਡੀਨਵਰ"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "ਮਾਊਨਟੇਨ ਟਾਈਮ"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "ਅਮਰੀਕਾ/ਡੀਟਰੋਟੀ"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "ਪੂਰਬੀ ਸਮਾਂ - ਮਿਸ਼ੀਗਨ - ਬਹੁਤੇ ਟਿਕਾਣੇ"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "ਅਮਰੀਕਾ/ਡੋਮੀਨੀਸਾ"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "ਅਮਰੀਕਾ/ਈਡਮੋਨਟੋਨ"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "ਮਾਊਨਟੇਨ ਟਾਈਮ - ਅਲਬੇਰਟਾ, ਪੂਰਬੀ ਬਰਿਟਸ਼ ਕੋਲੰਬੀਆਡਾਵਸਨ ਤੇ ਪੱਛਮੀ ਸਾਸਕਟਚੇਵਨ"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "ਅਮਰੀਕਾ/ਈਰੂਨੀਪੀ"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "W ਐਮਾਜ਼ੋਨਜ"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "ਅਮਰੀਕਾ/ਈਲਸਲਾਵਾਡੋਰ"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "ਅਮਰੀਕਾ/ਇਨਸੀਨਾਡਾ"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "ਅਮਰੀਕਾ/ਫੋਰਟਾਲੀਜ਼ਾ"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "NE ਬਰਾਜ਼ੀਲ (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "ਅਮਰੀਕਾ/ਫੋਰਟ ਬਾਯਨੀ"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "ਅਮਰੀਕਾ/ਗਲਾਸੀ ਖਾੜੀ"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr "ਐਟਲਾਂਟਿਕ ਸਮਾਂ - ਨੋਵਾ ਸਕੋਟੀਆ - ਥਾਂ ਜਿੱਥੇ DST 1966-1971 ਨਹੀਂ ਮਿਲਦਾ"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "ਅਮਰੀਕਾ/ਗੋਡਥਾਬ"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "ਬਹੁਤੇ ਟਿਕਾਣੇ"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "ਅਮਰੀਕਾ/ਗੂਜ਼ ਖਾੜੀ"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "ਐਟਲਾਂਟਿਕ ਸਮਾਂ - ਲੈਬਰੇਡਾਰ - ਵਧੇਰੇ ਸਥਿਤੀਆਂ"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "ਅਮਰੀਕਾ/ਗਰਾਂਡ ਤੁਰਕ"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "ਅਮਰੀਕਾ/ਗਰੀਨਾਡਾ"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "ਅਮਰੀਕਾ/ਗੂਡੀਲੋਊਪੀ"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "ਅਮਰੀਕਾ/ਗੁਆਟਾਮਾਲਾ"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "ਅਮਰੀਕਾ/ਗੁਯਾਕਿਊਲ"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "ਮੇਨਲੈਂਡ"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "ਅਮਰੀਕਾ/ਗੁਆਨਾ"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "ਅਮਰੀਕਾ/ਹਾਲੀਫੇਕਸ"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "ਐਟਲਾਂਟਿਕ ਸਮਾਂ - ਨੋਵਾ ਸਕੋਟੀਆ (ਵਧੇਰੇ ਸਥਿਤੀਆਂ), PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "ਅਮਰੀਕਾ/ਹਾਵਾਨਾ"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "ਅਮਰੀਕਾ/ਹੀਰਮੋਸੀਲੋ"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "ਮਾਊਂਨਟੇਨ ਸਟੈਂਡਰਡ ਸਮਾਂ - ਸੋਨੋਰਾ"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "ਅਮਰੀਕਾ/ਇੰਡੀਆਨਾ/ਇੰਡੀਆਨਾਪੋਲੀਸ"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "ਪੂਰਬੀ ਸਮਾਂ - ਇੰਡਿਆਨਾ - ਵਧੇਰੇ ਸਥਿਤੀਆਂ"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "ਅਮਰੀਕਾ/ਇੰਡੀਆਨਾ/ਕਨੋਸ਼"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "ਸੈਂਟਰਲ ਸਮਾਂ - ਇੰਡਿਆਨਾ - ਸਟਾਰਕੇ ਦੇਸ"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "ਅਮਰੀਕਾ/ਇੰਡੀਆਨਾ/ਮਰੀਨਗੋ"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "ਪੂਰਬੀ ਸਮਾਂ - ਇੰਡਿਆਨਾ - ਕਰਾਓਫੋਰਡ ਦੇਸ"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "ਅਮਰੀਕਾ/ਇੰਡੀਆਨਾ/ਪੀਟਰਸਬਰਗ"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "ਪੂਰਬੀ ਸਮਾਂ - ਇੰਡਿਆਨਾ - ਪਾਈਰ ਦੇਸ"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "ਅਮਰੀਕਾ/ਇੰਡੀਆਨਾਪੋਲੀਸ"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "ਅਮਰੀਕਾ/ਇੰਡਿਆਨਾ/ਟੈੱਲ_ਸਿਟੀ"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "ਸੈਂਟਰਲ ਟਾਈਮ - ਇੰਡਿਆਨਾ - ਪੈਰੀ ਦੇਸ"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "ਅਮਰੀਕਾ/ਇੰਡੀਆਨਾ/ਵੀਵਾਆ"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "ਪੂਰਬੀ ਸਮਾਂ - ਇੰਡਿਆਨਾ - ਸਵਿਜ਼ਰਲੈਂਡ ਦੇਸ"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "ਅਮਰੀਕਾ/ਇੰਡੀਆਨਾ/ਵੀਨਸੀਨਸ"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "ਪੂਰਬੀ ਸਮਾਂ - ਇੰਡਿਆਨਾ - ਡਾਵੀਏਸ, ਡੂਬੋਇਸ, ਕਨੋਕਸ ਤੇ ਮਾਰਟਿਨ ਦੇਸ"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "ਅਮਰੀਕਾ/ਇੰਡੀਆਨਾ/ਵੀਨਾਮੈਕ"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "ਪੂਰਬੀ ਸਮਾਂ - ਇੰਡਿਆਨਾ - ਪੂਲਾਸਕੀ ਦੇਸ"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "ਅਮਰੀਕਾ/ਇਨੂਵਿਕ"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "ਮਾਊਨਟੇਨ ਟਾਈਮ - ਪੱਛਮੀ ਉੱਤਰ-ਪੱਛਮੀ ਸ਼ਾਸ਼ਤ-ਪ੍ਰਦੇਸ"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "ਅਮਰੀਕਾ/ਇਊਲੂਟ"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "ਪੂਰਬੀ ਸਮਾਂ - ਪੂਰਬੀ ਨੂਨਾਵਟ - ਵਧੇਰੇ ਸਥਿਤੀਆਂ"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "ਅਮਰੀਕਾ/ਜੈਮਿਕਾ"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "ਅਮਰੀਕਾ/ਜੂਜਈ"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "ਅਮਰੀਕਾ/ਹੂਨਿਆਉ"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "ਅਲਾਸਕਾ ਟਾਈਮ - ਅਲਾਸਕਾ ਪਾਨਹੈਂਡਲ"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "ਅਮਰੀਕਾ/ਕੀਨਟੂਕੀ/ਲੂੳਸਵਿਲੀ"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "ਪੂਰਬੀ ਸਮਾਂ - ਕੀਨਟੂਕੀ - ਲੂੳਸਵਿਲੀ ਖੇਤਰ"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "ਅਮਰੀਕਾ/ਕੀਨਟੂਕੀ/ਮੋਨਟੀਸੀਲੋ"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "ਪੂਰਬੀ ਸਮਾਂ - ਕੀਨਟੂਕੀ - ਵਾਯਨੇ ਦੇਸ"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "ਅਮਰੀਕਾ/ਕਨੂਸ਼ ਇਨ"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "ਅਮਰੀਕਾ/ਲਾ ਪਾਜ਼"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "ਅਮਰੀਕਾ/ਲੀਮਾ"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "ਅਮਰੀਕਾ/ਲਾਸ ਏਜ਼ਲਸ"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ ਸਮਾਂ"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "ਅਮਰੀਕਾ/ਲੂਇਸਵਿਲੀ"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "ਅਮਰੀਕਾ/ਮਸੀਈ"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "ਅਲਾਗੋਆਸ, ਸੇਰਗਿਪੇ"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "ਅਮਰੀਕਾ/ਮਾਨਾਗੂਨਾ"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "ਅਮਰੀਕਾ/ਮਾਨਾਸ"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "ਈ ਐਮਾਜ਼ੋਨਸ"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "ਅਮਰੀਕਾ/ਮੈਰੀਗੋਟ"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "ਅਮਰੀਕਾ/ਮਾਰੀਟੀਕਿਊ"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "ਅਮਰੀਕਾ/ਮੈਟਾਮੋਰੋਸ"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid "US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr "ਯੂ ਐਸ ਸੈਂਟਰਲ ਟਾਈਮ - ਕੋਆਹੂਇਲਾ, ਡੂਰਾਂਗੋ, ਨੂਏਵੋ ਲੀਓਨ, ਟਾਮਾਊਲਿਪਸ ਯੂ ਐਸ ਸੀਮਾ ਦੇ ਨੇੜੇ"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "ਅਮਰੀਕਾ/ਮਾਜ਼ਾਟਲਾਨ"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "ਮਾਊਨਟੇਨ ਟਾਈਮ - ਐਸ ਬਾਜਾ, ਨਾਯਾਰਿਟ, ਸਿਨਾਲੋਆ"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "ਅਮਰੀਕਾ/ਮਾਨਡੋਜ਼ਾ"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "ਅਮਰੀਕਾ/ਮੀਨੋਮੀਨਈ"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "ਸੈਂਟਰਲ ਸਮਾਂ - ਮਿਚੀਗਨ - ਡਿਕਿਨਸਨ, ਜੀਗੈਬਿਕ, ਆਇਰਨ ਤੇ ਮੇਨੋਮਿਨੀ ਦੇਸ"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "ਅਮਰੀਕਾ/ਮੀਰਾਡਾ"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "ਸੈਂਟਰਲ ਟਾਈਮ - ਕੈਂਪੇਚੇ, ਯੂਕਾਟਨ"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "ਅਮਰੀਕਾ/ਮੈਕਸੀਕਿ ਸ਼ਹਿਰ"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "ਸੈਂਟਰਲ ਸਮਾਂ - ਬਹੁਤੇ ਟਿਕਾਣੇ"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "ਅਮਰੀਕਾ/ਮੀਕਊਇਲੋਨ"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "ਅਮਰੀਕਾ/ਮੋਨਸਟੋਨ"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "ਐਟਲਾਂਟਿਕ ਸਮਾਂ - ਨਿਊ ਬਰੂਨਸਵਿਕ"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "ਅਮਰੀਕਾ/ਮੋਨਟੀਰੀਓ"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr "ਮੈਕਸੀਕਨ ਸੈਂਟਰਲ ਟਾਈਮ - ਕੋਆਹੂਇਲਾ, ਡੂਰਾਂਗੋ, ਨੂਏਵੋ ਲੀਓਨ, ਟਾਮਾਊਲਿਪਸ ਯੂ ਐਸ ਸੀਮਾਂ ਤੋਂ ਦੂਰ"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "ਅਮਰੀਕਾ/ਮੋਨਟੀਵੀਡਿਓ"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "ਅਮਰੀਕਾ/ਮੋਨਟਰੀਲ"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "ਪੂਰਬੀ ਸਮਾਂ - ਕਿਊਬਕ - ਬਹੁਤੇ ਟਿਕਾਣੇ"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "ਅਮਰੀਕਾ/ਮੋਨਟਸੀਰੇਟ"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "ਅਮਰੀਕਾ/ਨੀਸਾਊ"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "ਅਮਰੀਕਾ/ਨਿਊ ਯਾਰਕ"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "ਪੂਰਬੀ ਸਮਾਂ"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "ਅਮਰੀਕਾ/ਨੀਪੀਗੋਨ"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid "Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr "ਪੂਰਬੀ ਸਮਾਂ - ਉਨਟਾਰੀਓ ਤੇ ਕੂਏਬੇਕ - ਸਥਿਤੀ ਜਿੱਥੇ DST 1967-1973 ਨਹੀਂ ਮਿਲਦੇ"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "ਅਮਰੀਕਾ/ਨੋਮੀ"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "ਅਲਾਸਕਾ ਸਮਾਂ - ਪੱਛਮੀ ਅਲਾਸਕਾ"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "ਅਮਰੀਕਾ/ਨੋਰੋਹਾ"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "ਐਟਲਾਟਿਕ ਟਾਪੂ"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "ਅਮਰੀਕਾ/ਉਤਰੀ ਡਾਕੋਟਾ/ਕੇਦਰੀ"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "ਸੈਂਟਰਲ ਸਮਾਂ - ਉੱਤਰੀ ਡੀਕੋਟਾ - ਓਲਿਵਰ ਦੇਸ"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "ਅਮਰੀਕਾ/ਉਤਰੀ ਡਾਕੋਟਾ/ਨਵਾਂਸਾਲੀਮ"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "ਸੈਂਟਰਲ ਸਮਾਂ - ਉੱਤਰੀ ਡੀਕੋਟਾ - ਮੌਰਟੋਨ ਦੇਸ (ਮੰਡਾਨ ਖੇਤਰ ਤੋਂ ਬਿਨਾਂ)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "ਅਮਰੀਕਾ/ਊਜੀਨਾਗਾ"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "ਯੂ ਐਸ ਮਾਊਨਟੇਨ ਟਾਈਮ - ਚਿਹੂਆਹੂਆ ਯੂ ਐਸ ਸੀਮਾਂ ਦੇ ਨੇੜੇ"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "ਅਮਰੀਕਾ/ਪੈਮਾਨਾ"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "ਅਮਰੀਕਾ/ਪਿਨਗਨੀਰਟੂਗ"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "ਪੂਰਬੀ ਸਮਾਂ - ਪੈਂਗਨਿਰਟੂੰਗ, ਨੂਨਾਵਟ"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "ਅਮਰੀਕਾ/ਪਾਰਾਮਾਰੀਬੋ"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "ਅਮਰੀਕਾ/ਫੋਨਿਸ਼"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "ਮਾਊਂਟੇਨ ਸਟੈਂਡਰਡ ਟਾਈਮ - ਅਰੀਜ਼ੋਨਾ"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "ਅਮਰੀਕਾ/ਪੋਰਟ-ਅਸ-ਪ੍ਰਿੰਸ"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "ਅਮਰੀਕਾ/ਪੋਰਟੋ ਅਸਰੀ"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "ਅਮਰੀਕਾ/ਪੋਰਟ ਆਫ ਸਪੇਨ"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "ਅਮਰੀਕਾ/ਪੋਰਟੋ ਵੀਲਹੋ"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "ਰੋਨਡੋਨੀਆ"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "ਅਮਰੀਕਾ/ਪੋਟਟੋ ਰੀਕੋ"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "ਅਮਰੀਕਾ/ਰੇਨੀ ਰੀਵਰ"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "ਸੈਂਟਰਲ ਟਾਈਮ - ਰੈਨੀ ਰਿਵਰ ਤੇ ਫੋਰਟ ਫਰਾਂਸ, ਓਨਟਾਰੀਓ"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "ਅਮਰੀਕਾ/ਰੈਨਿਕਿਨ ਇਨਲਿਟ"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "ਸੈਂਟਰਲ ਸਮਾਂ - ਕੇਂਦਰੀ ਨੂਨਾਵਟ"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "ਅਮਰੀਕਾ/ਰੀਸਾਈਸ"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "ਪੇਰਨਾਮਬੂਕੋ"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "ਅਮਰੀਕਾ/ਰੀਗੀਨਾ"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "ਸੈਂਟਰਲ ਸਟੈਂਡਰਡ ਟਾਈਮ - ਸਾਸਕਟਚੇਵਨ - ਵਧੇਰੇ ਸਥਿਤੀਆ"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "ਅਮਰੀਕਾ/ਰੌੰੋਲੂਟ"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "ਪੂਰਬੀ ਸਟੈਂਡਰਡ ਟਾਈਮ - ਰੈਜ਼ੋਲੂਟ, ਨੂਨਾਵਟ"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "ਅਮਰੀਕਾ/ਰਾਈ ਬਰਾਸਕੋ"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "ਏਕਰ"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "ਅਮਰੀਕਾ/ਰੋਸਾਰੀਉ"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "ਅਮਰੀਕਾ/ਸਾਂਟਾ_ਈਸੇਬਲ"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "ਮੈਕਸੀਕਨ ਪੈਸੀਫਿਕ ਟਾਈਮ - ਬਾਜਾ ਕੈਲੇਫੋਰਨੀਆਂ ਯੂ ਐਸ ਸੀਮਾਂ ਤੋਂ ਦੂਰ"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "ਅਮਰੀਕਾ/ਸੰਟੋਆਗੋ"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "W ਪਾਰਾ"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "ਅਮਰੀਕਾ/ਸੰਟੋਆਗੋ"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "ਅਮਰੀਕਾ/ਸੰਟੋ ਡੋਮੀਨਗੋ"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "ਅਮਰੀਕਾ/ਸਾਊ ਪਾਲੋ"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "S & SE ਬਰਾਜ਼ੀਲ (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "ਅਮਰੀਕਾ/ਸਕਰੋਸਬਸ਼ੂਡ"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "ਸਕੋਰਸਬਾਈਸਾਊਂਡ / ਇਟੋਕੋਰਟੂਰਮਿਟ"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "ਅਮਰੀਕਾ/ਸ਼ਿਪਰੋਕ"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "ਮਾਊਨਟੇਨ ਟਾਈਮ - ਨਵਾਜੋ"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "ਅਮਰੀਕਾ/ਸਟਬਾਰਥੇਲੇਮੀ"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "ਅਮਰੀਕਾ/ਸੇਟ ਜੋਨਸ"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "ਨਿਊਫਾਊਂਡਲੈਂਡ ਟਾਈਮ, SE ਲੈਬਰੇਡਾਰ ਸਮੇਤ"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "ਅਮਰੀਕਾ/ਸੇਟ ਕੀਟਸ"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "ਅਮਰੀਕਾ/ਸੇਟ ਲੂਸੀਕਾ"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "ਅਮਰੀਕਾ/ਸੇਟ ਥਾਮਸ"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "ਅਮਰੀਕਾ/ਸੇਟ ਵੀਨਸੇਟ"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "ਅਮਰੀਕਾ/ਸਵਿਫਟ ਕਰੰਟ"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "ਸੈਂਟਰਲ ਸਟੈਂਡਰਡ ਸਮਾਂ - ਸਾਸਕਟਚੇਵਨ - ਮੱਧ-ਪੱਛਮੀ"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "ਅਮਰੀਕਾ/ਟੀਗੂਸੀਗਾਲਪਾ"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "ਅਮਰੀਕਾ/ਥੂਲੀ"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "ਥੂਲੇ / ਪਿਟੂਫਿਕ"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "ਅਮਰੀਕਾ/ਥੰਡਰ ਖਾੜੀ"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "ਪੂਰਬੀ ਸਮਾਂ - ਥੰਡਰ ਬੇ, ਓਟਾਰੀਓ"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "ਅਮਰੀਕਾ/ਤੀਜ਼ੂਨਾ"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "ਯੂ ਐਸ ਪੈਸੀਫਿਕ ਟਾਈਮ - ਬਾਜਾ ਕੈਲੈਫੋਰਨੀਆ ਯੂ ਐਸ ਸੀਮਾ ਦੇ ਨੇੜੇ"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "ਅਮਰੀਕਾ/ਟੋਰਾਂਟੋਲਾ"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "ਪੂਰਬੀ ਸਮਾਂ - ਓਟਾਰੀਓ - ਬਹੁਤੇ ਟਿਕਾਣੇ"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "ਅਮਰੀਕਾ/ਟੋਰਟੋਲਾ"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "ਅਮਰੀਕਾ/ਵੇਨਸੋਵਰ"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "ਪੈਸੀਫਿਕ ਟਾਈਮ - ਪੱਛਮੀ ਬਰਿਟਸ਼ ਕੋਲੰਬੀਆ"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "ਅਮਰੀਕਾ/ਵਰਜੀਨੀਆ"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "ਅਮਰੀਕਾ/ਵਾਈਟਹਾਰਸ"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "ਪੈਸੀਫਿਕ ਟਾਈਮ - ਦੱਖਣੀ ਯੂਕੋਨ"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "ਅਮਰੀਕਾ/ਵੀਨਿਪੇਗ"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "ਸੈਂਟਰਲ ਟਾਈਮ - ਮਾਨੀਟੋਬਾ ਤੇ ਪੱਛਮੀ ਓਨਟਾਰੀਆ"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "ਅਮਰੀਕਾ/ਯਾਕੂਟਾਟ"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "ਅਲਾਸਕਾ ਟਾਈਮ - ਅਲਾਸਕਾ ਪਾਨਹੈਂਡਲ ਨੈੱਟ"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "ਅਮਰੀਕਾ/ਯੈਲੂਨਿਫ"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "ਮਾਊਨਟੇਨ ਟਾਈਮ - ਸੈਂਟਰਲ ਉੱਤਰੀ-ਪੱਛਮੀ ਸ਼ਾਸ਼ਕ-ਪ੍ਰਦੇਸ"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "ਅੰਟਰਾਟਿਕਾ/ਕੰਸੀ"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "ਕੇਸੇਈ ਸਟੇਸ਼ਨ, ਬੈਲੇ ਪੈਨਿਨਸੂਲਾ"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "ਅੰਟਰਾਟਿਕਾ/ਡਾਵਿਸ"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "ਡੇਵਿਸ ਸਟੇਸ਼ਨ, ਵੈਸਟਫੋਲਡ ਹਿੱਲਸ"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "ਅੰਟਰਾਟਿਕਾ/ਡੋਮੋਨਟਡਯਰਵਿਲੀ"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "ਡੂਮੌਂਟ-d' ਊਰਵਿਲੇ ਸਟੇਸ਼ਨ, ਟੇਰੇ ਐਡੇਲੀਏ"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "ਅੰਟਰਾਟਿਕਾ/ਮੈਕਕੁਆਰੀ"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "ਮੈਕਕੂਆਰੀ ਆਈਸਲੈਂਡ ਸਟੇਸ਼ਨ, ਮੈਕਕੂਆਰੀ ਆਈਸਲੈਂਡ"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "ਅੰਟਰਾਟਿਕਾ/ਮਾਵਸੋਨ"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "ਮਾਵਸੋਨ ਸਟੇਸ਼ਨ, ਹੋਲਮੇ ਬੇ"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "ਅੰਟਰਾਟਿਕਾ/ਮਕਮੂਰਡੋ"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "ਮਕਮੂਰਡੂ ਸਟੇਸ਼ਨ, ਰੋਸ ਆਈਸਲੈਂਡ"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "ਅੰਟਰਾਟਿਕਾ/ਪਾਲਮਾਰ"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "ਪਾਲਮਰ ਸਟੇਸ਼ਨ, ਅਨਵੇਰਸ ਆਈਸਲੈਂਡ"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "ਅੰਟਰਾਟਿਕਾ/ਰੋਥੇਰਾਰੁਵ"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "ਰੋਥੇਰਾ ਸਟੇਸ਼ਨ, ਐਡੀਲੇਡ ਆਈਸਲੈਂਡ"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "ਅੰਟਰਾਟਿਕਾ/ਦੱਖਣੀ ਧਰੁਵ"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "ਅਮੂੰਡਸੇਨ-ਸਕੌਟ ਸਟੇਸ਼ਨ, ਦੱਖਣੀ ਧੁਰਾ"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "ਅੰਟਰਾਟਿਕਾ/ਸਯੂਵਾ"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "ਸਯੋਵਾ ਸਟੇਸ਼ਨ, E ਉਨਗੂਲ I"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "ਅੰਟਰਾਟਿਕਾ/ਵੋਸਟੋਕ"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "ਵੋਸਟੋਕ ਸਟੇਸ਼ਨ, S ਮੈਗਨਿਟ ਧੁਰਾ"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "ਅਰਸਟਿਕ/ਲਾਗਯਿਅਰਬਯਾਨ"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "ਏਸ਼ੀਆ/ਅਦਾਨ"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "ਏਸ਼ੀਆ/ਅਲਮਾਟੀ"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "ਏਸ਼ੀਆ/ਅਮਾਨ"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "ਏਸ਼ੀਆ/ਅਨਾਡੀਰ"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "ਮਾਸਕੋ+08 - ਬੇਰਿੰਗ ਸਮੁੰਦਰ"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "ਏਸ਼ੀਆ/ਅਕਿਊਟ"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "ਅਟਯਰਾਊ (ਅਟੀਰਾਊ, Gur'yev), ਮੰਘੇਸਟਾਊ (ਮਾਨਕਿਸਟਾਊ)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "ਏਸ਼ੀਆ/ਅਕਿਊਬੀ"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "ਅਕਟੋਬੇ (ਅਕਟੋਬੇ)"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "ਏਸ਼ੀਆ/ਅਸ਼ਗੲਬਾਤ"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "ਏਸ਼ੀਆ/ਅਕਸ਼ਖਾਬਾਦ"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "ਏਸ਼ੀਆ/ਬਗਦਾਦ"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "ਏਸ਼ੀਆ/ਬਹਿਰਾਨ"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "ਏਸ਼ੀਆ/ਬਾਕੂ"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "ਏਸ਼ੀਆ/ਬੈਕਾਂਕ"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "ਏਸ਼ੀਆ/ਬੀਰੂਟ"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "ਏਸ਼ੀਆ/ਬਿਸਕਾਕ"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "ਏਸ਼ੀਆ/ਬਰੂਨੀ"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "ਏਸ਼ੀਆ/ਕਲਕੱਤਾ"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "ਏਸ਼ੀਆ/ਚੋਬਾਲਸਾਨ"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "ਡੋਰਨੋਡ, ਸੁਖਬਾਟਰ"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "ਏਸ਼ੀਆ/ਚੋਨਕਿੳਇੰਗ"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "ਸੈਂਟਰਲ ਚੀਨ - ਸਿਚੁਆਨ, ਯੂਨਾਨ, ਗੂਆਂਗਕਸੀ, ਸ਼ਾਂਕਸੀ, ਗੂਇਜ਼ਹੋਊ, ਆਦਿ।"
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "ਏਸ਼ੀਆ/ਚੰਗਕਿੰਗ"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "ਏਸ਼ੀਆ/ਕੋਲੰਬੋ"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "ਏਸ਼ੀਆ/ਡਾਸੀਆ"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "ਏਸ਼ੀਆ/ਡਾਮਸਾਊਸ"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "ਏਸ਼ੀਆ/ਢਾਕਾ"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "ਏਸ਼ੀਆ/ਦੀਲੀ"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "ਏਸ਼ੀਆ/ਡੁਬਈ"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "ਏਸ਼ੀਆ/ਡੂਸ਼ਾਨਬੀ"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "ਏਸ਼ੀਆ/ਗਾਜ਼ਾ"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "ਏਸ਼ੀਆ/ਹਰਬਿਨ"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "ਹੇਇਲੌਂਗਜੀਆਂਗ (ਮੋਹੇ ਤੋਂ ਬਿਨਾਂ), ਜਿਲਿਨ"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "ਏਸ਼ੀਆ/ਚੋਨਕਿੳਇੰਗ"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "ਏਸ਼ੀਆ/ਹਾਂਗਕਾਂਗ"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "ਏਸ਼ੀਆ/ਹੋਵਡ"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "ਬਾਯਾਨ-ਉਲਗਿਯੇ, ਗੋਵੀ-ਅਲਟਾਈ, ਹੋਵਡ, ਉਵਸ, ਜ਼ਾਵਖਾਨ"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "ਏਸ਼ੀਆ/ਆਈਰਲੂਸਕ"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "ਮਾਸਕੋ+05 - ਲਾਕੇ ਬੈਕਾਲ"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "ਏਸ਼ੀਆ/ਇਸਟਤਾਲਬੁਲ"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "ਏਸ਼ੀਆ/ਜੈਕਾਰਤਾ"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "ਜਾਵਾ ਤੇ ਸੁਮਾਤਰਾ"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "ਏਸ਼ੀਆ/ਜਾਇਪੁਰ"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "ਇਰਿਆਨ ਜਾਯਾ ਚੇ ਮੋਲੂਕਾਸ"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "ਏਸ਼ੀਆ/ਜ਼ੇਰੂਸ਼ੇਲਮ"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "ਏਸ਼ੀਆ/ਕਾਬਲ"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "ਏਸ਼ੀਆ/ਕਾਮਚਾਟਕਾ"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "ਮਾਸਕੋ+08 - ਕਾਮਚਾਟਕਾ"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "ਏਸ਼ੀਆ/ਕਰਾਚੀ"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "ਏਸ਼ੀਆ/ਕਾਸ਼ਗਰ"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "ਪੱਛਮੀ ਟਿਬੇਟ ਤੇ ਜ਼ਿਨਜਿਆਂਗ"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "ਏਸ਼ੀਆ/ਕਾਂਠਮਾਡੂ"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "ਏਸ਼ੀਆ/ਕਾਂਠਮਾਡੂ"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "ਏਸ਼ੀਆ/ਕੋਲਕਾਤਾ"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "ਏਸ਼ੀਆ/ਕਰਸਨੀਯਾਰਸ਼ਕ"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "ਮਾਸਕੋ+04 - ਯੇਨੀਸੇਈ ਰਿਵਰ"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "ਏਸ਼ੀਆ/ਕੁੰਆਲਾਮਪੁਰ"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "ਪੇਨਿਨਸੂਲਾਰ ਮਲੇਸ਼ੀਆ"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "ਏਸ਼ੀਆ/ਕੋਚੀਇੰਗ"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "ਸਾਬਾਹ ਤੇ ਸਾਰਾਵਾਕ"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "ਏਸ਼ੀਆ/ਕੁਵੈਤ"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "ਏਸ਼ੀਆ/ਮਾਸੀਕੋ"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "ਏਸ਼ੀਆ/ਮਾਸਕੁ"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "ਏਸ਼ੀਆ/ਮਾਗਾਡਾਨ"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "ਮਾਸਕੋ+08 - ਮਾਗਾਡਨ"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "ਏਸ਼ੀਆ/ਮਾਕਾਸਾਰ"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "ਪੂਰਬ ਤੇ ਦੱਖਣ ਬੋਰਨੇਓ, ਸੇਲੇਬੇਸ, ਬਾਲੀ, ਨੂਸਾ ਟੇਂਗਾਰਾ, ਪੱਛਮ ਟਿਮੋਰ"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "ਏਸ਼ੀਆ/ਮਾਨੀਲਾ"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "ਏਸ਼ੀਆ/ਮਾਸਕਟ"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "ਏਸ਼ੀਆ/ਨੀਸੋਸੀਆ"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "ਏਸ਼ੀਆ/ਨੋਵੋਕੂਜ਼ਨੇਟਸਕ"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "ਮਾਸਕੋ+03 - ਨੋਵੋਕੂਜ਼ਨੇਟਸਕ"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "ਏਸ਼ੀਆ/ਨੋਵੋਸੀਬੀਰਸਕ"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "ਮਾਸਕੋ+03 - ਨੋਵੋਸੀਬੀਰਸਕ"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "ਏਸ਼ੀਆ/ਓਮਸਕ"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "ਮਾਸਕੋ+03 - ਪੱਛਮੀ ਸਾਈਬੇਰੀਆ"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "ਏਸ਼ੀਆ/ਓਰਾਲ"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "ਪੱਛਮੀ ਕਜ਼ਾਖਸਤਾਨ"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "ਏਸ਼ੀਆ/ਫਨੋਮਪੇਨਹ"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "ਏਸ਼ੀਆ/ਪੋਨਰਿਨਕ"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "ਪੱਛਮੀ ਅਤੇ ਕੇਂਦਰੀ ਬੋਰਨੋ"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "ਏਸ਼ੀਆ/ਪਯੂਨਗਯਾਂਗ"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "ਏਸ਼ੀਆ/ਕਤਰ"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "ਏਸ਼ੀਆ/ਕਿਊਜ਼ਲੋਰਡਾ"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "ਕਯਜ਼ਾਈਲੋਰਡਾ (Kyzylorda, Kzyl-Orda)"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "ਏਸ਼ੀਆ/ਰੰਗੂਨ"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "ਏਸ਼ੀਆ/ਰੀਯਾਧ"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "ਏਸ਼ੀਆ/ਰੀਯਾਧ੮੭"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "ਏਸ਼ੀਆ/ਰੀਯਾਧ੮੮"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "ਏਸ਼ੀਆ/ਰੀਯਾਧ੮੯"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "ਏਸ਼ੀਆ/ਸਾਈਗੋਨ"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "ਏਸ਼ੀਆ/ਸਾਖਾਲੀਨ"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "ਮਾਸਕੋ+07 - ਸਾਖਾਲਿਨ ਆਈਸਲੈਂਡ"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "ਏਸ਼ੀਆ/ਸਮਕੰਦ"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "ਪੱਛਮੀ ਉਜ਼ੇਬਕਸਤਾਨ"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "ਏਸ਼ੀਆ/ਸਿਊਲ"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "ਏਸ਼ੀਆ/ਸਿੰਘਾਈ"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "ਪੂਰਬੀ ਚੀਨ - ਬੀਜ਼ਿੰਗ, ਗਾਂਗਡੋਗ, ਸ਼ਿੰਘਾਈ ਆਦਿ"
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "ਏਸ਼ੀਆ/ਸਿੰਘਾਪੁਰ"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "ਏਸ਼ੀਆ/ਤਾਈਪੀ"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "ਏਸ਼ੀਆ/ਤਾਸ਼ਕੰਦ"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "ਪੂਰਬੀ ਉਜ਼ੇਬਕਸਤਾਨ"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "ਏਸ਼ੀਆ/ਤਬੀਲੀਸੀ"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "ਏਸ਼ੀਆ/ਤਹਿਰਾਨ"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "ਏਸ਼ੀਆ/ਤੀਲਅਵਾਵ"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "ਏਸ਼ੀਆ/ਥੀਮਬੂ"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "ਏਸ਼ੀਆ/ਥੀਮਫੂ"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "ਏਸ਼ੀਆ/ਟੋਕੀਓ"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "ਏਸ਼ੀਆ/ਊਜ਼ੰਗ ਪਾਨਡਿੰਗ"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "ਏਸ਼ੀਆ/ਊਲਾਨਬਾਟਰ"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "ਏਸ਼ੀਆ/ਅਲਾਨਬਾਟੋਰ"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "ਏਸ਼ੀਆ/ੳਰੂਮਕੀ"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "ਬਹੁਤਾ ਤਿੱਬਤ ਅਤੇ ਜ਼ਿੰਜਾਂਗ"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "ਏਸ਼ੀਆ/ਵੀਅਤਨਾਮ"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "ਏਸ਼ੀਆ/ਵਲਾਡੀਵੋਸਟੋਕ"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "ਮਾਸਕੋ+07 - ਅਮੂਰ ਰਿਵਰ"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "ਏਸ਼ੀਆ/ਯਾਕੂਸਕ"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "ਮਾਸਕੋ+06 - ਲੇਨਾ ਰਿਵਰ"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "ਏਸ਼ੀਆ/ਯਾਕਟਾਇਬਰਗ"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "ਮਾਸਕੋ+02 - ਯੂਰਾਲ"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "ਏਸ਼ੀਆ/ਯਾਰੀਵਾਨ"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "ਐਟਲਾਟਿਕ/ਅਜ਼ੋਰਸ"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "ਅਜ਼ੋਰੇਸ"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "ਐਟਲਾਟਿਕ/ਬਾਰਾਮੂਡਾ"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "ਐਟਲਾਟਿਕ/ਕੰਨਰੀ"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "ਕੈਨਾਰੇ ਆਈਸਲੈਂਡ"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "ਐਟਲਾਟਿਕ/ਕੇਪ ਵਰਡੀ"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "ਐਟਲਾਟਿਕ/ਫਾਰੋਈ"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "ਐਟਲਾਂਟਾ/ਫਾਰੋਈ"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "ਐਟਲਾਟਿਕ/ਜਾਨ ਮਾਯਾਨ"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "ਐਟਲਾਟਿਕ/ਮਾਡਰੀਆ"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "ਮਾਡੇਇਰਾ ਆਈਸਲੈਂਡ"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "ਐਟਲਾਟਿਕ/ਰਾਯਕਾਜੋਵਿਕ"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "ਐਟਲਾਟਿਕ/ਦੱਖਣੀ ਜਾਰਜੀਆ"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "ਐਟਲਾਟਿਕ/ਸਟਨਲਿਆ"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "ਐਟਲਾਟਿਕ/ਸੇਟ ਹੀਲੀਨਾ"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "ਅਸਟਰੇਲੀਆ/ਏਸੀਟੀ"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "ਅਸਟਰੇਲੀਆ/ਐਂਡੀਲੈਂਡ"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "ਦੱਖਣੀ ਆਸਟਰੇਲੀਆ"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "ਅਸਟਰੇਲੀਆ/ਬਰਿਸਬੇਨ"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "ਕਿਊਂਜ਼ਲੈਂਡ - ਬਹੁਤੇ ਟਿਕਾਣੇ"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "ਅਸਟਰੇਲੀਆ/ਬਰੋਕਨ ਹਿਲ"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "ਨਿਊਜ਼ ਸਾਊਂਥ ਵੇਲਜ਼ - ਯਾਨਕੋਵਿਨਾ"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "ਅਸਟਰੇਲੀਆ/ਕੈਨਬਰਾ"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "ਅਸਟਰੇਲੀਆ/ਕੁੱਰਿਰਾ"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "ਤਸਮਾਨੀਆ - ਕਿੰਗ ਟਾਪੂ"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "ਅਸਟਰੇਲੀਆ/ਡਾਰਵਿਨ"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "ਉੱਤਰੀ ਖਿੱਤਾ"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "ਆਸਟਰੇਲੀਆ/ਇਊਕਲਾ"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "ਪੱਛਮੀ ਆਸਟਰੇਲੀਆ - ਇਊਕਲਾ ਖੇਤਰ"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "ਅਸਟਰੇਲੀਆ/ਹੋਬਰਟ"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "ਤਸਮਾਨੀਆ - ਬਹੁਤੇ ਟਿਕਾਣੇ"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "ਅਸਟਰੇਲੀਆ/ਐਲਐਚਆਈ"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "ਅਸਟਰੇਲੀਆ/ਲਿੰਡੀਮਾਨ"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "ਕਿਊਂਜ਼ਲੈਂਡ - ਹਾਲੀਡੇ ਟਾਪੂ"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "ਆਸਟਰੇਲੀਆ/ਲੋਰਡ ਹੋਵੀ"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "ਲੋਰਡ ਹੋਵੇ ਟੂਪ"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "ਅਸਟਰੇਲੀਆ/ਮੈਲਬੋਰਨ"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "ਵਿਕਟੋਰੀਆ"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "ਅਸਟਰੇਲੀਆ/ਉੱਤਰੀ"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "ਅਸਟਰੇਲੀਆ/ਐਨਐਸਡਬਲਿਊ"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "ਅਸਟਰੇਲੀਆ/ਪਰਥ"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "ਪੱਛਮੀ ਆਸਟਰੇਲੀਆ - ਬਹੁਤੇ ਟਿਕਾਣਾ"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "ਅਸਟਰੇਲੀਆ/ਕਿਊਂਜ਼ਲੈਡ"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "ਅਸਟਰੇਲੀਆ/ਦੱਖਣੀ"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "ਅਸਟਰੇਲੀਆ/ਸਿਡਨੀ"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "ਨਿਊਜ਼ ਸਾਊਂਥ ਵੇਲਜ਼ - ਬਹੁਤੇ ਟਿਕਾਣੇ"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "ਅਸਟਰੇਲੀਆ/ਤਸਮਾਨੀਆ"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "ਅਸਟਰੇਲੀਆ/ਵਿਕਟੋਰੀਆ"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "ਅਸਟਰੇਲੀਆ/ਪੱਛਮੀ"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "ਅਸਟਰੇਲੀਆ/ਯਾਨਕੂਵੀਨਾ"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "ਬਰਾਜ਼ੀਲ਼/ਅਸਰੀ"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "ਬਰਾਜ਼ੀਲ਼/ਡੀਨੋਟੋਹਾ"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "ਬਰਾਜ਼ੀਲ਼/ਪੂਰਬੀ"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "ਬਰਾਜ਼ੀਲ਼/ਪੱਛਮੀ"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "ਕੈਨੇਡਾ/ਐਟਲਾਇਕ"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "ਕੈਨੇਡਾ/ਕੇਦਰੀ"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "ਕੈਨੇਡਾ/ਪੂਰਬੀ"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "ਕੈਨੇਡਾ/ਪੂਰਬੀ-ਸਾਕਚੋਵਾਨ"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "ਕੈਨੇਡਾ/ਪਹਾੜੀ"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "ਕੈਨੇਡਾ/ਨਿਊਫਾਊਡਲੈਡ"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "ਕੈਨੇਡਾ/ਪ੍ਰਸ਼ਾਂਤ"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "ਕੈਨੇਡਾ/ਸਾਕੋਚਵਾਨ"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "ਕੈਨੇਡਾ/ਯੂਕੋਨ"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "ਚਿੱਲੀ/ਕੋਟੀਡੈਟਿਲ"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "ਚਿੱਲੀ/ਈਸਟਰ ਟਾਪੂ"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "ਕਿਊਬਾ"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "ਮਿਸਰ"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "ਈਰਿ"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "ਈਟੀਸੀ/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "ਈਟੀਸੀ/GMT"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "ਈਟੀਸੀ/GMT-੦"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "ਈਟੀਸੀ/GMT+੦"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "ਈਟੀਸੀ/GMT-੧"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "ਈਟੀਸੀ/GMT+੧"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "ਈਟੀਸੀ/GMT-੧੦"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "ਈਟੀਸੀ/GMT+੧੦"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "ਈਟੀਸੀ/GMT-੧੧"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "ਈਟੀਸੀ/GMT+੧੧"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "ਈਟੀਸੀ/GMT-੧੨"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "ਈਟੀਸੀ/GMT+੧੨"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "ਈਟੀਸੀ/GMT-੧੩"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "ਈਟੀਸੀ/GMT-੧੪"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "ਈਟੀਸੀ/GMT-੨"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "ਈਟੀਸੀ/GMT+੨"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "ਈਟੀਸੀ/GMT-੩"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "ਈਟੀਸੀ/GMT+੩"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "ਈਟੀਸੀ/GMT-੪"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "ਈਟੀਸੀ/GMT+੪"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "ਈਟੀਸੀ/GMT-੫"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "ਈਟੀਸੀ/GMT+੫"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "ਈਟੀਸੀ/GMT-੬"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "ਈਟੀਸੀ/GMT+੬"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "ਈਟੀਸੀ/GMT-੭"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "ਈਟੀਸੀ/GMT+੭"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "ਈਟੀਸੀ/GMT-੮"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "ਈਟੀਸੀ/GMT+੮"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "ਈਟੀਸੀ/GMT-੯"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "ਈਟੀਸੀ/GMT+੯"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "ਈਟੀਸੀ/ਗਰੀਨਵਿੱਚ"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "ਈਟੀਸੀ/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "ਈਟੀਸੀ/ਯੂਨੀਵਰਸਲ"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "ਈਟੀਸੀ/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "ਈਟੀਸੀ/ਜ਼ੂਲੂ"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "ਯੂਰਪ/ਅਮਸਟੀਡਮ"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "ਯੂਰਪ/ਐਨਡੋਰਾ"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "ਯੂਰਪ/ਐਥਨਜ਼"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "ਯੂਰਪ/ਬੀਲਫਾਸਟ"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "ਯੂਰਪ/ਬੀਲਗਰੇਡ"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "ਯੂਰਪ/ਬਰਲਿਨ"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "ਯੂਰਪ/ਬਰਾਟੀਸਲਾਵਾ"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "ਯੂਰਪ/ਬਰੂਸੀਲਸ"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "ਯੂਰਪ/ਬੂਚਰਸਟ"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "ਯੂਰਪ/ਬੁਡਾਪੈਸਟ"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "ਯੂਰਪ/ਚੀਸੀਨੂ"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "ਯੂਰਪ/ਕੋਪੀਨਹਾਗਨ"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "ਯੂਰਪ/ਡੂਬਲਿਨ"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "ਯੂਰਪ/ਗਿਬਰਲਟਾਰ"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "ਯੂਰਪ/ਗੁਈਰਨਸ"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "ਯੂਰਪ/ਹੀਲਸੀਨਕੀ"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "ਯੂਰਪ/ਇਸਲੀ_ਆਫ_ਮੈਨ"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "ਯੂਰਪ/ਇਸਟਾਨਬੂਲ"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "ਯੂਰਪ/ਜਰਸੀ"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "ਯੂਰਪ/ਕਾਲੀਨੀਗਰਾਡ"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "ਮਾਸਕੋ-01 - ਕਾਲਿੰਗਰਾਡ"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "ਯੂਰਪ/ਕੀਵ"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "ਯੂਰਪ/ਲਿਸਬੋਨ"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "ਯੂਰਪ/ਲਜਬਲੀਜਾਨਾ"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "ਯੂਰਪ/ਲੰਡਨ"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "ਯੂਰਪ/ਲਕਸ਼ਬਰਗ"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "ਯੂਰਪ/ਮਾਡਰੀਡ"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "ਯੂਰਪ/ਮਾਲਟਾ"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "ਯੂਰਪ/ਮੈਰੀਹਾਮੀਡ"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "ਯੂਰਪ/ਮੀਸਸ਼"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "ਯੂਰਪ/ਮੋਨਾਕੋ"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "ਯੂਰਪ/ਮਾਸਕੋ"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "ਮਾਸਕੋ+00 - ਪੱਛਮੀ ਰੂਸ"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "ਯੂਰਪ/ਨੀਕੋਸੀਆ"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "ਯੂਰਪ/ਓਸਲੋ"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "ਯੂਰਪ/ਪੈਰਿਸ"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "ਯੂਰਪ/ਪੋਡਗੋਰੀਸਾ"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "ਯੂਰਪ/ਪਰਗੂਈ"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "ਯੂਰਪ/ਰੀਗਾ"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "ਯੂਰਪ/ਰੋਮ"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "ਯੂਰਪ/ਸਾਮਾਰਾ"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "ਮਾਸਕੋ - ਸਾਮਾਰਾ, ਉਡਮੂਰਟੀਆ"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "ਯੂਰਪ/ਸਾਨਮਾਰੀਨੋ"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "ਯੂਰਪ/ਸਾਰਰਜੀਵੋ"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "ਯੂਰਪ/ਸਾਮੀਫਰੋਪੋਲ"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "ਸੈਂਟਰਲ ਕਰੀਮੀਆ"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "ਯੂਰਪ/ਸਕੋਪਜੀ"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "ਯੂਰਪ/ਸੋਫੀਆ"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "ਯੂਰਪ/ਸਟੋਕਖੋਲਮ"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "ਯੂਰਪ/ਟਾਲੀਨ"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "ਯੂਰਪ/ਈਰਆਨੀ"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "ਯੂਰਪ/ਤੀਰਸਪੋਲ"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "ਯੂਰਪ/ੳਜ਼ਹੋਰੋਡ"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "ਰੂਟੇਨੀਆ"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "ਯੂਰਪ/ਵਾਡੂਜ਼"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "ਯੂਰਪ/ਵਾਟੀਕਾਨ"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "ਯੂਰਪ/ਵੀਆਨਾ"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "ਯੂਰਪ/ਵੀਲਨੀਅਸ"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "ਯੂਰਪ/ਵੋਲਗੋਗਰਾਡ"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "ਮਾਸਕੋ+00 - ਕੈਸਪੀਅਨ ਸਮੁੰਦਰ"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "ਯੂਰਪ/ਵਾਟਸਾ"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "ਯੂਰਪ/ਜਾਗਰਬ"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "ਯੂਰਪ/ਜਾਪੋਰਪੋਜ਼ਈ"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "ਯੂਰਪ/ਜ਼ੂਰਿਸ਼"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "ਫੈਕਟਰੀ"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Eire"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "ਗਰੀਨਵਿੱਚ"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "ਹਾਂਗਕਾਂਗ"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "ਆਈਲੈਡ"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "ਇੰਡੀਆ/ਅਨੀਆਨਾਰੀਵੋ"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "ਇੰਡੀਆ/ਸ਼ਿਗੋਸ"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "ਇੰਡੀਆ/ਕ੍ਰਿਸ਼ਮਿਸ"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "ਇੰਡੀਆ/ਸੀਸੀਸ"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "ਇੰਡੀਆ/ਕੰਮੋਰੋ"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "ਇੰਡੀਆ/ਕਾਰਗੂਈਲੀਨ"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "ਇੰਡੀਆ/ਮਾਹੀ"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "ਇੰਡੀਆ/ਮਾਲਦੀਪ"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "ਇੰਡੀਆ/ਮਾਊਰਟੀਸ"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "ਇੰਡੀਆ/ਮਾਇਆਟੀ"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "ਇੰਡੀਆ/ਰੀਯੂਨਨ"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "ਈਰਾਨ"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "ਇਜ਼ਰਾਈਲ"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "ਜੈਮਿਕਾ"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "ਜਾਪਾਨ"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "ਕਯਾਜਾਲਿਨ"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "ਲੀਬੀਆ"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "ਮੈਕਸੀਕੋ/ਬਾਜ਼ਾਨੋਰਟੀ"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "ਮੈਕਸੀਕੋ/ਬਾਜ਼ਾਸੁਰ"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "ਮੈਕਸੀਕੋ/ਆਮ"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "ਮੱਧ-ਪੂਰਬੀ/ਰੀਯਾਡ੮੭"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "ਮੱਧ-ਪੂਰਬੀ/ਰੀਯਾਡ੮੮"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "ਮੱਧ-ਪੂਰਬੀ/ਰੀਯਾਡ੮੯"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "ਨਾਵਾਜੋ"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਅਪੀਆ"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਆਕਲੈਡ"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਚਾਥਾਮ"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "ਚਾਥਾਮ ਆਈਸਲੈਂਡ"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਚੂਕ"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "ਚੂਕ (ਟਰੁਕ) ਅਤੇ ਯਾਪ"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਈਸਟਰ"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "ਪੂਰਬੀ ਆਈਸਲੈਂਡ ਤੇ ਸਾਲਾ y ਗੋਮੇਜ਼"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਈਫੇਟ"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਐਡੀਰਬੁਰੀ"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "ਫੋਨਿਕਸ ਆਈਸਲੈਂਡ"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਫਾਕਾਉਫੁ"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਫਿਜ਼ੀ"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਫੂਨਾਫੁਟੀ"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਗਾਲਾਪਾਗੋਸ"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "ਗਾਲਾਪਾਗੋਸ ਆਈਸਲੈਂਡ"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਗਾਮਬੀਰ"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "ਗੈਂਬੀਅਰ ਆਈਸਲੈਂਡ"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਗੂਡਾਲਕਨਾਲ"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਗੂਆਮ"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਹੋਨੋਲੂਲੂ"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "ਹਾਵਾਈ"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਜਾਨਸਟੋਨ"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "ਜੋਹਨਸਟੋਨ ਅਟੋਲ"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਕੀਰਮੀਸਟੀ"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "ਲੇਨ ਟਾਪੂ"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਕੋਸਰਆ"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "ਕੋਸਰਏ"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਕਵਾਜਾਲੀਨਿ"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਮਾਜੋਰੂ"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਮਾਰੀਸ਼ਸ਼"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "ਮਾਰਕੂਈਸਾਸ ਆਈਸਲੈਂਡ"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਮਿਡਵੇ"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "ਮਿਡਵੇ ਟਾਪੂ"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਨਊਰੂ"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਨੀਊਈ"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਨੋਫੋਕ"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਨੁਊਮਇਆ"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਪਾਗੋ ਪਾਗੋ"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਪੀਲੀਉ"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਪਿਟਸਾਰਨ"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਪੋਨਾਪੀ"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "ਪੋਨਾਪੇ (ਪੋਹਨਪੇਈ)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਪੋਨਾਪੀ"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਪੋਰਟ ਮੋਰਸਬਾਏ"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਰਾਰੋਟੋਗਾ"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਸਾਈਪਾਨ"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਸਾਮੋਆ"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਤਾਹੀਟੀ"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "ਸੋਸਾਇਟੀ ਟਾਪੂ"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਤਰਵਾ"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "ਗਿਲਬਰਟ ਟਾਪੂ"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਟੋਨਗਾਟਾਪੂ"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਤੁਰਕ"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਵਾਕਾ"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "ਵੇਕ ਟਾਪੂ"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਵਾਲਿਸ਼"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "ਪ੍ਰਸ਼ਾਂਤ/ਯਾਪ"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "ਪੋਲੈਂਡ"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "ਪੁਰਤਗਾਲ"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "ਸਿੰਘਾਪੁਰ"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "ਤੁਰਕੀ"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "ਸੰਸਾਰ"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "ਅਮਰੀਕਾ/ਅਲਾਸਕਾ"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "ਅਮਰੀਕਾ/ਅਲੀਊਸਤਾਨ"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "ਅਮਰੀਕਾ/ਐਰੀਜੋਨਾ"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "ਅਮਰੀਕਾ/ਕੇਂਦਰੀ"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "ਅਮਰੀਕਾ/ਪੂਰਬੀ"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "ਅਮਰੀਕਾ/ਪੂਰਬੀ-ਇੰਡੀਆਨਾ"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "ਅਮਰੀਕਾ/ਹਾਵਾਈ"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "ਅਮਰੀਕਾ/ਇੰਡੀਆਨਾ-ਸਟਾਰਕੇ"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "ਅਮਰੀਕਾ/ਮਿਸ਼ੀਗਨ"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "ਅਮਰੀਕਾ/ਪਹਾੜੀ"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "ਅਮਰੀਕਾ/ਪ੍ਰਸ਼ਾਂਤ"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "ਅਮਰੀਕਾ/ਸਾਮੋਨਾ"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "ਜ਼ੂਲੂ"
+
+
diff --git a/panels/datetime/po-timezones/pl.po b/panels/datetime/po-timezones/pl.po
new file mode 100644
index 0000000..3ec8b6b
--- /dev/null
+++ b/panels/datetime/po-timezones/pl.po
@@ -0,0 +1,3259 @@
+# Polish translation for timezones.
+# Copyright © 2004, 2008, 2017 the timezones authors.
+# This file is distributed under the same license as the timezones package.
+# Radosław Zawartko <radzaw@lnet.szn.pl>, 2004.
+# Piotr Drąg <piotrdrag@gmail.com>, 2008, 2017.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2017-08-23 02:42+0200\n"
+"Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n"
+"Language-Team: Polish <trans-pl@lists.fedoraproject.org>\n"
+"Language: pl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Afryka/Abidżan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Afryka/Akra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Afryka/Addis_Abeba"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Afryka/Algier"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "Afryka/Asmara"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Afryka/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Afryka/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Afryka/Bangi"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Afryka/Bandźul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Afryka/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Afryka/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Afryka/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Afryka/Bużumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Afryka/Kair"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Afryka/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Afryka/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "Ceuta i Melilla"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Afryka/Konakri"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Afryka/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Afryka/Dar_es-Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Afryka/Dżibuti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Afryka/Duala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Afryka/Al-Ujun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Afryka/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Afryka/Gaborne"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Afryka/Harara"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Afryka/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Afryka/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Afryka/Chartum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Afryka/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Afryka/Kinszasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "Zachodnia Demokratyczna Republika Konga"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Afryka/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Afryka/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Afryka/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Afryka/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Afryka/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "Wschodnia Demokratyczna Republika Konga"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Afryka/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Afryka/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Afryka/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Afryka/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Afryka/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Afryka/Mogadiszu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Afryka/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Afryka/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Afryka/Ndżamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Afryka/Niamej"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Afryka/Nawakszut"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Afryka/Wagadugu"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Afryka/Porto_Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Afryka/São_Tomé"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Afryka/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Afryka/Trypolis"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Afryka/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Afryka/Windhuk"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Ameryka/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Wyspy Aleuckie"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Ameryka/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Czas Alaski"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Ameryka/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Ameryka/Antiqua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Ameryka/Araguaína"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "Tocantins"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Ameryka/Argentyna/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Buenos Aires (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Ameryka/Argentyna/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "Catamarca (CT), Chubut (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Ameryka/Argentyna/Comodoro_Rivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Ameryka/Argentyna/Kordowa"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "większość lokalizacji (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Ameryka/Argentyna/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Jujuy (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Ameryka/Argentyna/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "La Rioja (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Ameryka/Argentyna/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "Mendoza (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Ameryka/Argentyna/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "Santa Cruz (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "Ameryka/Argentyna/Salta"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Ameryka/Argentyna/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "San Juan (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "Ameryka/Argentyna/San_Luis"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "San Luis (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Ameryka/Argentyna/Tucumán"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "Tucuman (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Ameryka/Argentyna/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "Ziemia Ognista (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Ameryka/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Ameryka/Asunción"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Ameryka/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "Wschodni czas standardowy — Atikokan, Ontario i Southampton I, Nunavut"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Ameryka/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Ameryka/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "Bahia"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "Ameryka/Bahia_Banderas"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "Meksykański czas centralny — Bahia de Banderas"
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Ameryka/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Ameryka/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "Amapa, wschodnie Para"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Ameryka/Belize"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "Ameryka/Blanc-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "Atlantycki czas standardowy — Quebec — Lower North Shore"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Ameryka/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "Roraima"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Ameryka/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Ameryka/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "Czas górski — południowe Idaho i wschodni Oregon"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Ameryka/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Ameryka/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "Czas górski — zachodnie Nunavut"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "Ameryka/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "Mato Grosso do Sul"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Ameryka/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "Czas centralny — Quintana Roo"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Ameryka/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Ameryka/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Ameryka/Kajenna"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Ameryka/Kajmany"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Ameryka/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "Czas centralny"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Ameryka/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "Meksykański czas górski — Chihuahua poza granicą Stanów Zjednoczonych"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "Ameryka/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Ameryka/Kordowa"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Ameryka/Kostaryka"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Ameryka/Cuiabá"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "Mato Grosso"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Ameryka/Curacao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Ameryka/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "wschodnie wybrzeże, północ od Scoresbysund"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Ameryka/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "Czas pacyficzny — północny Jukon"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Ameryka/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+"Górski czas standardowy — Dawson Creek i Fort Saint John, Kolumbia Brytyjska"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Ameryka/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "Czas górski"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Ameryka/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "Czas wschodni — Michigan — większość lokalizacji"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Ameryka/Dominika"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Ameryka/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+"Czas górski — Alberta, wschodnia Kolumbia Brytyjska i zachodnie Saskatchewan"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Ameryka/Eirunepé"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "Zachodnia Amazonia"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Ameryka/Salwador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Ameryka/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Ameryka/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "Północno-wschodnia Brazylia (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Ameryka/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Ameryka/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+"Czas atlantycki — Nowa Szkocja — miejsca niekorzystające z DST w latach "
+"1966-1971"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Arktyka/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "większość lokalizacji"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Ameryka/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "Czas atlantycki — Labrador — większość lokalizacji"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Ameryka/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Ameryka/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Ameryka/Gwadelupa"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Ameryka/Gwatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Ameryka/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "główny ląd"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Ameryka/Gujana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Ameryka/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "Czas atlantycki — Nowa Szkocja (większość miejsc), PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Ameryka/Hawana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Ameryka/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "Górski czas standardowy — Sonora"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Ameryka/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "Czas wschodni — Indiana — większość lokalizacji"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Ameryka/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "Czas centralny — Indiana — hrabstwo Starke"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Ameryka/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "Czas wschodni — Indiana — hrabstwo Crawford"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "Ameryka/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "Czas wschodni — Indiana — hrabstwo Pike"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Ameryka/Indianapolis"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "Ameryka/Indiana/Tell_City"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "Czas centralny — Indiana — hrabstwo Perry"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Ameryka/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "Czas wschodni — Indiana — hrabstwo Switzerland"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "Ameryka/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "Czas wschodni — Indiana — hrabstwa Daviess, Dubois, Knox i Martin"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "Ameryka/Indiana/Winamac"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "Czas wschodni — Indiana — hrabstwo Pulaski"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Ameryka/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "Czas górski — wschodnie Terytoria Północno-Zachodnie"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Ameryka/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "Czas wschodni — wschodnie Nunavut — większość lokalizacji"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Ameryka/Jamajka"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Ameryka/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Ameryka/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "Czas Alaski — korytarz alaskański"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Ameryka/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Czas wschodni — Kentucky — obszar Louisville"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Ameryka/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "Czas wschodni — Kentucky — hrabstwo Wayne"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Ameryka/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Ameryka/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Ameryka/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Ameryka/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "Czas pacyficzny"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Ameryka/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Ameryka/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "Alagoas, Sergipe"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Ameryka/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Ameryka/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "Wschodnia Amazonia"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "Ameryka/Marigot"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Ameryka/Martynika"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "Ameryka/Matamoros"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+"Czas centralny Stanów Zjednoczonych — Coahuila, Durango, Nuevo Leon, "
+"Tamaulipas w pobliżu granicy Stanów Zjednoczonych"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Ameryka/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "Czas górski — południowe Baja, Nayarit, Sinaloa"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Ameryka/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Ameryka/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+"Czas centralny — Michigan — hrabstwa Dickinson, Gogebic, Iron i Menominee"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Ameryka/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "Czas centralny — Campeche, Jukatan"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Ameryka/Meksyk"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "Czas centralny — większość lokalizacji"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Ameryka/Miquelon"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "Ameryka/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "Czas atlantycki — Nowy Brunszwik"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Ameryka/Moterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+"Meksykański czas centralny — Coahuila, Durango, Nuevo Leon, Tamaulipas poza "
+"granicą Stanów Zjednoczonych"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Ameryka/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Ameryka/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "Czas wschodni — Quebec — większość lokalizacji"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Ameryka/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Ameryka/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Ameryka/Nowy_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "Czas wschodni"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Ameryka/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+"Czas wschodni — Ontario i Quebec — miejsca niekorzystające z DST w latach "
+"1967-1973"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Ameryka/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "Czas Alaski — zachodnia Alaska"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Ameryka/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "Wyspy atlantyckie"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Ameryka/Dakota_Północna/Centrum"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "Czas centralny — Dakota Północna — hrabstwo Oliver"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "Ameryka/Dakota_Północna/New_Salem"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+"Czas centralny — Dakota Północna — hrabstwo Morton (poza obszarem Mandan)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "Ameryka/Ojinaga"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+"Czas górski Stanów Zjednoczonych — Chihuahua w pobliżu granicy Stanów "
+"Zjednoczonych"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Ameryka/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Ameryka/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "Czas wschodni — Pangnirtung, Nunavut"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Ameryka/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Ameryka/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "Górski czas standardowy — Arizona"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Ameryka/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Ameryka/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Ameryka/Port-of-Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Ameryka/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "Rondonia"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Ameryka/Portoryko"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Ameryka/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "Czas centralny — Rainy River i Fort Frances, Ontario"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Ameryka/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "Czas centralny — centralne Nunavut"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Ameryka/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "Pernambuco"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Ameryka/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "Centralny czas standardowy — Saskatchewan — większość lokalizacji"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "Ameryka/Resolute"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "Wschodni czas standardowy — Resolute, Nunavut"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Ameryka/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "Acre"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Ameryka/Rosario"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "Ameryka/Santa_Isabel"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+"Meksykański czas pacyficzny — Baja California poza granicą Stanów "
+"Zjednoczonych"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "Ameryka/Santarem"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "Zachodnie Para"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Ameryka/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Ameryka/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Ameryka/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+"Południowa i południowo-wschodnia Brazylia (GO, DF, MG, ES, RJ, SP, PR, SC, "
+"RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Arktyka/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "Scoresbysund/Ittoqqortoormiit"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Ameryka/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "Czas górski — Navajo"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "Ameryka/St_Barthelemy"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Ameryka/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "Czas nowofundlandzki, w tym południowo-wschodni Labrador"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Ameryka/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Ameryka/St_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Ameryka/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Ameryka/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Ameryka/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "Centralny czas standardowy — Saskatchewan — środkowy zachód"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Ameryka/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Ameryka/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "Thule/Pituffik"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Ameryka/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "Czas wschodni — Thunder Bay, Ontario"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Ameryka/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+"Czas pacyficzny Stanów Zjednoczonych — Baja California w pobliżu granicy "
+"Stanów Zjednoczonych"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "Ameryka/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "Czas wschodni — Ontario — większość lokalizacji"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Ameryka/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Ameryka/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "Czas pacyficzny — zachodnia Kolumbia Brytyjska"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Ameryka/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Ameryka/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "Czas pacyficzny — południowy Jukon"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Ameryka/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "Czas centralny — Manitoba i zachodnie Ontario"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Ameryka/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "Czas Alaski — korytarz alaskański"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Ameryka/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "Czas górski — centralne Terytoria Północno-Zachodnie"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antarktyda/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "Stacja Casey, półwysep Bailey"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antarktyda/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "Stacja Davis, Vestfold Hills"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antarktyda/Dumont d’Urville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "Stacja Dumont-d’Urville, Terre Adelie"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "Antarktyda/Macquarie"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "Stacja Macquarie Island, Wyspa Macquarie"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antarktyda/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "Stacja Mawson, zatoka Holme"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antarktyda/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "Stacja McMurdo, Wyspa Rossa"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antarktyda/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "Stacja Palmera, Wyspy Anvers"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antarktyda/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "Stacja Rothera, Wyspy Królowej Adelajdy"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antarktyda/Biegun_Południowy"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "Stacja Amundsena i Scotta, biegun południowy"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antarktyda/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "Stacja Syowa, wschodni Ongul I"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antarktyda/Wostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "Stacja Wostok, południowy biegun magnetyczny"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Arktyka/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Azja/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Azja/Ałma Ata"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Azja/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Azja/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "Moskwa+08 — Morze Beringa"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Azja/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "Atyrau (Atirau, Gurjew), Mangghystau (Mankistau)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Azja/Aktobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "Aktobe (Aktiubińsk)"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Azja/Aszchabad"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Azja/Aszchabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Azja/Bagdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Azja/Bahrajn"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Azja/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Azja/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Azja/Bejrut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Azja/Biszkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Azja/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Azja/Kalkuta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Azja/Czojbalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "Ajmak wschodni, Suche Bator"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Azja/Czungcing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "Środkowe Chiny — Syczuan, Yunnan, Guangxi, Shaanxi, Guizhou itp."
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Azja/Chongqing"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Azja/Kolombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Azja/Dhaka"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Azja/Damaszek"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Azja/Dhaka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Azja/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Azja/Dubaj"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Azja/Duszanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Azja/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Azja/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "Heilongjiang (poza Mohe), Jilin"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Azja/Ho_Chi_Minh"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Azja/Hongkong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Azja/Kobdo"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "Ajmak bajanolgijski, gobijsko-ałtajski, kobdoski, uwski, dzawchański"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Azja/Irkuck"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Moskwa+05 — Jezioro Bajkał"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Azja/Stambuł"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Azja/Dżakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "Jawa i Sumatra"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Azja/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "Jaya i Moluccas irańskie"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Azja/Jerozolima"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Azja/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Azja/Kamczatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "Moskwa+08 — Kamczatka"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Azja/Karaczi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Azja/Kaszgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "zachodni Tybet i Sinciang"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "Azja/Katmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Azja/Katmandu"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "Azja/Kalkuta"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Azja/Krasnojarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "Moskwa+04 — Rzeka Jenisej"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Azja/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "Półwysep Malajski"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Azja/Kuczing"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "Sabah i Sarawak"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Azja/Kuwejt"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Azja/Makao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Azja/Makau"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Azja/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "Moskwa+08 — Magadan"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Azja/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+"Wschodnie i południowe Borneo, Celebes, Bali, Nusa Tengarra, zachodni Timor"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Azja/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Azja/Maskat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Azja/Nikozja"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "Azja/Nowokuźnieck"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Moskwa+03 — Nowokuźnieck"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Azja/Nowosybirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Moskwa+03 — Nowosybirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Azja/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "Moskwa+03 — zachodnia Syberia"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Azja/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "Zachodni Kazachstan"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Azja/Phnom_Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Azja/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "Zachodnie i środkowe Borneo"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Azja/Pjongjang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Azja/Katar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Azja/Kyzyłorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "Kyzyłorda (Kyzył-Orda, Kzył-Orda)"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Azja/Rangun"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Azja/Rijad"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Azja/Rijad87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Azja/Rijad88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Azja/Rijad89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Azja/Sajgon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Azja/Sachalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "Moskwa+07 — Wyspa Sachalin"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Azja/Samarkanda"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "Zachodni Uzbekistan"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Azja/Seul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Azja/Szanghaj"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "wschodnie Chiny — Pekin, Guangdong, Szanghaj itp."
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Azja/Singapur"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Azja/Tajpej"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Azja/Taszkient"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "Wschodni Uzbekistan"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Azja/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Azja/Teheran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Azja/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Azja/Thimphu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Azja/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Azja/Tokio"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Azja/Ujung_Pandag"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Azja/Ułan Bator"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Azja/Ułan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Azja/Urumczi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "Większość Tybetu i Sinciang"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Azja/Wientian"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Azja/Władywostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "Moskwa+07 — Rzeka Amur"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Azja/Jakuck"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "Moskwa+06 — Rzeka Lena"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Azja/Jekaterynburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "Moskwa+02 — Góry Ural"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Azja/Erewan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlantyk/Azory"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "Azory"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlantyk/Bermudy"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlantyk/Kanary"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "Wyspy Kanaryjskie"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlantyk/Wyspy_Zielonego_Przylądka"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlantyk/Wyspy_Owcze"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "Atlantyk/Wyspy_Owcze"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlantyk/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlantyk/Madera"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "Wyspy Madera"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlantyk/Rejkiawik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlantyk/Georgia_Południowa"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlantyk/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlantyk/Św._Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Australia/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Australia/Adelajda"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "Południowa Australia"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Australia/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "Queensland — większość lokalizacji"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Australia/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "Nowa Południowa Walia — Yancowinna"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Australia/Canberra"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Australia/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "Tasmania — Wyspa King"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Australia/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "Terytorium Północne"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "Australia/Eucla"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "Zachodnia Australia — obszar Eucla"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Australia/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "Tasmania — większość lokalizacji"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Australia/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Australia/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "Queensland — Wyspy Bożego Narodzenia"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Australia/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "Wyspa Lord Howe"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Australia/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Australia/Północ"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Australia/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Australia/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "Zachodnia Australia — większość lokalizacji"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Australia/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Australia/Południe"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Australia/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "Nowa Południowa Walia — większość lokalizacji"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Australia/Tasmania"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Australia/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Australia/Zachód"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Australia/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brazylia/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brazylia/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brazylia/Wschodni"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brazylia/Zachodni"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Kanada/Atlantycki"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Kanada/Centralny"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Kanada/Wschodni"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Kanada/Wschodni-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Kanada/Górski"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Kanada/Nowofundlandzki"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Kanada/Pacyficzny"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Kanada/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Kanada/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Chile/Kontynentalny"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Chile/Wyspa Wielkanocna"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Kuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Egipt"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Eire"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Uniwersalny"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Europa/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Europa/Andora"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Europa/Ateny"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Europa/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Europa/Belgrad"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Europa/Berlin"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Europa/Bratysława"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Europa/Bruksela"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Europa/Bukareszt"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Europa/Budapeszt"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Europa/Kiszyniów"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Europa/Kopenhaga"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Europa/Dublin"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Europa/Gibraltar"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Europa/Guernsey"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Europa/Helsinki"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Europa/Wyspa_Man"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Europa/Istambuł"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Europa/Jersey"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Europa/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Moskwa-01 — Kaliningrad"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Europa/Kijów"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Europa/Lizbona"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Europa/Lublana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Europa/Londyn"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Europa/Luksemburg"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Europa/Madryt"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Europa/Malta"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Europa/Maarianhamina"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Europa/Mińsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Europa/Monako"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Europa/Moskwa"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "Moskwa+00 — zachodnia Rosja"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Europa/Nikozja"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Europa/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Europa/Paryż"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Europa/Podgorica"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Europa/Praga"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Europa/Ryga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Europa/Rzym"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Europa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Moskwa — Samara, Udmurta"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Europa/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Europa/Sarajewo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Europa/Symferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "Środkowy Krym"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Europa/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Europa/Sofia"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Europa/Sztokholm"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Europa/Tallin"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Europa/Tirana"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Europa/Terespol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Europa/Użhorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "Ruś"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Europa/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Europa/Watykan"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Europa/Wiedeń"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Europa/Wilno"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Europa/Wołgograd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "Moskwa+00 — Morze Kaspijskie"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Europa/Warszawa"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Europa/Zagrzeb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Europa/Zaporoże"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "Zaporoże, wschodni Ługańsk/Zaporoże, wschodni Ługańsk"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Europa/Zurych"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Factory"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Eire"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Islandia"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Ocean Indyjski/Antananarywa"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Ocean Indyjski/Czagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Ocean Indyjski/Wyspa Bożego Narodzenia"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Ocean Indyjski/Wyspy Kokosowe"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Ocean Indyjski/Komory"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Ocean Indyjski/Wyspy Kerguelena"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Ocean Indyjski/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Ocean Indyjski/Malediwy"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Ocean Indyjski/Mauritius"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Ocean Indyjski/Majotta"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Ocean Indyjski/Reunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Iran"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Izrael"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamajka"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Japonia"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Libia"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Meksyk/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Meksyk/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Meksyk/Ogólny"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Mideast/Rijad87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Mideast/Rijad88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Mideast/Rijad89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Ocean Spokojny/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Ocean Spokojny/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Ocean Spokojny/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "Wyspy Chatham"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "Ocean Spokojny/Chuuk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "Chuuk (Truk) i Yap"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Ocean Spokojny/Wyspa Wielkanocna"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "Wyspy Wielkanocne i Sala y Gomez"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Ocean Spokojny/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Ocean Spokojny/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "Wyspy Feniks"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Ocean Spokojny/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Ocean Spokojny/Fidżi"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Ocean Spokojny/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Ocean Spokojny/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "Wyspy Galapagos"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Ocean Spokojny/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "Wyspy Gambiera"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Ocean Spokojny/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Ocean Spokojny/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Ocean Spokojny/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "Hawaje"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Ocean Spokojny/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "Atol Johnstona"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Ocean Spokojny/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "Wyspy Line"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Ocean Spokojny/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "Kosrae"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Ocean Spokojny/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Ocean Spokojny/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Ocean Spokojny/Markizy"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "Markizy"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Ocean Spokojny/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "Wyspy Midway"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Ocean Spokojny/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Ocean Spokojny/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Ocean Spokojny/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Ocean Spokojny/Numea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Ocean Spokojny/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Ocean Spokojny/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Ocean Spokojny/Pitcairn"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "Ocean Spokojny/Pohnpei"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "Pohnpei (Ponape)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Ocean Spokojny/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Ocean Spokojny/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Ocean Spokojny/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Ocean Spokojny/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Ocean Spokojny/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Ocean Spokojny/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "Wyspy Towarzystwa"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Ocean Spokojny/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "Wyspy Gilberta"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Ocean Spokojny/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Ocean Spokojny/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Ocean Spokojny/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "Wyspa Wake"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Ocean Spokojny/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Ocean Spokojny/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Polska"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugalia"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "Reguły POSIX"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapur"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Turcja"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Uniwersalny"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "US/Alaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "US/Aleuty"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "US/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "US/Centralny"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "US/Wschodni"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "US/Wschodni-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "US/Hawaje"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "US/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "US/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "US/Górski"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "US/Pacyficzny"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "US/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
diff --git a/panels/datetime/po-timezones/pt.po b/panels/datetime/po-timezones/pt.po
new file mode 100644
index 0000000..7305196
--- /dev/null
+++ b/panels/datetime/po-timezones/pt.po
@@ -0,0 +1,3298 @@
+# Portuguese localization of Red Hat Linux
+# Pedro Morais <morais@kde.org>
+# José Nuno Pires <jncp@netcabo.pt>
+# Rui Gouveia <rui.gouveia@gmail.com>, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-08-30 15:33+0100\n"
+"Last-Translator: Rui Gouveia <rui.gouveia@gmail.com>\n"
+"Language-Team: trans-pt@lists.fedoraproject.org\n"
+"Language: pt\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Virtaal 0.6.1\n"
+"X-POFile-SpellExtra: Volgograd New DakotadoNorte Blanc\n"
+"X-Poedit-Language: Portuguese\n"
+"X-Poedit-Country: PORTUGAL\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "África/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "África/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "África/Addis_Ababa"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "África/Algiers"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "África/Asmara"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "África/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "África/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "África/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "África/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "África/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "África/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "África/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "África/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "África/Cairo"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "África/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "África/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "Ceuta & Melilla"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "África/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "África/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "África/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "África/Djibouti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "África/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "África/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "África/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "África/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "África/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "África/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "África/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "África/Khartoum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "África/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "África/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "Rep. Dem. Ocid. do Congo"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "África/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "África/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "África/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "África/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "África/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "Rep. Dem. Oriental do Congo"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "África/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "África/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "África/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "África/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "África/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "África/Mogadishu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "África/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "África/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "África/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "África/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "África/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "África/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "África/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "África/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "África/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "África/Tripoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "África/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "África/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "América/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Ilhas Aleutianas"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "América/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Hora do Alasca"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "América/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "América/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "América/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "Tocantins"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "América/Argentina/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Buenos Aires (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "América/Argentina/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "Catamarca (CT), Chubut (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "América/Argentina/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "América/Argentina/Córdova"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "maioria das localidades (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "América/Argentina/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Jujuy (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "América/Argentina/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "La Rioja (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "América/Argentina/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "Mendoza (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "América/Argentina/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "Santa Cruz (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "América/Argentina/Salta"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "América/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "San Juan (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "América/Argentina/San_Luis"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "San Luis (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "América/Argentina/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "Tucuman (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "América/Argentina/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "Tierra del Fuego (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "América/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "América/Asuncion"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "América/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "Hora-Padrão Oriental - Atikokan, Ontário e Southampton I, Nunavut"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "América/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "América/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "Bahia"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "América/Bahia_Banderas"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "Horário central Mexicano - Bahia de Banderas"
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "América/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "América/Belém"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "Amapa, E Para"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "América/Belize"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "América/Blanc-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "Hora-Padrão do Atlântico - Quebeque - Baía Inferior do Norte"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "América/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "Roraima"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "América/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "América/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "Hora de Montanha - Sul do Idaho & Oregon oriental"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "América/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "América/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "Hora de Montanha - Nunavut ocidental"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "América/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "Mato Grosso do Sul"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "América/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "Hora Central - Quintana Roo"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "América/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "América/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "América/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "América/Cayman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "América/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "Hora Central"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "América/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+"Hora das regiões montanhosas do México - Chihuahua afastado da fronteira dos "
+"E.U."
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "América/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "América/Cordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "América/Costa_Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "América/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "Mato Grosso"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "América/Curacao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "América/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "costa oriental, norte de Scoresbysund"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "América/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "Hora do Pacífico - norte do Yukon"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "América/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+"Hora-Padrão de Montanha - Dawson Creek & Fort Saint John, Columbia Britânica"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "América/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "Hora de Montanha"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "América/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "Hora Oriental - Michigan - maioria das localidades"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "América/Dominica"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "América/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+"Hora de Montanha - Alberta, Columbia Britânica oriental e oeste de "
+"Saskatchewan"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "América/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "Amazonas O"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "América/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "América/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "América/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "Brasil NE (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "América/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "América/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+"Hora do Atlântico - Nova Escócia - locais que não aplicam a DST 1966-1971"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "América/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "maioria das localidades"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "América/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "Hora do Atlântico - Labrador - maioria das localidades"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "América/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "América/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "América/Guadeloupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "América/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "América/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "continente"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "América/Guyana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "América/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "Hora do Atlântico - Nova Escócia (maioria das localidades), PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "América/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "América/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "Hora-Padrão da Montanha - Sonora"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "América/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "Hora Oriental - Indiana - maioria das localidades"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "América/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "Hora Central - Indiana - Condado de Starke"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "América/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "Hora Oriental - Indiana - Condado de Crawford"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "América/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "Hora Oriental - Indiana - Condado de Pike"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "América/Indianapolis"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "América/Indiana/Tell_City"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "Hora Central - Indiana - Condado de Perry"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "América/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "Hora Oriental - Indiana - Condado de Switzerland"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "América/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "Hora Oriental - Indiana - Condados de Daviess, Dubois, Knox & Martin"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "América/Indiana/Winamac"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "Hora Oriental - Indiana - Condado de Pulaski"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "América/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "Hora de Montanha - oeste dos Territórios de Noroeste"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "América/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "Hora Oriental - Nunavut oriental - maioria das localidades"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "América/Jamaica"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "América/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "América/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "Hora do Alasca - planalto do Alasca"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "América/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Hora Oriental - Kentucky - área de Louisville"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "América/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "Hora Oriental - Kentucky - Condado de Wayne"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "América/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "América/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "América/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "América/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "Hora do Pacífico"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "América/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "América/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "Alagoas, Sergipe"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "América/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "América/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "Amazonas E"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "América/Marigot"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "América/Martinique"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "América/Matamoros"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+"Hora Central E.U. - Coahuila, Durango, Nuevo León, Tamaulipas, perto da "
+"fronteira dos E.U."
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "América/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "Hora de Montanha - S Baja, Nayarit, Sinaloa"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "América/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "América/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+"Hora Central - Michigan - Condados de Dickinson, Gogebic, Iron & Menominee"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "América/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "Hora Central - Campeche, Yucatan"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "América/Mexico_City"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "Hora Central - maioria das localidades"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "América/Miquelon"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "América/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "Hora do Atlântico - New Brunswick"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "América/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+"Hora Central Mexicana - Coahuila, Durango, Nuevo Leon, Tamaulipas afastado "
+"da fronteira dos E.U."
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "América/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "América/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "Hora Oriental - Quebeque - maioria das localidades"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "América/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "América/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "América/New_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "Hora Oriental"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "América/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+"Hora Oriental - Ontário & Quebeque - locais que não aplicam a DST 1967-1973"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "América/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "Hora do Alasca - Alasca ocidental"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "América/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "Ilhas do Atlântico"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "América/Dakota do Norte/Centro"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "Hora Central - Dakota do Norte - Condado de Oliver"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "América/Dakota_do_Norte/New_Salem"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+"Hora Central - Dakota do Norte - Condado de Morton (excepto área de Mandan)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "América/Ojinaga"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "Hora de Montanha dos E.U. - Chihuahua perto da fronteira com os E.U."
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "América/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "América/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "Hora Oriental - Pangnirtung, Nunavut"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "América/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "América/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "Hora-Padrão de Montanha - Arizona"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "América/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "América/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "América/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "América/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "Rondonia"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "América/Puerto_Rico"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "América/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "Hora Central - Rainy River & Fort Frances, Ontário"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "América/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "Hora Central - Nunavut central"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "América/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "Pernambuco"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "América/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "Hora-Padrão Central - Saskatchewan - maioria das localidades"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "América/Resolute"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "Hora Oriental - Nunavut oriental - maioria das localidades"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "América/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "Acre"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "América/Rosario"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "América/Santa_Isabel"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+"Hora do Pacífico Mexicana - Baixa Califórnia longe da fronteira com os E.U."
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "América/Santarém"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "Para O"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "América/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "América/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "América/São_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "Brasil S & SE (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "América/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "Scoresbysund / Ittoqqortoormiit"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "América/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "Hora de Montanha - Navajo"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "América/St_Barthelemy"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "América/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "Hora de Newfoundland, incluindo Labrador SE"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "América/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "América/St_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "América/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "América/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "América/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "Hora-Padrão Central - Saskatchewan - centro-oeste"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "América/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "América/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "Thule / Pituffik"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "América/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "Hora Oriental - Thunder Bay, Ontário"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "América/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+"Hora do Pacífico E.U. - Baixa Califórnia perto da fronteira com os E.U."
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "América/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "Hora Oriental - Ontário - maioria das localidades"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "América/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "América/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "Hora do Pacífico - Columbia Britânica ocidental"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "América/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "América/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "Hora do Pacífico - sul do Yukon"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "América/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "Hora Central - Manitoba & Ontário ocidental"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "América/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "Hora do Alasca - sopé do planalto do Alasca"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "América/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "Hora de Montanha - Territórios do Noroeste centrais"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antárctica/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "Estação Casey, Península de Bailey"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antárctica/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "Estação Davis, Vestfold Hills"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antárctica/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "Estação Dumont-d'Urville, Terre Adelie"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "Antárctica/Macquarie"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "Estação da Ilha Macquarie, Ilha Macquarie"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antárctica/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "Estação Mawson, Baía de Holme"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antárctica/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "Estação McMurdo, Ilha de Ross"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antárctica/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "Estação Palmer, Ilha Anvers"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antárctica/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "Estação Rothera, Ilha de Adelaide"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antárctica/Pólo_Sul"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "Estação Amundsen-Scott, Pólo Sul"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antárctica/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "Estação de Syowa, E Ongul I"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antárctica/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "Estação Vostok, Pólo Sul Magnético"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Árctico/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Ásia/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Ásia/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Ásia/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Ásia/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "Moscovo+08 - Mar Bering"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Ásia/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Ásia/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "Aqtobe (Aktobe)"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Ásia/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Ásia/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Ásia/Baghdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Ásia/Bahrain"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Ásia/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Ásia/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Ásia/Beirut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Ásia/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Ásia/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Ásia/Calcutta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Ásia/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "Dornod, Sukhbaatar"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Ásia/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "China central - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Ásia/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Ásia/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Ásia/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Ásia/Damascus"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Ásia/Dhaka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Ásia/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Ásia/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Ásia/Dushanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Ásia/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Ásia/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "Heilongjiang (excepto Mohe), Jilin"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Ásia/Ho_Chi_Minh"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Ásia/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Ásia/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Ásia/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Moscovo+05 - Lago Baical"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Ásia/Istanbul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Ásia/Jakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "Java & Sumatra"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Ásia/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "Irian Jaya & as Molucas"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Ásia/Jerusalem"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Ásia/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Ásia/Kamchatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "Moscovo+08 - Kamchatka"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Ásia/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Ásia/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "Tibete ocidental & Xinjiang"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "Ásia/Áden"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Ásia/Katmandu"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "Ásia/Kolkata"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Ásia/Krasnoyarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "Moscovo+04 - Rio Jenissei"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Ásia/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "Malásia peninsular"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Ásia/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "Sabah & Sarawak"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Ásia/Kuwait"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Ásia/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Ásia/Macau"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Ásia/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "Moscovo+08 - Magadan"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Ásia/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "Borneo oriental e sul, Celebes, Bali, Nusa Tengarra, Timor ocidental"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Ásia/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Ásia/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Ásia/Nicosia"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "Ásia/Novokuznetsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Moscovo+03 - Novokuznetsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Ásia/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Moscovo+03 - Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Ásia/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "Moscovo+03 - Sibéria ocidental"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Ásia/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "Cazaquistão ocidental"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Ásia/Phnom_Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Ásia/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "Borneo ocidental & central"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Ásia/Pyongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Ásia/Qatar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Ásia/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Ásia/Rangoon"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Ásia/Riyadh"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Ásia/Riyadh87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Ásia/Riyadh88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Ásia/Riyadh89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Ásia/Saigon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Ásia/Sakhalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "Moscovo+07 - Ilha Sakhalin"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Ásia/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "Uzbequistão ocidental"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Ásia/Seoul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Ásia/Shanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "China oriental - Pequim, Guangdong, Xangai, etc."
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Ásia/Singapore"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Ásia/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Ásia/Tashkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "Uzbequistão oriental"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Ásia/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Ásia/Tehran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Ásia/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Ásia/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Ásia/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Ásia/Tokyo"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Ásia/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Ásia/Ulaanbaatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Ásia/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Ásia/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "maioria do Tibete & Xinjiang"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Ásia/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Ásia/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "Moscovo+07 - Rio Amur"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Ásia/Yakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "Moscovo+06 - Rio Lena"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Ásia/Yekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "Moscovo+02 - Urais"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Ásia/Yerevan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlântico/Açores"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "Açores"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlântico/Bermuda"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlântico/Canárias"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "Ilhas Canárias"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlântico/Cabo_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlântico/Faeroe"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "Atlântico/Faroe"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlântico/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlântico/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "Arquipélago da Madeira"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlântico/Reykjavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlântico/South_Georgia"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlântico/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlântico/St_Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Austrália/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Austrália/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "Sul da Austrália"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Austrália/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "Queensland - maioria das localidades"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Austrália/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "Nova Gales do Sul - Yancowinna"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Austrália/Canberra"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Austrália/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "Tasmânia - King Island"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Austrália/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "Território do Norte"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "Austrália/Eucla"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "Austrália Ocidental - área de Eucla"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Austrália/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "Tasmânia - maioria das localidades"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Austrália/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Austrália/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "Queensland - Holiday Islands"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Austrália/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "Ilha Lord Howe"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Austrália/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "Vitória"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Austrália/North"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Austrália/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Austrália/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "Austrália ocidental - maioria das localidades"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Austrália/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Austrália/South"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Austrália/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "Nova Gales do Sul - maioria das localidades"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Austrália/Tasmania"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Austrália/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Austrália/West"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Austrália/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brasil/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brasil/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brasil/Este"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brasil/Oeste"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Canadá/Atlantic"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Canadá/Central"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Canadá/Eastern"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Canadá/East-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Canadá/Mountain"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Canadá/Newfoundland"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Canadá/Pacific"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Canadá/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Canadá/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Chile/Continental"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Chile/EasterIsland"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Cuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Egipto"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Eire"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Europa/Amsterdão"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Europa/Andorra"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Europa/Atenas"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Europa/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Europa/Belgrado"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Europa/Berlim"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Europa/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Europa/Bruxelas"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Europa/Bucareste"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Europa/Budapeste"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Europa/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Europa/Copenhaga"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Europa/Dublin"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Europa/Gibraltar"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Europa/Guernsey"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Europa/Helsinquia"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Europa/Isle_of_Man"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Europa/Istanbul"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Europa/Jersey"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Europa/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Moscovo-01 - Kalininegrado"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Europa/Kiev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Europa/Lisboa"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Europa/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Europa/Londres"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Europa/Luxemburgo"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Europa/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Europa/Malta"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Europa/Mariehamn"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Europa/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Europa/Mónaco"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Europa/Moscovo"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "Moscovo+00 - Rússia ocidental"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Europe/Nicosia"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Europa/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Europa/Paris"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Europa/Podgorica"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Europa/Praga"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Europa/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Europa/Roma"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Europa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Moscovo - Samara, Udmurtia"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Europa/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Europa/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Europa/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "Crimeia central"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Europa/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Europa/Sofia"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Europa/Estocolmo"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Europa/Tallinn"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Europa/Tirane"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Europa/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Europa/Uzhgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "Ruténia"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Europa/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Europa/Vaticano"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Europa/Viena"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Europa/Vilnius"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Europa/Volgograd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "Moscovo+00 - Mar Cáspio"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Europa/Varsóvia"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Europa/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Europa/Zaporozhye"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "Zaporozh'ye, Lugansk / Zaporizhia E, Luhansk E"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Europa/Zurich"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Fábrica"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Eire"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Islândia"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Índia/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Índia/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Índia/Christmas"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Índia/Cocos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Índia/Comoro"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Índia/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Índia/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Índia/Maldives"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Índia/Mauritius"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Índia/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Índia/Reunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Irão"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "Fecha aba"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Israel"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamaica"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Japão"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Líbia"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "México/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "México/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "México/General"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Mideast/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Mideast/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Mideast/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Pacífico/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Pacífico/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Pacífico/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "Ilhas Chatham"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "Pacífico/Chuuk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "Chuuk (Truk) e Yap"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Pacífico/Páscoa"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "Ilha da Páscoa & Sala y Gomez"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Pacífico/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Pacífico/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "Ilhas Fénix"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Pacífico/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Pacífico/Fiji"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Pacífico/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Pacífico/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "Ilhas Galápagos"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Pacífico/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "Ilhas Gambier"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Pacífico/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Pacífico/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Pacífico/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "Havai"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Pacífico/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "Atol Johnston"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Pacífico/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "Ilhas Line"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Pacífico/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "Kosrae"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Pacífico/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Pacífico/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Pacífico/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "Ilhas Marquesas"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Pacífico/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "Atol de Midway"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Pacífico/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Pacífico/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Pacífico/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Pacífico/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Pacífico/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Pacífico/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Pacífico/Pitcairn"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "Pacífico/Pohnpei"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "Pohnpei (Ponape)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Pacífico/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Pacífico/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Pacífico/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Pacífico/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Pacífico/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Pacífico/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "Ilhas Sociedade"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Pacífico/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "Ilhas Gilbert"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Pacífico/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Pacífico/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Pacífico/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "Ilha de Wake"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Pacífico/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Pacífico/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Polónia"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugal"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "Regras Posix"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapura"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Turquia"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "EUA/Alasca"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "EUA/Aleutian"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "EUA/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "EUA/Central"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "EUA/Eastern"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "EUA/East-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "EUA/Hawaii"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "EUA/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "EUA/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "EUA/Mountain"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "EUA/Pacific"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "EUA/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
+
+#~ msgid "US/Pacific-New"
+#~ msgstr "EUA/Pacific-New"
+
+#~ msgid "SystemV/AST4"
+#~ msgstr "SystemV/AST4"
+
+#~ msgid "SystemV/AST4ADT"
+#~ msgstr "SystemV/AST4ADT"
+
+#~ msgid "SystemV/CST6"
+#~ msgstr "SystemV/CST6"
+
+#~ msgid "SystemV/CST6CDT"
+#~ msgstr "SystemV/CST6CDT"
+
+#~ msgid "SystemV/EST5"
+#~ msgstr "SystemV/EST5"
+
+#~ msgid "SystemV/EST5EDT"
+#~ msgstr "SystemV/EST5EDT"
+
+#~ msgid "SystemV/HST10"
+#~ msgstr "SystemV/HST10"
+
+#~ msgid "SystemV/MST7"
+#~ msgstr "SystemV/MST7"
+
+#~ msgid "SystemV/MST7MDT"
+#~ msgstr "SystemV/MST7MDT"
+
+#~ msgid "SystemV/PST8"
+#~ msgstr "SystemV/PST8"
+
+#~ msgid "SystemV/PST8PDT"
+#~ msgstr "SystemV/PST8PDT"
+
+#~ msgid "SystemV/YST9"
+#~ msgstr "SystemV/YST9"
+
+#~ msgid "SystemV/YST9YDT"
+#~ msgstr "SystemV/YST9YDT"
diff --git a/panels/datetime/po-timezones/pt_BR.po b/panels/datetime/po-timezones/pt_BR.po
new file mode 100644
index 0000000..b5c0f90
--- /dev/null
+++ b/panels/datetime/po-timezones/pt_BR.po
@@ -0,0 +1,3252 @@
+# Brazilian Portuguese translation of the "timezones" messages
+# Copyright (C) 1996,2003,2004, 2006, 2008 Free Software Foundation, Inc.
+#
+# Wanderlei Antonio Cavassin <cavassin@conectiva.com.br>, 1997.
+# Paul Gampe <pgampe@redhat.com>, 2003.
+# David Barzilay <barzilay@redhat.com>, 2004.
+# Rodrigo Padula de Oliveira <rodrigopadula@gmail.com>, 2006.
+# Igor Pires Soares <igor@projetofedora.org>, 2006, 2010.
+# Rodrigo Padula de Oliveira <rodrigopadula@projetofedora.org>, 2008.
+# Taylon Silmer <taylonsilva@gmail.com>, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: system-config-date-timezones\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-09-03 15:09-0300\n"
+"Last-Translator: Igor Pires Soares <igor@projetofedora.org>\n"
+"Language-Team: Brazilian Portuguese <trans-pt_br@lists.fedoraproject.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: pt_BR\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+"X-Generator: KBabel 1.11.4\n"
+"X-Poedit-Language: Portuguese\n"
+"X-Poedit-Country: BRAZIL\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "África/Abidjã"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "África/Acra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "África/Adis Abeba"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "África/Argélia"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "África/Asmara"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "África/Asmara"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Áfrca/Bamaco"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "África/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "África/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "África/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "África/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "África/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "África/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "África/Cairo"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "África/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "África/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "Ceuta & Melilla"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "África/Conacri"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "África/Dacar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "África/Dar es Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "África/Djibuti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "África/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "África/El Aiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "África/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "África/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "África/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "África/Johanesburgo"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "África/Campala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "África/Cartum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "África/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "África/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "Oeste da Rep. Dem. do Congo"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "África/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "África/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "África/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "África/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "África/Lumbubashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "Leste da Rep. Dem. do Congo"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "África/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "África/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "África/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "África/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "África/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "África/Mogadishu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "África/Monróvia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "África/Nairóbi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "África/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "África/Niamei"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "África/Nuakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "África/Uagadugu"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "África/Porto Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "África/São Tomé"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "África/Tombouctou"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "África/Trípoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "África/Túnis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "África/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "América/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Ilhas Aleutas"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "América/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Horário do Alasca"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "América/Anguila"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "América/Antígua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "América/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "Tocantins"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "América/Argentina/Buenos Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Buenos Aires (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "América/Argentina/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "Catamarca (CT), Chubut (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "America/Argentina/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "América/Argentina/Córdoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "Maioria das localidades (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "América/Argentina/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Jujuy (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "América/Argentina/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "La Rioja (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "América/Argentina/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "Mendoza (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "América/Argentina/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "Santa Cruz (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "América/Argentina/Salta"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "América/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "San Juan (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "América/Argentina/San_Luis"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "San Luis (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "América/Argentina/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "Tucuman (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "América/Argentina/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "Tierra del Fuego (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "América/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "América/Assunção"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "América/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "Horário padrão do leste - Atikokan, Ontario e Southampton I, Nunavut"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "América/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "América/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "Bahia"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "América/Bahia_Banderas"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "Horário central do México - Bahia de Banderas"
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "América/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "América/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "Amapá, leste do Pará"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "América/Belize"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "América/Blanc-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "Horário padrão do Atlântico - Quebec - Lower North Shore"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "América/Boa Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "Roraima"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "América/Bogotá"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "América/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "Mountain Time - sul de Idaho & leste do Oregon"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "América/Buenos Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "América/Gambridge Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "Mountain Time - oeste de Nunavut"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "América/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "Mato Grosso do Sul"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "América/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "Horário central - Quintana Roo"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "América/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "América/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "América/Caiena"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "América/Caimãs"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "América/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "Horário central"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "América/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "Mexican Mountain Time - Chihuahua away from US border"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "América/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "América/Córdoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "América/Costa Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "América/Cuiabá"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "Mato Grosso"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "América/Curaçao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "América/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "Costa leste, norte de Scoresbysund"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "América/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "Horário do Pacífico - norte de Yukon"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "América/Dawson Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid "Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr "Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "América/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "Mountain Time"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "América/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "Horário do leste - Michigan - maioria das localidades"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "América/Dominica"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "América/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "Mountain Time - Alberta, leste de British Columbia & oeste de Saskatchewan"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "América/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "Oeste do Amazonas"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "América/El Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "América/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "América/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "Nordeste do Brasil (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "América/Fort Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "América/Glace Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr "Horário do Atlântico - Nova Scotia - lugares que não consideram o DST 1966-1971"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "América/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195
+#: timezones.h:364
+#: timezones.h:453
+#: timezones.h:591
+#: timezones.h:754
+#: timezones.h:852
+#: timezones.h:894
+msgid "most locations"
+msgstr "Maioria das localidades"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "América/Goose Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "Horário do Atlântico - Labrador - maioria das localidades"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "América/Grand Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "América/Granada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "América/Guadalupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "América/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "América/Guaiaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205
+#: timezones.h:757
+#: timezones.h:763
+msgid "mainland"
+msgstr "Localidade principal"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "América/Guiana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "América/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "Horário do Atlântico - Nova Scotia (maioria das localidades), PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "América/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "América/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "Mountain Standard Time - Sonora"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "América/Indiana/Indianápolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "Horário do leste - Indiana - maioria das localidades"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "América/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "Horário central - Indiana - Condado de Starke"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "América/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "Horário do leste - Indiana - Condado de Crawford"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "América/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "Horário do leste - Indiana - Condado Pike"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "América/Indianápolis"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "América/Indiana/Tell_City"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "Horário central - Indiana - Condado Perry"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "América/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "Horário do leste - Indiana - Condado Switzerland"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "América/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "Horário do leste - Indiana - Condados de Daviess, Dubois, Knox & Martin"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "América/Indiana/Winamac"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "Horário do leste - Indiana - Condado Pulaski"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "América/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "Mountain Time - oeste de Northwest Territories"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "América/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "Eastern Time - leste de Nunavut - maioria das localidades"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "América/Jamaica"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "América/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "América/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "Horário do Alasca - Alaska panhandle"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "América/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Horário do leste - Kentucky - Área de Louisville"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "América/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "Horário do leste - Kentucky - Condado Wayne"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "América/Knox IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "América/La Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "América/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "América/Los Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "Horário do Pacífico"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "América/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "América/Maceió"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "Alagoas, Sergipe"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "América/Manágua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "América/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "Leste do Amazonas"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "América/Marigot"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "América/Martinica"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "America/Matamoros"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid "US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr "US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "América/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "Mountain Time - S Baja, Nayarit, Sinaloa"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "América/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "América/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "Horário central - Michigan - Condados de Dickinson, Gogebic, Iron & Menominee"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "América/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "Horário central - Campeche, Yucatan"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "América/Cidade do México"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "Horário central - maioria das localidades"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "América/Miquelon"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "América/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "Horário do Atlântico - New Brunswick"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "América/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid "Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from US border"
+msgstr "Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from US border"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "América/Montevidéu"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "América/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "Horário do leste - Quebec - maioria das localidades"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "América/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "América/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "América/Nova Iorque"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "Horário do leste"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "América/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid "Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr "Horário do leste - Ontario & Quebec - lugares que não consideram o DST 1967-1973"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "América/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "Horário do Alasca - oeste do Alasca"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "América/Fernando_de_Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "Ilhas Atlânticas"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "América/_Dakota_do_Norte/Centro"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "Horário central - North Dakota - Condado Oliver"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "América/Dakota_do_Norte/Nova_Salém"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "Horário central - North Dakota - Condado Morton (exceto a área de Mandan)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "America/Ojinaga"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "US Mountain Time - Chihuahua near US border"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "América/Panamá"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "América/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "Horário do leste - Pangnirtung, Nunavut"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "América/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "América/Fênix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "Mountain Standard Time - Arizona"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "América/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "América/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "América/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "América/Porto Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "Rondônia"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "América/Porto Rico"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "América/Rainy River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "Horário central - Rainy River & Fort Frances, Ontário"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "América/Rankin Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "Horário central - Nunavut central"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "América/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "Pernambuco"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "América/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "Horário central padrão - Saskatchewan - maioria das localidades"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "América/Resolute"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "Horário padrão do leste - Resolute, Nunavut"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "América/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "Acre"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "América/Rosário"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "América/Santa_Isabel"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "Horário do pacífico mexicano - Baja California away from US border"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "América/Santarém"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "Oeste do Pará"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "América/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "América/Santo Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "América/São Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "Sul, sudeste e parte do centro-oeste do Brasil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "América/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "Scoresbysund / Ittoqqortoormiit"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "América/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "Mountain Time - Navajo"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "América/St_Barthelemy"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "América/St Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "Horário de Newfoundland, incluindo o sudeste de Labrador"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "América/St Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "América/Santa Lúcia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "América/St Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "América/São Vicente"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "América/Swift Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "Horário central padrão - Saskatchewan - meio-oeste"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "América/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "América/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "Thule / Pituffik"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "América/Thunder Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "Horário do leste - Thunder Bay, Ontário"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "América/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "Horário do pacífico US - Baja California near US border"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "América/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "Horário do leste - Ontário - maioria das localidades"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "América/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "América/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "Horário do Pacífico - oeste de British Columbia"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "América/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "América/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "Horário do Pacífico - sul de Yukon"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "América/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "Horário central - Manitoba & oeste de Ontário"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "América/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "Horário do Alasca - Alaska panhandle neck"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "América/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "Mountain Time - Northwest Territories centrais"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antártica/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "Casey Station, Península de Bailey"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antártica/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "Davis Station, Vestfold Hills"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antártica/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "Dumont-d'Urville Station, Terre Adelie"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "Antártica/Macquarie"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "Macquarie Island Station, Macquarie Island"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antártica/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "Mawson Station, Baía Holme"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antártica/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "McMurdo Station, Ilha Ross"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antártica/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "Palmer Station, Ilha Anvers"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antártica/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "Rothera Station, Ilha Adelaide"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antártica/Polo Sul"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "Amundsen-Scott Station, Pólo Sul"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antártica/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "Syowa Station, Leste de Ongul I"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antártica/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "Vostok Station, Pólo Sul Magnético"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Ártico/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Ásia/Áden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Ásia/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Ásia/Amã"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Ásia/Anadir"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "Moscow+08 - Mar de Bering"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Ásia/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Ásia/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "Aqtobe (Aktobe)"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Ásia/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Ásia/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Ásia/Bagdá"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Ásia/Barein"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Ásia/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Ásia/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Ásia/Beirute"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Ásia/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Ásia/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Ásia/Calcutá"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Ásia/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "Dornod, Sukhbaatar"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Ásia/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "China central - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Ásia/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Ásia/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Ásia/Daca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Ásia/Damasco"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Ásia/Dhaka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Ásia/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Ásia/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Ásia/Dushanbê"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Ásia/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Ásia/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "Heilongjiang (exceto Mohe), Jilin"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Ásia/Ho_Chi_Minh"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Ásia/Hong Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Ásia/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Ásia/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Moscow+05 - Lago Baikal"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Ásia/Istanbul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Ásia/Jacarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "Java & Sumatra"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Ásia/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "Irian Jaya & As Moluccas"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Ásia/Jerusalém"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Ásia/Cabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Ásia/Kamchatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "Moscow+08 - Kamchatka"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Ásia/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Ásia/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "Oeste do Tibet & Xinjiang"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "Ásia/Kathmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Ásia/Katmandu"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "Ásia/Kolkata"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Ásia/Krasnoyarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "Moscow+04 - Rio Yenisei"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Ásia/Kuala Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "Malásia peninsular"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Ásia/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "Sabah & Sarawak"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Ásia/Kuwait"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Ásia/Macau"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Ásia/Macau"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Ásia/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "Moscow+08 - Magadan"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Ásia/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "Leste & sul de Borneo, Celebes, Bali, Nusa Tengarra, oeste de Timor"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Ásia/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Ásia/Mascate"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Ásia/Nicósia"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "Ásia/Novokuznetsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Moscow+03 - Novokuznetsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Ásia/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Moscow+03 - Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Ásia/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "Moscow+03 - oeste da Sibéria"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Ásia/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "Oeste do Cazaquistão"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Ásia/Phnom Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Ásia/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "Oeste & centro de Borneo"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Ásia/Pyongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Ásia/Catar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Ásia/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Ásia/Yangun"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Ásia/Riad"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Ásia/Riad87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Ásia/Riad88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Ásia/Riad89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Ásia/Saigon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Ásia/Sakhalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "Moscow+07 - Ilha Sakhalin"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Ásia/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "Oeste do Uzbequistão"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Ásia/Seul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Ásia/Xangai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "Leste da China - Pequim, Guangdong, Shanghai, etc."
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Ásia/Cingapura"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Ásia/Taipé"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Ásia/Tashkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "Leste do Uzbequistão"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Ásia/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Ásia/Teerã"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Ásia/Tel Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Ásia/Timbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Ásia/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Ásia/Tóquio"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Ásia/Ujung Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Ásia/Ulaanbaatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Ásia/Ulan Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Ásia/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "maior parte do Tibet & Xinjiang"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Ásia/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Ásia/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "Moscow+07 - Rio Amur"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Ásia/Yakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "Moscow+06 - Rio Lena"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Ásia/Yekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "Moscow+02 - Urais"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Ásia/Yerevan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlântico/Açores"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "Açores"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlântico/Bermuda"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlântico/Canárias"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "Ilhas Canárias"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlântico/Cabo Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlântico/Faroe"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "Atlântico/Faroe"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlântico/Jan Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlântico/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "Ilha da Madeira"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlântico/Reykjavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlântico/Geórgia do Sul"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlântico/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlântico/Santa Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Austrália/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Austrália/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "Sul da Austrália"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Austrália/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "Queensland - maioria das localidades"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Austrália/Broken Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "New South Wales - Yancowinna"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Austrália/Camberra"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Austrália/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "Tasmânia - Ilha King"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Austrália/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "Northern Territory"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "Austrália/Eucla"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "Oeste da Australia - área de Eucla"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Austrália/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "Tasmânia - maioria das localidades"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Austrália/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Austrália/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "Queensland - Ilhas Holiday"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Austrália/Lord Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "Ilha Lord Howe"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Austrália/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Austrália/Norte"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Austrália/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Austrália/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "Oeste da Austrália - maioria das localidades"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Austrália/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Austrália/Sul"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Austrália/Sidnei"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "New South Wales - maioria das localidades"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Austrália/Tasmânia"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Austrália/Vitória"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Austrália/Oeste"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Austrália/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brasil/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brasil/Fernando de Noronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brasil/Leste"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brasil/Oeste"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Canadá/Atlântico"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Canadá/Central"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Canadá/Leste"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Canadá/Leste-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Canadá/Montanhas"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Canadá/Terra Nova"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Canadá/Pacífico"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Canadá/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Canadá/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Chile/Continental"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Chile/Ilha de Páscoa"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Cuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Egito"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Irlanda"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Europa/Amsterdã"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Europa/Andorra"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Europa/Atenas"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Europa/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Europa/Belgrado"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Europa/Berlim"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Europa/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Europa/Bruxelas"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Europa/Bucareste"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Europa/Budapeste"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Europa/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Europa/Copenhague"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Europa/Dublin"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Europa/Gibraltar"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Europa/Guernsey"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Europa/Helsinque"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Europa/Ilha de Man"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Europa/Instanbul"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Europa/Jersey"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Europa/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Moscow-01 - Kaliningrad"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Europa/Kiev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Europa/Lisboa"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Europa/Liubliana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Europa/Londres"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Europa/Luxenburgo"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Europa/Madri"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Europa/Malta"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Europa/Mariehamn"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Europa/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Europa/Mônaco"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Europa/Moscou"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "Moscow+00 - oeste da Rússia"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Europa/Nicosia"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Europa/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Europa/Paris"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Europa/Podgorica"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Europa/Praga"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Europa/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Europa/Roma"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Europa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Moscow - Samara, Udmurtia"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Europa/São Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Europa/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Europa/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "Crimea central"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Europa/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Europa/Sófia"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Europa/Estocolmo"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Europa/Tallinn"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Europa/Tirana"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Europa/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Europa/Uzhgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "Ruthenia"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Europa/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Europa/Vaticano"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Europa/Viena"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Europa/Vilnius"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Europa/Volgogrado"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "Moscow+00 - Mar Cáspio"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Europa/Varsóvia"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Europa/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Europa/Zaporozhye"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "Zaporozh'ye, Leste de Lugansk / Zaporizhia, Leste de Luhansk"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Europa/Zurique"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Fábrica"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB Eire"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hong Kong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Islândia"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Índico/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Índico/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Índico/Christmas"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Índico/Cocos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Índico/Comores"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Índico/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Índico/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Índico/Maldivas"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Índico/Maurício"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Índico/Mayote"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Índico/Reunião"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Irã"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Israel"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamaica"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Japão"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835
+#: timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Líbia"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "México/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "México/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "México/Geral"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Oriente Médio/Riad87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Oriente Médio/Riad88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Oriente Médio/Riad89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Pacífico/Ápia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Pacífico/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Pacífico/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "Ilhas Chatham"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "Pacífico/Chuuk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "Chuuk (Truk) e Yap"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Pacífico/Ilha de Páscoa"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "Ilha de Páscoa & Sala y Gomez"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Pacífico/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Pacífico/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "Ilhas Phoenix"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Pacífico/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Pacífico/Fiji"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Pacífico/Funafati"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Pacífico/Galápagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "Ilhas Galápagos"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Pacífico/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "Ilhas Gambier"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Pacífico/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Pacífico/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Pacífico/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "Havaí"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Pacífico/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "Johnston Atoll"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Pacífico/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "Ilhas Line"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Pacífico/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "Kosrae"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Pacífico/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Pacífico/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Pacífico/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "Ilhas Marquesas"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Pacífico/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "Ilhas Midway"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Pacífico/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Pacífico/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Pacífico/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Pacífico/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Pacífico/Pago Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Pacífico/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Pacífico/Pitcairn"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "Pacífico/Pohnpei"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "Pohnpei (Ponape)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Pacífico/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Pacífico/Port Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Pacífico/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Pacífico/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Pacífico/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Pacífico/Taiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "Ilhas Society"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Pacífico/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "Ilhas Gilbert"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Pacífico/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Pacífico/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Pacífico/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "Ilha Wake"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Pacífico/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Pacífico/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Polônia"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugal"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Cingapura"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Turquia"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "US/Alasca"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "US/Ilhas Aleutas"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "US/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "US/Central"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "US/Leste"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "US/Leste-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "US/Havai"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "US/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "US/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "US/Montanhas"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "US/Pacífico"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "US/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
+
+#~ msgid "US/Pacific-New"
+#~ msgstr "US/Pacífico-Novo"
diff --git a/panels/datetime/po-timezones/ro.po b/panels/datetime/po-timezones/ro.po
new file mode 100644
index 0000000..238764c
--- /dev/null
+++ b/panels/datetime/po-timezones/ro.po
@@ -0,0 +1,3284 @@
+# translation of ro.po to
+# Romanian translation of timezone
+#
+#
+# Cristian Gafton <gafton@redhat.com>, 2004.
+# Răzvan Corneliu C.R. VILT <razvan.vilt@linux360.ro>, 2006.
+# Alexandru Szasz <alexxed@gmail.com>, 2006.
+# Mircea Daniel <visez.trance@gmail.com>, 2007.
+msgid ""
+msgstr ""
+"Project-Id-Version: ro\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2007-02-05 21:44+0200\n"
+"Last-Translator: Mircea Daniel <visez.trance@gmail.com>\n"
+"Language-Team: <ro@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Africa/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Africa/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Africa/Addis_Ababa"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Africa/Algiers"
+
+#: timezones.h:5
+#, fuzzy
+msgid "Africa/Asmara"
+msgstr "Africa/Asmera"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Africa/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Africa/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Africa/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Africa/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Africa/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Africa/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Africa/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Africa/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Africa/Cairo"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Africa/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Africa/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Africa/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Africa/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Africa/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Africa/Djibouti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Africa/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Africa/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Africa/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Africa/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Africa/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Africa/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Africa/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Africa/Khartoum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Africa/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Africa/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Africa/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Africa/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Africa/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Africa/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Africa/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Africa/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Africa/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Africa/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Africa/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Africa/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Africa/Mogadishu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Africa/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Africa/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Africa/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Africa/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Africa/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Africa/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Africa/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Africa/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Africa/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Africa/Tripoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Africa/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Africa/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "America/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+#, fuzzy
+msgid "Aleutian Islands"
+msgstr "Australia/Queensland"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "America/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+#, fuzzy
+msgid "Alaska Time"
+msgstr "US/Alaska"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "America/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "America/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "America/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "America/Argentina/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "America/Argentina/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "America/Argentina/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "America/Argentina/Cordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "America/Argentina/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "America/Argentina/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "America/Argentina/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "America/Argentina/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+#, fuzzy
+msgid "America/Argentina/Salta"
+msgstr "America/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "America/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+#, fuzzy
+msgid "America/Argentina/San_Luis"
+msgstr "America/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "America/Argentina/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "America/Argentina/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "America/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "America/Asuncion"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "America/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "America/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "America/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "America/Bahia"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "America/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "America/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "America/Belize"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "America/Blanc-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "America/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "America/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "America/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "America/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "America/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "America/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "America/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "America/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "America/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "America/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "America/Cayman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "America/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+#, fuzzy
+msgid "Central Time"
+msgstr "US/Central"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "America/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "America/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "America/Cordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "America/Costa_Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "America/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "America/Curacao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "America/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "America/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "America/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "America/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+#, fuzzy
+msgid "Mountain Time"
+msgstr "US/Mountain"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "America/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "America/Dominica"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "America/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "America/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "America/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "America/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "America/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "America/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "America/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "America/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "America/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "America/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "America/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "America/Guadeloupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "America/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "America/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "America/Guyana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "America/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "America/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "America/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "America/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "America/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "America/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "America/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "America/Indianapolis"
+
+#: timezones.h:227
+#, fuzzy
+msgid "America/Indiana/Tell_City"
+msgstr "America/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "America/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "America/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+#, fuzzy
+msgid "America/Indiana/Winamac"
+msgstr "America/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "America/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "America/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "America/Jamaica"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "America/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "America/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "America/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+#, fuzzy
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "America/Kentucky/Louisville"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "America/Kentucky/Montevideo"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "America/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "America/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "America/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "America/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+#, fuzzy
+msgid "Pacific Time"
+msgstr "Pacific/Niue"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "America/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "America/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "America/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "America/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+#, fuzzy
+msgid "America/Marigot"
+msgstr "America/Maceio"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "America/Martinique"
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "America/Manaus"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "America/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "America/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "America/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "America/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "America/Mexico_City"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "America/Miquelon"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "America/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "America/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "America/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "America/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "America/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "America/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "America/New_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+#, fuzzy
+msgid "Eastern Time"
+msgstr "US/Eastern"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "America/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "America/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "America/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+#, fuzzy
+msgid "Atlantic islands"
+msgstr "Atlantic/Canary"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "America/North_Dakota/Center"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "America/North_Dakota/New_Salem"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "America/Managua"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "America/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "America/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "America/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "America/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "America/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "America/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "America/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "America/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "America/Puerto_Rico"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "America/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "America/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "America/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "America/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+#, fuzzy
+msgid "America/Resolute"
+msgstr "America/Belem"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "America/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "America/Rosario"
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "America/Santiago"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+#, fuzzy
+msgid "America/Santarem"
+msgstr "America/Santiago"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "America/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "America/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "America/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "America/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "America/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+#, fuzzy
+msgid "America/St_Barthelemy"
+msgstr "America/Belem"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "America/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "America/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "America/St_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "America/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "America/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "America/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "America/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "America/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "America/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "America/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "America/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "America/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "America/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "America/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "America/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "America/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "America/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "America/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antarctica/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antarctica/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antarctica/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+#, fuzzy
+msgid "Antarctica/Macquarie"
+msgstr "Antarctica/McMurdo"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antarctica/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antarctica/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antarctica/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antarctica/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antarctica/South_Pole"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antarctica/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antarctica/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Arctic/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Asia/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Asia/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Asia/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Asia/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Asia/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Asia/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Asia/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Asia/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Asia/Baghdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Asia/Bahrain"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Asia/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Asia/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Asia/Beirut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Asia/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Asia/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Asia/Calcutta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Asia/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Asia/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Asia/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Asia/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Asia/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Asia/Damascus"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Asia/Dhaka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Asia/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Asia/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Asia/Dushanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Asia/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Asia/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+#, fuzzy
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Asia/Chongqing"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Asia/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Asia/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Asia/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Asia/Istanbul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Asia/Jakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Asia/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Asia/Jerusalem"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Asia/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Asia/Kamchatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Asia/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Asia/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+#, fuzzy
+msgid "Asia/Kathmandu"
+msgstr "Asia/Katmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Asia/Katmandu"
+
+#: timezones.h:518
+#, fuzzy
+msgid "Asia/Kolkata"
+msgstr "Asia/Jakarta"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Asia/Krasnoyarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Asia/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Asia/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Asia/Kuwait"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Asia/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Asia/Macau"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Asia/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Asia/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Asia/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Asia/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Asia/Nicosia"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "Asia/Irkutsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Asia/Novosibirsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Asia/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+#, fuzzy
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Asia/Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Asia/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Asia/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Asia/Phnom_Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Asia/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Asia/Pyongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Asia/Qatar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Asia/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Asia/Rangoon"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Asia/Riyadh"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Asia/Riyadh87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Asia/Riyadh88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Asia/Riyadh89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Asia/Saigon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Asia/Sakhalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Asia/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Asia/Seoul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Asia/Shanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Asia/Singapore"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Asia/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Asia/Tashkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Asia/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Asia/Tehran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Asia/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Asia/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Asia/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Asia/Tokyo"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Asia/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Asia/Ulaanbaatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Asia/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Asia/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Asia/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Asia/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Asia/Yakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Asia/Yekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Asia/Yerevan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlantic/Azores"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlantic/Bermuda"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlantic/Canary"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlantic/Cape_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlantic/Faeroe"
+
+#: timezones.h:616
+#, fuzzy
+msgid "Atlantic/Faroe"
+msgstr "Atlantic/Faeroe"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlantic/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlantic/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlantic/Reykjavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlantic/South_Georgia"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlantic/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlantic/St_Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Australia/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Australia/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+#, fuzzy
+msgid "South Australia"
+msgstr "Australia/ACT"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Australia/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Australia/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Australia/Canberra"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Australia/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Australia/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+#, fuzzy
+msgid "Australia/Eucla"
+msgstr "Australia/Queensland"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+#, fuzzy
+msgid "Western Australia - Eucla area"
+msgstr "Australia/Queensland"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Australia/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Australia/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Australia/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Australia/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Australia/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+#, fuzzy
+msgid "Victoria"
+msgstr "Australia/Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Australia/North"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Australia/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Australia/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Australia/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Australia/South"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Australia/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Australia/Tasmania"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Australia/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Australia/West"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Australia/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brazil/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brazil/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brazil/East"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brazil/West"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Canada/Atlantic"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Canada/Central"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Canada/Eastern"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Canada/East-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Canada/Mountain"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Canada/Newfoundland"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Canada/Pacific"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Canada/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Canada/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Chile/Continental"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Chile/EasterIsland"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Cuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Egypt"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Eire"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Europa/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Europa/Andorra"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Europa/Athens"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Europa/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Europa/Belgrad"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Europa/Berlin"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Europa/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Europa/Brussels"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Europa/Bucureşti"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Europa/Budapesta"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Europa/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Europa/Copenhagen"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Europa/Dublin"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Europa/Gibraltar"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Europe/Guernsey"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Europa/Helsinki"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Europe/Isle_of_Man"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Europa/Istanbul"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Europe/Jersey"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Europa/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Europa/Kiev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Europa/Lisabona"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Europa/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Europa/London"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Europa/Luxemburg"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Europa/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Europa/Malta"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Europa/Mariehamn"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Europa/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Europa/Monaco"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Europa/Moscova"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Europa/Nicosia"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Europa/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Europa/Paris"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Europe/Podgorica"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Europa/Prague"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Europa/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Europa/Roma"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Europa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Europa/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Europa/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Europa/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Europa/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Europa/Sofia"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Europa/Stockholm"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Europa/Tallinn"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Europa/Tirane"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Europa/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Europa/Uzhgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Europa/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Europa/Vatican"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Europa/Vienna"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Europa/Vilnius"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Europe/Volgograd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Europa/Warsaw"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Europa/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Europa/Zaporozhye"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Europa/Zurich"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Factory"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Eire"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Iceland"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Indian/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Indian/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Indian/Christmas"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Indian/Cocos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Indian/Comoro"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Indian/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Indian/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Indian/Maldives"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Indian/Mauritius"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Indian/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Indian/Reunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Iran"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Israel"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamaica"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Japan"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Libya"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Mexic/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Mexic/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Mexic/General"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Mideast/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Mideast/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Mideast/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Pacific/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Pacific/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Pacific/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+#, fuzzy
+msgid "Chatham Islands"
+msgstr "Chile/EasterIsland"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "Pacific/Truk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+#, fuzzy
+msgid "Pacific/Easter"
+msgstr "Pacific/Easter"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Pacific/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Pacific/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Pacific/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Pacific/Fiji"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Pacific/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Pacific/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Pacific/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Pacific/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Pacific/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Pacific/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+#, fuzzy
+msgid "Hawaii"
+msgstr "US/Hawaii"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Pacific/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Pacific/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Pacific/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+#, fuzzy
+msgid "Kosrae"
+msgstr "Israel"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Pacific/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Pacific/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Pacific/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Pacific/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Pacific/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Pacific/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Pacific/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Pacific/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Pacific/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Pacific/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Pacific/Pitcairn"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "Pacific/Ponape"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Pacific/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Pacific/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Pacific/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Pacific/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Pacific/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Pacific/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Pacific/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+#, fuzzy
+msgid "Gilbert Islands"
+msgstr "Chile/EasterIsland"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Pacific/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Pacific/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Pacific/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Pacific/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Pacific/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Poland"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugal"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapore"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Turkey"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "US/Alaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "US/Aleutian"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "US/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "US/Central"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "US/Eastern"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "US/East-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "US/Hawaii"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "US/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "US/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "US/Mountain"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "US/Pacific"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "US/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
+
+#~ msgid "US/Pacific-New"
+#~ msgstr "US/Pacific-New"
diff --git a/panels/datetime/po-timezones/ru.po b/panels/datetime/po-timezones/ru.po
new file mode 100644
index 0000000..92e6683
--- /dev/null
+++ b/panels/datetime/po-timezones/ru.po
@@ -0,0 +1,3250 @@
+# translation of ru.po to Russian
+# Andrew Martynov <andrewm@inventa.ru>, 2004, 2006.
+# Yulia <ypoyarko@redhat.com>, 2006, 2009, 2010.
+# translation of ru.po to
+msgid ""
+msgstr ""
+"Project-Id-Version: ru\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-09-06 09:19\n"
+"Last-Translator: Yulia <ypoyarko@redhat.com>\n"
+"Language-Team: Russian\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: \n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Африка/Абиджан"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Африка/Аккра"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Африка/Аддис-Абеба"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Африка/Алжир"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "Африка/Асмара"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Африка/Асмэра"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Африка/Бамако"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Африка/Банги"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Африка/Банжул"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Африка/Бисау"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Африка/Блантайр"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Африка/Браззавиль"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Африка/Бужумбура"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Африка/Каир"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Африка/Касабланка"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Африка/Сеута"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "Сеута и Мелилла"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Африка/Конакри"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Африка/Дакар"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Африка/Дар-эс-Салам"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Африка/Джибути"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Африка/Дуала"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Африка/Эль_Аюн"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Африка/Фритаун"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Африка/Габороне"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Африка/Хараре"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Африка/Йоханнесбург"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Африка/Кампала"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Африка/Хартум"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Африка/Кигали"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Африка/Киншаса"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "Запад Дем. Республики Конго"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Африка/Лагос"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Африка/Либревиль"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Африка/Ломе"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Африка/Луанда"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Африка/Лубумбаши"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "Восток Дем. Республики Конго"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Африка/Лусака"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Африка/Малабо"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Африка/Мапуту"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Африка/Масеру"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Африка/Мамбоне"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Африка/Могадишо"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Африка/Монровия"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Африка/Найроби"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Африка/Нджамена"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Африка/Ниамей"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Африка/Нуакшот"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Африка/Уагадугу"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Африка/Порто-Ново"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Африка/Сан_Томе"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Африка/Томбукту"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Африка/Триполи"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Африка/Тунис"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Африка/Виндхук"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Америка/Адак"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Алеутские острова"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Америка/Анкоридж"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Аляска время"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Америка/Ангилья"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Америка/Антигуа"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Америка/Арагуаина"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "Токантинс"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Америка/Аргентина/Буэнос_Айрес"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Буэнос-Айрес (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Америка/Аргентина/Катамарка"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "Катамарка (CT), Чубут (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Америка/Аргентина/Комодоро-Ривадавия"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Америка/Аргентина/Кордова"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "основная часть (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Америка/Аргентина/Жужуй"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Жужуй (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Америка/Аргентина/Ла-Риоха"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "Ла-Риоха (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Америка/Аргентина/Мендоса"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "Мендоза (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Америка/Аргентина/Рио-Гальегос"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "Санта-Круз (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "Америка/Аргентина/Сальта"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Америка/Аргентина/Сан-Хуан"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "Сан-Хуан (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "Америка/Аргентина/Сан-Луис"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "Сан-Луис (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Америка/Аргентина/Тукуман"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "Тукуман (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Америка/Аргентина/Ушуая"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "Архипелаг Огненная Земля (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Америка/Аруба"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Америка/Асунсьон"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Америка/Атикокан"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "Восточное стандартное время &mdash; Атикокан, Онтарио и Саутгемптон, Нунавут"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Америка/Атка"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Америка/Байя"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "Байя"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "Америка/Байя-де-Бандерас"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "Центральное время (Мексика) &mdash; Байя-де-Бандерас"
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Америка/Барбадос"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Америка/Белен"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "Амапа, восток Пара"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Америка/Белиз"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "Америка/Бланк-Саблон"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "Атлантическое стандартное время &mdash; Квебек - Северный берег"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Америка/Боа_Виста"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "Рорайма"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Америка/Богота"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Америка/Бойсе"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "Горное время &mdash; южный Айдахо и восточный Орегон"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Америка/Буэнос_Айрес"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Америка/Кеймбридж-Бей"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "Горное время &mdash; западный Нунавут"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "Америка/Кампо-Гранде"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "Мато-Гроссо-ду-Сул"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Америка/Канкун"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "Центральное время &mdash; Квинтана-Роо"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Америка/Каракас"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Америка/Катамарка"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Америка/Кайенна"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Америка/Кайманы"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Америка/Чикаго"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "Центральное время"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Америка/Чиуауа"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "Горное время (Мексика) &mdash; Чиуауа за пределами границы США"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "Америка/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Америка/Кордова"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Америка/Коста_Рика"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Америка/Куяба"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "Мато-Гроссо"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Америка/Кюрасао"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Америка/Денмаркшавн"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "востоное побережье, север Скорсбизунд"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Америка/Доусон"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "Тихоокеанское время &mdash; северный Юкон"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Америка/Досон_Крик"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid "Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+"Горное стандартное время &mdash; Досон крик, Форт Сен-Джон, Британская "
+"Колумбия"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Америка/Денвер"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "Горное время"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Америка/Детройт"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "Восточное время &mdash; Мичиган - основная часть"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Америка/Доминиканская_респ"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Америка/Эдмонтон"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+"Горное время &mdash; Альберта, восток Британской Колумбии и западный "
+"Саскачеван"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Америка/Эйрунепе"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "Амазонас, запад"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Америка/Сальвадор"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Америка/Енсенада"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Америка/Форталеза"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "Северо-восток Бразилии (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Америка/Форт-Уэйн"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Америка/Глейс-Бей"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+"Атлантическое время &mdash; Новая Шотландия - где не учитывается дневной "
+"стандарт 1966-1971"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Америка/Готхоб"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "основная часть"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Америка/Гус_Бей"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "Атлантическое время &mdash; Лабрадор - основная часть"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Америка/Гранд_Терк"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Америка/Гренада"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Америка/Гуаделупе"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Америка/Гватемала"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Америка/Гуаякиль"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "материк"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Америка/Гайана"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Америка/Галифакс"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "Атлантическое время &mdash; Новая Шотландия (основная часть)"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Америка/Гавана"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Америка/Эрмосильо"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "Горное стандартное время &mdash; Сонора"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Америка/Индиана/Индианаполис"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "Восточное время &mdash; Индиана - основная часть"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Америка/Индиана/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "Центральное время &mdash; Индиана - округ Старк"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Америка/Индиана/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "Восточное время &mdash; Индиана - округ Кроуфорд"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "Америка/Индиана/Петербург"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "Восточное время &mdash; Индиана - округ Пайк"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Америка/Индианаполис"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "Америка/Индиана/Tell_City"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "Центральное время &mdash; Индиана - округ Перри"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Америка/Индиана/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "Восточное время &mdash; Индиана - округ Швейцария"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "Америка/Индиана/Винсеннес"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "Восточное время &mdash; Индиана - округ Дейвес, Дюбуа, Нокс, Мартин"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "Америка/Индиана/Winamac"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "Восточное время &mdash; Индиана - округ Пуласки"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Америка/Инувик"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "Горное время &mdash; западная часть Северозападных Территорий"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Америка/Икалуит"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "Восточное время &mdash; восточный Нунавут - основная часть"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Америка/Ямайка"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Америка/Жужуй"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Америка/Джуно"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "Аляска"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Америка/Кентукки/Луисвилл"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Восточное время &mdash; Кентукки - Луисвилл"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Америка/Кентукки/Монтичелло"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "Восточное время &mdash; Кентукки - округ Уэйн"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Америка/Кнокс_Ин"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Америка/Ла_Пас"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Америка/Лима"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Америка/Лос_Анжелес"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "Тихоокеанское время"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Америка/Луисвилл"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Америка/Масейо"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "Алагоас, Серджпайп"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Америка/Манагуа"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Америка/Манаус"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "Амазонас, восток"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "Америка/Маригот"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Америка/Мартиника"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "Америка/Матаморос"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid "US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+"Центральное время (США) &mdash; Коауила, Дуранго, Нуэво-Леон, Тамаулипас "
+"возле границы США"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Америка/Масатлан"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "Горное время &mdash; Байя, Наярит, Синалоа"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Америка/Мендоса"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Америка/Меномини"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "Центральное время &mdash; Мичиган - округ Дикинсон, Годжебик, Айрон, Меномини"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Америка/Мерида"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "Центральное время &mdash; Кампече, Юкатан"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Америка/Мехико"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "Центральное время &mdash; основная часть"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Америка/Микелон"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "Америка/Монктон"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "Атлантическое время &mdash; Новый Брансвик"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Америка/Монтеррей"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+"Центральное время (Мексика) &mdash; Коауила, Дуранго, Нуэво-Леон, Тамаулипас "
+"за пределами границы США"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Америка/Монтевидео"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Америка/Монреаль"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "Восточное время &mdash; Квебек - основная часть"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Америка/Монтсеррат"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Америка/Нассау"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Америка/Нью_Йорк"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "Восточное время"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Америка/Нипигон"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid "Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+"Восточное время &mdash; Онтарио и Квебек - где не учитывается дневной "
+"стандарт 1967-1973"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Америка/Ном"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "Аляска время &mdash; западная Аляска"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Америка/Норонья"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "Острова Атлантического океана"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Америка/Северная_Дакота/Центр"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "Центральное время &mdash; Северная Дакота - Округ Оливер"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "Америка/Северная_Дакота/Нью_Салем"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "Центральное время &mdash; Северная Дакота - Округ Мортон (кроме Мандэн)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "Америка/Охинага"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "Горное время (США) &mdash; Чиуауа возле границы США"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Америка/Панама"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Америка/Пангниртанг"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "Восточное время &mdash; Паниртанг, Нунавут"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Америка/Парамарибо"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Америка/Феникс"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "Горное стандартное время &mdash; Аризона"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Америка/Порт-о-Пренс"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Америка/Порт_Акра"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Америка/Порт_оф_Спейн"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Америка/Порто_Велью"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "Рондония"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Америка/Пуэрто-Рико"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Америка/река_Рейни"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "Центральное время &mdash; Рейни Ривер и Форт Франсис, Онтарио"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Америка/залив_Ранкин"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "Центральное время &mdash; центральный Нунавут"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Америка/Ресифи"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "Пернамбуку"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Америка/Реджайна"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "Центральное стандартное время &mdash; Саскачеван - основная часть"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "Америка/Резолют"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "Восточное стандартное время &mdash; Резолют, Нунавут"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Америка/Риу_Бранку"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "Акре"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Америка/Росарио"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "Америка/Санта-Изабел"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+"Тихоокеанское время (Мексика) &mdash; Нижняя Калифорния за пределами границы "
+"США"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "Америка/Сантарем"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "Запад Пара"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Америка/Сантьяго"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Америка/Санто-Доминго"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Америка/Сан_Паулу"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "Юг и юго-восток Бразилии (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Америка/Скорсбисунн"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "Скорсбизунд / Итокортурмиит"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Америка/Шипрок"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "Горное время &mdash; Навахо"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "Америка/St_Barthelemy"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Америка/Сент-Джонс"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "Ньюфаундленд, юго-восток Лабрадора"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Америка/Сент-Китс"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Америка/Сент-Люсия"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Америка/Сент_Томас"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Америка/Сент_Винсент"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Америка/Суифт-Каррент"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "Центральное стандартное время &mdash; Саскачеван - средний запад"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Америка/Тегусигальпа"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Америка/Туле"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "Туле / Питуфик"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Америка/Тандер-Бей"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "Восточное время &mdash; Тандер-Бей, Онтарио"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Америка/Тихуана"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "Тихоокеанское время (США) &mdash; Нижняя Калифорния возле границы США"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "Америка/Торонто"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "Восточное время &mdash; Онтарио - основная часть"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Америка/Тортола"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Америка/Ванкувер"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "Тихоокеанское время &mdash; западная часть Британской Колумбии"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Америка/Вирджин"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Америка/Уайтхорс"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "Тихоокеанское время &mdash; южный Юкон"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Америка/Виннипег"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "Центральное время &mdash; Манитоба и западный Онтарио"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Америка/Якутат"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "Аляска время &mdash; Аляска, перешеек"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Америка/Йеллоунайф"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "Горное время &mdash; центральная часть Северозападных Территорий"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Антарктика/Кейси"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "Кейси, станция Кейси, полуостров Бейли"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Антарктика/Дейвис"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "Дейвис, станция Дейвис, Вестфолд Хиллс"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Антарктика/Дюмон_д_Юрвиль"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "Дюмон-д-Юрвиль, станция Дюмон-д-Юрвиль, Терра-Адели"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "Антарктика/Маккуори"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "Станция на острове Маккуори, о. Маккуори"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Антарктика/Моусон"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "Моусон, станция Моусон, бух. Холме"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Антарктика/Мак_Мердо"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "Мак-Мердо, станция Мак-Мердо, остров Росс"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Антарктика/Палмер"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "Палмер, станция Палмер, остров Анверс"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Антарктика/Ротера"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "Ротера, станция Ротера, остров Аделаиды"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Антарктика/Южный_Полюс"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "Амудсен-Скотт, станция Амудсен-Скотт, Южный полюс"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Антарктика/Сёва"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "Сёва, станция Сёва"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Антарктика/Восток"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "Станция Восток, Южный полюс"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Арктика/Лонгйир"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Азия/Аден"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Азия/Алматы"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Азия/Амман"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Азия/Анадырь"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "Москва+08 &mdash; Берингово море"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Азия/Актау"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "Атырау (бывший Гурьев), Мангыстау"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Азия/Актюбинск"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "Актюбинск"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Азия/Ашгабад"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Азия/Ашхабад"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Азия/Багдад"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Азия/Бахрейн"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Азия/Баку"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Азия/Банкок"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Азия/Бейрут"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Азия/Бишкек"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Азия/Бруней"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Азия/Калькутта"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Азия/Чойбалсан"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "Дорнод, Сухбатаар"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Азия/Чунцин"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "Центральная часть Китая - Сычуань, Юннань, Гуанси, Шеньси, Гуанчжоу и др."
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Азия/Чункинг"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Азия/Коломбо"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Азия/Дака"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Азия/Дамаск"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Азия/Дакка"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Азия/Дили"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Азия/Дубай"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Азия/Душанбе"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Азия/Газа"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Азия/Харбин"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "Хэйлунцзян (кроме Мохе), Цзилинь"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Азия/Хо-Чи-Мин"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Азия/Гонконг"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Азия/Ховд"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "Байан-Олгы, Гови-Алтай, Ховд, Увс, Завхан"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Азия/Иркутск"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Москва+05 - Байкал"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Азия/Стамбул"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Азия/Джакарта"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "Ява и Суматра"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Азия/Джаяпура"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "Ириан Джайя и Молуккские острова"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Азия/Иерусалим"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Азия/Кабул"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Азия/Камчатка"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "Москва+08 &mdash; Камчатка"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Азия/Карачи"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Азия/Кашгар"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "Западный Тибет и Синцзян"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "Азия/Катманду"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Азия/Катманду"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "Азия/Калькутта"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Азия/Красноярск"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "Москва+04 - Енисей"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Азия/Куала_Лумпур"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "Малайзия, полуостровная"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Азия/Кучинг"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "Саба и Саравак"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Азия/Кувейт"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Азия/Макао"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Азия/Макао"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Азия/Магадан"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "Москва+08 - Магадан"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Азия/Макасарский_пролив"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "Южный и восточный Борнео, Целебес, Бали, Нуса Тенгара, западный Тимор"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Азия/Манила"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Азия/Маскат"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Азия/Никозия"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "Азия/Новокузнецк"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Москва+03 &mdash; Новокузнецк"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Азия/Новосибирск"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Москва+03 - Новосибирск"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Азия/Омск"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "Москва+03 - запад Сибири"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Азия/Уральск"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "Западная часть Казахстана"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Азия/Пномпень"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Азия/Понтианак"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "Западный и центральный Борнео"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Азия/Пхеньян"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Азия/Катар"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Азия/Кзыл-Орда"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "Кызылорда"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Азия/Рангун"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Азия/Эр-Рияд"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Азия/Эр-Рияд87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Азия/Эр-Рияд88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Азия/Эр-Рияд89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Азия/Сайгон"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Азия/Сахалин"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "Москва+07 - Сахалин, остров"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Азия/Самарканд"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "Западная часть Узбекистана"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Азия/Сеул"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Азия/Шанхай"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "Восточная часть Китая - Пекин, Гуандун, Шанхай и др."
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Азия/Сингапур"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Азия/Тайпей"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Азия/Ташкент"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "Восточная часть Узбекистана"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Азия/Тбилиси"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Азия/Тегеран"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Азия/Тель-Авив"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Азия/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Азия/Тхимпху"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Азия/Токио"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Азия/Юнг_Падан"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Азия/Улан-Батор"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Азия/Улан_Батор"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Азия/Урумчи"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "Основная часть Тибета и Синцзян"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Азия/Вьентьян"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Азия/Владивосток"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "Москва+07 - Амур"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Азия/Якутск"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "Москва+06 - река Лена"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Азия/Екатеринбург"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "Москва+02 - Урал"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Азия/Ереван"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Атлантический океан/Азорские_острова"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "Азорские острова"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Атлантический океан/Бермуды"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Атлантический океан/Канары"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "Канарские острова"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Атлантический океан/Острова_Зеленого_Мыса"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Атлантический океан/Фарерские_острова"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "Атлантический океан/Фарерские_острова"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Атлантический океан/Ян_Майен"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Атлантический океан/Мадейра"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "Мадейра, острова"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Атлантический океан/Рейкявик"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Атлантический океан/Южная_Георгия"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Атлантический океан/Фолклендские_острова"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Атлантический океан/Св_Елена"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Австралия/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Австралия/Аделаида"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "Южная Австралия"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Австралия/Брисбен"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "Квинсленд - основная часть"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Австралия/Брокен_Хилл"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "Новый Южный Уэльс - Янковинна"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Австралия/Канберра"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Австралия/Кернс"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "Тасмания - остров Кинг"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Австралия/Дарвин"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "Северная территория"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "Австралия/Юкла"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "Западная Австралия - Юкла"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Австралия/Хобарт"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "Тасмания - основная часть"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Австралия/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Австралия/Линдеман"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "Квинсленд - острова Холидей"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Австралия/Лорд_Хау"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "Лорд Хау, остров"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Австралия/Мельбурн"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "Виктория"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Австралия/Север"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Австралия/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Австралия/Перт"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "Западная Австралия - основная часть"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Австралия/Квинсленд"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Австралия/Юг"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Австралия/Сидней"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "Новый Южный Уэльс - основная часть"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Австралия/Тасмания"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Австралия/Виктория"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Австралия/Запад"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Австралия/Янковина"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Бразилия/Акри"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Бразилия/ДеНоронья"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Бразилия/Запад"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Бразилия/Восток"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Канада/Атлантика"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Канада/Центр"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Канада/Восток"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Канада/Восточный_Саскачеван"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Канада/Горы"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Канада/Ньюфаундленд"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Канада/Тихий_океан"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Канада/Саскачеван"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Канада/Юкон"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Чили/Континентальный"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Чили/Остров_Пасхи"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Куба"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Египт"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Eire"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Гринвич"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Зулу"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Европа/Амстердам"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Европа/Андорра"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Европа/Афины"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Европа/Белфаст"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Европа/Белград"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Европа/Берлин"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Европа/Братислава"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Европа/Брюссель"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Европа/Бухарест"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Европа/Будапешт"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Европа/Кишинев"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Европа/Копенгаген"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Европа/Дублин"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Европа/Гибралтар"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Европа/Гернси"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Европа/Хельсинки"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Европа/Остров_Мэн"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Европа/Стамбул"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Европа/Джерси"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Европа/Калининград"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Москва-01 - Калининград"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Европа/Киев"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Европа/Лиссабон"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Европа/Любляна"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Европа/Лондон"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Европа/Люксембург"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Европа/Мадрид"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Европа/Мальта"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Европа/Мариехамн"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Европа/Минск"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Европа/Монако"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Европа/Москва"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "Москва+00 - Западная часть России"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Европа/Никозия"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Европа/Осло"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Европа/Париж"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Европа/Подгорица"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Европа/Прага"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Европа/Рига"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Европа/Рим"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Европа/Самара"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Москва &mdash; Самара, Удмуртия"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Европа/Сан_Марино"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Европа/Сараево"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Европа/Симферополь"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "Центральный Крым"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Европа/Скопье"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Европа/София"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Европа/Стокгольм"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Европа/Таллинн"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Европа/Тарана"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Европа/Тирасполь"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Европа/Ужгород"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "Малороссия"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Европа/Вадуц"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Европа/Ватикан"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Европа/Вена"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Европа/Вильнюс"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Европа/Волгоград"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "Москва+00 - Каспийское море"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Европа/Варшава"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Европа/Загреб"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Европа/Запорожье"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "Запорожье, Луганск"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Европа/Цюрих"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Factory"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Eire"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Гринвич"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Гонконг"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Исландия"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Индия/Антананариву"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Индия/Чагос"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Индия/Остров_Рождества"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Индия/Кокосовые_острова"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Индия/Коморские_острова"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Индия/Кергелен"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Индия/Маэ"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Индия/Мальдивская_респ"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Индия/Маврикий"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Индия/Майотта"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Индия/Реюньон"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Иран"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Израиль"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Ямайка"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Япония"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Кваджалейн"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Ливия"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Мексика/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Мексика/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Мексика/General"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Средняя_Азия/Рияд87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Средняя_Азия/Рияд88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Средняя_Азия/Рияд89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Тихий океан/Апиа"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Тихий океан/Окленд"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Тихий океан/Чатем"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "Чатем, острова"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "Тихий океан/Чуук"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "Чуук (Трук) и Яп"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Тихий океан/Остров_Пасхи"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "Остров Пасхи и Сала-и-Гомес"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Тихий океан/Эфате"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Тихий океан/Эндербери"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "Феникс, острова"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Тихий океан/Факаофо"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Тихий океан/Фиджи"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Тихий океан/Фунафути"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Тихий океан/Галапагоские_острова"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "Галапагосские острова"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Тихий океан/Гамбье"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "Острова Гамбье"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Тихий океан/Гуадалканал"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Тихий океан/Гуам"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Тихий океан/Гонолулу"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "Гавайи"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Тихий океан/Джонстон"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "Атолл Джонстон"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Тихий океан/Киритимати"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "Лайн, острова"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Тихий океан/Кусаие"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "Косрае"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Тихий океан/Кваджалейн"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Тихий океан/Маджуро"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Тихий океан/Маркизские_острова"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "Маркизские острова"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Тихий океан/Мидуэй"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "Мидуэй, острова"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Тихий океан/Науру"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Тихий океан/Ниуэ"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Тихий океан/Норфолк"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Тихий океан/Нумеа"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Тихий океан/Паго_Паго"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Тихий океан/Палау"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Тихий океан/Острова_Питкерн"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "Тихий океан/Понпеи"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "Понпеи (Понапе)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Тихий океан/Понпеи"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Тихий океан/Порт_Морсби"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Тихий океан/Раротонга"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Тихий океан/Сайпан"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Тихий океан/Самоа"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Тихий океан/Таити"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "Острова Общества"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Тихий океан/Тарава"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "Гилберта, острова"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Тихий океан/Тонгатапу"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Тихий океан/Трук"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Тихий океан/Уэйк"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "Уэйк, остров"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Тихий океан/Уоллис"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Тихий океан/Яп"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Польша"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Португалия"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Сингапур"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Турция"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "США/Аляска"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "США/Алеутские_острова"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "США/Аризона"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "США/Центр"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "США/Восток"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "США/Западная_Индиана"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "США/Гавайи"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "США/Индиана-Старк"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "США/Мичиган"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "США/Горы"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "США/Тихий_океан"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "США/Самоа"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Зулу"
+
diff --git a/panels/datetime/po-timezones/si.po b/panels/datetime/po-timezones/si.po
new file mode 100644
index 0000000..03725dc
--- /dev/null
+++ b/panels/datetime/po-timezones/si.po
@@ -0,0 +1,3283 @@
+# translation of si.po to Sinhala
+# Sinhalese translations for PACKAGE package.
+# Copyright (C) 2004 THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Automatically generated, 2004.
+# Tyronne Wickramarathne <tywickra@redhat.com>, 2006.
+msgid ""
+msgstr ""
+"Project-Id-Version: si\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2006-12-13 12:26+0530\n"
+"Last-Translator: Tyronne Wickramarathne <tywickra@redhat.com>\n"
+"Language-Team: Sinhala <en@li.org>\n"
+"Language: si\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "අප්‍රිකාව/අබිජාන්"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "අප්‍රිකාව/අක්‍රා"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "අප්‍රිකාව/අඩ්ඩිස්_අබබා"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "අප්‍රිකාව/ඇල්ජියර්ස්"
+
+#: timezones.h:5
+#, fuzzy
+msgid "Africa/Asmara"
+msgstr "අප්‍රිකාව/ඇස්මරා"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "අප්‍රිකාව/ඇස්මරා"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "අප්‍රිකාව/බැමාකෝ"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "අප්‍රිකාව/බැන්ගුයි"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "අප්‍රිකාව/බැන්ජුල්"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "අප්‍රිකාව/බිස්සායු"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "අප්‍රිකාව/බ්ලැන්ටියර්"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "අප්‍රිකාව/බ්‍රැස්සාවිල්"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "අප්‍රිකාව/බුජුම්බරා"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "අප්‍රිකාව/කයිරෝ"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "අප්‍රිකාව/කැසබලැන්කා"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "අප්‍රිකාව/කියුටා"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "අප්‍රිකාව/කොනාක්‍රි"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "අප්‍රිකාව/ඩකාර්"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "අප්‍රිකාව/ඩාර්_එස්_සලාම්"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "අප්‍රිකාව/ජිබූටි"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "අප්‍රිකාව/ඩුආලා"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "අප්‍රිකාව/එල්_ආයුන්"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "අප්‍රිකාව/ෆ්‍රීටවුන්"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "අප්‍රිකාව/ගැබොරෝන්"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "අප්‍රිකාව/හරාරෙ"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "අප්‍රිකාව/ජොහැනස්බර්ග්"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "අප්‍රිකාව/කම්පාලා"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "අප්‍රිකාව/කාර්ටූම්"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "අප්‍රිකාව/කිලාගි"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "අප්‍රිකාව/කින්ෂාසා"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "අප්‍රිකාව/ලාගොස්"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "අප්‍රිකාව/ලිබ්‍රවිල්"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "අප්‍රිකාව/ලෝම්"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "අප්‍රිකාව/ලුඅන්ඩා"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "අප්‍රිකාව/ලුබුම්බාෂි"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "අප්‍රිකාව/ලුසාකා"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "අප්‍රිකාව/මාලබෝ"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "අප්‍රිකාව/මැපූටෝ"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "අප්‍රිකාව/මැසෙරු"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "අප්‍රිකාව/ම්බැබේන්"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "අප්‍රිකාව/මොගඩිෂු"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "අප්‍රිකාව/මොනොරොවියා"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "අප්‍රිකාව/නයිරෝබි"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "අප්‍රිකාව/ජැමිනා"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "අප්‍රිකාව/නියාමෙයි"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "අප්‍රිකාව/නොයුආක්චොට්"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "අප්‍රිකාව/ඕවාගොඩෞගෝ"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "අප්‍රිකාව/පෝර්ටෝ-නෝවෝ"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "අප්‍රිකාව/සාවො_ටෝම්"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "අප්‍රිකාව/ටිම්බුක්ටු"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "අප්‍රිකාව/ට්‍රිපොලි"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "අප්‍රිකාව/ටියුනිස්"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "අප්‍රිකාව/වින්ඩ්හෝක්"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "ඇමෙරිකාව/ඇඩක්"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+#, fuzzy
+msgid "Aleutian Islands"
+msgstr "ඕස්ට්‍රේලියාච/ක්වීනස්ලන්ඩ්"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "ඇමෙරිකාව/ඇන්කොරාජ්"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+#, fuzzy
+msgid "Alaska Time"
+msgstr "එජ/ඇලස්කාව"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "ඇමෙරිකාව/ඇන්ගුයිලා"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "ඇමෙරිකාව/ඇන්ටිගුවා"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "ඇමෙරිකාව/ඇරගුයිනා"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "ඇමෙරිකාව/අර්ජෙන්ටිනාව/බුවනෝර්ස්_අයර්ස්"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "ඇමෙරිකාව/අර්ජෙන්ටිනාව/කැටමර්කාව"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "ඇමෙරිකාව/අර්ජෙන්ටිනාව/කොමොද්රිවඩවියා"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "ඇමෙරිකාව/අර්ජෙන්ටිනාව/කොර්ඩොබා"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "ඇමෙරිකාව/අර්ජෙන්ටිනාව/ජූජුයි"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "ඇමෙරිකාව/අර්ජෙන්ටිනාව/ලා_රියෝජා"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "ඇමෙරිකාව/අර්ජෙන්ටිනාව/මෙන්ඩෝසා"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "ඇමෙරිකාව/අර්ජෙන්ටිනාව/රියෝ_ගැල්ලෙගොස්"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+#, fuzzy
+msgid "America/Argentina/Salta"
+msgstr "ඇමෙරිකාව/අර්ජෙන්ටිනාව/සෑන්_ජුවෑන්"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "ඇමෙරිකාව/අර්ජෙන්ටිනාව/සෑන්_ජුවෑන්"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+#, fuzzy
+msgid "America/Argentina/San_Luis"
+msgstr "ඇමෙරිකාව/අර්ජෙන්ටිනාව/සෑන්_ජුවෑන්"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "ඇමෙරිකාව/අර්ජෙන්ටිනාව/ටුකුමාන්"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "ඇමෙරිකාව/අර්ජෙන්ටිනාව/උෂුයේයියා"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "ඇමරිකාව/ඇරුබා"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "ඇමරිකාව/ඇසුන්සියොන්"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "ඇමරිකාව/ඇටිකොකාන්"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "ඇමරිකාව/ඇට්කා"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "ඇමරිකාව/බාහියා"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "ඇමරිකාව/බාහියා"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "ඇමරිකාව/බාර්බෙඩාස්"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "ඇමරිකාව/බේලෙම්"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "ඇමරිකාව/බෙලිස්"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "ඇමරිකාව/බ්ලැන්ක්-සැබ්ලොන්"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "ඇමරිකාව/බොවා_විස්ටා"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "ඇමරිකාව/බොගෝටා"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "ඇමරිකාව/බොයිස්"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "ඇමරිකාව/බුවනෝ_අයර්ස්"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "ඇමරිකාව/කේම්බ්‍රිජ්_බොක්ක"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "ඇමරිකාව/කැම්පො_ග්‍රැන්ඩෙ"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "ඇමරිකාව/කන්කුන්"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "ඇමරිකාව/කැරකාස්"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "ඇමරිකාව/කැටමර්කාව"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "ඇමරිකාව/කේයින්නෙ"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "ඇමරිකාව/කේමන්"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "ඇමරිකාව/චිකාගෝ"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+#, fuzzy
+msgid "Central Time"
+msgstr "එජ/මධ්‍යම"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "ඇමරිකාව/චිහුවාහා"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "ඇමරිකාව/කෝරල්_හාර්බර්"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "ඇමරිකාව/කොර්ඩොබා"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "ඇමරිකාව/කොස්ටා_රිකා"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "ඇමරිකාව/කයුයිබා"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "ඇමරිකාව/කුරාකාවෝ"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "ඇමරිකාව/ඩැන්මාර්ක්සෂාව්න්"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "ඇමරිකාව/ඩෝසන්"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "ඇමරිකාව/ඩෝසන්_ක්‍රීක්"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "ඇමරිකාව/ඩෙන්වර්"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+#, fuzzy
+msgid "Mountain Time"
+msgstr "එජ/කඳුකර"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "ඇමරිකාව/ඩේට්‍රියට්"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "ඇමරිකාව/ඩොමිනිකා"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "ඇමරිකාව/එඩ්මන්ටන්"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "ඇමරිකාව/අයිරුනෙපෙ"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "ඇමරිකාව/එල්_සැල්වදෝරය"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "ඇමරිකාව/එන්සෙනඩාව"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "ඇමරිකාව/ෆෝර්ටලේසා"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "ඇමරිකාව/ෆෝර්ට්_වෙයින්"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "ඇමරිකාව/ග්ලේස්_බොක්ක"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "ඇමරිකාව/ගෝඩ්තාබ්"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "ඇමරිකාව/ගූස්_බොක්ක"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "ඇමරිකාව/ග්‍රෑන්ඩ්_ටර්ක්"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "ඇමරිකාව/ග්‍රෙනඩාව"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "ඇමරිකාව/ගෝඩෙලූප්"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "ඇමරිකාව/ගෝතමාලාව"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "ඇමරිකාව/ගෝයාක්විල්"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "ඇමරිකාව/ගයානාව"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "ඇමරිකාව/හේලිෆැක්ස්"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "ඇමරිකාව/හවානා"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "ඇමරිකාව/හර්මොසිල්ලෝ"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "ඇමරිකාව/ඉන්දියානාව/ඉන්දියානාපොලිස්"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "ඇමරිකාව/ඉන්දියානාව/ක්නොක්ස්"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "ඇමරිකාව/ඉන්දියානාව/මෙරෙන්ගෝ"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "ඇමරිකාව/ඉන්දියානාව/පීටර්ස්බර්ග්"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "ඇමරිකාව/ඉන්දියානාපොලිස්/"
+
+#: timezones.h:227
+#, fuzzy
+msgid "America/Indiana/Tell_City"
+msgstr "ඇමරිකාව/ඉන්දියානාව/වෙවෙයි"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "ඇමරිකාව/ඉන්දියානාව/වෙවෙයි"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "ඇමරිකාව/ඉන්දියානාව/වින්සෙන්ස්"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+#, fuzzy
+msgid "America/Indiana/Winamac"
+msgstr "ඇමරිකාව/ඉන්දියානාව/වින්සෙන්ස්"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "ඇමරිකාව/ඉනුවික්"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "ඇමරිකාව/ඉකාලුයිට්"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "ඇමරිකාව/ජැමෙයිකාව"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "ඇමරිකාව/ජූජුයි"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "ඇමරිකාව/ජුනේයු"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "ඇමරිකාව/කෙන්ටකි/ලුයිස්විල්"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+#, fuzzy
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "ඇමරිකාව/කෙන්ටකි/ලුයිස්විල්"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "ඇමරිකාව/කෙන්ටකි/මොන්ටිසෙල්ලෝ"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "ඇමරිකාව/ක්නොකස්_ඉන්"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "ඇමරිකාව/ලා_පෑස්"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "ඇමරිකාව/ලීමා"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "ඇමරිකාව/ලොස්_ඇන්ජලිස්"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+#, fuzzy
+msgid "Pacific Time"
+msgstr "පැසිපික්/නියූ"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "ඇමරිකාව/ලුයිස්විල්"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "ඇමරිකාව/මැසියෝ"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "ඇමරිකාව/මැනගුවා"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "ඇමරිකාව/මැනැයුස්"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+#, fuzzy
+msgid "America/Marigot"
+msgstr "ඇමරිකාව/මැසියෝ"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "ඇමරිකාව/මාර්ටිනික්"
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "ඇමරිකාව/මැනැයුස්"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "ඇමරිකාව/මැසැට්ලෑන්"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "ඇමරිකාව/මෙන්ඩෝසා"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "ඇමරිකාව/මෙනොමිනී"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "ඇමරිකාව/මෙරිඩා"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "ඇමරිකාව/මෙක්සිකෝ _නගරය"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "ඇමරිකාව/මික්විලෝන්"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "ඇමරිකාව/මොන්ක්ටෝන්"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "ඇමරිකාව/මොන්ටෙර්රෙයි"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "ඇමරිකාව/මොන්ටෙවිඩියෝ"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "ඇමරිකාව/මොන්ටෙරියල්"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "ඇමරිකාව/මොන්ට්සෙරාට්"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "ඇමරිකාව/නස්සායු"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "ඇමරිකාව/නිව්_යෝර්ක්"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+#, fuzzy
+msgid "Eastern Time"
+msgstr "එජ/නැගෙනහිර"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "ඇමරිකාව/නිපිගන්"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "ඇමරිකාව/නෝම්"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "ඇමරිකාව/නොරොන්හා"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+#, fuzzy
+msgid "Atlantic islands"
+msgstr "අත්ලාන්තික්/කැනාරි"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "ඇමරිකාව/උතුරු_ඩකෝටා/මධ්‍යම"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "ඇමරිකාව/උතුරු_ඩකෝටා/නව_සාලෙම්"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "ඇමරිකාව/මැනගුවා"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "ඇමරිකාව/පැනමාව"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "ඇමරිකාව/පැනග්නර්ටන්ග්"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "ඇමරිකාව/පැරමාරිබෝ"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "ඇමරිකාව/ෆීනික්ස්"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "ඇමරිකාව/පොර්ට්-ආවු-ප්‍රිනස්"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "ඇමරිකාව/පෝර්ටෝ_ආක්‍රෙ"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "ඇමරිකාව/පෝර්ට්_ඔෆ්_ස්පේන්"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "ඇමරිකාව/පෝර්ටෝ_වෙල්හෝ"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "ඇමරිකාව/පොර්ටෝ_රිකෝ"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "ඇමරිකාව/රේනි_රිවර්"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "ඇමරිකාව/රැන්කින්_ඉන්ලට්"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "ඇමරිකාව/රේසිෆ්"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "ඇමරිකාව/රෙජිනා"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+#, fuzzy
+msgid "America/Resolute"
+msgstr "ඇමරිකාව/බේලෙම්"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "ඇමරිකාව/රියෝ_බ්‍රැන්කෝ"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "ඇමරිකාව/රොසාරියෝ"
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "ඇමරිකාව/සන්තියාගු"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+#, fuzzy
+msgid "America/Santarem"
+msgstr "ඇමරිකාව/සන්තියාගු"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "ඇමරිකාව/සන්තියාගු"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "ඇමරිකාව/සැන්ටෝ_ඩොමින්ගෝ"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "ඇමරිකාව/සාවෝ_පාලෝ"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "ඇමරිකාව/ස්කොර්ස්බිසන්ඩ්"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "ඇමරිකාව/ෂිප්රොක්"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+#, fuzzy
+msgid "America/St_Barthelemy"
+msgstr "ඇමරිකාව/බේලෙම්"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "ඇමරිකාව/ශාන්ත්ත_ජෝන්ස්"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "ඇමරිකාව/ශාන්ත_කිට්ස්"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "ඇමරිකාව/සාන්ත_ලුසියා"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "ඇමරිකාව/ශාන්ත_තෝමස්"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "ඇමරිකාව/ශාන්ත_වින්සන්"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "ඇමරිකාව/ශීඝ්‍ර_වත්මන්"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "ඇමරිකාව/ටෙගුසිගාල්පා"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "ඇමරිකාව/තූල්"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "ඇමරිකාව/තන්ඩර්_බොක්ක"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "ඇමරිකාව/ටිජුවානා"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "ඇමරිකාව/ටොරොන්ටෝ"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "ඇමරිකාව/ටොර්ටෝලා"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "ඇමරිකාව/වැන්කූවර්"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "ඇමරිකාව/වර්ජින්"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "ඇමරිකාව/වයිට්හෝර්ස්"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "ඇමරිකාව/වින්නිපෙග්"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "ඇමරිකාව/යකුටැට්"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "ඇමරිකාව/යෙලෝනයිෆ්"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "ඇන්ටාක්ටිකාව/කැසේ"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "ඇන්ටාක්ටිකාව/ඩේවිස්"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "ඇන්ටාක්ටිකාව/ඩුමොන්ට්ඩර්විල්"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+#, fuzzy
+msgid "Antarctica/Macquarie"
+msgstr "ඇන්ටාක්ටිකාව/මැක්මර්ඩෝ"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "ඇන්ටාක්ටිකාව/මෝසන්"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "ඇන්ටාක්ටිකාව/මැක්මර්ඩෝ"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "ඇන්ටාක්ටිකාව/පාමර්"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "ඇන්ටාක්ටිකාව/රොතේරා"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "ඇන්ටාක්ටිකාව/සවුත්_පෝල්"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "ඇන්ටාක්ටිකාව/සියෝවා"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "ඇන්ටාක්ටිකාව/වොස්ටොක්"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "ආර්ක්ටික්/ලෝන්ග්ඉයර්බ්යෙන්"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "අසියාව/ඒඩන්"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "අසියාව/ඕල්මැටි"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "අසියාව/අම්මාන්"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "අසියාව/ඇනඩිර්"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "අසියාව/ඇක්ටාවු"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "අසියාව/ඇක්ටෝබ්"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "අසියාව/ඇශ්ගාබාට්"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "අසියාව/අශ්කාබාඩ්"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "අසියාව/බෑග්ඩෑග්"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "අසියාව/බහරේන්"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "අසියාව/බකූ"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "අසියාව/බැංකොක්"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "අසියාව/බීරූට්"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "අසියාව/බිෂ්කෙක්"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "අසියාව/බෲනායි"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "අසියාව/කල්කටා"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "අසියාව/චොයිබල්සාන්"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "අසියාව/චොන්කින්"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "අසියාව/චුන්කින්"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "අසියාව/කොළඹ"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "අසියාව/ඩැක්කා"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "අසියාව/ඩෙමස්කස්"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "අසියාව/ඩකා"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "අසියාව/ඩිලි"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "අසියාව/ඩුබායි"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "අසියාව/ඩුෂාන්බෙ"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "අසියාව/ගාසා"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "අසියාව/හාර්බින්"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+#, fuzzy
+msgid "Asia/Ho_Chi_Minh"
+msgstr "අසියාව/චොන්කින්"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "අසියාව/හොං_කොං"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "අසියාව/හෝව්ඩ්"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "අසියාව/ඉර්කට්ස්ක්"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "අසියාව/ඉස්තාන්බුල්"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "අසියාව/ජකර්තා"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "අසියාව/ජයවර්ධන_පුර"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "අසියාව/ජෙරුසලම"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "අසියාව/කාබුල්"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "අසියාව/කම්චට්කා"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "අසියාව/කරච්චිය"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "අසියාව/කෂ්ගාර්"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+#, fuzzy
+msgid "Asia/Kathmandu"
+msgstr "අසියාව/කත්මන්ඩු"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "අසියාව/කත්මන්ඩු"
+
+#: timezones.h:518
+#, fuzzy
+msgid "Asia/Kolkata"
+msgstr "අසියාව/ජකර්තා"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "අසියාව/ක්‍රැස්නොයාර්ස්ක්"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "අසියාව/ක්වාලා_ලම්පූර්"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "අසියාව/කුචින්ග්"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "අසියාව/කුවේට්"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "අසියාව/මැකාවෝ"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "අසියාව/මැකෝ"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "අසියාව/මැගඩෑන්"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "අසියාව/මකැස්සාර්"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "අසියාව/මැනිලා"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "අසියාව/මස්කට්"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "අසියාව/නිකෝසියාව"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "අසියාව/ඉර්කට්ස්ක්"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "අසියාව/නොවොසිබ්‍රිස්ක්"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "අසියාව/නොවොසිබ්‍රිස්ක්"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+#, fuzzy
+msgid "Moscow+03 - Novosibirsk"
+msgstr "අසියාව/නොවොසිබ්‍රිස්ක්"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "අසියාව/ඕම්ස්ක්"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "අසියාව/ඕරල්"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "අසියාව/නොම්_පෙන්"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "අසියාව/පොන්ටියානක්"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "අසියාව/යොංයෑං"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "අසියාව/කටාර්"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "අසියාව/කිසිලෝර්ඩා"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "අසියාව/රැන්ගූන්"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "අසියාව/රියාද්"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "අසියාව/රියාද්87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "අසියාව/රියාද්88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "අසියාව/රියාද්89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "අසියාව/සයගෝන්"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "අසියාව/සකාලින්"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "අසියාව/සැමර්කාන්ඩ්"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "අසියාව/සෝල්"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "අසියාව/ෂැංග්හායි"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "අසියාව/සිංගප්පූරුව"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "අසියාව/තායිපෙ"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "අසියාව/තාෂ්කෙන්ට්"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "අසියාව/බිලිසි"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "අසියාව/ටෙහෙරානය"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "අසියාව/ටෙල්_අවීව්"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "අසියාව/තිම්බු"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "අසියාව/තිම්පු"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "අසියාව/ටෝකියෝ"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "අසියාව/උජන්ග්_පැන්ඩෑං"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "අසියාව/උලාන්බාටර්"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "අසියාව/උලාන්_බාටෝර්"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "අසියාව/උරුම්කි"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "අසියාව/වියටියෙන්"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "අසියාව/ව්ලැඩිවොස්ටොක්"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "අසියාව/යකුට්ස්ක්"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "ආසියාව/යෙකාටෙරින්බර්ග්"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "අසියාව/යෙරෙවාන්"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "අත්ලාන්තික්/ඇසෝරස්"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "අත්ලාන්තික්/බර්මුඩා"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "අත්ලාන්තික්/කැනාරි"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "අත්ලාන්තික්/කේප්_වර්ඩෙ"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "අත්ලාන්තික්/ෆේරෝ"
+
+#: timezones.h:616
+#, fuzzy
+msgid "Atlantic/Faroe"
+msgstr "අත්ලාන්තික්/ෆේරෝ"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "අත්ලාන්තික්/ජෑන්_මායෙන්"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "අත්ලාන්තික්/මැඩේයිරා"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "අත්ලාන්තික්/රෙක්යාවික්"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "අත්ලාන්තික්/දකුණු_ජෝජියාව"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "අත්ලාන්තික්/ස්ටැන්ලි"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "අත්ලාන්තික්/ශාන්ත_හෙලෙනා"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "අත්ලාන්තික්/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "ඕස්ට්‍රේලියාච/ඇඩිලේඩ්"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+#, fuzzy
+msgid "South Australia"
+msgstr "අත්ලාන්තික්/ACT"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "ඕස්ට්‍රේලියාච/බ්‍රිස්බේන්"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "ඕස්ට්‍රේලියාච/බ්‍රෝකන්_හිල්"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "ඕස්ට්‍රේලියාච/කැන්බරා"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "ඕස්ට්‍රේලියාච/කුරී"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "ඕස්ට්‍රේලියාච/ඩාර්වින්"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+#, fuzzy
+msgid "Australia/Eucla"
+msgstr "ඕස්ට්‍රේලියාච/ක්වීනස්ලන්ඩ්"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+#, fuzzy
+msgid "Western Australia - Eucla area"
+msgstr "ඕස්ට්‍රේලියාච/ක්වීනස්ලන්ඩ්"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "ඕස්ට්‍රේලියාච/හෝබාර්ට්"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "ඕස්ට්‍රේලියාච/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "ඕස්ට්‍රේලියාච/ලින්ඩ්මාන්"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "ඕස්ට්‍රේලියාච/ලෝර්ඩ්_හෝව්"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "ඕස්ට්‍රේලියාච/මෙල්බෝන්"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+#, fuzzy
+msgid "Victoria"
+msgstr "ඕස්ට්‍රේලියාච/වික්ටෝරියා"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "ඕස්ට්‍රේලියාච/උතුරු"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "ඕස්ට්‍රේලියාච/නිව්_සවුත්_වේල්ස්"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "ඕස්ට්‍රේලියාච/පර්ත්"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "ඕස්ට්‍රේලියාච/ක්වීනස්ලන්ඩ්"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "ඕස්ට්‍රේලියාච/දකුණු"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "ඕස්ට්‍රේලියාච/සිඩ්නි"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "ඕස්ට්‍රේලියාච/ටස්මේනියාව"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "ඕස්ට්‍රේලියාච/වික්ටෝරියා"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "ඕස්ට්‍රේලියාච/බටහිර"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "ඕස්ට්‍රේලියාච/යැන්කොවින්නා"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "බ්‍රසිලය/ඇක්‍රෙ"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "බ්‍රසිලය/ඩෙනොරොන්හා"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "බ්‍රසිලය/නැගෙනහිර"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "බ්‍රසිලය/බටහිර"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "කැනඩා/අත්ලාන්තික්"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "කැනඩා/මධ්‍යම"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "කැනඩා/නැගෙනහිර"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "කැනඩාව/නැගෙනහිර-සැස්කැච්වාන්"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "කැනඩා/කඳුකර"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "කැනඩා/නිව්ෆවුන්ඩ්ලන්ඩ්"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "කැනඩා/පැසිෆික්"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "කැනඩාව/සැස්කැච්වාන්"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "කැනඩා/යූකෝන්"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "චිලී/කොන්ටිනෙන්ටල්"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "චිලී/ඊස්ටර්අයිලන්ඩ්"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "කියුබාව"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "ඊජිප්තුව"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "අයරය"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/ග්‍රීන්විච්"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/සම්මත"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/සූලු"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "යුරෝපය/ඇමස්ටර්ඩෑම්"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "යුරෝපය/ඇන්ඩෝරා"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "යුරෝපය/ඇතන්ස්"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "යුරෝපය/බෙල්ෆාස්ට්"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "යුරෝපය/බෙල්ග්‍රේඩ්"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "යුරෝපය/බර්ලින්"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "යුරෝපය/බ්‍රැටිස්ලාවා"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "යුරෝපය/බ්‍රසල්ස්"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "යුරෝපය/බුකරස්ට්"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "යුරෝපය/බුඩපෙස්ට්"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "යුරෝපය/චිසිනාවු"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "යුරෝපය/කොපෙන්හාගෙන්"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "යුරෝපය/ඩබ්ලින්"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "යුරෝපය/ගිබ්‍රෝල්ටාර්"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "යුරෝපය/ගුවර්න්සි"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "යුරෝපය/හෙල්සින්කි"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "යුරෝපය/අයිල්_ඔෆ්_මෑන්"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "යුරෝපය/ඉස්තානබුල්"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "යුරෝපය/ජර්සි"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "යුරෝපය/කලිනින්ග්‍රාඩ්"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "යුරෝපය/කීයෙව්"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "යුරෝපය/ලිස්බොන්"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "යුරෝපය/ලුබ්ජානා"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "යුරෝපය/ලන්ඩන්"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "යුරෝපය/ලක්සම්බර්ග්"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "යුරෝපය/මෑඩ්රීඩ්"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "යුරෝපය/මෝල්ටා"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "යුරෝපය/මැරීහැම්න්"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "යුරෝපය/මින්ස්ක්"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "යුරෝපය/මොනාකෝ"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "යුරෝපය/මොස්කව්"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "යුරෝපය/නිකෝසියා"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "යුරෝපය/ඔස්ලෝ"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "යුරෝපය/පැරිස්"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "යුරෝපය/පොඩ්ගොරිකාග්‍රාඩ්"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "යුරෝපය/ප්‍රාග්"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "යුරෝපය/රිගා"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "යුරෝපය/රෝමය"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "යුරෝපය/සමාරා"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "යුරෝපය/සැන්_මැරිනෝ"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "යුරෝපය/සරයේවෝ"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "යුරෝපය/සිම්ෆෙරොපොල්"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "යුරෝපය/ස්කෝයෙ"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "යුරෝපය/සොෆියා"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "යුරෝපය/ස්ටොක්හෝම්"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "යුරෝපය/ටල්ලින්"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "යුරෝපය/ටිරෙන්"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "යුරෝපය/ටිරාස්පොල්"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "යුරෝපය/උස්ගොරෝඩ්"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "යුරෝපය/වැඩුස්"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "යුරෝපය/වතිකානුව"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "යුරෝපය/වියානා"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "යුරෝපය/විල්නියුස්"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "යුරෝපය/වෝලොග්‍රාඩ්"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "යුරෝපය/වෝර්සෝව්"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "යුරෝපය/සැග්රෙබ්"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "යුරෝපය/සැපොරොස්හයි"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "යුරෝපය/සූරික්"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "ෆැක්ටොරි"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "මබ්‍රි"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "මබ්‍රි-ඊරෙ"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "ග්‍රීන්විච්"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "හොංකොං"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "අයිස්ලන්තය"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "ඉන්දියානු/ඇන්ටනානාරිවෝ"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "ඉන්දියානු/චාගොස්"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "ඉන්දියානු/ක්‍රිස්ට්මස්"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "ඉන්දියානු/කොකොස්"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "ඉන්දියානු/කොමොරෝ"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "ඉන්දියානු/කර්ගුයිලෙන්"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "ඉන්දියානු/මේහෙ"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "ඉන්දියානු/මාලදිවයින"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "ඉන්දියානු/මරූටි"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "ඉන්දියානු/මේයොට්"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "ඉන්දියානු/රීයුනියන්"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "ඉරානය"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "ඊශ්‍රායලය"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "ජැමෙයිකාව"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "ජපානය"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "ක්වජලීන්"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "ලිබියාව"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "මෙක්සිකෝ/බජානොර්ටේ"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "මෙක්සිකෝ/බජාසර්"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "මෙක්සිකෝ/සාමාන්‍ය"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "මැදපරදිග/රියාද්87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "මැදපරදිග/රියාද්88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "මැදපරදිග/රියාද්89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "නවජෝ"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "පැසිපික්/ඇපියා"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "පැසිපික්/ඕක්ලන්තය"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "පැසිපික්/චැතම්"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+#, fuzzy
+msgid "Chatham Islands"
+msgstr "චිලී/ඊස්ටර්අයිලන්ඩ්"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "පැසිපික්/ට්‍රක්"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+#, fuzzy
+msgid "Pacific/Easter"
+msgstr "පැසිපික්/ඊස්ටර්"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "පැසිපික්/එෆේට්"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "පැසිපික්/එන්ඩබරි"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "පැසිපික්/ෆැකාවොෆො"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "පැසිපික්/ෆිජි"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "පැසිපික්/ෆුනාෆුටි"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "පැසිපික්/ගලැපැගොස්"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "පැසිපික්/ගැම්බියර්"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "පැසිපික්/ගෝඩල්කැනෑල්"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "පැසිපික්/ගෝම්"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "පැසිපික්/හොනලුලූ"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+#, fuzzy
+msgid "Hawaii"
+msgstr "එජ/හවායි"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "පැසිපික්/ජොන්ස්ටන්"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "පැසිපික්/කිරිටිමාටි"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "පැසිපික්/කොස්රේ"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+#, fuzzy
+msgid "Kosrae"
+msgstr "ඊශ්‍රායලය"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "පැසිපික්/ක්වාජලීන්"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "පැසිපික්/මාජුරෝ"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "පැසිපික්/මාර්ක්‍යුසාස්"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "පැසිපික්/මිඩ්වේ"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "පැසිපික්/නෝරු"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "පැසිපික්/නියූ"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "පැසිපික්/නෝෆෝක්"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "පැසිපික්/නෞමෙයා"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "පැසිපික්/පාගෝ_පාගෝ"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "පැසිපික්/පාලෝ"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "පැසිපික්/පිට්කෙයාර්න්"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "පැසිපික්/පොනාපෙ"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "පැසිපික්/පොනාපෙ"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "පැසිපික්/පෝර්ට්_මොර්ස්බි"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "පැසිපික්/රැරොටොන්ගා"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "පැසිපික්/සායිපාන්"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "පැසිපික්/සැමෝවා"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "පැසිපික්/තයිටි"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "පැසිපික්/ටරාවා"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+#, fuzzy
+msgid "Gilbert Islands"
+msgstr "චිලී/ඊස්ටර්අයිලන්ඩ්"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "පැසිපික්/ටොන්ගටාපු"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "පැසිපික්/ට්‍රක්"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "පැසිපික්/වේක්"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "පැසිපික්/වෝලිස්"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "පැසිපික්/යැප්"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "පෝලන්තය"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "පෘතුගාලය"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "සිංගප්පූරුව"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "තුර්කිය"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "සම්මත"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "එජ/ඇලස්කාව"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "එජ/ඇලූෂන්"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "එජ/ඇරිසෝනාව"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "එජ/මධ්‍යම"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "එජ/නැගෙනහිර"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "එජ/නැගෙනහිර-ඉන්දියානාව"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "එජ/හවායි"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "එජ/ඉන්දියානා-සටාර්ක්"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "එජ/මිචිගන්"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "එජ/කඳුකර"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "එජ/පැසිපික්"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "එජ/සැමෝවා"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "සූලු"
+
+#~ msgid "US/Pacific-New"
+#~ msgstr "එජ/නව-පැසිපික්"
diff --git a/panels/datetime/po-timezones/sk.po b/panels/datetime/po-timezones/sk.po
new file mode 100644
index 0000000..70cdb40
--- /dev/null
+++ b/panels/datetime/po-timezones/sk.po
@@ -0,0 +1,3293 @@
+# timezones sk.po
+# Copyright (C) 2002-2008 RedHat, Inc.
+#
+# Stanislav Meduna <stano@eunet.sk>, 1999.
+# Marcel Telka <marcel@telka.sk>, 2002.
+# Mike Karas <zoliqe@gmail.com>, 2007.
+# Pavol Šimo <palo.simo@gmail.com>, 2008.
+# Ondrej Šulek <feonsu@gmail.com>, 2009, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-10-10 13:33+0200\n"
+"Last-Translator: Ondrej Šulek <feonsu@gmail.com>\n"
+"Language-Team: Slovak <fedora-trans-sk@redhat.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: sk\n"
+"X-Generator: Lokalize 1.1\n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Afrika/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Afrika/Akkra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Afrika/Adis_Abeba"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Afrika/Alžír"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "Afrika/Asmara"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Afrika/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Afrika/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Afrika/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Afrika/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Afrika/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Afrika/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Afrika/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Afrika/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Afrika/Káhira"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Afrika/Kasablanka"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Afrika/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "Ceuta a Melilla"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Afrika/Konakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Afrika/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Afrika/Dar_es_Salám"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Afrika/Džibuti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Afrika/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Afrika/El-Aaiún"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Afrika/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Afrika/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Afrika/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Afrika/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Afrika/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Afrika/Khartoum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Afrika/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Afrika/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "západná Konžská Dem. Rep."
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Afrika/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Afrika/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Afrika/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Afrika/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Afrika/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "východná Konžská Dem. Rep."
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Afrika/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Afrika/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Afrika/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Afrika/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Afrika/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Afrika/Mogadishu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Afrika/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Afrika/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Afrika/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Afrika/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Afrika/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Afrika/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Afrika/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Afrika/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Afrika/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Afrika/Tripoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Afrika/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Afrika/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Amerika/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Aleuty"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Amerika/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Aljašský čas"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Amerika/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Amerika/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Amerika/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "Tocantins"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Amerika/Argentína/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Buenos Aires (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Amerika/Argentína/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "Catamarca (CT), Chubut (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Amerika/Argentína/Rivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Amerika/Argentína/Kordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "väčšina územia (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Amerika/Argentína/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Jujuy (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Amerika/Argentína/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "La Rioja (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Amerika/Argentína/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "Mendoza (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Amerika/Argentína/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "Santa Cruz (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "Amerika/Argentína/Salta"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Amerika/Argentína/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "San Juan (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "Amerika/Argentína/San_Luis"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "San Luis (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Amerika/Argentína/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "Tucuman (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Amerika/Argentína/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "Ohňová zem (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Amerika/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Amerika/Asuncion"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Amerika/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "Východný štandardný čas - Ontário a Southampton I, Nunavut"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Amerika/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Amerika/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "Bahia"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "Amerika/Bahia de Banderas"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "Mexický centrálny čas - Bahia de Banderas"
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Amerika/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Amerika/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "Amapa, E Para"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Amerika/Belize"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "Amerika/Blanc-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "Atlantický štandardný čas - Quebec - Lower North Shore"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Amerika/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "Roraima"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Amerika/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Amerika/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "Horský čas - južné Idaho a východný Oregon"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Amerika/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Amerika/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "Horský čas - západné Nunavut"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "Amerika/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "Mato Grosso do Sul"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Amerika/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "Centrálny čas - Quintana Roo"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Amerika/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Amerika/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Amerika/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Amerika/Cayman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Amerika/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "Centrálny čas"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Amerika/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "Mexický horský čas - Chihuahua ďaleko od hraníc USA"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "Amerika/Coral_Harbour"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Amerika/Cordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Amerika/Costa_Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Amerika/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "Mato Grosso"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Amerika/Curacao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Amerika/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "východné pobrežie, severne od Scoresbysund"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Amerika/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "Pacifický čas - severný Yukon"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Amerika/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+"Horský štandardný čas - Dawson Creek a Fort Saint John, Britská Kolumbia"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Amerika/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "Horský čas"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Amerika/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "Východný čas - Michigan - väčšina územia"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Amerika/Dominica"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Amerika/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "Horský čas - Alberta, východná Britská Kolumbia a západný Saskatchewan"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Amerika/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "Západné Amazonas"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Amerika/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Amerika/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Amerika/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "NE Brazília (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Amerika/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Amerika/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+"Atlantický čas - Nové Škótsko - miesta bez zmeny DST času v rokoch 1966-1971"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Amerika/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "väčšina územia"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Amerika/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "Atlantický čas - Labrador - väčšina územia"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Amerika/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Amerika/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Amerika/Guadeloupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Amerika/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Amerika/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "pevnina"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Amerika/Guyana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Amerika/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "Atlantický čas - Nové Škótsko (väčšina územia), PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Amerika/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Amerika/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "Horský štandardný čas - Sonora"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Amerika/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "Východný čas - Indiana - väčšina územia"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Amerika/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "Centrálny čas - Indiana - Starke County"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Amerika/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "Východný čas - Indiana - Crawford County"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "Amerika/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "Východný čas - Indiana - Pike County"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Amerika/Indianapolis"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "Amerika/Indiana/Tell_City"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "Centrálny čas - Indiana - Perry County"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "Východný čas - Indiana - Switzerland County"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "Amerika/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "Východný čas - Indiana - Daviess, Dubois, Knox a Martin Counties"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "Amerika/Indiana/Winamac"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "Východný čas - Indiana - Pulaski County"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Amerika/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "Horský čas - západné Severozápadné teritóriá"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Amerika/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "Východný čas - východné Nunavut - väčšina územia"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Amerika/Jamaica"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Amerika/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Amerika/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "Aljašský čas - Aljaška panhandle"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Amerika/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Východný čas - Kentucky - oblasť Louisville"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Amerika/Kentucky/Montevideo"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "Východný čas - Kentucky - Wayne County"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Amerika/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Amerika/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Amerika/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Amerika/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "Pacifický čas"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Amerika/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Amerika/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "Alagoas, Sergipe"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Amerika/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Amerika/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "Východné Amazonas"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "Amerika/Marigot"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Amerika/Martinik"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "Amerika/Matamoros"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+"Centrálny čas USA - Coahuila, Durango, Nuevo Leon, Tamaulipas pri hraniciach "
+"USA"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Amerika/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "Horský čas - S Baja, Nayarit, Sinaloa"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Amerika/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Amerika/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+"Centrálny čas - Michigan - Dickinson, Gogebic, Iron a Menominee Counties"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Amerika/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "Centrálny čas - Campeche, Yucatan"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Amerika/Mexico_City"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "Centrálny čas - väčšina územia"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Amerika/Miquelon"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "Amerika/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "Atlantický čas - New Brunswick"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Amerika/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+"Mexický centrálny čas - Coahuila, Durango, Nuevo Leon, Tamaulipas ďaleko od "
+"hraníc USA"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Amerika/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Amerika/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "Východný čas - Quebec - väčšina územia"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Amerika/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Amerika/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Amerika/New_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "Východný čas"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Amerika/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+"Východný čas - Ontário a Quebec - miesta bez zmeny DST času v rokoch 1967-"
+"1973"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Amerika/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "Aljašský čas - západná Aljaška"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Amerika/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "Atlantické ostrovy"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Amerika/North_Dakota/Center"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "Centrálny čas - Severná Dakota - Oliver County"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "Amerika/North_Dakota/New_Salem"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "Centrálny čas - Severná Dakota - Morton County (okrem oblasti Mandan)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "America/Ojinaga"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "Horský čas USA - Chihuahua pri hraniciach USA"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Amerika/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Amerika/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "Východný čas - Pangnirtung, Nunavut"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Amerika/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Amerika/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "Horský štandardný čas - Arizona"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Amerika/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Amerika/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Amerika/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Amerika/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "Rondonia"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Amerika/Puerto_Rico"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Amerika/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "Centrálny čas - Rainy River a Fort Frances, Ontário"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Amerika/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "Centrálny čas - centrálne Nunavut"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Amerika/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "Pernambuco"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Amerika/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "Centrálny štandardný čas - Saskatchewan - väčšina územia"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "Amerika/Resolute"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "Východný štandardný čas - Resolute, Nunavut"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Amerika/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "Acre"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Amerika/Rosario"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "America/Santa_Isabel"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "Mexický pacifický čas - Baja California ďaleko od hraníc USA"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "Amerika/Santarem"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "Západná Para"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Amerika/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Amerika/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Amerika/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "S a SE Brazília (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Amerika/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "Scoresbysund / Ittoqqortoormiit"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Amerika/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "Horský čas - Navajo"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "Amerika/St_Barthélemy"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Amerika/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "Newfoundlandský čas, vrátane SE Labrador"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Amerika/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Amerika/St_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Amerika/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Amerika/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Amerika/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "Centrálny štandardný čas - Saskatchewan - stredný západ"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Amerika/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Amerika/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "Thule / Pituffik"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Amerika/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "Východný čas - Thunder Bay, Ontário"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Amerika/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "USA pacifický čas - Baja California pri hraniciach USA"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "Amerika/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "Východný čas - Ontario - väčšina územia"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Amerika/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Amerika/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "Pacifický čas - západná Britská Kolumbia"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Amerika/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Amerika/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "Pacifický čas - južný Yukon"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Amerika/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "Centrálny čas - Manitoba a západné Ontário"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Amerika/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "Aljašský čas - Aljaška panhandle neck"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Amerika/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "Horský čas - centrálne Severozápadné teritóriá"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antarktída/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "Stanica Casey, Bailey Peninsula"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antarktída/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "Stanica Davis, Vestfold Hills"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antarktída/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "Stanica Dumont-d'Urville, Terre Adelie"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "Antarctica/Macquarie"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "Stanica ostrova Macquarie, Ostrov Macquarie"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antarktída/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "Stanica Mawson, Zátoka Holme"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antarktída/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "Stanica McMurdo, Rossov ostrov"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antarktída/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "Stanica Palmer, Ostrov Anvers"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antarktída/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "Stanica Rothera, Ostrov Adelaide"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antarktída/South_Pole"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "Stanica Amundsen-Scott, Južný pól"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antarktída/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "Stanica Syowa, E Ongul I"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antarktída/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "Stanica Vostok, Južný magnetický pól"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Arktída/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Ázia/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Ázia/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Ázia/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Ázia/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "Moskva+08 - Beringovo more"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Ázia/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Ázia/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "Aqtobe (Aktobe)"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Ázia/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Ázia/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Ázia/Baghdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Ázia/Bahrain"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Ázia/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Ázia/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Ázia/Beirut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Ázia/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Ázia/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Ázia/Calcutta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Ázia/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "Dornod, Sukhbaatar"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Ázia/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "centrálna Čína - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, atď."
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Ázia/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Ázia/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Ázia/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Ázia/Damascus"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Ázia/Dhaka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Ázia/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Ázia/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Ázia/Dušanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Ázia/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Ázia/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "Heilongjiang (okrem Mohe), Jilin"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Ázia/Ho_Chi_Minh"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Ázia/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Ázia/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Ázia/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Moskva+05 - Jazero Bajkal"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Ázia/Istanbul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Ázia/Jakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "Java a Sumatra"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Ázia/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "Irian Jaya a Moluccas"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Ázia/Jeruzalem"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Ázia/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Ázia/Kamčatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "Moskva+08 - Kamčatka"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Ázia/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Ázia/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "západný Tibet a Xinjiang"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "Ázia/Káthmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Ázia/Katmandu"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "Ázia/Kalkata"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Ázia/Krasnoyarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "Moskva+04 - Jenisej"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Ázia/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "Malajský poloostrov"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Ázia/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "Sabah a Sarawak"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Ázia/Kuwait"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Ázia/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Ázia/Macau"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Ázia/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "Moskva+08 - Magadan"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Ázia/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "východné a južné Borneo, Celebes, Bali, Nusa Tengarra, západný Timor"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Ázia/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Ázia/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Ázia/Nicosia"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "Ázia/Novokuzneck"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Moskva+03 - Novokuzneck"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Ázia/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Moskva+03 - Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Ázia/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "Moskva+03 - západný Sibír"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Ázia/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "Západný Kazachstan"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Ázia/Phnom_Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Ázia/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "západné a centrálne Borneo"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Ázia/Pyongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Ázia/Qatar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Ázia/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Ázia/Rangoon"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Ázia/Riyadh"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Ázia/Riyadh87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Ázia/Riyadh88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Ázia/Riyadh89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Ázia/Saigon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Ázia/Sakhalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "Moskva+07 - Ostrov Sachalin"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Ázia/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "západný Uzbekistan"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Ázia/Seoul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Ázia/Shanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "východná Čína - Peking, Guangdong, Šanghaj, atď."
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Ázia/Singapúr"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Ázia/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Ázia/Taškent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "východný Uzbekistan"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Ázia/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Ázia/Teherán"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Ázia/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Ázia/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Ázia/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Ázia/Tokyo"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Ázia/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Ázia/Ulaanbaatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Ázia/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Ázia/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "väčšina Tibetu a Xinjiang"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Ázia/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Ázia/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "Moskva+07 - rieka Amur"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Ázia/Yakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "Moskva+06 - rieka Lena"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Ázia/Yekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "Moskva+02 - Ural"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Ázia/Yerevan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlantik/Azory"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "Azory"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlantik/Bermudy"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlantik/Canary"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "Kanárske ostrovy"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlantik/Cape_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlantik/Faerské ostrovy"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "Atlantik/Faerské ostrovy"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlantik/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlantik/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "Madeira"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlantik/Reykjavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlantik/South_Georgia"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlantik/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlantik/St_Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Austrália/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Austrália/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "Južná Austrália"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Austrália/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "Queensland - väčšina uzemia"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Austrália/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "Nový Južný Wales - Yancowinna"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Austrália/Canberra"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Austrália/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "Tasmánia - Ostrov King"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Austrália/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "Severné teritórium"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "Austrália/Eucla"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "Západná Austrália - oblasť Eucla"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Austrália/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "Tasmánia - väčšina územia"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Austrália/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Austrália/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "Queensland - ostrovy Holiday"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Austrália/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "Ostrov lorda Howa"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Austrália/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Austrália/Sever"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Austrália/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Austrália/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "Západná Austrália - väčšina územia"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Austrália/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Austrália/Juh"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Austrália/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "Nový Južný Wales - väčšina územia"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Austrália/Tasmania"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Austrália/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Austrália/Západ"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Austrália/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brazília/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brazília/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brazília/Východ"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brazília/Západ"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Kanada/Atlantik"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Kanada/Central"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Kanada/Eastern"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Kanada/East-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Kanada/Mountain"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Kanada/Newfoundland"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Kanada/Pacifický"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Kanada/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Kanada/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Chile/Continental"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Chile/EasterIsland"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Kuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Egypt"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Eire"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Iné/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Iné/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Iné/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Iné/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Iné/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Iné/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Iné/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Iné/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Iné/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Iné/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Iné/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Iné/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Iné/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Iné/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Iné/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Iné/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Iné/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Iné/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Iné/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Iné/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Iné/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Iné/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Iné/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Iné/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Iné/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Iné/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Iné/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Iné/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Iné/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Iné/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Iné/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Iné/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Iné/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Iné/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Iné/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Európa/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Európa/Andorra"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Európa/Atény"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Európa/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Európa/Belgrade"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Európa/Berlín"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Európa/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Európa/Brusel"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Európa/Bukurešť"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Európa/Budapešť"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Európa/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Európa/Kobenhavn"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Európa/Dublin"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Európa/Gibraltar"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Európa/Guernsey"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Európa/Helsinki"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Európa/Isle_of_Man"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Európa/Istanbul"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Európa/Jersey"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Európa/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Moskva-01 - Kaliningrad"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Európa/Kiev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Európa/Lisbon"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Európa/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Európa/Londýn"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Európa/Luxemburg"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Európa/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Európa/Malta"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Európa/Mariehamn"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Európa/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Európa/Monaco"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Európa/Moskva"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "Moskva+00 - západné Rusko"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Európa/Nicosia"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Európa/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Európa/Paríž"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Európa/Podgorica"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Európa/Praha"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Európa/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Európa/Rím"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Európa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Moskva - Samara, Udmurtsko"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Európa/San_Maríno"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Európa/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Európa/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "centrum Krym"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Európa/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Európa/Sofia"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Európa/Stockholm"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Európa/Tallinn"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Európa/Tirane"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Európa/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Európa/Užhorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "Ruthenia"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Európa/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Európa/Vatikán"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Európa/Viedeň"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Európa/Viľňus"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Európa/Volgograd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "Moskva+00 - Kaspické more"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Európa/Varšava"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Európa/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Európa/Zaporozhye"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "Záporožie, E Lugansk"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Európa/Zurich"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Továrenské"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Eire"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Island"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Indický/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Indický/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Indický/Christmas"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Indický/Kokosové ostrovy"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Indický/Komory"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Indický/Kergueleny"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Indický/Mahé"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Indický/Maledivy"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Indický/Maurícius"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Indický/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Indický/Reunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Irán"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Izrael"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamajka"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Japonsko"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Líbya"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Mexiko/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Mexiko/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Mexiko/Všeobecný"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Mideast/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Mideast/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Mideast/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Pacifik/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Pacifik/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Pacifik/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "Chathamské ostrovy"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "Pacifik/Chuuk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "Chuuk (Truk) a Yap"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Pacifik/Easter"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "Veľkonočný ostrov a Sala y Gomez"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Pacifik/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Pacifik/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "Phoenixské ostrovy"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Pacifik/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Pacifik/Fiji"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Pacifik/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Pacifik/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "Galapágy"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Pacifik/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "Gambierove ostrovy"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Pacifik/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Pacifik/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Pacifik/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "Hawaii"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Pacifik/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "Atol Johnston"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Pacifik/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "Ostrovy Line"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Pacifik/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "Kosrae"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Pacifik/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Pacifik/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Pacifik/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "Markézy"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Pacifik/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "Midwayské ostrovy"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Pacifik/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Pacifik/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Pacifik/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Pacifik/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Pacifik/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Pacifik/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Pacifik/Pitcairn"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "Pacifik/Pohnpei"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "Pohnpei (Ponape)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Pacifik/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Pacifik/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Pacifik/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Pacifik/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Pacifik/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Pacifik/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "Spoločenské ostrovy"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Pacifik/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "Gilbertove ostrovy"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Pacifik/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Pacifik/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Pacifik/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "Ostrov Wake"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Pacifik/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Pacifik/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Poľsko"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugalsko"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapúr"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Turecko"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "US/Aljaška"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "US/Aleutian"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "US/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "US/Central"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "US/Eastern"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "US/East-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "US/Hawaii"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "US/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "US/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "US/Mountain"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "US/Pacific"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "US/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
+
+#~ msgid "US/Pacific-New"
+#~ msgstr "US/Pacific-nový"
+
+#~ msgid "SystemV/AST4"
+#~ msgstr "SystemV/AST4"
+
+#~ msgid "SystemV/AST4ADT"
+#~ msgstr "SystemV/AST4ADT"
+
+#~ msgid "SystemV/CST6"
+#~ msgstr "SystemV/CST6"
+
+#~ msgid "SystemV/CST6CDT"
+#~ msgstr "SystemV/CST6CDT"
+
+#~ msgid "SystemV/EST5"
+#~ msgstr "SystemV/EST5"
+
+#~ msgid "SystemV/EST5EDT"
+#~ msgstr "SystemV/EST5EDT"
+
+#~ msgid "SystemV/HST10"
+#~ msgstr "SystemV/HST10"
+
+#~ msgid "SystemV/MST7"
+#~ msgstr "SystemV/MST7"
+
+#~ msgid "SystemV/MST7MDT"
+#~ msgstr "SystemV/MST7MDT"
+
+#~ msgid "SystemV/PST8"
+#~ msgstr "SystemV/PST8"
+
+#~ msgid "SystemV/PST8PDT"
+#~ msgstr "SystemV/PST8PDT"
+
+#~ msgid "SystemV/YST9"
+#~ msgstr "SystemV/YST9"
+
+#~ msgid "SystemV/YST9YDT"
+#~ msgstr "SystemV/YST9YDT"
diff --git a/panels/datetime/po-timezones/sl.po b/panels/datetime/po-timezones/sl.po
new file mode 100644
index 0000000..6547fa5
--- /dev/null
+++ b/panels/datetime/po-timezones/sl.po
@@ -0,0 +1,3350 @@
+# SLOVENIAN TRANSLATION OF TIMEZONES.
+# Copyright (C) 2003 THE PACKAGE'S COPYRIGHT HOLDER
+# Roman Maurer <roman@lugos.si>, 2001.
+# $Id: sl.po,v 1.7 2007/04/27 09:16:29 nphilipp Exp $
+# $Source: /home/fedora/mmcgrath/elvis/cvs/redhat-config-date/po/timezones/sl.po,v $
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones 9.1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2003-06-24 18:50+0200\n"
+"Last-Translator: Roman Maurer <roman@lugos.si>\n"
+"Language-Team: Slovenian <translation-team-sl@lists.sourceforge.net>\n"
+"Language: sl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Afrika/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Afrika/Akra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Afrika/Adis_Abeba"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Afrika/Alžir"
+
+#: timezones.h:5
+#, fuzzy
+msgid "Africa/Asmara"
+msgstr "Afrika/Asmera"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Afrika/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Afrika/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Afrika/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Afrika/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Afrika/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Afrika/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Afrika/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Afrika/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Afrika/Kairo"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Afrika/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Afrika/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Afrika/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Afrika/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Afrika/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Afrika/Džibuti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Afrika/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Afrika/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Afrika/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Afrika/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Afrika/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Afrika/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Afrika/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Afrika/Khartoum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Afrika/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Afrika/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Afrika/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Afrika/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Afrika/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Afrika/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Afrika/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Afrika/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Afrika/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Afrika/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Afrika/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Afrika/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Afrika/Mogadiš"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Afrika/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Afrika/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Afrika/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Afrika/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Afrika/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Afrika/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Afrika/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Afrika/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Afrika/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Afrika/Tripoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Afrika/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Afrika/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Amerika/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+#, fuzzy
+msgid "Aleutian Islands"
+msgstr "Avstralija/Queensland"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Amerika/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+#, fuzzy
+msgid "Alaska Time"
+msgstr "US/Aljaska"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Amerika/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Amerika/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Amerika/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+#, fuzzy
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Amerika/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+#, fuzzy
+msgid "America/Argentina/Catamarca"
+msgstr "Amerika/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+#, fuzzy
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Amerika/Indiana/Indianapolis"
+
+#: timezones.h:78
+#, fuzzy
+msgid "America/Argentina/Cordoba"
+msgstr "Amerika/Cordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+#, fuzzy
+msgid "America/Argentina/Jujuy"
+msgstr "Amerika/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+#, fuzzy
+msgid "America/Argentina/La_Rioja"
+msgstr "Amerika/Araguaina"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+#, fuzzy
+msgid "America/Argentina/Mendoza"
+msgstr "Amerika/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+#, fuzzy
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Amerika/Indiana/Marengo"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+#, fuzzy
+msgid "America/Argentina/Salta"
+msgstr "Amerika/Antigua"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+#, fuzzy
+msgid "America/Argentina/San_Juan"
+msgstr "Amerika/Antigua"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+#, fuzzy
+msgid "America/Argentina/San_Luis"
+msgstr "Amerika/Antigua"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+#, fuzzy
+msgid "America/Argentina/Tucuman"
+msgstr "Amerika/Antigua"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+#, fuzzy
+msgid "America/Argentina/Ushuaia"
+msgstr "Amerika/Araguaina"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Amerika/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Amerika/Asuncion"
+
+#: timezones.h:110
+#, fuzzy
+msgid "America/Atikokan"
+msgstr "Amerika/Atka"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Amerika/Atka"
+
+#: timezones.h:114
+#, fuzzy
+msgid "America/Bahia"
+msgstr "Amerika/Boa_Vista"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "Amerika/Boa_Vista"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Amerika/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Amerika/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Amerika/Belize"
+
+#: timezones.h:125
+#, fuzzy
+msgid "America/Blanc-Sablon"
+msgstr "Amerika/Cancun"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Amerika/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Amerika/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Amerika/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Amerika/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Amerika/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+#, fuzzy
+msgid "America/Campo_Grande"
+msgstr "Amerika/Cayman"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Amerika/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Amerika/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Amerika/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Amerika/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Amerika/Cayman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Amerika/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+#, fuzzy
+msgid "Central Time"
+msgstr "US/Centralni"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Amerika/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+#, fuzzy
+msgid "America/Coral_Harbour"
+msgstr "Amerika/Curacao"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Amerika/Cordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Amerika/Kostarika"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Amerika/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Amerika/Curacao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Amerika/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Amerika/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Amerika/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Amerika/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+#, fuzzy
+msgid "Mountain Time"
+msgstr "US/Mountain"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Amerika/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Amerika/Dominica"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Amerika/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Amerika/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Amerika/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Amerika/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Amerika/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Amerika/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Amerika/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Amerika/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Amerika/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Amerika/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Amerika/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Amerika/Guadeloupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Amerika/Gvatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Amerika/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Amerika/Gvajana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Amerika/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Amerika/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Amerika/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Amerika/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Amerika/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Amerika/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+#, fuzzy
+msgid "America/Indiana/Petersburg"
+msgstr "Amerika/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Amerika/Indianapolis"
+
+#: timezones.h:227
+#, fuzzy
+msgid "America/Indiana/Tell_City"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+#, fuzzy
+msgid "America/Indiana/Vincennes"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+#, fuzzy
+msgid "America/Indiana/Winamac"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Amerika/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Amerika/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Amerika/Jamajka"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Amerika/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Amerika/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Amerika/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+#, fuzzy
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Amerika/Kentucky/Louisville"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Amerika/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Amerika/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Amerika/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Amerika/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Amerika/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+#, fuzzy
+msgid "Pacific Time"
+msgstr "Pacifik/Niue"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Amerika/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Amerika/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Amerika/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Amerika/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+#, fuzzy
+msgid "America/Marigot"
+msgstr "Amerika/Maceio"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Amerika/Martinik"
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "Amerika/Manaus"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Amerika/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Amerika/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Amerika/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Amerika/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Amerika/Mexico_City"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Amerika/Miquelon"
+
+#: timezones.h:289
+#, fuzzy
+msgid "America/Moncton"
+msgstr "Amerika/Edmonton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Amerika/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Amerika/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Amerika/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Amerika/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Amerika/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Amerika/New_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+#, fuzzy
+msgid "Eastern Time"
+msgstr "US/Vzhodni"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Amerika/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Amerika/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Amerika/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+#, fuzzy
+msgid "Atlantic islands"
+msgstr "Atlantik/Kanari"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Amerika/Severna_Dakota/Center"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+#, fuzzy
+msgid "America/North_Dakota/New_Salem"
+msgstr "Amerika/Severna_Dakota/Center"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "Amerika/Managua"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Amerika/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Amerika/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Amerika/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Amerika/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Amerika/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Amerika/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Amerika/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Amerika/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Amerika/Puerto_Rico"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Amerika/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Amerika/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Amerika/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Amerika/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+#, fuzzy
+msgid "America/Resolute"
+msgstr "Amerika/Belem"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Amerika/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Amerika/Rosario"
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "Amerika/Santiago"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+#, fuzzy
+msgid "America/Santarem"
+msgstr "Amerika/Santiago"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Amerika/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Amerika/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Amerika/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Amerika/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Amerika/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+#, fuzzy
+msgid "America/St_Barthelemy"
+msgstr "Amerika/Belem"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Amerika/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Amerika/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Amerika/St_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Amerika/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Amerika/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Amerika/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Amerika/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Amerika/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Amerika/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Amerika/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+#, fuzzy
+msgid "America/Toronto"
+msgstr "Amerika/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Amerika/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Amerika/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Amerika/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Amerika/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Amerika/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Amerika/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Amerika/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antarktika/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antarktika/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antarktika/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+#, fuzzy
+msgid "Antarctica/Macquarie"
+msgstr "Antarktika/McMurdo"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antarktika/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antarktika/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antarktika/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+#, fuzzy
+msgid "Antarctica/Rothera"
+msgstr "Antarktika/Južni_pol"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antarktika/Južni_pol"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antarktika/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antarktika/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Arktika/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Azija/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Azija/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Azija/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Azija/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Azija/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Azija/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Azija/Ašgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Azija/Aškhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Azija/Bagdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Azija/Bahrein"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Azija/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Azija/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Azija/Bejrut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Azija/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Azija/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Azija/Kalkuta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Azija/Čoibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Azija/Čongking"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Azija/Čungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Azija/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Azija/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Azija/Damask"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Azija/Dhaka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Azija/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Azija/Dubaj"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Azija/Dushanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Azija/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Azija/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+#, fuzzy
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Azija/Čongking"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Azija/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Azija/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Azija/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Azija/Carigrad"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Azija/Džakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Azija/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Azija/Jeruzalem"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Azija/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Azija/Kamčatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Azija/Karači"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Azija/Kašgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+#, fuzzy
+msgid "Asia/Kathmandu"
+msgstr "Azija/Katmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Azija/Katmandu"
+
+#: timezones.h:518
+#, fuzzy
+msgid "Asia/Kolkata"
+msgstr "Azija/Džakarta"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Azija/Krasnojarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Azija/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Azija/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Azija/Kuvajt"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Azija/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Azija/Macao"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Azija/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Azija/Makasar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Azija/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Azija/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Azija/Nikozija"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "Azija/Irkutsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Azija/Novosibirsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Azija/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+#, fuzzy
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Azija/Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Azija/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Azija/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Azija/Pnom_Pen"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Azija/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Azija/Pjongjang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Azija/Katar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Azija/Kizilorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Azija/Rangun"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Azija/Riyadh"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Azija/Riyadh87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Azija/Riyadh88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Azija/Riyadh89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Azija/Sajgon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Azija/Sahalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Azija/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Azija/Seul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Azija/Šanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Azija/Singapur"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Azija/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Azija/Taškent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Azija/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Azija/Teheran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Azija/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Azija/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Azija/Timfu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Azija/Tokio"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Azija/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Azija/Ulan_Bator"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Azija/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Azija/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Azija/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Azija/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Azija/Jakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Azija/Ekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Azija/Erevan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlantik/Azuri"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlantik/Bermuda"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlantik/Kanari"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlantik/Cape_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlantik/Faeroe"
+
+#: timezones.h:616
+#, fuzzy
+msgid "Atlantic/Faroe"
+msgstr "Atlantik/Faeroe"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlantik/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlantik/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlantik/Reykjavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlantik/Južna_Georgia"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlantik/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlantik/St_Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Avstralija/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Avstralija/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+#, fuzzy
+msgid "South Australia"
+msgstr "Avstralija/ACT"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Avstralija/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Avstralija/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Avstralija/Canberra"
+
+#: timezones.h:636
+#, fuzzy
+msgid "Australia/Currie"
+msgstr "Avstralija/Canberra"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Avstralija/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+#, fuzzy
+msgid "Australia/Eucla"
+msgstr "Avstralija/Queensland"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+#, fuzzy
+msgid "Western Australia - Eucla area"
+msgstr "Avstralija/Queensland"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Avstralija/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Avstralija/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Avstralija/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Avstralija/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Avstralija/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+#, fuzzy
+msgid "Victoria"
+msgstr "Avstralija/Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Avstralija/Sever"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Avstralija/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Avstralija/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Avstralija/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Avstralija/Jug"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Avstralija/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Avstralija/Tasmanija"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Avstralija/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Avstralija/Zahod"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Avstralija/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brazilija/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brazilija/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brazilija/Vzhod"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brazilija/Zahod"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Kanada/Atlantik"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Kanada/Centralna"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Kanada/Vzhodna"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Kanada/Vzhodni-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Kanada/Mountain"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Kanada/Nova_Funlandija"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Kanada/Pacifik"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Kanada/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Kanada/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "SEČ"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Čile/Continental"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Čile/EasterIsland"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Kuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "VEČ"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Egipt"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Irska"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Itd/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Itd/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Itd/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Itd/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Itd/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Itd/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Itd/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Itd/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Itd/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Itd/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Itd/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Itd/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Itd/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Itd/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Itd/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Itd/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Itd/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Itd/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Itd/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Itd/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Itd/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Itd/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Itd/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Itd/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Itd/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Itd/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Itd/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Itd/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Itd/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Itd/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Itd/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Itd/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Itd/Univerzalni"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Itd/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Itd/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Evropa/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Evropa/Andora"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Evropa/Atene"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Evropa/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Evropa/Beograd"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Evropa/Berlin"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Evropa/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Evropa/Bruselj"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Evropa/Bukarešta"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Evropa/Budimpešta"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Evropa/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Evropa/Koebenhaven"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Evropa/Dublin"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Evropa/Gibraltar"
+
+#: timezones.h:744
+#, fuzzy
+msgid "Europe/Guernsey"
+msgstr "Evropa/Atene"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Evropa/Helsinki"
+
+#: timezones.h:746
+#, fuzzy
+msgid "Europe/Isle_of_Man"
+msgstr "Evropa/Oslo"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Evropa/Carigrad"
+
+#: timezones.h:748
+#, fuzzy
+msgid "Europe/Jersey"
+msgstr "Evropa/Pariz"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Evropa/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Evropa/Kijev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Evropa/Lizbona"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Evropa/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Evropa/London"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Evropa/Luksemburg"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Evropa/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Evropa/Malta"
+
+#: timezones.h:765
+#, fuzzy
+msgid "Europe/Mariehamn"
+msgstr "Evropa/Madrid"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Evropa/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Evropa/Monako"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Evropa/Moskva"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Evropa/Nikozija"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Evropa/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Evropa/Pariz"
+
+#: timezones.h:774
+#, fuzzy
+msgid "Europe/Podgorica"
+msgstr "Evropa/Andora"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Evropa/Praga"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Evropa/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Evropa/Rim"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Evropa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Evropa/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Evropa/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Evropa/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Evropa/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Evropa/Sofija"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Evropa/Stockholm"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Evropa/Tallinn"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Evropa/Tirana"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Evropa/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Evropa/Užgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Evropa/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Evropa/Vatikan"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Evropa/Benetke"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Evropa/Vilnius"
+
+#: timezones.h:799
+#, fuzzy
+msgid "Europe/Volgograd"
+msgstr "Evropa/Beograd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Evropa/Varšava"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Evropa/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Evropa/Zaporožje"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Evropa/Zürich"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Tovarniški"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "VB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "VB-Irska"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GVČ"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GVČ0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GVČ-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GVČ+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Iceland"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Indijski/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Indijski/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Indijski/Christmas"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Indijski/Cocos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Indijski/Comoro"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Indijski/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Indijski/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Indijski/Maldivi"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Indijski/Mauricius"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Indijski/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Indijski/Reunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Iran"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Izrael"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamajka"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Japonska"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Libija"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "SEČ"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Mehika/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Mehika/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Mehika/General"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Mideast/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Mideast/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Mideast/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Pacifik/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Pacifik/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Pacifik/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+#, fuzzy
+msgid "Chatham Islands"
+msgstr "Čile/EasterIsland"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "Pacifik/Truk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+#, fuzzy
+msgid "Pacific/Easter"
+msgstr "Pacifik/Easter"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Pacifik/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Pacifik/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Pacifik/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Pacifik/Fidži"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Pacifik/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Pacifik/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Pacifik/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Pacifik/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Pacifik/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Pacifik/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+#, fuzzy
+msgid "Hawaii"
+msgstr "US/Hawaii"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Pacifik/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Pacifik/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Pacifik/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+#, fuzzy
+msgid "Kosrae"
+msgstr "Izrael"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Pacifik/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Pacifik/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Pacifik/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Pacifik/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Pacifik/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Pacifik/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Pacifik/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Pacifik/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Pacifik/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Pacifik/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Pacifik/Pitcairn"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "Pacifik/Ponape"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Pacifik/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Pacifik/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Pacifik/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Pacifik/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Pacifik/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Pacifik/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Pacifik/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+#, fuzzy
+msgid "Gilbert Islands"
+msgstr "Čile/EasterIsland"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Pacifik/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Pacifik/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Pacifik/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Pacifik/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Pacifik/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Poljska"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugalska"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapur"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Turčija"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Univerzalni"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "US/Aljaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "US/Aleutian"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "US/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "US/Centralni"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "US/Vzhodni"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "US/Vzhodna-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "US/Hawaii"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "US/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "US/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "US/Mountain"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "US/Pacifik"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "US/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "ZEČ"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
+
+#, fuzzy
+#~ msgid "US/Pacific-New"
+#~ msgstr "US/Pacifik"
+
+#~ msgid "SystemV/AST4"
+#~ msgstr "SystemV/AST4"
+
+#~ msgid "SystemV/AST4ADT"
+#~ msgstr "SystemV/AST4ADT"
+
+#~ msgid "SystemV/CST6"
+#~ msgstr "SystemV/CST6"
+
+#~ msgid "SystemV/CST6CDT"
+#~ msgstr "SystemV/CST6CDT"
+
+#~ msgid "SystemV/EST5"
+#~ msgstr "SystemV/EST5"
+
+#~ msgid "SystemV/EST5EDT"
+#~ msgstr "SystemV/EST5EDT"
+
+#~ msgid "SystemV/HST10"
+#~ msgstr "SystemV/HST10"
+
+#~ msgid "SystemV/MST7"
+#~ msgstr "SystemV/MST7"
+
+#~ msgid "SystemV/MST7MDT"
+#~ msgstr "SystemV/MST7MDT"
+
+#~ msgid "SystemV/PST8"
+#~ msgstr "SystemV/PST8"
+
+#~ msgid "SystemV/PST8PDT"
+#~ msgstr "SystemV/PST8PDT"
+
+#~ msgid "SystemV/YST9"
+#~ msgstr "SystemV/YST9"
+
+#~ msgid "SystemV/YST9YDT"
+#~ msgstr "SystemV/YST9YDT"
diff --git a/panels/datetime/po-timezones/sq.po b/panels/datetime/po-timezones/sq.po
new file mode 100644
index 0000000..7159c2c
--- /dev/null
+++ b/panels/datetime/po-timezones/sq.po
@@ -0,0 +1,3278 @@
+# Albanian Translation of Timezones.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the Timezones package.
+# Besnik Bleta <besnik@programeshqip.org>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: master\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2008-09-27 10:37+0200\n"
+"Last-Translator: Besnik Bleta <besnik@programeshqip.org>\n"
+"Language-Team: Albanian <besnik@programeshqip.org>\n"
+"Language: sq\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Afrikë/Abixhan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Afrikë/Akra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Afrikë/Adis_Abeba"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Afrikë/Algjer"
+
+#: timezones.h:5
+#, fuzzy
+msgid "Africa/Asmara"
+msgstr "Afrikë/Asmera"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Afrikë/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Afrikë/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Afrikë/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Afrikë/Banxhul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Afrikë/Bisau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Afrikë/Blentajër"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Afrikë/Brazavil"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Afrikë/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Afrikë/Kairo"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Afrikë/Kazablanka"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Afrikë/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Afrikë/Konakri"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Afrikë/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Afrikë/Dar_es_Salam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Afrikë/Xhibut"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Afrikë/Duala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Afrikë/El_Ajun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Afrikë/Fritaun"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Afrikë/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Afrikë/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Afrikë/Johanesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Afrikë/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Afrikë/Kartum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Afrikë/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Afrikë/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Afrikë/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Afrikë/Librëvil"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Afrikë/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Afrikë/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Afrikë/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Afrikë/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Afrikë/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Afrikë/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Afrikë/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Afrikë/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Afrikë/Mogadishu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Afrikë/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Afrikë/Najrobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Afrikë/Nxhamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Afrikë/Niamei"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Afrikë/Nuakshot"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Afrikë/Uagadugu"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Afrikë/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Afrikë/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Afrikë/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Afrikë/Tripoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Afrikë/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Afrikë/Uindhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Amerikë/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+#, fuzzy
+msgid "Aleutian Islands"
+msgstr "Australi/Kuinslend"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Amerikë/Ankorazh"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+#, fuzzy
+msgid "Alaska Time"
+msgstr "SHBA/Alaskë "
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Amerikë/Anguila"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Amerikë/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Amerikë/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Amerikë/Argjentinë/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Amerikë/Argjentinë/Katamarka"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Amerikë/Argjentinë/KomodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Amerikë/Argjentinë/Kordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Amerikë/Argjentinë/Jujui"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Amerikë/Argjentinë/La_Rioha"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Amerikë/Argjentinë/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Amerikë/Argjentinë/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+#, fuzzy
+msgid "America/Argentina/Salta"
+msgstr "Amerikë/Argjentinë/San_Huan"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Amerikë/Argjentinë/San_Huan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+#, fuzzy
+msgid "America/Argentina/San_Luis"
+msgstr "Amerikë/Argjentinë/San_Huan"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Amerikë/Argjentinë/Tukuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Amerikë/Argjentinë/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Amerikë/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Amerikë/Asuncion"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Amerikë/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Amerikë/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Amerikë/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "Amerikë/Bahia"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Amerikë/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Amerikë/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Amerikë/Belize"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "Amerikë/Blank-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Amerikë/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Amerikë/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Amerikë/Buazë"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Amerikë/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Amerikë/Kembrixh_Bej"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "Amerikë/Kampo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Amerikë/Kankun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Amerikë/Karakas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Amerikë/Katamarka"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Amerikë/Kajen"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Amerikë/Kajmën"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Amerikë/Çikago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+#, fuzzy
+msgid "Central Time"
+msgstr "SHBA/Qendrore"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Amerikë/Çiuaua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "Amerikë/Porti_i_Koraleve"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Amerikë/Kordoba "
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Amerikë/Kosta_Rika"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Amerikë/Kujaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Amerikë/Kuraçao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Amerikë/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Amerikë/Douson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Amerikë/Douson_Krik"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Amerikë/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+#, fuzzy
+msgid "Mountain Time"
+msgstr "SHBA/Mali"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Amerikë/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Amerikë/Dominika"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Amerikë/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Amerikë/Irunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Amerikë/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Amerikë/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Amerikë/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Amerikë/Fort_Uejn"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Amerikë/Glas_Bej"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Amerikë/Gotab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Amerikë/Gus_Bej"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Amerikë/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Amerikë/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Amerikë/Guadalupë"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Amerikë/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Amerikë/Guajakil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Amerikë/Guajana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Amerikë/Halifaks"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Amerikë/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Amerikë/Hermosilo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Amerikë/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Amerikë/Indiana/Noks"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Amerikë/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "Amerikë/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Amerikë/Indianapolis"
+
+#: timezones.h:227
+#, fuzzy
+msgid "America/Indiana/Tell_City"
+msgstr "Amerikë/Indiana/Vevej"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Amerikë/Indiana/Vevej"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "Amerikë/Indiana/Vincen"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+#, fuzzy
+msgid "America/Indiana/Winamac"
+msgstr "Amerikë/Indiana/Vincen"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Amerikë/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Amerikë/Ikaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Amerikë/Xhamaikë"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Amerikë/Jujui"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Amerikë/Zhuno"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Amerikë/Kentaki/Luisvil"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+#, fuzzy
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Amerikë/Kentaki/Luisvil"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Amerikë/Kentaki/Montiçelo"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Amerikë/Noks_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Amerikë/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Amerikë/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Amerikë/Los_Anxhelos"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+#, fuzzy
+msgid "Pacific Time"
+msgstr "Paqësor/Niue"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Amerikë/Luisvil"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Amerikë/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Amerikë/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Amerikë/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+#, fuzzy
+msgid "America/Marigot"
+msgstr "Amerikë/Maceio"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Amerikë/Martinikë"
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "Amerikë/Manaus"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Amerikë/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Amerikë/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Amerikë/Menomini"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Amerikë/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Amerikë/Meksiko_Siti"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Amerikë/Mikëlon"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "Amerikë/Monkton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Amerikë/Monterrej"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Amerikë/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Amerikë/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Amerikë/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Amerikë/Nasau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Amerikë/Nju_Jork"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+#, fuzzy
+msgid "Eastern Time"
+msgstr "SHBA/Lindore"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Amerikë/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Amerikë/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Amerikë/Noronja"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+#, fuzzy
+msgid "Atlantic islands"
+msgstr "Atlantik/Kanarie"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Amerikë/Dakota_e_Veriut/Qendrore"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "Amerikë/Dakota_e_Veriut/Salemi_i_Ri"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "Amerikë/Managua"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Amerikë/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Amerikë/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Amerikë/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Amerikë/Feniks"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Amerikë/Port-o-Prins"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Amerikë/Porto_Akre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Amerikë/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Amerikë/Porto_Velo"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Amerikë/Porto_Riko"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Amerikë/Reini_Rivër"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Amerikë/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Amerikë/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Amerikë/Rexhina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+#, fuzzy
+msgid "America/Resolute"
+msgstr "Amerikë/Belem"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Amerikë/Rio_Branko"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Amerikë/Rozario"
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "Amerikë/Santiago"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+#, fuzzy
+msgid "America/Santarem"
+msgstr "Amerikë/Santiago"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Amerikë/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Amerikë/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Amerikë/San_Paolo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Amerikë/Skorsbajsund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Amerikë/Shiprok"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+#, fuzzy
+msgid "America/St_Barthelemy"
+msgstr "Amerikë/Belem"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Amerikë/St_Xhons"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Amerikë/St_Kits"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Amerikë/St_Luçia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Amerikë/St_Tomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Amerikë/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Amerikë/Suift_Kurrent"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Amerikë/Teguçigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Amerikë/Tjul"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Amerikë/Gjiri_i_Rrufesë"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Amerikë/Tihuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "Amerikë/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Amerikë/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Amerikë/Vankuver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Amerikë/Virgjërt"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Amerikë/Uajthors"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Amerikë/Uinipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Amerikë/Jakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Amerikë/Jellounajf"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antarktidë/Kasi"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antarktidë/Dejvis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antarktidë/DymoDYrvil"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+#, fuzzy
+msgid "Antarctica/Macquarie"
+msgstr "Antarktidë/MkMërdo"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antarktidë/Mouson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antarktidë/MkMërdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antarktidë/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antarktidë/Rotera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antarktidë/Poli_i_Jugut"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antarktidë/Sjoua"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antarktidë/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Arktik/Longjirbajën"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Azi/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Azi/Almati"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Azi/Aman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Azi/Anadir"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Azi/Aktau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Azi/Aktobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Azi/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Azi/Ashkabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Azi/Bagdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Azi/Bahrein"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Azi/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Azi/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Azi/Bejrut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Azi/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Azi/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Azi/Kalkuta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Azi/Koibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Azi/Congqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Azi/Çungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Azi/Kolombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Azi/Daca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Azi/Damask"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Azi/Daka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Azi/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Azi/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Azi/Dushanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Azi/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Azi/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+#, fuzzy
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Azi/Congqing"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Azi/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Azi/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Azi/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Azi/Stamboll"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Azi/Xhakartë"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Azi/Xhajapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Azi/Jerusalem"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Azi/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Azi/Kamçatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Azi/Karashi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Azi/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+#, fuzzy
+msgid "Asia/Kathmandu"
+msgstr "Azi/Katmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Azi/Katmandu"
+
+#: timezones.h:518
+#, fuzzy
+msgid "Asia/Kolkata"
+msgstr "Azi/Xhakartë"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Azi/Krasnojarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Azi/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Azi/Kushing"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Azi/Kuvait"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Azi/Makao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Azi/Makau"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Azi/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Azi/Makasar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Azi/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Azi/Muskat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Azi/Nikozia"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "Azi/Irkutsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Azi/Novosibirsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Azi/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+#, fuzzy
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Azi/Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Azi/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Azi/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Azi/Phnom_Pen"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Azi/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Azi/Pjongjang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Azi/Katar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Azi/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Azi/Rangun"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Azi//Riad"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Azi//Riad87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Azi//Riad88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Azi//Riad89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Azi/Sajgon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Azi/Sakalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Azi/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Azi/Seul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Azi/Shangai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Azi/Singapor"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Azi/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Azi/Tashkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Azi/Tbilis"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Azi/Teheran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Azi/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Azi/Timbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Azi/Timpu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Azi/Tokio"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Azi/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Azi/Ulaanbaatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Azi/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Azi/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Azi/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Azi/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Azi/Jakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Azi/Ekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Azi/Erevan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlantik/Azore"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlantik/Bermuda"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlantik/Kanarie"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlantik/Kepi_i_Gjelbër"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlantik/Faroe"
+
+#: timezones.h:616
+#, fuzzy
+msgid "Atlantic/Faroe"
+msgstr "Atlantik/Faroe"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlantik/Jan_Majen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlantik/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlantik/Reikjavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlantik/Gjeorgji_e_Jugut"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlantik/Stanlei"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlantik/Shën_Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Australi/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Australi/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+#, fuzzy
+msgid "South Australia"
+msgstr "Australi/ACT"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Australi/Brisbën"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Australi/Kodr_´_e_Thyer"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Australi/Kanberrë"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Australi/Kurri"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Australi/Darvin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+#, fuzzy
+msgid "Australia/Eucla"
+msgstr "Australi/Kuinslend"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr ""
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Australi/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Australi/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Australi/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Australi/Lord_Houv"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Australi/Melburn"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+#, fuzzy
+msgid "Victoria"
+msgstr "Australi/Viktoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Australi/Veri"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Australi/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Australi/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Australi/Kuinslend"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Australi/Jug"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Australi/Sidni"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Australi/Tasmani"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Australi/Viktoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Australi/Perëndim"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Australi/Jankovina"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brazil/Akre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brazil/DeNoronja"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brazil/Lindje"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brazil/Perëndim"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Kanada/Atlantik"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Kanada/Qendrore"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Kanada/Lindore"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Kanada/Saskaçevan_i_Lindjes"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Kanada/Malore"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Kanada/Njufaundlend"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Kanada/Paqësor"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Kanada/Saskaçevan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Kanada/Jukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Kili/Kontinentale"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Kili/Ishulli_Lindor"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Kubë"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Egjypt"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Irlandë"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Grinuiç"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universale"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Europë/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Europë/Andorra"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Europë/Athinë"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Europë/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Europë/Beograd"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Europë/Berlin"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Europë/Bratislavë"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Europë/Bruksel"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Europë/Bukuresht"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Europë/Budapest"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Europë/Kishinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Europë/Kopenhagen"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Europë/Dublin"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Europë/Gjibraltar"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Europë/Guernsi"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Europë/Helsinki"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Europë/Ishulli_i_Robit"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Europë/Stamboll"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Europë/Xhersi"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Europë/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Europë/Kiev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Europë/Lisbonë"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Europë/Ljubljanë"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Europë/Londër"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Europë/Luksemburg"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Europë/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Europë/Maltë"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Europë/Marihamn"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Europë/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Europë/Monako"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Europë/Moskë"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Europë/Nikozi"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Europë/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Europë/Paris"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Europë/Podgoricë"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Europë/Pragë"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Europë/Rigë"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Europë/Romë"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Europë/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Europë/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Europë/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Europë/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Europë/Shkup"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Europë/Sofie"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Europë/Stokholm"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Europë/Talin"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Europë/Tiranë"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Europë/Amsterdam"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Europë/Uzhgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Europë/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Europë/Vatikan"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Europë/Vienë"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Europë/Vilnius"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Europë/Volgograd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Europë/Varshavë"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Europë/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Europë/Zaporozhje"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Europë/Zyrih"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Punishte"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "BM"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "BM-Irlandë"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Grinuiç"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Islandë"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Indian/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Indian/Çagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Indian/Kërshëndella"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Indian/Kokos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Indian/Komoro"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Indian/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Indian/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Indian/Maldive"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Indian/Mauricius"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Indian/Majot"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Indian/Ribashkim"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Iran"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Izrael"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Xhamaika"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Japoni"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kuajalin"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Libi"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Meksikë/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Meksikë/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Meksikë/E-përgjithshme"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Lindje_e_Mesme/Riad87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Lindje_e_Mesme/Riad88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Lindje_e_Mesme/Riad89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navaho"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Paqësor/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Paqësor/Okland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Paqësor/Çatëm"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+#, fuzzy
+msgid "Chatham Islands"
+msgstr "Kili/Ishulli_Lindor"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "Paqësor/Truk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Paqësor/Pashkë"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Paqësor/Efat"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Paqësor/Enderbëri"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Paqësor/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Paqësor/Fixhi"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Paqësor/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Paqësor/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Paqësor/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Paqësor/Guadalkanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Paqësor/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Paqësor/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+#, fuzzy
+msgid "Hawaii"
+msgstr "SHBA/Havai"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Paqësor/Xhonston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Paqësor/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Paqësor/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+#, fuzzy
+msgid "Kosrae"
+msgstr "Izrael"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Paqësor/Kuajalin"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Paqësor/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Paqësor/Markuezas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Paqësor/Miduej"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Paqësor/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Paqësor/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Paqësor/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Paqësor/Numea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Paqësor/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Paqësor/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Paqësor/Pitkern"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "Paqësor/Ponape"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Paqësor/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Paqësor/Port_Moresbi"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Paqësor/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Paqësor/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Paqësor/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Paqësor/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Paqësor/Taraua"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+#, fuzzy
+msgid "Gilbert Islands"
+msgstr "Kili/Ishulli_Lindor"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Paqësor/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Paqësor/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Paqësor/Uejk"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Paqësor/Ualis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Paqësor/Jap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Poloni"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugali"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapor"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Turqi"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Universale"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "SHBA/Alaskë "
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "SHBA/Aleutine"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "SHBA/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "SHBA/Qendrore"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "SHBA/Lindore"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "SHBA/Indiana-e-Lindjes"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "SHBA/Havai"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "SHBA/Indiana-Stark"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "SHBA/Miçigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "SHBA/Mali"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "SHBA/Paqësor"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "SHBA/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
+
+#~ msgid "US/Pacific-New"
+#~ msgstr "SHBA/Paqësor-I-ri"
diff --git a/panels/datetime/po-timezones/sr.po b/panels/datetime/po-timezones/sr.po
new file mode 100644
index 0000000..fafbe59
--- /dev/null
+++ b/panels/datetime/po-timezones/sr.po
@@ -0,0 +1,3255 @@
+# Serbian translations for timezones
+# Copyright (C) 2005 Red Hat, Inc.
+# This file is distributed under the same license as the timezones package.
+# Zoltan Čala <zolika@sezampro.yu>, 1999.
+# Miloš Komarčević <kmilos@gmail.com>, 2005.
+# Igor Miletic <grejigl-gnomeprevod@yahoo.ca>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-04-20 22:13+0100\n"
+"Last-Translator: Miloš Komarčević <kmilos@gmail.com>\n"
+"Language-Team: Serbian <trans-sr@lists.fedoraproject.org>\n"
+"Language: sr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Африка/Абиџан"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Африка/Акра"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Африка/Адис_Абеба"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Африка/Алжир"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "Африка/Асмара"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Африка/Асмера"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Африка/Бамако"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Африка/Бангуј"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Африка/Банџул"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Африка/Бисау"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Африка/Блентајр"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Африка/Бразавил"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Африка/Буџумбура"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Африка/Каиро"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Африка/Казабланка"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Африка/Сеута"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "Сеута и Мелиља"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Африка/Конакри"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Африка/Дакар"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Африка/Дар_ес_Салам"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Африка/Џибути"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Африка/Дуала"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Африка/Ел_Ајун"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Африка/Фритаун"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Африка/Габорон"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Африка/Хараре"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Африка/Јоханесбург"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Африка/Кампала"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Африка/Картум"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Африка/Кигали"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Африка/Киншаса"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "западна Дем. Реп. Конго"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Африка/Лагос"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Африка/Либервил"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Африка/Ломе"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Африка/Луанда"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Африка/Лубумбаши"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "источна Дем. Реп. Конго"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Африка/Лусака"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Африка/Малабо"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Африка/Мапуто"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Африка/Масеру"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Африка/Мбабане"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Африка/Могадиш"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Африка/Монровија"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Африка/Најроби"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Африка/Нџамена"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Африка/Ниамеј"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Африка/Нуакчот"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Африка/Уагадугу"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Африка/Порто-Ново"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Африка/Сао_Томе"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Африка/Тимбукту"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Африка/Триполи"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Африка/Тунис"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Африка/Виндхук"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Америка/Адак"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Алеутска острва"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Америка/Енкориџ"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Аљашко време"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Америка/Ангвила"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Америка/Антигва"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Америка/Арагвијана"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "Токантинс"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Америка/Аргентина/Буенос_Ајрес"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Буенос Ајрес (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Америка/Аргентина/Катамарка"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "Катамарка (CT), Чубут (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Америка/Аргентина/КомодороРивадавиа"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Америка/Аргентина/Кордоба"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "већина места (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Америка/Аргентина/Хухуи"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Хухуи (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Америка/Аргентина/Ла_Риоха"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "Ла Риоха (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Америка/Аргентина/Мендоза"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "Мендоза (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Америка/Аргентина/Рио_Гаљегос"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "Санта Круз (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "Америка/Аргентина/Салта"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Америка/Аргентина/Сан_Хуан"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "Сан Хуан (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "Америка/Аргентина/Сан_Луис"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "Сан Луис (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Америка/Аргентина/Тукуман"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "Тукуман (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Америка/Аргентина/Ушуаја"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "Огњена земља (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Америка/Аруба"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Америка/Асунсион"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Америка/Атикокан"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "Источно стандардно време - Атикокан, Онтарио и О. Саутемптон, Нунавут"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Америка/Атка"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Америка/Баија"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "Баија"
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "Америка/Баија"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Америка/Барбадос"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Америка/Белем"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "Амапа, И Пара"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Америка/Белизе"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "Америка/Блан-Саблон"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "Атлантско стандардно време - Квебек - Нижа северна обала"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Америка/Боа_Виста"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "Рораима"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Америка/Богота"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Америка/Боизе"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "Планинско време - јужни Ајдахо и источни Орегон"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Америка/Буенос_Ајрес"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Америка/Кембриџ_Беј"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "Планинско време - западни Нунавут"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "Америка/Кампо_Гранде"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "Мато Гросо до Сул"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Америка/Канкун"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "Централно време - Кинтана Ро"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Америка/Каракас"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Америка/Катамарка"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Америка/Кајен"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Америка/Кајман"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Америка/Чикаго"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "Централно време"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Америка/Чивава"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "Мексичко планинско време - Чивава далеко од границе САД"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "Америка/Корал_Харбор"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Америка/Кордоба"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Америка/Костарика"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Америка/Кујаба"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "Мато Гросо"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Америка/Куракао"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Америка/Денмарксхавен"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "источна обала, северно од Скорзбисунда"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Америка/Досон"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "Пацифичко време - северни Јукон"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Америка/Досон_Крик"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+"Планинско стандардно време - Досон Крик и Форт Сент Џон, Британска Колумбија"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Америка/Денвер"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "Планинско време"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Америка/Детроит"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "Источно време - Мичиген - већина места"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Америка/Доминика"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Америка/Едмонтон"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+"Планинско време - Алберта, источна Британска Колумбија и западни Саскачеван"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Америка/Ејрунепе"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "З Амазонија"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Америка/Ел_Салвадор"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Америка/Енсенада"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Америка/Форталеза"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "СИ Бразил (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Америка/Форт_Вејн"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Америка/Глејс_Беј"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr "Атлантско време - Нова Шкотска - места која нису пратила DST 1966-1971"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Америка/Годтаб"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "већина места"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Америка/Гус_Беј"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "Атлантско време - Лабрадор - већина места"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Америка/Гранд_Турк"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Америка/Гренада"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Америка/Гваделуп"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Америка/Гватемала"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Америка/Гвајаквил"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "матично копно"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Америка/Гијана"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Америка/Халифакс"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "Атлантско време - Нова Шкотска (већина места), ОПЕ"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Америка/Хавана"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Америка/Ермосиљо"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "Планинско стандардно време - Сонора"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Америка/Индијана/Индијанаполис"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "Источно време - Индијана - већина места"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Америка/Индијана/Нокс"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "Централно време - Индијана - Округ Старк"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Америка/Индијана/Маренго"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "Источно време - Индијана - Округ Крофорд"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "Америка/Индијана/Питерсбург"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "Источно време - Индијана - Округ Пајк"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Америка/Индијанаполис"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "Америка/Индијана/Тел_Сити"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "Централно време - Индијана - Округ Пери"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Америка/Индијана/Вевај"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "Источно време - Индијана - Округ Свицерленд"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "Америка/Индијана/Винсенс"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "Источно време - Индијана - Окрузи Давис, Дубоа, Нокс и Мартин"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "Америка/Индијана/Винамак"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "Источно време - Индијана - Округ Пуласки"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Америка/Инувик"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "Планинско време - западне Северозападне територије"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Америка/Икалујт"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "Источно време - источни Нунавут - већина места"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Америка/Јамајка"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Америка/Хухуи"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Америка/Жуно"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "Аљашко време - избочина Аљаске"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Америка/Кентаки/Луивил"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Источно време - Кентаки - подручје Луивила"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Америка/Кентаки/Монтичело"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "Источно време - Кентаки - Округ Вејн"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Америка/Нокс_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Америка/Ла_Паз"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Америка/Лима"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Америка/Лос_Анђелес"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "Пацифичко време"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Америка/Луивил"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Америка/Масејо"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "Алагоас, Сержипе"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Америка/Манагва"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Америка/Манаус"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "И Амазонија"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "Америка/Мариго"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Америка/Мартиник"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "Америка/Матаморос"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+"САД централно време - Куауила, Дуранго, Нуево Леон, Тамаулипас у близини "
+"границе САД"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Америка/Мазатлан"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "Планинско време - Ј Баха, Најарит, Синалоа"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Америка/Мендоза"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Америка/Меномини"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+"Централно време - Мичиген - Окрузи Дикинскон, Гогебик, Ајрон и Меномини"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Америка/Мерида"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "Централно време - Кампеће, Јукатан"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Америка/Мексико_Сити"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "Централно време - већина места"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Америка/Микелон"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "Америка/Монктон"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "Атлантско време - Њу Бранзвик"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Америка/Монтереј"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+"Мексичко централно време - Куауила, Дуранго, Нуево Леон, Тамаулипас далеко "
+"од границе САД"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Америка/Монтевидео"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Америка/Монтреал"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "Источно време - Квебек - већина места"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Америка/Монтсерат"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Америка/Насау"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Америка/Њујорк"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "Источно време"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Америка/Нипигон"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+"Источно време - Онтарио и Квебек - места која нису пратила DST 1967-1973"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Америка/Ном"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "Аљашко време - западна Аљаска"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Америка/Нороња"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "Атлантска острва"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Америка/Северна_Дакота/Центар"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "Централно време - Северна Дакота - Округ Оливер"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "Америка/Северна_Дакота/Њу_Салем"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+"Централно време - Северна Дакота - Округ Мортон (изузев подручја Мандана)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "Америка/Охинага"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "САД планинско време - Чивава у близини границе САД"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Америка/Панама"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Америка/Пангниртунг"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "Источно време - Пангниртунг, Нунавут"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Америка/Парамарибо"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Америка/Феникс"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "Планинско стандардно време - Аризона"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Америка/Порт-о-Принс"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Америка/Порто_Акри"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Америка/Порт_оф_Спејн"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Америка/Порто_Вело"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "Рондонија"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Америка/Порторико"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Америка/Рејни_Ривер"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "Централно време - Рејни Ривер и Форт Франсис, Онтарио"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Америка/Ранкинов_рукавац"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "Централно време - централни Нунавут"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Америка/Ресифи"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "Пернамбуко"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Америка/Регина"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "Централно стандардно време - Саскачеван - већина места"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "Америка/Резолут"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "Источно стандардно време - Резолут, Нунавут"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Америка/Рио_Бранко"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "Акри"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Америка/Розарио"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "Америка/Санта_Изабел"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "Мексичко пацифичко време - Доња Калифорнија далеко од границе САД"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "Америка/Сантарем"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "З Пара"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Америка/Сантјаго"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Америка/Санто_Доминго"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Америка/Сао_Паоло"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "Ј и ЈИ Бразил (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Америка/Скорзбисунд"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "Скорзбисунд / Итокортормит"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Америка/Шипрок"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "Планинско време - Навахо"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "Америка/Св_Бартоломеј"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Америка/Сент_Џон"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "Њуфаундлендско време, укључујући ЈИ Лабрадор"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Америка/Св_Китс"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Америка/Св_Луција"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Америка/Сент_Томас"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Америка/Св_Винсент"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Америка/Свифт_Карент"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "Централно стандардно време - Саскачеван - средњи запад"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Америка/Тегусигалпа"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Америка/Туле"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "Туле / Питуфик"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Америка/Тандер_Беј"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "Источно време - Тандер Беј, Онтарио"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Америка/Тихуана"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "САД пацифичко време - Доња Калифорнија у близини границе САД"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "Америка/Торонто"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "Источно време - Онтарио - већина места"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Америка/Тортола"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Америка/Ванкувер"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "Пацифичко време - западна Британска Колумбија"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Америка/Вирџин"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Америка/Вајтхорс"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "Пацифичко време - јужни Јукон"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Америка/Винипег"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "Централно време - Манитоба и западни Онтарио"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Америка/Јакутат"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "Аљашко време - врат избочине Аљаске"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Америка/Јелоунајф"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "Планинско време - централне Северозападне територије"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Антарктик/Кејси"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "Станица Кејси, Полуострво Бејли"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Антарктик/Дејвис"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "Станица Дејвис, Вестфолд Хилс"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Антарктик/ДимонДИрвил"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "Станица Димон д'Ирвил, Аделина земља"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "Антарктик/Макуори"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "Станица Острва Макуори, Острво Макуори"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Антарктик/Мосон"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "Станица Мосон, Залив Холм"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Антарктик/МекМурдо"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "Станица МекМурдо, Острво Рос"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Антарктик/Палмер"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "Станица Палмер, Острво Анверс"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Антарктик/Ротера"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "Станица Ротера, Острво Аделејд"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Антарктик/Јужни_пол"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "Станица Амундсен-Скот, јужни пол"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Антарктик/Сјова"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "Станица Сјова, О. и. Онгул"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Антарктик/Восток"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "Станица Восток, ј. магнетни пол"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Арктик/Лонгјирбјен"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Азија/Аден"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Азија/Алмати"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Азија/Аман"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Азија/Анадир"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "Москва+08 - Берингово море"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Азија/Актау"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "Атирау (Гурјев), Мангистау"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Азија/Актобе"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "Актобе"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Азија/Ашгабат"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Азија/Ашкабад"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Азија/Багдад"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Азија/Бахреин"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Азија/Баку"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Азија/Банкок"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Азија/Бејрут"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Азија/Бишкек"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Азија/Брунеји"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Азија/Калкута"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Азија/Чојбалсан"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "Дорнод, Сухбатар"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Азија/Чонкинг"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "централна Кина - Сечуан, Јунан, Гуангси, Шанси, Гуиџоу, итд."
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Азија/Чункинг"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Азија/Коломбо"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Азија/Дака"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Азија/Дамаск"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Азија/Дака"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Азија/Дили"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Азија/Дубаји"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Азија/Душанбе"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Азија/Газа"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Азија/Харбин"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "Хеилунгђанг (изузев Мохе), Ђилин"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Азија/Хо_Ши_Мин"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Азија/Хонг_Конг"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Азија/Ховд"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "Бајан-Улгиј, Гови-Алтај, Ховд, Увс, Завхај"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Азија/Иркутск"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Москва+05 - Бајкалско језеро"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Азија/Цариград"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Азија/Џакарта"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "Јава и Суматра"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Азија/Џајапура"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "Иријан Џаја и Молуци"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Азија/Јерусалим"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Азија/Кабул"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Азија/Камчатка"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "Москва+08 - Камчатка"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Азија/Карачи"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Азија/Кашгар"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "западни Тибет и Синђанг"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "Азија/Катманду"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Азија/Катманду"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "Азија/Калкута"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Азија/Краснојарск"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "Москва+04 - Река Јенисеј"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Азија/Куала_Лумпур"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "полуострвска Малезија"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Азија/Кучинг"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "Сабах и Саравак"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Азија/Кувајт"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Азија/Макао"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Азија/Макао"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Азија/Магадан"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "Москва+08 - Магадан"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Азија/Макасар"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "источни и јужни Борнео, Сулавеси, Бали, Мали Сунди, западни Тимор"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Азија/Манила"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Азија/Мускат"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Азија/Никозија"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "Азија/Новокузњецк"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Москва+03 - Новокузњецк"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Азија/Новосибирск"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Москва+03 - Новосибирск"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Азија/Омск"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "Москва+03 - западни Сибир"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Азија/Орал"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "Западни Казахстан"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Азија/Пном_Пен"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Азија/Понтијанак"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "западни и централни Борнео"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Азија/Пјонгјанг"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Азија/Катар"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Азија/Кизилорда"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "Кизилорда"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Азија/Рангун"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Азија/Ријад"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Азија/Ријад87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Азија/Ријад88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Азија/Ријад89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Азија/Сајгон"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Азија/Сахалин"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "Москва+07 - Острво Сахалин"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Азија/Самарканд"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "западни Узбекистан"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Азија/Сеул"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Азија/Шангај"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "источна Кина - Пекинг, Гуангдунг, Шангај, итд."
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Азија/Сингапур"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Азија/Тајпеј"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Азија/Ташкент"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "источни Узбекистан"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Азија/Тбилиси"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Азија/Техеран"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Азија/Тел_Авив"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Азија/Тимбу"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Азија/Тимпу"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Азија/Токио"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Азија/Ујанг_Панданг"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Азија/Уланбатар"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Азија/Улан_Батор"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Азија/Урумчи"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "већина Тибета и Синђанг"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Азија/Вијентијан"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Азија/Владивосток"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "Москва+07 - Река Амур"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Азија/Јакутск"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "Москва+06 - Река Лена"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Азија/Јекатеринбург"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "Москва+02 - Урал"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Азија/Јереван"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Атлантик/Азори"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "Азорска острва"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Атлантик/Бермуде"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Атлантик/Канарска_острва"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "Канарска острва"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Атлантик/Кејп_Верде"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Атлантик/Фарска_острва"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "Атлантик/Фарска_острва"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Атлантик/Јан_Мајен"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Атлантик/Мадеира"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "Острва Мадеира"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Атлантик/Рејкјавик"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Атлантик/Јужна_Џорџија"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Атлантик/Стенли"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Атлантик/Св_Хелена"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Аустралија/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Аустралија/Аделејд"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "Јужна Аустралија"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Аустралија/Бризбејн"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "Квинсленд - већина места"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Аустралија/Брокен_Хил"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "Нови Јужни Велс - Јанковина"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Аустралија/Канбера"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Аустралија/Кјури"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "Тасманија - Острво Кинг"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Аустралија/Дарвин"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "Северна територија"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "Аустралија/Јукла"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "Западна Аустралија - подручје Јукле"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Аустралија/Хобарт"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "Тасманија - већина места"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Аустралија/ОЛХ"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Аустралија/Линдеман"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "Квинсленд - Празнична острва"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Аустралија/Лорд_Хоу"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "Острво Лорда Хоуа"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Аустралија/Мелбурн"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "Викторија"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Аустралија/Север"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Аустралија/НЈВ"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Аустралија/Перт"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "Западна Аустралија - већина места"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Аустралија/Квинсленд"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Аустралија/Југ"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Аустралија/Сиднеј"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "Нови Јужни Велс - већина места"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Аустралија/Тасманија"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Аустралија/Викторија"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Аустралија/Запад"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Аустралија/Јанковина"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Бразил/Акри"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Бразил/ДеНороња"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Бразил/Исток"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Бразил/Запад"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Канада/Атлантик"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Канада/Централна"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Канада/Источна"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Канада/Исток-Саскачеван"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Канада/Планине"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Канада/Њуфаундленд"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Канада/Пацифик"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Канада/Саскачеван"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Канада/Јукон"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Чиле/Континентални"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Чиле/Ускршње_острво"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Куба"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Египат"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Ирска"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Итд/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Итд/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Итд/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Итд/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Итд/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Итд/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Итд/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Итд/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Итд/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Итд/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Итд/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Итд/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Итд/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Итд/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Итд/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Итд/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Итд/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Итд/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Итд/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Итд/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Итд/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Итд/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Итд/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Итд/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Итд/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Итд/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Итд/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Итд/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Итд/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Итд/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Итд/Гринич"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Итд/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Итд/Универзално"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Итд/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Итд/Зулу"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Европа/Амстердам"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Европа/Андора"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Европа/Атина"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Европа/Белфаст"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Европа/Београд"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Европа/Берлин"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Европа/Братислава"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Европа/Брисел"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Европа/Букурешт"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Европа/Будимпешта"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Европа/Кишињев"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Европа/Копенхаген"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Европа/Даблин"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Европа/Гибралтар"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Европа/Гернзи"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Европа/Хелсинки"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Европа/Острво Ман"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Европа/Цариград"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Европа/Џерзи"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Европа/Калињинград"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Москва-01 - Калињинград"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Европа/Кијев"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Европа/Лисабон"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Европа/Љубљана"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Европа/Лондон"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Европа/Луксембург"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Европа/Мадрид"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Европа/Малта"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Европа/Маријехамн"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Европа/Минск"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Европа/Монако"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Европа/Москва"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "Москва+00 - западна Русија"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Европа/Никозија"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Европа/Осло"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Европа/Париз"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Европа/Подгорица"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Европа/Праг"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Европа/Рига"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Европа/Рим"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Европа/Самара"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Москва - Самара, Удмуртија"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Европа/Сан_Марино"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Европа/Сарајево"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Европа/Симферопољ"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "централни Крим"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Европа/Скопље"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Европа/Софија"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Европа/Стокхолм"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Европа/Талин"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Европа/Тирана"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Европа/Тираспољ"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Европа/Ужгород"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "Рутенија"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Европа/Вадуз"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Европа/Ватикан"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Европа/Беч"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Европа/Вилнијус"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Европа/Волгоград"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "Москва+00 - Каспијско море"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Европа/Варшава"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Европа/Загреб"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Европа/Запорожје"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "Запорожје, И Луганск"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Европа/Цирих"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Фабрика"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "ВБ"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "ВБ-Ирска"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Гринич"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Хонгконг"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Исланд"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Индијски_океан/Антананариво"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Индијски_океан/Чагос"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Индијски_океан/Божићна_острва"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Индијски_океан/Кокос"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Индијски_океан/Коморо"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Индијски_океан/Кергулен"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Индијски_океан/Махе"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Индијски_океан/Малдиви"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Индијски_океан/Маурицијус"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Индијски_океан/Мајот"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Индијски_океан/Реунион"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Иран"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Израел"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Јамајка"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Јапан"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Кваџалин"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Либија"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Мексико/БахаНорте"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Мексико/БахаСур"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Мексико/Опште"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Блиски исток/Ријад87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Блиски исток/Ријад88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Блиски исток/Ријад89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Навахо"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "НЗ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "НЗ-ЧАТ"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Пацифик/Апиа"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Пацифик/Окленд"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Пацифик/Чатам"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "Острва Чатам"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "Пацифик/Трук"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+#, fuzzy
+msgid "Chuuk (Truk) and Yap"
+msgstr "Трук (Чуук) и Јап"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Пацифик/Ускршње_острво"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "Ускршње острво и Сала и Гомез"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Пацифик/Ефате"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Пацифик/Ендербури"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "Острва Феникс"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Пацифик/Факаофо"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Пацифик/Фиџи"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Пацифик/Фунафути"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Пацифик/Галапагос"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "Острва Галапагос"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Пацифик/Гамбије"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "Острва Гамбије"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Пацифик/Гвадалканал"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Пацифик/Гуам"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Пацифик/Хонолулу"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "Хаваји"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Пацифик/Џонстон"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "Атол Џонстон"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Пацифик/Киритимати"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "Линијска острва"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Пацифик/Косре"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "Косре"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Пацифик/Кваџалин"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Пацифик/Маџуро"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Пацифик/Маркиз"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "Острва Маркиз"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Пацифик/Мидвеј"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "Острва Мидвеј"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Пацифик/Науру"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Пацифик/Ниуе"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Пацифик/Норфолк"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Пацифик/Ноумеа"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Пацифик/Паго_Паго"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Пацифик/Палау"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Пацифик/Питкаирн"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "Пацифик/Понапе"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+#, fuzzy
+msgid "Pohnpei (Ponape)"
+msgstr "Понапе (Понпеи)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Пацифик/Понапе"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Пацифик/Порт_Морезби"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Пацифик/Раротонга"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Пацифик/Саипан"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Пацифик/Самоа"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Пацифик/Тахити"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "Друштвена острва"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Пацифик/Тарава"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "Острва Гилберт"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Пацифик/Тонгатапу"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Пацифик/Трук"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Пацифик/Вејк"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "Острво Вејк"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Пацифик/Валис"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Пацифик/Јап"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Пољска"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Португал"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Сингапур"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Турска"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Универзално"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "САД/Аљаска"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "САД/Алеутска_острва"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "САД/Аризона"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "САД/Централне"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "САД/Источне"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "САД/Исток-Индијана"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "САД/Хаваји"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "САД/Индијана-Старк"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "САД/Мичиген"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "САД/Планине"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "САД/Пацифик"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "САД/Самоа"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Зулу"
diff --git a/panels/datetime/po-timezones/sr@latin.po b/panels/datetime/po-timezones/sr@latin.po
new file mode 100644
index 0000000..8079172
--- /dev/null
+++ b/panels/datetime/po-timezones/sr@latin.po
@@ -0,0 +1,3255 @@
+# Serbian(Latin) translations for timezones
+# Copyright (C) 2005 Red Hat, Inc.
+# This file is distributed under the same license as the timezones package.
+# Zoltan Čala <zolika@sezampro.yu>, 1999.
+# Miloš Komarčević <kmilos@gmail.com>, 2005.
+# Igor Miletic <grejigl-gnomeprevod@yahoo.ca>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-04-20 22:13+0100\n"
+"Last-Translator: Miloš Komarčević <kmilos@gmail.com>\n"
+"Language-Team: Serbian <trans-sr@lists.fedoraproject.org>\n"
+"Language: sr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Afrika/Abidžan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Afrika/Akra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Afrika/Adis_Abeba"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Afrika/Alžir"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "Afrika/Asmara"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Afrika/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Afrika/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Afrika/Banguj"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Afrika/Bandžul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Afrika/Bisau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Afrika/Blentajr"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Afrika/Brazavil"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Afrika/Budžumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Afrika/Kairo"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Afrika/Kazablanka"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Afrika/Seuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "Seuta i Melilja"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Afrika/Konakri"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Afrika/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Afrika/Dar_es_Salam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Afrika/Džibuti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Afrika/Duala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Afrika/El_Ajun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Afrika/Fritaun"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Afrika/Gaboron"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Afrika/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Afrika/Johanesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Afrika/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Afrika/Kartum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Afrika/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Afrika/Kinšasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "zapadna Dem. Rep. Kongo"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Afrika/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Afrika/Libervil"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Afrika/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Afrika/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Afrika/Lubumbaši"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "istočna Dem. Rep. Kongo"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Afrika/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Afrika/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Afrika/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Afrika/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Afrika/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Afrika/Mogadiš"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Afrika/Monrovija"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Afrika/Najrobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Afrika/Ndžamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Afrika/Niamej"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Afrika/Nuakčot"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Afrika/Uagadugu"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Afrika/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Afrika/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Afrika/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Afrika/Tripoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Afrika/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Afrika/Vindhuk"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Amerika/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Aleutska ostrva"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Amerika/Enkoridž"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Aljaško vreme"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Amerika/Angvila"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Amerika/Antigva"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Amerika/Aragvijana"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "Tokantins"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Amerika/Argentina/Buenos_Ajres"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Buenos Ajres (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Amerika/Argentina/Katamarka"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "Katamarka (CT), Čubut (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Amerika/Argentina/KomodoroRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Amerika/Argentina/Kordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "većina mesta (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Amerika/Argentina/Huhui"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Huhui (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Amerika/Argentina/La_Rioha"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "La Rioha (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Amerika/Argentina/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "Mendoza (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Amerika/Argentina/Rio_Galjegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "Santa Kruz (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "Amerika/Argentina/Salta"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Amerika/Argentina/San_Huan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "San Huan (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "Amerika/Argentina/San_Luis"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "San Luis (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Amerika/Argentina/Tukuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "Tukuman (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Amerika/Argentina/Ušuaja"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "Ognjena zemlja (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Amerika/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Amerika/Asunsion"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Amerika/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "Istočno standardno vreme - Atikokan, Ontario i O. Sautempton, Nunavut"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Amerika/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Amerika/Baija"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "Baija"
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "Amerika/Baija"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Amerika/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Amerika/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "Amapa, I Para"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Amerika/Belize"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "Amerika/Blan-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "Atlantsko standardno vreme - Kvebek - Niža severna obala"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Amerika/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "Roraima"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Amerika/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Amerika/Boize"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "Planinsko vreme - južni Ajdaho i istočni Oregon"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Amerika/Buenos_Ajres"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Amerika/Kembridž_Bej"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "Planinsko vreme - zapadni Nunavut"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "Amerika/Kampo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "Mato Groso do Sul"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Amerika/Kankun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "Centralno vreme - Kintana Ro"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Amerika/Karakas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Amerika/Katamarka"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Amerika/Kajen"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Amerika/Kajman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Amerika/Čikago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "Centralno vreme"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Amerika/Čivava"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "Meksičko planinsko vreme - Čivava daleko od granice SAD"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "Amerika/Koral_Harbor"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Amerika/Kordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Amerika/Kostarika"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Amerika/Kujaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "Mato Groso"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Amerika/Kurakao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Amerika/Denmarkshaven"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "istočna obala, severno od Skorzbisunda"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Amerika/Doson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "Pacifičko vreme - severni Jukon"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Amerika/Doson_Krik"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+"Planinsko standardno vreme - Doson Krik i Fort Sent Džon, Britanska Kolumbija"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Amerika/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "Planinsko vreme"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Amerika/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "Istočno vreme - Mičigen - većina mesta"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Amerika/Dominika"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Amerika/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+"Planinsko vreme - Alberta, istočna Britanska Kolumbija i zapadni Saskačevan"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Amerika/Ejrunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "Z Amazonija"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Amerika/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Amerika/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Amerika/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "SI Brazil (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Amerika/Fort_Vejn"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Amerika/Glejs_Bej"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr "Atlantsko vreme - Nova Škotska - mesta koja nisu pratila DST 1966-1971"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Amerika/Godtab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "većina mesta"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Amerika/Gus_Bej"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "Atlantsko vreme - Labrador - većina mesta"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Amerika/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Amerika/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Amerika/Gvadelup"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Amerika/Gvatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Amerika/Gvajakvil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "matično kopno"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Amerika/Gijana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Amerika/Halifaks"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "Atlantsko vreme - Nova Škotska (većina mesta), OPE"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Amerika/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Amerika/Ermosiljo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "Planinsko standardno vreme - Sonora"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Amerika/Indijana/Indijanapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "Istočno vreme - Indijana - većina mesta"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Amerika/Indijana/Noks"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "Centralno vreme - Indijana - Okrug Stark"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Amerika/Indijana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "Istočno vreme - Indijana - Okrug Kroford"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "Amerika/Indijana/Pitersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "Istočno vreme - Indijana - Okrug Pajk"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Amerika/Indijanapolis"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "Amerika/Indijana/Tel_Siti"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "Centralno vreme - Indijana - Okrug Peri"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Amerika/Indijana/Vevaj"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "Istočno vreme - Indijana - Okrug Svicerlend"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "Amerika/Indijana/Vinsens"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "Istočno vreme - Indijana - Okruzi Davis, Duboa, Noks i Martin"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "Amerika/Indijana/Vinamak"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "Istočno vreme - Indijana - Okrug Pulaski"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Amerika/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "Planinsko vreme - zapadne Severozapadne teritorije"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Amerika/Ikalujt"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "Istočno vreme - istočni Nunavut - većina mesta"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Amerika/Jamajka"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Amerika/Huhui"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Amerika/Žuno"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "Aljaško vreme - izbočina Aljaske"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Amerika/Kentaki/Luivil"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Istočno vreme - Kentaki - područje Luivila"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Amerika/Kentaki/Montičelo"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "Istočno vreme - Kentaki - Okrug Vejn"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Amerika/Noks_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Amerika/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Amerika/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Amerika/Los_Anđeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "Pacifičko vreme"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Amerika/Luivil"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Amerika/Masejo"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "Alagoas, Seržipe"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Amerika/Managva"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Amerika/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "I Amazonija"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "Amerika/Marigo"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Amerika/Martinik"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "Amerika/Matamoros"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+"SAD centralno vreme - Kuauila, Durango, Nuevo Leon, Tamaulipas u blizini "
+"granice SAD"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Amerika/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "Planinsko vreme - J Baha, Najarit, Sinaloa"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Amerika/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Amerika/Menomini"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+"Centralno vreme - Mičigen - Okruzi Dikinskon, Gogebik, Ajron i Menomini"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Amerika/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "Centralno vreme - Kampeće, Jukatan"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Amerika/Meksiko_Siti"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "Centralno vreme - većina mesta"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Amerika/Mikelon"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "Amerika/Monkton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "Atlantsko vreme - Nju Branzvik"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Amerika/Monterej"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+"Meksičko centralno vreme - Kuauila, Durango, Nuevo Leon, Tamaulipas daleko "
+"od granice SAD"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Amerika/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Amerika/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "Istočno vreme - Kvebek - većina mesta"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Amerika/Montserat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Amerika/Nasau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Amerika/Njujork"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "Istočno vreme"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Amerika/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+"Istočno vreme - Ontario i Kvebek - mesta koja nisu pratila DST 1967-1973"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Amerika/Nom"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "Aljaško vreme - zapadna Aljaska"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Amerika/Noronja"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "Atlantska ostrva"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Amerika/Severna_Dakota/Centar"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "Centralno vreme - Severna Dakota - Okrug Oliver"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "Amerika/Severna_Dakota/Nju_Salem"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+"Centralno vreme - Severna Dakota - Okrug Morton (izuzev područja Mandana)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "Amerika/Ohinaga"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "SAD planinsko vreme - Čivava u blizini granice SAD"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Amerika/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Amerika/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "Istočno vreme - Pangnirtung, Nunavut"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Amerika/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Amerika/Feniks"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "Planinsko standardno vreme - Arizona"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Amerika/Port-o-Prins"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Amerika/Porto_Akri"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Amerika/Port_of_Spejn"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Amerika/Porto_Velo"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "Rondonija"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Amerika/Portoriko"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Amerika/Rejni_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "Centralno vreme - Rejni River i Fort Fransis, Ontario"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Amerika/Rankinov_rukavac"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "Centralno vreme - centralni Nunavut"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Amerika/Resifi"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "Pernambuko"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Amerika/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "Centralno standardno vreme - Saskačevan - većina mesta"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "Amerika/Rezolut"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "Istočno standardno vreme - Rezolut, Nunavut"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Amerika/Rio_Branko"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "Akri"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Amerika/Rozario"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "Amerika/Santa_Izabel"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "Meksičko pacifičko vreme - Donja Kalifornija daleko od granice SAD"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "Amerika/Santarem"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "Z Para"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Amerika/Santjago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Amerika/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Amerika/Sao_Paolo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "J i JI Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Amerika/Skorzbisund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "Skorzbisund / Itokortormit"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Amerika/Šiprok"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "Planinsko vreme - Navaho"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "Amerika/Sv_Bartolomej"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Amerika/Sent_Džon"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "Njufaundlendsko vreme, uključujući JI Labrador"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Amerika/Sv_Kits"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Amerika/Sv_Lucija"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Amerika/Sent_Tomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Amerika/Sv_Vinsent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Amerika/Svift_Karent"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "Centralno standardno vreme - Saskačevan - srednji zapad"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Amerika/Tegusigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Amerika/Tule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "Tule / Pitufik"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Amerika/Tander_Bej"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "Istočno vreme - Tander Bej, Ontario"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Amerika/Tihuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "SAD pacifičko vreme - Donja Kalifornija u blizini granice SAD"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "Amerika/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "Istočno vreme - Ontario - većina mesta"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Amerika/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Amerika/Vankuver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "Pacifičko vreme - zapadna Britanska Kolumbija"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Amerika/Virdžin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Amerika/Vajthors"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "Pacifičko vreme - južni Jukon"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Amerika/Vinipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "Centralno vreme - Manitoba i zapadni Ontario"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Amerika/Jakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "Aljaško vreme - vrat izbočine Aljaske"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Amerika/Jelounajf"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "Planinsko vreme - centralne Severozapadne teritorije"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antarktik/Kejsi"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "Stanica Kejsi, Poluostrvo Bejli"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antarktik/Dejvis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "Stanica Dejvis, Vestfold Hils"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antarktik/DimonDIrvil"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "Stanica Dimon d'Irvil, Adelina zemlja"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "Antarktik/Makuori"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "Stanica Ostrva Makuori, Ostrvo Makuori"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antarktik/Moson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "Stanica Moson, Zaliv Holm"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antarktik/MekMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "Stanica MekMurdo, Ostrvo Ros"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antarktik/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "Stanica Palmer, Ostrvo Anvers"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antarktik/Rotera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "Stanica Rotera, Ostrvo Adelejd"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antarktik/Južni_pol"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "Stanica Amundsen-Skot, južni pol"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antarktik/Sjova"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "Stanica Sjova, O. i. Ongul"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antarktik/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "Stanica Vostok, j. magnetni pol"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Arktik/Longjirbjen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Azija/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Azija/Almati"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Azija/Aman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Azija/Anadir"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "Moskva+08 - Beringovo more"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Azija/Aktau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "Atirau (Gurjev), Mangistau"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Azija/Aktobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "Aktobe"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Azija/Ašgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Azija/Aškabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Azija/Bagdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Azija/Bahrein"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Azija/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Azija/Bankok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Azija/Bejrut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Azija/Biškek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Azija/Bruneji"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Azija/Kalkuta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Azija/Čojbalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "Dornod, Suhbatar"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Azija/Čonking"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "centralna Kina - Sečuan, Junan, Guangsi, Šansi, Guidžou, itd."
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Azija/Čunking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Azija/Kolombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Azija/Daka"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Azija/Damask"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Azija/Daka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Azija/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Azija/Dubaji"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Azija/Dušanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Azija/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Azija/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "Heilungđang (izuzev Mohe), Đilin"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Azija/Ho_Ši_Min"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Azija/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Azija/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "Bajan-Ulgij, Govi-Altaj, Hovd, Uvs, Zavhaj"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Azija/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Moskva+05 - Bajkalsko jezero"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Azija/Carigrad"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Azija/Džakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "Java i Sumatra"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Azija/Džajapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "Irijan Džaja i Moluci"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Azija/Jerusalim"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Azija/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Azija/Kamčatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "Moskva+08 - Kamčatka"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Azija/Karači"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Azija/Kašgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "zapadni Tibet i Sinđang"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "Azija/Katmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Azija/Katmandu"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "Azija/Kalkuta"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Azija/Krasnojarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "Moskva+04 - Reka Jenisej"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Azija/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "poluostrvska Malezija"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Azija/Kučing"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "Sabah i Saravak"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Azija/Kuvajt"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Azija/Makao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Azija/Makao"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Azija/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "Moskva+08 - Magadan"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Azija/Makasar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "istočni i južni Borneo, Sulavesi, Bali, Mali Sundi, zapadni Timor"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Azija/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Azija/Muskat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Azija/Nikozija"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "Azija/Novokuznjeck"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Moskva+03 - Novokuznjeck"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Azija/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Moskva+03 - Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Azija/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "Moskva+03 - zapadni Sibir"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Azija/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "Zapadni Kazahstan"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Azija/Pnom_Pen"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Azija/Pontijanak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "zapadni i centralni Borneo"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Azija/Pjongjang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Azija/Katar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Azija/Kizilorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "Kizilorda"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Azija/Rangun"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Azija/Rijad"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Azija/Rijad87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Azija/Rijad88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Azija/Rijad89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Azija/Sajgon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Azija/Sahalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "Moskva+07 - Ostrvo Sahalin"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Azija/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "zapadni Uzbekistan"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Azija/Seul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Azija/Šangaj"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "istočna Kina - Peking, Guangdung, Šangaj, itd."
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Azija/Singapur"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Azija/Tajpej"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Azija/Taškent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "istočni Uzbekistan"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Azija/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Azija/Teheran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Azija/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Azija/Timbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Azija/Timpu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Azija/Tokio"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Azija/Ujang_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Azija/Ulanbatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Azija/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Azija/Urumči"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "većina Tibeta i Sinđang"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Azija/Vijentijan"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Azija/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "Moskva+07 - Reka Amur"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Azija/Jakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "Moskva+06 - Reka Lena"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Azija/Jekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "Moskva+02 - Ural"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Azija/Jerevan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlantik/Azori"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "Azorska ostrva"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlantik/Bermude"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlantik/Kanarska_ostrva"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "Kanarska ostrva"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlantik/Kejp_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlantik/Farska_ostrva"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "Atlantik/Farska_ostrva"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlantik/Jan_Majen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlantik/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "Ostrva Madeira"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlantik/Rejkjavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlantik/Južna_Džordžija"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlantik/Stenli"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlantik/Sv_Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Australija/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Australija/Adelejd"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "Južna Australija"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Australija/Brizbejn"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "Kvinslend - većina mesta"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Australija/Broken_Hil"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "Novi Južni Vels - Jankovina"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Australija/Kanbera"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Australija/Kjuri"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "Tasmanija - Ostrvo King"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Australija/Darvin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "Severna teritorija"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "Australija/Jukla"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "Zapadna Australija - područje Jukle"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Australija/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "Tasmanija - većina mesta"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Australija/OLH"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Australija/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "Kvinslend - Praznična ostrva"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Australija/Lord_Hou"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "Ostrvo Lorda Houa"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Australija/Melburn"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "Viktorija"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Australija/Sever"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Australija/NJV"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Australija/Pert"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "Zapadna Australija - većina mesta"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Australija/Kvinslend"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Australija/Jug"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Australija/Sidnej"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "Novi Južni Vels - većina mesta"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Australija/Tasmanija"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Australija/Viktorija"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Australija/Zapad"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Australija/Jankovina"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brazil/Akri"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brazil/DeNoronja"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brazil/Istok"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brazil/Zapad"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Kanada/Atlantik"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Kanada/Centralna"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Kanada/Istočna"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Kanada/Istok-Saskačevan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Kanada/Planine"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Kanada/Njufaundlend"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Kanada/Pacifik"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Kanada/Saskačevan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Kanada/Jukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Čile/Kontinentalni"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Čile/Uskršnje_ostrvo"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Kuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Egipat"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Irska"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Itd/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Itd/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Itd/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Itd/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Itd/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Itd/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Itd/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Itd/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Itd/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Itd/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Itd/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Itd/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Itd/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Itd/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Itd/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Itd/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Itd/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Itd/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Itd/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Itd/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Itd/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Itd/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Itd/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Itd/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Itd/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Itd/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Itd/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Itd/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Itd/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Itd/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Itd/Grinič"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Itd/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Itd/Univerzalno"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Itd/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Itd/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Evropa/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Evropa/Andora"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Evropa/Atina"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Evropa/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Evropa/Beograd"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Evropa/Berlin"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Evropa/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Evropa/Brisel"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Evropa/Bukurešt"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Evropa/Budimpešta"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Evropa/Kišinjev"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Evropa/Kopenhagen"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Evropa/Dablin"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Evropa/Gibraltar"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Evropa/Gernzi"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Evropa/Helsinki"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Evropa/Ostrvo Man"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Evropa/Carigrad"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Evropa/Džerzi"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Evropa/Kalinjingrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Moskva-01 - Kalinjingrad"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Evropa/Kijev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Evropa/Lisabon"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Evropa/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Evropa/London"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Evropa/Luksemburg"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Evropa/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Evropa/Malta"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Evropa/Marijehamn"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Evropa/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Evropa/Monako"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Evropa/Moskva"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "Moskva+00 - zapadna Rusija"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Evropa/Nikozija"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Evropa/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Evropa/Pariz"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Evropa/Podgorica"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Evropa/Prag"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Evropa/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Evropa/Rim"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Evropa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Moskva - Samara, Udmurtija"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Evropa/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Evropa/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Evropa/Simferopolj"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "centralni Krim"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Evropa/Skoplje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Evropa/Sofija"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Evropa/Stokholm"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Evropa/Talin"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Evropa/Tirana"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Evropa/Tiraspolj"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Evropa/Užgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "Rutenija"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Evropa/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Evropa/Vatikan"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Evropa/Beč"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Evropa/Vilnijus"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Evropa/Volgograd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "Moskva+00 - Kaspijsko more"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Evropa/Varšava"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Evropa/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Evropa/Zaporožje"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "Zaporožje, I Lugansk"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Evropa/Cirih"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Fabrika"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "VB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "VB-Irska"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Grinič"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "Island"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Indijski_okean/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Indijski_okean/Čagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Indijski_okean/Božićna_ostrva"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Indijski_okean/Kokos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Indijski_okean/Komoro"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Indijski_okean/Kergulen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Indijski_okean/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Indijski_okean/Maldivi"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Indijski_okean/Mauricijus"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Indijski_okean/Majot"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Indijski_okean/Reunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Iran"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Izrael"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamajka"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Japan"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kvadžalin"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Libija"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Meksiko/BahaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Meksiko/BahaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Meksiko/Opšte"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Bliski istok/Rijad87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Bliski istok/Rijad88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Bliski istok/Rijad89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navaho"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-ČAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Pacifik/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Pacifik/Oklend"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Pacifik/Čatam"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "Ostrva Čatam"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "Pacifik/Truk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+#, fuzzy
+msgid "Chuuk (Truk) and Yap"
+msgstr "Truk (Čuuk) i Jap"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Pacifik/Uskršnje_ostrvo"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "Uskršnje ostrvo i Sala i Gomez"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Pacifik/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Pacifik/Enderburi"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "Ostrva Feniks"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Pacifik/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Pacifik/Fidži"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Pacifik/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Pacifik/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "Ostrva Galapagos"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Pacifik/Gambije"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "Ostrva Gambije"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Pacifik/Gvadalkanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Pacifik/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Pacifik/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "Havaji"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Pacifik/Džonston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "Atol Džonston"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Pacifik/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "Linijska ostrva"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Pacifik/Kosre"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "Kosre"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Pacifik/Kvadžalin"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Pacifik/Madžuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Pacifik/Markiz"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "Ostrva Markiz"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Pacifik/Midvej"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "Ostrva Midvej"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Pacifik/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Pacifik/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Pacifik/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Pacifik/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Pacifik/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Pacifik/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Pacifik/Pitkairn"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "Pacifik/Ponape"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+#, fuzzy
+msgid "Pohnpei (Ponape)"
+msgstr "Ponape (Ponpei)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Pacifik/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Pacifik/Port_Morezbi"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Pacifik/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Pacifik/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Pacifik/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Pacifik/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "Društvena ostrva"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Pacifik/Tarava"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "Ostrva Gilbert"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Pacifik/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Pacifik/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Pacifik/Vejk"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "Ostrvo Vejk"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Pacifik/Valis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Pacifik/Jap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Poljska"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portugal"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapur"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Turska"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Univerzalno"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "SAD/Aljaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "SAD/Aleutska_ostrva"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "SAD/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "SAD/Centralne"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "SAD/Istočne"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "SAD/Istok-Indijana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "SAD/Havaji"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "SAD/Indijana-Stark"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "SAD/Mičigen"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "SAD/Planine"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "SAD/Pacifik"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "SAD/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
diff --git a/panels/datetime/po-timezones/sv.po b/panels/datetime/po-timezones/sv.po
new file mode 100644
index 0000000..3f150b3
--- /dev/null
+++ b/panels/datetime/po-timezones/sv.po
@@ -0,0 +1,3221 @@
+# Swedish messages for timezones.
+# Copyright © 2004, 2006, 2008, 2010 Free Software Foundation, Inc.
+# Christian Rose <menthos@menthos.com>, 2004, 2005, 2006
+# Magnus Larsson <fedoratrans@gmail.com>, 2007, 2009.
+# Göran Uddeborg <goeran@uddeborg.se>, 2008, 2010.
+#
+# $Revision: 1.2 $
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-04-20 16:04+0200\n"
+"PO-Revision-Date: 2010-08-23 21:07+0200\n"
+"Last-Translator: Göran Uddeborg <goeran@uddeborg.se>\n"
+"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Afrika/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Afrika/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Afrika/Addis_Abeba"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Afrika/Alger"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "Afrika/Asmara"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Afrika/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Afrika/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Afrika/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Afrika/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Afrika/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Afrika/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Afrika/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Afrika/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Afrika/Kairo"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Afrika/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Afrika/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "Ceuta & Melilla"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Afrika/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Afrika/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Afrika/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Afrika/Djibouti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Afrika/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Afrika/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Afrika/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Afrika/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Afrika/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Afrika/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Afrika/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Afrika/Khartoum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Afrika/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Afrika/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "västra Dem. Rep. Kongo"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Afrika/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Afrika/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Afrika/Lomé"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Afrika/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Afrika/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "östra Dem. Rep. Kongo"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Afrika/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Afrika/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Afrika/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Afrika/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Afrika/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Afrika/Mogadishu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Afrika/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Afrika/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Afrika/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Afrika/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Afrika/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Afrika/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Afrika/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Afrika/São_Tomé"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Afrika/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Afrika/Tripoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Afrika/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Afrika/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Amerika/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Aleutianska öarna"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Amerika/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Alaska-tid"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Amerika/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Amerika/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Amerika/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "Tocantins"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Amerika/Argentina/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Buenos Aires (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Amerika/Argentina/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "Catamarca (CT), Chubut (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "America/Argentina/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Amerika/Argentina/Cordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "de flesta platserna (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Amerika/Argentina/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Jujuy (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Amerika/Argentina/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "La Rioja (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Amerika/Argentina/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "Mendoza (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Amerika/Argentina/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "Santa Cruz (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "Amerika/Argentina/Salta"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Amerika/Argentina/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "San Juan (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "Amerika/Argentina/San_Luis"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "San Luis (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "America/Argentina/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "Tucuman (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Amerika/Argentina/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "Tierra del Fuego (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Amerika/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Amerika/Asunción"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Amerika/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "Östlig standardtid - Atikokan, Ontario och Southampton I, Nunavut"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Amerika/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Amerika/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "Bahia"
+
+#: timezones.h:117
+msgid "America/Barbados"
+msgstr "Amerika/Barbados"
+
+#: timezones.h:118
+msgid "America/Belem"
+msgstr "Amerika/Belém"
+
+#. comment for time zone America/Belem
+#: timezones.h:120
+msgid "Amapa, E Para"
+msgstr "Amapá, Ö Pará"
+
+#: timezones.h:121
+msgid "America/Belize"
+msgstr "Amerika/Belize"
+
+#: timezones.h:122
+msgid "America/Blanc-Sablon"
+msgstr "America/Blanc-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:124
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "Atlantisk standardtid - Quebec - Nedre nordkusten"
+
+#: timezones.h:125
+msgid "America/Boa_Vista"
+msgstr "Amerika/Boa_Vísta"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:127
+msgid "Roraima"
+msgstr "Roraima"
+
+#: timezones.h:128
+msgid "America/Bogota"
+msgstr "Amerika/Bogotá"
+
+#: timezones.h:129
+msgid "America/Boise"
+msgstr "Amerika/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:131
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "Bergstid - södra Idaho och östra Oregon"
+
+#: timezones.h:132
+msgid "America/Buenos_Aires"
+msgstr "Amerika/Buenos_Aires"
+
+#: timezones.h:133
+msgid "America/Cambridge_Bay"
+msgstr "Amerika/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:135
+msgid "Mountain Time - west Nunavut"
+msgstr "Bergstid - västra Nunavut"
+
+#: timezones.h:136
+msgid "America/Campo_Grande"
+msgstr "Amerika/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:138
+msgid "Mato Grosso do Sul"
+msgstr "Mato Grosso do Sul"
+
+#: timezones.h:139
+msgid "America/Cancun"
+msgstr "Amerika/Cancún"
+
+#. comment for time zone America/Cancun
+#: timezones.h:141
+msgid "Central Time - Quintana Roo"
+msgstr "Centraltid - Quintana Roo"
+
+#: timezones.h:142
+msgid "America/Caracas"
+msgstr "Amerika/Caracas"
+
+#: timezones.h:143
+msgid "America/Catamarca"
+msgstr "Amerika/Catamarca"
+
+#: timezones.h:144
+msgid "America/Cayenne"
+msgstr "Amerika/Cayenne"
+
+#: timezones.h:145
+msgid "America/Cayman"
+msgstr "Amerika/Cayman"
+
+#: timezones.h:146
+msgid "America/Chicago"
+msgstr "Amerika/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:148
+msgid "Central Time"
+msgstr "Centraltid"
+
+#: timezones.h:149
+msgid "America/Chihuahua"
+msgstr "Amerika/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:151
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "Mexikansk bergstid - Chihuahua på avstånd från USA-gränsen"
+
+#: timezones.h:152
+msgid "America/Coral_Harbour"
+msgstr "Amerika/Coral_Harbour"
+
+#: timezones.h:153
+msgid "America/Cordoba"
+msgstr "Amerika/Cordoba"
+
+#: timezones.h:154
+msgid "America/Costa_Rica"
+msgstr "Amerika/Costa_Rica"
+
+#: timezones.h:155
+msgid "America/Cuiaba"
+msgstr "Amerika/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:157
+msgid "Mato Grosso"
+msgstr "Mato Grosso"
+
+#: timezones.h:158
+msgid "America/Curacao"
+msgstr "Amerika/Curacão"
+
+#: timezones.h:159
+msgid "America/Danmarkshavn"
+msgstr "Amerika/Danmarkshamn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:161
+msgid "east coast, north of Scoresbysund"
+msgstr "östkusten, norr om Scoresbysund"
+
+#: timezones.h:162
+msgid "America/Dawson"
+msgstr "Amerika/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:164
+msgid "Pacific Time - north Yukon"
+msgstr "Stillahavstid - norra Yukon"
+
+#: timezones.h:165
+msgid "America/Dawson_Creek"
+msgstr "Amerika/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:167
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr "Bergsstandardtid - Dawson Creek och Fort Saint John, British Columbia"
+
+#: timezones.h:168
+msgid "America/Denver"
+msgstr "Amerika/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:170
+msgid "Mountain Time"
+msgstr "Bergstid"
+
+#: timezones.h:171
+msgid "America/Detroit"
+msgstr "Amerika/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:173
+msgid "Eastern Time - Michigan - most locations"
+msgstr "Östtid - Michigan - de flesta platser"
+
+#: timezones.h:174
+msgid "America/Dominica"
+msgstr "Amerika/Dominica"
+
+#: timezones.h:175
+msgid "America/Edmonton"
+msgstr "Amerika/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:177
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "Bergstid - Alberta, östra British Columbia och västra Saskatchewan"
+
+#: timezones.h:178
+msgid "America/Eirunepe"
+msgstr "Amerika/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:180
+msgid "W Amazonas"
+msgstr "V Amazonas"
+
+#: timezones.h:181
+msgid "America/El_Salvador"
+msgstr "Amerika/El_Salvador"
+
+#: timezones.h:182
+msgid "America/Ensenada"
+msgstr "Amerika/Ensenada"
+
+#: timezones.h:183
+msgid "America/Fortaleza"
+msgstr "Amerika/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:185
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "NÖ Brasilien (MA, PI, CE, RN, PB)"
+
+#: timezones.h:186
+msgid "America/Fort_Wayne"
+msgstr "Amerika/Fort_Wayne"
+
+#: timezones.h:187
+msgid "America/Glace_Bay"
+msgstr "Amerika/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:189
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr "Atlanttid - Nova Scotia - platser som inte hade sommartid 1966-1971"
+
+#: timezones.h:190
+msgid "America/Godthab"
+msgstr "Amerika/Godthåb"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:192 timezones.h:361 timezones.h:450 timezones.h:588
+#: timezones.h:751 timezones.h:849 timezones.h:888
+msgid "most locations"
+msgstr "de flesta platserna"
+
+#: timezones.h:193
+msgid "America/Goose_Bay"
+msgstr "Amerika/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:195
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "Atlanttid - Labrador - de flesta platser"
+
+#: timezones.h:196
+msgid "America/Grand_Turk"
+msgstr "Amerika/Grand_Turk"
+
+#: timezones.h:197
+msgid "America/Grenada"
+msgstr "Amerika/Grenada"
+
+#: timezones.h:198
+msgid "America/Guadeloupe"
+msgstr "Amerika/Guadeloupe"
+
+#: timezones.h:199
+msgid "America/Guatemala"
+msgstr "Amerika/Guatemala"
+
+#: timezones.h:200
+msgid "America/Guayaquil"
+msgstr "Amerika/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:202 timezones.h:754 timezones.h:760
+msgid "mainland"
+msgstr "fastlandet"
+
+#: timezones.h:203
+msgid "America/Guyana"
+msgstr "Amerika/Guyana"
+
+#: timezones.h:204
+msgid "America/Halifax"
+msgstr "Amerika/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:206
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "Atlanttid - Nova Scotia (de flesta platser), Prins Edvards ö"
+
+#: timezones.h:207
+msgid "America/Havana"
+msgstr "Amerika/Havanna"
+
+#: timezones.h:208
+msgid "America/Hermosillo"
+msgstr "Amerika/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:210
+msgid "Mountain Standard Time - Sonora"
+msgstr "Bergsstandardtid - Sonora"
+
+#: timezones.h:211
+msgid "America/Indiana/Indianapolis"
+msgstr "Amerika/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:213
+msgid "Eastern Time - Indiana - most locations"
+msgstr "Östtid - Indiana - de flesta platser"
+
+#: timezones.h:214
+msgid "America/Indiana/Knox"
+msgstr "Amerika/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:216
+msgid "Central Time - Indiana - Starke County"
+msgstr "Centraltid - Indiana - Starke County"
+
+#: timezones.h:217
+msgid "America/Indiana/Marengo"
+msgstr "Amerika/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:219
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "Östtid - Indiana - Crawford County"
+
+#: timezones.h:220
+msgid "America/Indiana/Petersburg"
+msgstr "America/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "Östtid - Indiana - Pike County"
+
+#: timezones.h:223
+msgid "America/Indianapolis"
+msgstr "Amerika/Indianapolis"
+
+#: timezones.h:224
+msgid "America/Indiana/Tell_City"
+msgstr "Amerika/Indiana/Tell_City"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:226
+msgid "Central Time - Indiana - Perry County"
+msgstr "Centraltid - Indiana - Perry County"
+
+#: timezones.h:227
+msgid "America/Indiana/Vevay"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:229
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "Östtid - Indiana - Switzerland County"
+
+#: timezones.h:230
+msgid "America/Indiana/Vincennes"
+msgstr "America/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "Östtid - Indiana - Daviess, Dubois, Knox och Martin County"
+
+#: timezones.h:233
+msgid "America/Indiana/Winamac"
+msgstr "America/Indiana/Winamac"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "Östtid - Indiana - Pulaski County"
+
+#: timezones.h:236
+msgid "America/Inuvik"
+msgstr "Amerika/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:238
+msgid "Mountain Time - west Northwest Territories"
+msgstr "Bergstid - västra Nordvästterritorierna"
+
+#: timezones.h:239
+msgid "America/Iqaluit"
+msgstr "Amerika/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:241
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "Östtid - östra Nunavut - de flesta platser"
+
+#: timezones.h:242
+msgid "America/Jamaica"
+msgstr "Amerika/Jamaica"
+
+#: timezones.h:243
+msgid "America/Jujuy"
+msgstr "Amerika/Jujuy"
+
+#: timezones.h:244
+msgid "America/Juneau"
+msgstr "Amerika/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:246
+msgid "Alaska Time - Alaska panhandle"
+msgstr "Alaskatid - Alaskautlöparen"
+
+#: timezones.h:247
+msgid "America/Kentucky/Louisville"
+msgstr "Amerika/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:249
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Östlig tid - Kentucky - Louisville-området"
+
+#: timezones.h:250
+msgid "America/Kentucky/Monticello"
+msgstr "Amerika/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "Östtid - Kentucky - Wayne County"
+
+#: timezones.h:253
+msgid "America/Knox_IN"
+msgstr "Amerika/Knox_Indiana"
+
+#: timezones.h:254
+msgid "America/La_Paz"
+msgstr "Amerika/La_Paz"
+
+#: timezones.h:255
+msgid "America/Lima"
+msgstr "Amerika/Lima"
+
+#: timezones.h:256
+msgid "America/Los_Angeles"
+msgstr "Amerika/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:258
+msgid "Pacific Time"
+msgstr "Stilla havet-tid"
+
+#: timezones.h:259
+msgid "America/Louisville"
+msgstr "Amerika/Louisville"
+
+#: timezones.h:260
+msgid "America/Maceio"
+msgstr "Amerika/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:262
+msgid "Alagoas, Sergipe"
+msgstr "Alagoas, Sergipe"
+
+#: timezones.h:263
+msgid "America/Managua"
+msgstr "Amerika/Managua"
+
+#: timezones.h:264
+msgid "America/Manaus"
+msgstr "Amerika/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:266
+msgid "E Amazonas"
+msgstr "Ö Amazonas"
+
+#: timezones.h:267
+msgid "America/Marigot"
+msgstr "America/Marigot"
+
+#: timezones.h:268
+msgid "America/Martinique"
+msgstr "Amerika/Martinique"
+
+#: timezones.h:269
+msgid "America/Matamoros"
+msgstr "Amerika/Matamoros"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:271
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr "USA:s centraltid - Coahuila, Durango, Nuevo Leon, Tamaulipas nära USA:gränsen"
+
+#: timezones.h:272
+msgid "America/Mazatlan"
+msgstr "Amerika/Mazatlán"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:274
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "Bergstid - S Baja, Nayarit, Sinaloa"
+
+#: timezones.h:275
+msgid "America/Mendoza"
+msgstr "Amerika/Mendoza"
+
+#: timezones.h:276
+msgid "America/Menominee"
+msgstr "Amerika/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:278
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "Centraltid - Michigan - Dickinson, Gogebic, Iron och Menominee County"
+
+#: timezones.h:279
+msgid "America/Merida"
+msgstr "Amerika/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:281
+msgid "Central Time - Campeche, Yucatan"
+msgstr "Centraltid - Campeche, Yucatan"
+
+#: timezones.h:282
+msgid "America/Mexico_City"
+msgstr "Amerika/Mexico_City"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:284
+msgid "Central Time - most locations"
+msgstr "Centraltid - de flesta platser"
+
+#: timezones.h:285
+msgid "America/Miquelon"
+msgstr "Amerika/Miquelon"
+
+#: timezones.h:286
+msgid "America/Moncton"
+msgstr "America/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:288
+msgid "Atlantic Time - New Brunswick"
+msgstr "Atlanttid - New Brunswick"
+
+#: timezones.h:289
+msgid "America/Monterrey"
+msgstr "Amerika/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:291
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr "Mexicansk centraltid - Coahuila, Durango, Nuevo Leon, Tamaulipas på avstånd från USA-gränsen"
+
+#: timezones.h:292
+msgid "America/Montevideo"
+msgstr "Amerika/Montevideo"
+
+#: timezones.h:293
+msgid "America/Montreal"
+msgstr "Amerika/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:295
+msgid "Eastern Time - Quebec - most locations"
+msgstr "Östtid - Quebec - de flesta platser"
+
+#: timezones.h:296
+msgid "America/Montserrat"
+msgstr "Amerika/Montserrat"
+
+#: timezones.h:297
+msgid "America/Nassau"
+msgstr "Amerika/Nassau"
+
+#: timezones.h:298
+msgid "America/New_York"
+msgstr "Amerika/New_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:300
+msgid "Eastern Time"
+msgstr "Östlig tid"
+
+#: timezones.h:301
+msgid "America/Nipigon"
+msgstr "Amerika/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:303
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr "Östtid - Ontario och Quebec - platser som inte hade sommartid 1967-1973"
+
+#: timezones.h:304
+msgid "America/Nome"
+msgstr "Amerika/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:306
+msgid "Alaska Time - west Alaska"
+msgstr "Alaskatid - västra Alaska"
+
+#: timezones.h:307
+msgid "America/Noronha"
+msgstr "Amerika/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:309
+msgid "Atlantic islands"
+msgstr "Atlantiska öarna"
+
+#: timezones.h:310
+msgid "America/North_Dakota/Center"
+msgstr "Amerika/Norddakota/Centrala"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:312
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "Centraltid - North Dakota - Oliver County"
+
+#: timezones.h:313
+msgid "America/North_Dakota/New_Salem"
+msgstr "America/North_Dakota/New_Salem"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:315
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "Centraltid - North Dakota - Morton county (utom Mandan-området)"
+
+#: timezones.h:316
+msgid "America/Ojinaga"
+msgstr "Amerika/Ojinaga"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:318
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "USA:s bergstid - Chihuahua nära USA-gränsen"
+
+#: timezones.h:319
+msgid "America/Panama"
+msgstr "Amerika/Panamá"
+
+#: timezones.h:320
+msgid "America/Pangnirtung"
+msgstr "Amerika/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:322
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "Östtid - Pangnirtung, Nunavut"
+
+#: timezones.h:323
+msgid "America/Paramaribo"
+msgstr "Amerika/Paramaribo"
+
+#: timezones.h:324
+msgid "America/Phoenix"
+msgstr "Amerika/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:326
+msgid "Mountain Standard Time - Arizona"
+msgstr "Bergsstandardtid - Arizona"
+
+#: timezones.h:327
+msgid "America/Port-au-Prince"
+msgstr "Amerika/Port-au-Prince"
+
+#: timezones.h:328
+msgid "America/Porto_Acre"
+msgstr "Amerika/Porto_Acre"
+
+#: timezones.h:329
+msgid "America/Port_of_Spain"
+msgstr "Amerika/Port_of_Spain"
+
+#: timezones.h:330
+msgid "America/Porto_Velho"
+msgstr "Amerika/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:332
+msgid "Rondonia"
+msgstr "Rondônia"
+
+#: timezones.h:333
+msgid "America/Puerto_Rico"
+msgstr "Amerika/Puerto_Rico"
+
+#: timezones.h:334
+msgid "America/Rainy_River"
+msgstr "Amerika/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:336
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "Centraltid - Rainy River & Fort Frances, Ontario"
+
+#: timezones.h:337
+msgid "America/Rankin_Inlet"
+msgstr "Amerika/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:339
+msgid "Central Time - central Nunavut"
+msgstr "Centraltid - centrala Nunavut"
+
+#: timezones.h:340
+msgid "America/Recife"
+msgstr "Amerika/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:342
+msgid "Pernambuco"
+msgstr "Pernambuco"
+
+#: timezones.h:343
+msgid "America/Regina"
+msgstr "Amerika/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:345
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "Centralstandardtid - Saskatchewan - de flesta platser"
+
+#: timezones.h:346
+msgid "America/Resolute"
+msgstr "America/Resolute"
+
+#. comment for time zone America/Resolute
+#: timezones.h:348
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "Öststandardtid - Resolute, Nunavut"
+
+#: timezones.h:349
+msgid "America/Rio_Branco"
+msgstr "Amerika/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:351
+msgid "Acre"
+msgstr "Acre"
+
+#: timezones.h:352
+msgid "America/Rosario"
+msgstr "Amerika/Rosario"
+
+#: timezones.h:353
+msgid "America/Santa_Isabel"
+msgstr "Amerika/Santa_Isabel"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:355
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "Mexikansk stillahavstid - Baja California på avstånd från USA-gränsen"
+
+#: timezones.h:356
+msgid "America/Santarem"
+msgstr "Amerika/Santarem"
+
+#. comment for time zone America/Santarem
+#: timezones.h:358
+msgid "W Para"
+msgstr "V Para"
+
+#: timezones.h:359
+msgid "America/Santiago"
+msgstr "Amerika/Santiago"
+
+#: timezones.h:362
+msgid "America/Santo_Domingo"
+msgstr "Amerika/Santo_Domingo"
+
+#: timezones.h:363
+msgid "America/Sao_Paulo"
+msgstr "Amerika/São_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:365
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "S & SÖ Brasilien (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:366
+msgid "America/Scoresbysund"
+msgstr "Amerika/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:368
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "Scoresbysund / Ittoqqortoormiit"
+
+#: timezones.h:369
+msgid "America/Shiprock"
+msgstr "Amerika/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:371
+msgid "Mountain Time - Navajo"
+msgstr "Bergstid - Navajo"
+
+#: timezones.h:372
+msgid "America/St_Barthelemy"
+msgstr "America/St_Barthelemy"
+
+#: timezones.h:373
+msgid "America/St_Johns"
+msgstr "Amerika/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:375
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "Newfoundlandtid, inklusive SÖ Labrador"
+
+#: timezones.h:376
+msgid "America/St_Kitts"
+msgstr "Amerika/St_Kitts"
+
+#: timezones.h:377
+msgid "America/St_Lucia"
+msgstr "Amerika/St_Lucia"
+
+#: timezones.h:378
+msgid "America/St_Thomas"
+msgstr "Amerika/St_Thomas"
+
+#: timezones.h:379
+msgid "America/St_Vincent"
+msgstr "Amerika/St_Vincent"
+
+#: timezones.h:380
+msgid "America/Swift_Current"
+msgstr "Amerika/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:382
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "Centralstandardtid - Saskatchewan - mellanvästern"
+
+#: timezones.h:383
+msgid "America/Tegucigalpa"
+msgstr "Amerika/Tegucigalpa"
+
+#: timezones.h:384
+msgid "America/Thule"
+msgstr "Amerika/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:386
+msgid "Thule / Pituffik"
+msgstr "Thule / Pituffik"
+
+#: timezones.h:387
+msgid "America/Thunder_Bay"
+msgstr "Amerika/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:389
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "Östlig tid - Thunder Bay, Ontario"
+
+#: timezones.h:390
+msgid "America/Tijuana"
+msgstr "Amerika/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:392
+msgid "US Pacific Time - Baja California near US border"
+msgstr "USA:s stillahavstid - Baja California nära USA-gränsen"
+
+#: timezones.h:393
+msgid "America/Toronto"
+msgstr "Amerika/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:395
+msgid "Eastern Time - Ontario - most locations"
+msgstr "Östtid - Ontario - de flesta platser"
+
+#: timezones.h:396
+msgid "America/Tortola"
+msgstr "Amerika/Tortola"
+
+#: timezones.h:397
+msgid "America/Vancouver"
+msgstr "Amerika/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:399
+msgid "Pacific Time - west British Columbia"
+msgstr "Stillahavstid - västra British Columbia"
+
+#: timezones.h:400
+msgid "America/Virgin"
+msgstr "Amerika/Jungfruöarna"
+
+#: timezones.h:401
+msgid "America/Whitehorse"
+msgstr "Amerika/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:403
+msgid "Pacific Time - south Yukon"
+msgstr "Stillahavstid - södra Yukon"
+
+#: timezones.h:404
+msgid "America/Winnipeg"
+msgstr "Amerika/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:406
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "Centraltid - Manitoba och västra Ontario"
+
+#: timezones.h:407
+msgid "America/Yakutat"
+msgstr "Amerika/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:409
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "Alaskatid - Alaska panhandle neck"
+
+#: timezones.h:410
+msgid "America/Yellowknife"
+msgstr "Amerika/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:412
+msgid "Mountain Time - central Northwest Territories"
+msgstr "Bergstid - centrala Nordvästterritorierna"
+
+#: timezones.h:413
+msgid "Antarctica/Casey"
+msgstr "Antarktis/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:415
+msgid "Casey Station, Bailey Peninsula"
+msgstr "Casey Station, Baileyhalvön"
+
+#: timezones.h:416
+msgid "Antarctica/Davis"
+msgstr "Antarktis/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:418
+msgid "Davis Station, Vestfold Hills"
+msgstr "Davis-stationen, Vestfold Hills"
+
+#: timezones.h:419
+msgid "Antarctica/DumontDUrville"
+msgstr "Antarktis/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:421
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "Dumont-d'Urville-stationen, Adélieland"
+
+#: timezones.h:422
+msgid "Antarctica/Macquarie"
+msgstr "Antarktis/Macquarie"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:424
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "Macquarieöstaionen, Macquarieön"
+
+#: timezones.h:425
+msgid "Antarctica/Mawson"
+msgstr "Antarktis/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:427
+msgid "Mawson Station, Holme Bay"
+msgstr "Mawson-stationen, Holme Bay"
+
+#: timezones.h:428
+msgid "Antarctica/McMurdo"
+msgstr "Antarktis/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:430
+msgid "McMurdo Station, Ross Island"
+msgstr "McMurdo-stationen, Ross Island"
+
+#: timezones.h:431
+msgid "Antarctica/Palmer"
+msgstr "Antarktis/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:433
+msgid "Palmer Station, Anvers Island"
+msgstr "Palmer-stationen, Anversön"
+
+#: timezones.h:434
+msgid "Antarctica/Rothera"
+msgstr "Antarktis/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:436
+msgid "Rothera Station, Adelaide Island"
+msgstr "Rothera-stationen, Adelaideön"
+
+#: timezones.h:437
+msgid "Antarctica/South_Pole"
+msgstr "Antarktis/Sydpolen"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:439
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "Amundsen-Scott-stationen, Sydpolen"
+
+#: timezones.h:440
+msgid "Antarctica/Syowa"
+msgstr "Antarktis/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:442
+msgid "Syowa Station, E Ongul I"
+msgstr "Syowa-stationen, Ö Ongulön"
+
+#: timezones.h:443
+msgid "Antarctica/Vostok"
+msgstr "Antarktis/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:445
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "Vostok-stationen, S magnetiska polen"
+
+#: timezones.h:446
+msgid "Arctic/Longyearbyen"
+msgstr "Arktis/Longyearbyen"
+
+#: timezones.h:447
+msgid "Asia/Aden"
+msgstr "Asien/Aden"
+
+#: timezones.h:448
+msgid "Asia/Almaty"
+msgstr "Asien/Alma-ata"
+
+#: timezones.h:451
+msgid "Asia/Amman"
+msgstr "Asien/Amman"
+
+#: timezones.h:452
+msgid "Asia/Anadyr"
+msgstr "Asien/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:454
+msgid "Moscow+08 - Bering Sea"
+msgstr "Moskva+08 - Berings hav"
+
+#: timezones.h:455
+msgid "Asia/Aqtau"
+msgstr "Asien/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:457
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+
+#: timezones.h:458
+msgid "Asia/Aqtobe"
+msgstr "Asien/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:460
+msgid "Aqtobe (Aktobe)"
+msgstr "Aqtobe (Aktobe)"
+
+#: timezones.h:461
+msgid "Asia/Ashgabat"
+msgstr "Asien/Ashgabat"
+
+#: timezones.h:462
+msgid "Asia/Ashkhabad"
+msgstr "Asien/Ashkhabad"
+
+#: timezones.h:463
+msgid "Asia/Baghdad"
+msgstr "Asien/Bagdad"
+
+#: timezones.h:464
+msgid "Asia/Bahrain"
+msgstr "Asien/Bahrain"
+
+#: timezones.h:465
+msgid "Asia/Baku"
+msgstr "Asien/Baku"
+
+#: timezones.h:466
+msgid "Asia/Bangkok"
+msgstr "Asien/Bangkok"
+
+#: timezones.h:467
+msgid "Asia/Beirut"
+msgstr "Asien/Beirut"
+
+#: timezones.h:468
+msgid "Asia/Bishkek"
+msgstr "Asien/Bisjkek"
+
+#: timezones.h:469
+msgid "Asia/Brunei"
+msgstr "Asien/Brunei"
+
+#: timezones.h:470
+msgid "Asia/Calcutta"
+msgstr "Asien/Calcutta"
+
+#: timezones.h:471
+msgid "Asia/Choibalsan"
+msgstr "Asien/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:473
+msgid "Dornod, Sukhbaatar"
+msgstr "Dornod, Sukhbaatar"
+
+#: timezones.h:474
+msgid "Asia/Chongqing"
+msgstr "Asien/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:476
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "centrala Kina - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou etc."
+
+#: timezones.h:477
+msgid "Asia/Chungking"
+msgstr "Asien/Chungking"
+
+#: timezones.h:478
+msgid "Asia/Colombo"
+msgstr "Asien/Colombo"
+
+#: timezones.h:479
+msgid "Asia/Dacca"
+msgstr "Asien/Dacca"
+
+#: timezones.h:480
+msgid "Asia/Damascus"
+msgstr "Asien/Damaskus"
+
+#: timezones.h:481
+msgid "Asia/Dhaka"
+msgstr "Asien/Dhaka"
+
+#: timezones.h:482
+msgid "Asia/Dili"
+msgstr "Asien/Dili"
+
+#: timezones.h:483
+msgid "Asia/Dubai"
+msgstr "Asien/Dubai"
+
+#: timezones.h:484
+msgid "Asia/Dushanbe"
+msgstr "Asien/Dushanbe"
+
+#: timezones.h:485
+msgid "Asia/Gaza"
+msgstr "Asien/Gaza"
+
+#: timezones.h:486
+msgid "Asia/Harbin"
+msgstr "Asien/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:488
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "Heilongjiang (utom Mohe), Jilin"
+
+#: timezones.h:489
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Asien/Ho_Chi_Minh"
+
+#: timezones.h:490
+msgid "Asia/Hong_Kong"
+msgstr "Asien/Hong_Kong"
+
+#: timezones.h:491
+msgid "Asia/Hovd"
+msgstr "Asien/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:493
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+
+#: timezones.h:494
+msgid "Asia/Irkutsk"
+msgstr "Asien/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:496
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Moskva+05 - Baikal-sjön"
+
+#: timezones.h:497
+msgid "Asia/Istanbul"
+msgstr "Asien/Istanbul"
+
+#: timezones.h:498
+msgid "Asia/Jakarta"
+msgstr "Asien/Jakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:500
+msgid "Java & Sumatra"
+msgstr "Java & Sumatra"
+
+#: timezones.h:501
+msgid "Asia/Jayapura"
+msgstr "Asien/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:503
+msgid "Irian Jaya & the Moluccas"
+msgstr "Irian Jaya och Moluckerna"
+
+#: timezones.h:504
+msgid "Asia/Jerusalem"
+msgstr "Asien/Jerusalem"
+
+#: timezones.h:505
+msgid "Asia/Kabul"
+msgstr "Asien/Kabul"
+
+#: timezones.h:506
+msgid "Asia/Kamchatka"
+msgstr "Asien/Kamtjatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:508
+msgid "Moscow+08 - Kamchatka"
+msgstr "Moskva+08 - Kamtjatka"
+
+#: timezones.h:509
+msgid "Asia/Karachi"
+msgstr "Asien/Karachi"
+
+#: timezones.h:510
+msgid "Asia/Kashgar"
+msgstr "Asien/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:512
+msgid "west Tibet & Xinjiang"
+msgstr "västra Tibet & Xinjiang"
+
+#: timezones.h:513
+msgid "Asia/Kathmandu"
+msgstr "Asien/Katmandu"
+
+#: timezones.h:514
+msgid "Asia/Katmandu"
+msgstr "Asien/Katmandu"
+
+#: timezones.h:515
+msgid "Asia/Kolkata"
+msgstr "Asien/Kolkata"
+
+#: timezones.h:516
+msgid "Asia/Krasnoyarsk"
+msgstr "Asien/Krasnojarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:518
+msgid "Moscow+04 - Yenisei River"
+msgstr "Moskva+04 - Yenisei-floden"
+
+#: timezones.h:519
+msgid "Asia/Kuala_Lumpur"
+msgstr "Asien/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:521
+msgid "peninsular Malaysia"
+msgstr "halvön av Malaysia"
+
+#: timezones.h:522
+msgid "Asia/Kuching"
+msgstr "Asien/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:524
+msgid "Sabah & Sarawak"
+msgstr "Sabah & Sarawak"
+
+#: timezones.h:525
+msgid "Asia/Kuwait"
+msgstr "Asien/Kuwait"
+
+#: timezones.h:526
+msgid "Asia/Macao"
+msgstr "Asien/Macao"
+
+#: timezones.h:527
+msgid "Asia/Macau"
+msgstr "Asien/Macao"
+
+#: timezones.h:528
+msgid "Asia/Magadan"
+msgstr "Asien/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:530
+msgid "Moscow+08 - Magadan"
+msgstr "Moskva+08 - Magadan"
+
+#: timezones.h:531
+msgid "Asia/Makassar"
+msgstr "Asien/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:533
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "östra & södra Borneo, Celebes, Bali, Nusa Tengarra, väst-Timor"
+
+#: timezones.h:534
+msgid "Asia/Manila"
+msgstr "Asien/Manila"
+
+#: timezones.h:535
+msgid "Asia/Muscat"
+msgstr "Asien/Muscat"
+
+#: timezones.h:536
+msgid "Asia/Nicosia"
+msgstr "Asien/Nicosia"
+
+#: timezones.h:537
+msgid "Asia/Novokuznetsk"
+msgstr "Asien/Novokuznetsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:539
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Moskva+03 - Novokuznetsk"
+
+#: timezones.h:540
+msgid "Asia/Novosibirsk"
+msgstr "Asien/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:542
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Moskva+03 - Novosibirsk"
+
+#: timezones.h:543
+msgid "Asia/Omsk"
+msgstr "Asien/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:545
+msgid "Moscow+03 - west Siberia"
+msgstr "Moskva+03 - västra Siberien"
+
+#: timezones.h:546
+msgid "Asia/Oral"
+msgstr "Asien/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:548
+msgid "West Kazakhstan"
+msgstr "Västra Kazakhstan"
+
+#: timezones.h:549
+msgid "Asia/Phnom_Penh"
+msgstr "Asien/Phnom_Penh"
+
+#: timezones.h:550
+msgid "Asia/Pontianak"
+msgstr "Asien/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:552
+msgid "west & central Borneo"
+msgstr "västra & centrala Borneo"
+
+#: timezones.h:553
+msgid "Asia/Pyongyang"
+msgstr "Asien/Pyongyang"
+
+#: timezones.h:554
+msgid "Asia/Qatar"
+msgstr "Asien/Qatar"
+
+#: timezones.h:555
+msgid "Asia/Qyzylorda"
+msgstr "Asien/Kzyl-Orda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:557
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+
+#: timezones.h:558
+msgid "Asia/Rangoon"
+msgstr "Asien/Rangoon"
+
+#: timezones.h:559
+msgid "Asia/Riyadh"
+msgstr "Asien/Riyadh"
+
+#: timezones.h:560
+msgid "Asia/Riyadh87"
+msgstr "Asien/Riyadh87"
+
+#: timezones.h:561
+msgid "Asia/Riyadh88"
+msgstr "Asien/Riyadh88"
+
+#: timezones.h:562
+msgid "Asia/Riyadh89"
+msgstr "Asien/Riyadh89"
+
+#: timezones.h:563
+msgid "Asia/Saigon"
+msgstr "Asien/Saigon"
+
+#: timezones.h:564
+msgid "Asia/Sakhalin"
+msgstr "Asien/Sachalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:566
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "Moskva+07 - Sakhalin-ön"
+
+#: timezones.h:567
+msgid "Asia/Samarkand"
+msgstr "Asien/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:569
+msgid "west Uzbekistan"
+msgstr "västra Uzbekistan"
+
+#: timezones.h:570
+msgid "Asia/Seoul"
+msgstr "Asien/Söul"
+
+#: timezones.h:571
+msgid "Asia/Shanghai"
+msgstr "Asien/Shanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:573
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "östra Kina - Beijing, Guangdong, Shanghai etc."
+
+#: timezones.h:574
+msgid "Asia/Singapore"
+msgstr "Asien/Singapore"
+
+#: timezones.h:575
+msgid "Asia/Taipei"
+msgstr "Asien/Taipei"
+
+#: timezones.h:576
+msgid "Asia/Tashkent"
+msgstr "Asien/Tasjkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:578
+msgid "east Uzbekistan"
+msgstr "östra Uzbekistan"
+
+#: timezones.h:579
+msgid "Asia/Tbilisi"
+msgstr "Asien/Tbilisi"
+
+#: timezones.h:580
+msgid "Asia/Tehran"
+msgstr "Asien/Tehran"
+
+#: timezones.h:581
+msgid "Asia/Tel_Aviv"
+msgstr "Asien/Tel_Aviv"
+
+#: timezones.h:582
+msgid "Asia/Thimbu"
+msgstr "Asien/Thimbu"
+
+#: timezones.h:583
+msgid "Asia/Thimphu"
+msgstr "Asien/Thimphu"
+
+#: timezones.h:584
+msgid "Asia/Tokyo"
+msgstr "Asien/Tokyo"
+
+#: timezones.h:585
+msgid "Asia/Ujung_Pandang"
+msgstr "Asien/Ujung_Pandang"
+
+#: timezones.h:586
+msgid "Asia/Ulaanbaatar"
+msgstr "Asien/Ulaanbaatar"
+
+#: timezones.h:589
+msgid "Asia/Ulan_Bator"
+msgstr "Asien/Ulan_Bator"
+
+#: timezones.h:590
+msgid "Asia/Urumqi"
+msgstr "Asien/Ürumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:592
+msgid "most of Tibet & Xinjiang"
+msgstr "det mesta av Tibet & Xinjiang"
+
+#: timezones.h:593
+msgid "Asia/Vientiane"
+msgstr "Asien/Vientiane"
+
+#: timezones.h:594
+msgid "Asia/Vladivostok"
+msgstr "Asien/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:596
+msgid "Moscow+07 - Amur River"
+msgstr "Moskva+07 - Amur-floden"
+
+#: timezones.h:597
+msgid "Asia/Yakutsk"
+msgstr "Asien/Jakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:599
+msgid "Moscow+06 - Lena River"
+msgstr "Moskva+06 - Lena-floden"
+
+#: timezones.h:600
+msgid "Asia/Yekaterinburg"
+msgstr "Asien/Jekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:602
+msgid "Moscow+02 - Urals"
+msgstr "Moskva+02 - Uralbergen"
+
+#: timezones.h:603
+msgid "Asia/Yerevan"
+msgstr "Asien/Jerevan"
+
+#: timezones.h:604
+msgid "Atlantic/Azores"
+msgstr "Atlanten/Azorerna"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:606
+msgid "Azores"
+msgstr "Azorerna"
+
+#: timezones.h:607
+msgid "Atlantic/Bermuda"
+msgstr "Atlanten/Bermuda"
+
+#: timezones.h:608
+msgid "Atlantic/Canary"
+msgstr "Atlanten/Kanarieöarna"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:610
+msgid "Canary Islands"
+msgstr "Kanarieöarna"
+
+#: timezones.h:611
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlanten/Kap_Verde"
+
+#: timezones.h:612
+msgid "Atlantic/Faeroe"
+msgstr "Atlanten/Färöarna"
+
+#: timezones.h:613
+msgid "Atlantic/Faroe"
+msgstr "Atlanten/Färöarna"
+
+#: timezones.h:614
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlanten/Jan_Mayen"
+
+#: timezones.h:615
+msgid "Atlantic/Madeira"
+msgstr "Atlanten/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:617
+msgid "Madeira Islands"
+msgstr "Madeira-öarna"
+
+#: timezones.h:618
+msgid "Atlantic/Reykjavik"
+msgstr "Atlanten/Reykjavik"
+
+#: timezones.h:619
+msgid "Atlantic/South_Georgia"
+msgstr "Atlanten/Sydgeorgia"
+
+#: timezones.h:620
+msgid "Atlantic/Stanley"
+msgstr "Atlanten/Stanley"
+
+#: timezones.h:621
+msgid "Atlantic/St_Helena"
+msgstr "Atlanten/St_Helena"
+
+#: timezones.h:622
+msgid "Australia/ACT"
+msgstr "Australien/ACT"
+
+#: timezones.h:623
+msgid "Australia/Adelaide"
+msgstr "Australien/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:625
+msgid "South Australia"
+msgstr "Sydaustralien"
+
+#: timezones.h:626
+msgid "Australia/Brisbane"
+msgstr "Australien/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:628
+msgid "Queensland - most locations"
+msgstr "Queensland - de flesta platserna"
+
+#: timezones.h:629
+msgid "Australia/Broken_Hill"
+msgstr "Australien/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:631
+msgid "New South Wales - Yancowinna"
+msgstr "New South Wales - Yancowinna"
+
+#: timezones.h:632
+msgid "Australia/Canberra"
+msgstr "Australien/Canberra"
+
+#: timezones.h:633
+msgid "Australia/Currie"
+msgstr "Australien/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:635
+msgid "Tasmania - King Island"
+msgstr "Tasmanien - King Island"
+
+#: timezones.h:636
+msgid "Australia/Darwin"
+msgstr "Australien/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:638
+msgid "Northern Territory"
+msgstr "Norra territoriet"
+
+#: timezones.h:639
+msgid "Australia/Eucla"
+msgstr "Australia/Eucla"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:641
+msgid "Western Australia - Eucla area"
+msgstr "Västa Australien - Eucla-området"
+
+#: timezones.h:642
+msgid "Australia/Hobart"
+msgstr "Australien/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:644
+msgid "Tasmania - most locations"
+msgstr "Tasmanien - de flesta platserna"
+
+#: timezones.h:645
+msgid "Australia/LHI"
+msgstr "Australien/LHI"
+
+#: timezones.h:646
+msgid "Australia/Lindeman"
+msgstr "Australien/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:648
+msgid "Queensland - Holiday Islands"
+msgstr "Queensland - Whitsundayöarna"
+
+#: timezones.h:649
+msgid "Australia/Lord_Howe"
+msgstr "Australien/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:651
+msgid "Lord Howe Island"
+msgstr "Lord Howeön"
+
+#: timezones.h:652
+msgid "Australia/Melbourne"
+msgstr "Australien/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:654
+msgid "Victoria"
+msgstr "Victoria"
+
+#: timezones.h:655
+msgid "Australia/North"
+msgstr "Australien/North"
+
+#: timezones.h:656
+msgid "Australia/NSW"
+msgstr "Australien/Nya Sydwales"
+
+#: timezones.h:657
+msgid "Australia/Perth"
+msgstr "Australien/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:659
+msgid "Western Australia - most locations"
+msgstr "Västra Australien - de flesta platserna"
+
+#: timezones.h:660
+msgid "Australia/Queensland"
+msgstr "Australien/Queensland"
+
+#: timezones.h:661
+msgid "Australia/South"
+msgstr "Australien/Syd"
+
+#: timezones.h:662
+msgid "Australia/Sydney"
+msgstr "Australien/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:664
+msgid "New South Wales - most locations"
+msgstr "New South Wales - de flesta platser"
+
+#: timezones.h:665
+msgid "Australia/Tasmania"
+msgstr "Australien/Tasmanien"
+
+#: timezones.h:666
+msgid "Australia/Victoria"
+msgstr "Australien/Victoria"
+
+#: timezones.h:667
+msgid "Australia/West"
+msgstr "Australien/Väst"
+
+#: timezones.h:668
+msgid "Australia/Yancowinna"
+msgstr "Australien/Yancowinna"
+
+#: timezones.h:669
+msgid "Brazil/Acre"
+msgstr "Brasilien/Acre"
+
+#: timezones.h:670
+msgid "Brazil/DeNoronha"
+msgstr "Brasilien/De_Noroña"
+
+#: timezones.h:671
+msgid "Brazil/East"
+msgstr "Brasilien/Öst"
+
+#: timezones.h:672
+msgid "Brazil/West"
+msgstr "Brasilien/Väst"
+
+#: timezones.h:673
+msgid "Canada/Atlantic"
+msgstr "Kanada/Atlanten"
+
+#: timezones.h:674
+msgid "Canada/Central"
+msgstr "Kanada/Centrala"
+
+#: timezones.h:675
+msgid "Canada/Eastern"
+msgstr "Kanada/Östra"
+
+#: timezones.h:676
+msgid "Canada/East-Saskatchewan"
+msgstr "Kanada/Öst-Saskatchewan"
+
+#: timezones.h:677
+msgid "Canada/Mountain"
+msgstr "Kanada/Mountain"
+
+#: timezones.h:678
+msgid "Canada/Newfoundland"
+msgstr "Kanada/Newfoundland"
+
+#: timezones.h:679
+msgid "Canada/Pacific"
+msgstr "Kanada/Pacific"
+
+#: timezones.h:680
+msgid "Canada/Saskatchewan"
+msgstr "Kanada/Saskatchewan"
+
+#: timezones.h:681
+msgid "Canada/Yukon"
+msgstr "Kanada/Yukon"
+
+#: timezones.h:682
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:683
+msgid "Chile/Continental"
+msgstr "Chile/Kontinental"
+
+#: timezones.h:684
+msgid "Chile/EasterIsland"
+msgstr "Chile/Påskön"
+
+#: timezones.h:685
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:686
+msgid "Cuba"
+msgstr "Kuba"
+
+#: timezones.h:687
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:688
+msgid "Egypt"
+msgstr "Egypten"
+
+#: timezones.h:689
+msgid "Eire"
+msgstr "Eire"
+
+#: timezones.h:690
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:691
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:692
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:693
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:694
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:695
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:696
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:697
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:698
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:699
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:700
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:701
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:702
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:703
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:704
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:705
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:706
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:707
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:708
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:709
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:710
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:711
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:712
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:713
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:714
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:715
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:716
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:717
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:718
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:719
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:720
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:721
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:722
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#: timezones.h:723
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:724
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:725
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:726
+msgid "Etc/Zulu"
+msgstr "Etc/Nollmeredianen"
+
+#: timezones.h:727
+msgid "Europe/Amsterdam"
+msgstr "Europa/Amsterdam"
+
+#: timezones.h:728
+msgid "Europe/Andorra"
+msgstr "Europa/Andorra"
+
+#: timezones.h:729
+msgid "Europe/Athens"
+msgstr "Europa/Aten"
+
+#: timezones.h:730
+msgid "Europe/Belfast"
+msgstr "Europa/Belfast"
+
+#: timezones.h:731
+msgid "Europe/Belgrade"
+msgstr "Europa/Belgrad"
+
+#: timezones.h:732
+msgid "Europe/Berlin"
+msgstr "Europa/Berlin"
+
+#: timezones.h:733
+msgid "Europe/Bratislava"
+msgstr "Europa/Bratislava"
+
+#: timezones.h:734
+msgid "Europe/Brussels"
+msgstr "Europa/Bryssel"
+
+#: timezones.h:735
+msgid "Europe/Bucharest"
+msgstr "Europa/Bukarest"
+
+#: timezones.h:736
+msgid "Europe/Budapest"
+msgstr "Europa/Budapest"
+
+#: timezones.h:737
+msgid "Europe/Chisinau"
+msgstr "Europa/Chisinau"
+
+#: timezones.h:738
+msgid "Europe/Copenhagen"
+msgstr "Europa/Köpenhamn"
+
+#: timezones.h:739
+msgid "Europe/Dublin"
+msgstr "Europa/Dublin"
+
+#: timezones.h:740
+msgid "Europe/Gibraltar"
+msgstr "Europa/Gibraltar"
+
+#: timezones.h:741
+msgid "Europe/Guernsey"
+msgstr "Europe/Guernsey"
+
+#: timezones.h:742
+msgid "Europe/Helsinki"
+msgstr "Europa/Helsingfors"
+
+#: timezones.h:743
+msgid "Europe/Isle_of_Man"
+msgstr "Europe/Isle_of_Man"
+
+#: timezones.h:744
+msgid "Europe/Istanbul"
+msgstr "Europa/Istanbul"
+
+#: timezones.h:745
+msgid "Europe/Jersey"
+msgstr "Europe/Jersey"
+
+#: timezones.h:746
+msgid "Europe/Kaliningrad"
+msgstr "Europa/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:748
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Moskva-01 - Kaliningrad"
+
+#: timezones.h:749
+msgid "Europe/Kiev"
+msgstr "Europa/Kiev"
+
+#: timezones.h:752
+msgid "Europe/Lisbon"
+msgstr "Europa/Lissabon"
+
+#: timezones.h:755
+msgid "Europe/Ljubljana"
+msgstr "Europa/Ljubljana"
+
+#: timezones.h:756
+msgid "Europe/London"
+msgstr "Europa/London"
+
+#: timezones.h:757
+msgid "Europe/Luxembourg"
+msgstr "Europa/Luxemburg"
+
+#: timezones.h:758
+msgid "Europe/Madrid"
+msgstr "Europa/Madrid"
+
+#: timezones.h:761
+msgid "Europe/Malta"
+msgstr "Europa/Malta"
+
+#: timezones.h:762
+msgid "Europe/Mariehamn"
+msgstr "Europa/Mariehamn"
+
+#: timezones.h:763
+msgid "Europe/Minsk"
+msgstr "Europa/Minsk"
+
+#: timezones.h:764
+msgid "Europe/Monaco"
+msgstr "Europa/Monaco"
+
+#: timezones.h:765
+msgid "Europe/Moscow"
+msgstr "Europa/Moskva"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:767
+msgid "Moscow+00 - west Russia"
+msgstr "Moskva+00 - västra Ryssland"
+
+#: timezones.h:768
+msgid "Europe/Nicosia"
+msgstr "Europa/Nicosia"
+
+#: timezones.h:769
+msgid "Europe/Oslo"
+msgstr "Europa/Oslo"
+
+#: timezones.h:770
+msgid "Europe/Paris"
+msgstr "Europa/Paris"
+
+#: timezones.h:771
+msgid "Europe/Podgorica"
+msgstr "Europe/Podgorica"
+
+#: timezones.h:772
+msgid "Europe/Prague"
+msgstr "Europa/Prag"
+
+#: timezones.h:773
+msgid "Europe/Riga"
+msgstr "Europa/Riga"
+
+#: timezones.h:774
+msgid "Europe/Rome"
+msgstr "Europa/Rom"
+
+#: timezones.h:775
+msgid "Europe/Samara"
+msgstr "Europa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:777
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Moskva - Samarra, Udmurtien"
+
+#: timezones.h:778
+msgid "Europe/San_Marino"
+msgstr "Europa/San_Marino"
+
+#: timezones.h:779
+msgid "Europe/Sarajevo"
+msgstr "Europa/Sarajevo"
+
+#: timezones.h:780
+msgid "Europe/Simferopol"
+msgstr "Europa/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:782
+msgid "central Crimea"
+msgstr "centrala Crimea"
+
+#: timezones.h:783
+msgid "Europe/Skopje"
+msgstr "Europa/Skopje"
+
+#: timezones.h:784
+msgid "Europe/Sofia"
+msgstr "Europa/Sofia"
+
+#: timezones.h:785
+msgid "Europe/Stockholm"
+msgstr "Europa/Stockholm"
+
+#: timezones.h:786
+msgid "Europe/Tallinn"
+msgstr "Europa/Tallinn"
+
+#: timezones.h:787
+msgid "Europe/Tirane"
+msgstr "Europa/Tirana"
+
+#: timezones.h:788
+msgid "Europe/Tiraspol"
+msgstr "Europa/Tiraspol"
+
+#: timezones.h:789
+msgid "Europe/Uzhgorod"
+msgstr "Europa/Uzjgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:791
+msgid "Ruthenia"
+msgstr "Ruthenia"
+
+#: timezones.h:792
+msgid "Europe/Vaduz"
+msgstr "Europa/Vaduz"
+
+#: timezones.h:793
+msgid "Europe/Vatican"
+msgstr "Europa/Vatikanstaten"
+
+#: timezones.h:794
+msgid "Europe/Vienna"
+msgstr "Europa/Wien"
+
+#: timezones.h:795
+msgid "Europe/Vilnius"
+msgstr "Europa/Vilnius"
+
+#: timezones.h:796
+msgid "Europe/Volgograd"
+msgstr "Europe/Volgograd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:798
+msgid "Moscow+00 - Caspian Sea"
+msgstr "Moskva+00 - Kaspiska havet"
+
+#: timezones.h:799
+msgid "Europe/Warsaw"
+msgstr "Europa/Warszawa"
+
+#: timezones.h:800
+msgid "Europe/Zagreb"
+msgstr "Europa/Zagreb"
+
+#: timezones.h:801
+msgid "Europe/Zaporozhye"
+msgstr "Europa/Zaporozje"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:803
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "Zaporozh'ye, Ö Lugansk / Zaporizhia, Ö Luhansk"
+
+#: timezones.h:804
+msgid "Europe/Zurich"
+msgstr "Europa/Zürich"
+
+#: timezones.h:805
+msgid "Factory"
+msgstr "Fabrik"
+
+#: timezones.h:806
+msgid "GB"
+msgstr "Storbritannien"
+
+#: timezones.h:807
+msgid "GB-Eire"
+msgstr "Storbritannien-Irland"
+
+#: timezones.h:808
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:809
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:810
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:811
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:812
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:813
+msgid "Hongkong"
+msgstr "Hong Kong"
+
+#: timezones.h:814
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:815
+msgid "Iceland"
+msgstr "Island"
+
+#: timezones.h:816
+msgid "Indian/Antananarivo"
+msgstr "Indiska_Oceanen/Antananarivo"
+
+#: timezones.h:817
+msgid "Indian/Chagos"
+msgstr "Indiska_Oceanen/Chagos"
+
+#: timezones.h:818
+msgid "Indian/Christmas"
+msgstr "Indiska_Oceanen/Julön"
+
+#: timezones.h:819
+msgid "Indian/Cocos"
+msgstr "Indiska_Oceanen/Cocos"
+
+#: timezones.h:820
+msgid "Indian/Comoro"
+msgstr "Indiska_Oceanen/Komorerna"
+
+#: timezones.h:821
+msgid "Indian/Kerguelen"
+msgstr "Indiska_Oceanen/Kerguelen"
+
+#: timezones.h:822
+msgid "Indian/Mahe"
+msgstr "Indiska_Oceanen/Mahe"
+
+#: timezones.h:823
+msgid "Indian/Maldives"
+msgstr "Indiska_Oceanen/Maldiverna"
+
+#: timezones.h:824
+msgid "Indian/Mauritius"
+msgstr "Indiska_Oceanen/Mauritius"
+
+#: timezones.h:825
+msgid "Indian/Mayotte"
+msgstr "Indiska_Oceanen/Mayotte"
+
+#: timezones.h:826
+msgid "Indian/Reunion"
+msgstr "Indiska_Oceanen/Réunion"
+
+#: timezones.h:827
+msgid "Iran"
+msgstr "Iran"
+
+#: timezones.h:828
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:829
+msgid "Israel"
+msgstr "Israel"
+
+#: timezones.h:830
+msgid "Jamaica"
+msgstr "Jamaica"
+
+#: timezones.h:831
+msgid "Japan"
+msgstr "Japan"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:832 timezones.h:885
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:833
+msgid "Libya"
+msgstr "Libyen"
+
+#: timezones.h:834
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:835
+msgid "Mexico/BajaNorte"
+msgstr "Mexiko/BajaNorte"
+
+#: timezones.h:836
+msgid "Mexico/BajaSur"
+msgstr "Mexiko/BajaSur"
+
+#: timezones.h:837
+msgid "Mexico/General"
+msgstr "Mexiko/General"
+
+#: timezones.h:838
+msgid "Mideast/Riyadh87"
+msgstr "Mellanöstern/Riyadh87"
+
+#: timezones.h:839
+msgid "Mideast/Riyadh88"
+msgstr "Mellanöstern/Riyadh88"
+
+#: timezones.h:840
+msgid "Mideast/Riyadh89"
+msgstr "Mellanöstern/Riyadh89"
+
+#: timezones.h:841
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:842
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:843
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:844
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:845
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:846
+msgid "Pacific/Apia"
+msgstr "Stilla_Havet/Apia"
+
+#: timezones.h:847
+msgid "Pacific/Auckland"
+msgstr "Stilla_Havet/Auckland"
+
+#: timezones.h:850
+msgid "Pacific/Chatham"
+msgstr "Stilla_Havet/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:852
+msgid "Chatham Islands"
+msgstr "Chatham-öarna"
+
+#: timezones.h:853
+msgid "Pacific/Easter"
+msgstr "Stilla_Havet/Påskön"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:855
+msgid "Easter Island & Sala y Gomez"
+msgstr "Påskön & Sala y Gomez"
+
+#: timezones.h:856
+msgid "Pacific/Efate"
+msgstr "Stilla_Havet/Efate"
+
+#: timezones.h:857
+msgid "Pacific/Enderbury"
+msgstr "Stilla_Havet/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:859
+msgid "Phoenix Islands"
+msgstr "Fenix-öarna"
+
+#: timezones.h:860
+msgid "Pacific/Fakaofo"
+msgstr "Stilla_Havet/Fakaofo"
+
+#: timezones.h:861
+msgid "Pacific/Fiji"
+msgstr "Stilla_Havet/Fiji"
+
+#: timezones.h:862
+msgid "Pacific/Funafuti"
+msgstr "Stilla_Havet/Funafuti"
+
+#: timezones.h:863
+msgid "Pacific/Galapagos"
+msgstr "Stilla_Havet/Galápagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:865
+msgid "Galapagos Islands"
+msgstr "Galapagosöarna"
+
+#: timezones.h:866
+msgid "Pacific/Gambier"
+msgstr "Stilla_Havet/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:868
+msgid "Gambier Islands"
+msgstr "Gambieröarna"
+
+#: timezones.h:869
+msgid "Pacific/Guadalcanal"
+msgstr "Stilla_Havet/Guadalcanal"
+
+#: timezones.h:870
+msgid "Pacific/Guam"
+msgstr "Stilla_Havet/Guam"
+
+#: timezones.h:871
+msgid "Pacific/Honolulu"
+msgstr "Stilla_Havet/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:873
+msgid "Hawaii"
+msgstr "Hawaii"
+
+#: timezones.h:874
+msgid "Pacific/Johnston"
+msgstr "Stilla_Havet/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:876
+msgid "Johnston Atoll"
+msgstr "Johnston-atollen"
+
+#: timezones.h:877
+msgid "Pacific/Kiritimati"
+msgstr "Stilla_Havet/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:879
+msgid "Line Islands"
+msgstr "Line-öarna"
+
+#: timezones.h:880
+msgid "Pacific/Kosrae"
+msgstr "Stilla_Havet/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:882
+msgid "Kosrae"
+msgstr "Kosrae"
+
+#: timezones.h:883
+msgid "Pacific/Kwajalein"
+msgstr "Stilla_Havet/Kwajalein"
+
+#: timezones.h:886
+msgid "Pacific/Majuro"
+msgstr "Stilla_Havet/Majuro"
+
+#: timezones.h:889
+msgid "Pacific/Marquesas"
+msgstr "Stilla_Havet/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:891
+msgid "Marquesas Islands"
+msgstr "Marquesasöarna"
+
+#: timezones.h:892
+msgid "Pacific/Midway"
+msgstr "Stilla_Havet/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:894
+msgid "Midway Islands"
+msgstr "Midwayöarna"
+
+#: timezones.h:895
+msgid "Pacific/Nauru"
+msgstr "Stilla_Havet/Nauru"
+
+#: timezones.h:896
+msgid "Pacific/Niue"
+msgstr "Stilla_Havet/Niue"
+
+#: timezones.h:897
+msgid "Pacific/Norfolk"
+msgstr "Stilla_Havet/Norfolk"
+
+#: timezones.h:898
+msgid "Pacific/Noumea"
+msgstr "Stilla_Havet/Noumea"
+
+#: timezones.h:899
+msgid "Pacific/Pago_Pago"
+msgstr "Stilla_Havet/Pago_Pago"
+
+#: timezones.h:900
+msgid "Pacific/Palau"
+msgstr "Stilla_Havet/Palau"
+
+#: timezones.h:901
+msgid "Pacific/Pitcairn"
+msgstr "Stilla_Havet/Pitcairn"
+
+#: timezones.h:902
+msgid "Pacific/Ponape"
+msgstr "Stilla_Havet/Ponape"
+
+#. comment for time zone Pacific/Ponape
+#: timezones.h:904
+msgid "Ponape (Pohnpei)"
+msgstr "Pohnpei (Ponape)"
+
+#: timezones.h:905
+msgid "Pacific/Port_Moresby"
+msgstr "Stilla_Havet/Port_Moresby"
+
+#: timezones.h:906
+msgid "Pacific/Rarotonga"
+msgstr "Stilla_Havet/Rarotonga"
+
+#: timezones.h:907
+msgid "Pacific/Saipan"
+msgstr "Stilla_Havet/Saipan"
+
+#: timezones.h:908
+msgid "Pacific/Samoa"
+msgstr "Stilla_Havet/Samoa"
+
+#: timezones.h:909
+msgid "Pacific/Tahiti"
+msgstr "Stilla_Havet/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:911
+msgid "Society Islands"
+msgstr "Sällskapsöarna"
+
+#: timezones.h:912
+msgid "Pacific/Tarawa"
+msgstr "Stilla_Havet/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:914
+msgid "Gilbert Islands"
+msgstr "Gilbertöarna"
+
+#: timezones.h:915
+msgid "Pacific/Tongatapu"
+msgstr "Stilla_Havet/Tongatapu"
+
+#: timezones.h:916
+msgid "Pacific/Truk"
+msgstr "Stilla_Havet/Truk"
+
+#. comment for time zone Pacific/Truk
+#: timezones.h:918
+msgid "Truk (Chuuk) and Yap"
+msgstr "Truk (Chuuk) och Yap"
+
+#: timezones.h:919
+msgid "Pacific/Wake"
+msgstr "Stilla_Havet/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:921
+msgid "Wake Island"
+msgstr "Wake-ön"
+
+#: timezones.h:922
+msgid "Pacific/Wallis"
+msgstr "Stilla_Havet/Wallis"
+
+#: timezones.h:923
+msgid "Pacific/Yap"
+msgstr "Stilla_Havet/Yap"
+
+#: timezones.h:924
+msgid "Poland"
+msgstr "Polen"
+
+#: timezones.h:925
+msgid "Portugal"
+msgstr "Portugal"
+
+#: timezones.h:926
+msgid "posixrules"
+msgstr "posixregler"
+
+#: timezones.h:927
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:928
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:929
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:930
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:931
+msgid "Singapore"
+msgstr "Singapore"
+
+#: timezones.h:932
+msgid "Turkey"
+msgstr "Turkiet"
+
+#: timezones.h:933
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:934
+msgid "Universal"
+msgstr "Universell"
+
+#: timezones.h:935
+msgid "US/Alaska"
+msgstr "USA/Alaska"
+
+#: timezones.h:936
+msgid "US/Aleutian"
+msgstr "USA/Aleutian"
+
+#: timezones.h:937
+msgid "US/Arizona"
+msgstr "USA/Arizona"
+
+#: timezones.h:938
+msgid "US/Central"
+msgstr "USA/Central"
+
+#: timezones.h:939
+msgid "US/Eastern"
+msgstr "USA/Östlig"
+
+#: timezones.h:940
+msgid "US/East-Indiana"
+msgstr "USA/Öst-Indiana"
+
+#: timezones.h:941
+msgid "US/Hawaii"
+msgstr "USA/Hawaii"
+
+#: timezones.h:942
+msgid "US/Indiana-Starke"
+msgstr "USA/Indiana-Starke"
+
+#: timezones.h:943
+msgid "US/Michigan"
+msgstr "USA/Michigan"
+
+#: timezones.h:944
+msgid "US/Mountain"
+msgstr "USA/Mountain"
+
+#: timezones.h:945
+msgid "US/Pacific"
+msgstr "USA/Pacific"
+
+#: timezones.h:946
+msgid "US/Samoa"
+msgstr "USA/Samoa"
+
+#: timezones.h:947
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:948
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:949
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:950
+msgid "Zulu"
+msgstr "Z-tid"
diff --git a/panels/datetime/po-timezones/ta.po b/panels/datetime/po-timezones/ta.po
new file mode 100644
index 0000000..e4e0bf8
--- /dev/null
+++ b/panels/datetime/po-timezones/ta.po
@@ -0,0 +1,3246 @@
+# translation of system-config-date.master-timezones.ta.po to Tamil
+# translation of ta.po to
+# This file is distributed under the same license as the PACKAGE package.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER, 2006.
+#
+# Felix <ifelix@redhat.com>, 2006.
+# I. Felix <ifelix@redhat.com>, 2008, 2009.
+# I Felix <ifelix@redhat.com>, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: system-config-date.master-timezones.ta\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-12-07 11:20+0530\n"
+"Last-Translator: I Felix <ifelix@redhat.com>\n"
+"Language-Team: Tamil <kde-i18n-doc@kde.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ta\n"
+"X-Generator: Lokalize 1.0\n"
+"Plural-Forms: nplurals=2; plural=(n!=1);\\n\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "ஆப்ரிக்கா/அபிட்ஜான்"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "ஆப்ரிக்கா/அக்க்ரா"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "ஆப்ரிக்கா/அட்டிச்"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "ஆப்ரிக்கா/அல்கெர்ஸ்"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "ஆப்ரிக்கா/அஸ்மாரா"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "ஆப்ரிக்கா/அழ்மேரா"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "ஆப்ரிக்கா/பமாகொ"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "ஆப்ரிக்கா/பான்குவி"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "ஆப்ரிக்கா/பான்ஜுல்"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "ஆப்ரிக்கா/பிசௌ"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "ஆப்ரிக்கா/பிலநன்டைர்"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "ஆப்ரிக்கா/பிரஸ்விசி"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "ஆப்ரிக்கா/புஜும்புரா"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "ஆப்ரிக்கா/காரியோ"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "ஆப்ரிக்கா/காசபலான்கா"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "ஆப்ரிக்கா/செயூடா"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "செய்டா & மெலில்லா"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "ஆப்ரிக்கா/கோனாக்ரி"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "ஆப்ரிக்கா/டாகர்"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "ஆப்ரிக்கா/டர்_ச்_சலாம்"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "ஆப்ரிக்கா/டஜ்ப்பௌடி"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "ஆப்ரிக்கா/டவ்லா"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "ஆப்ரிக்கா/அல்_ஐரன்"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "ஆப்ரிக்கா/ஃப்ரீட்வுன்"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "ஆப்ரிக்கா/கபரொனெ"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "ஆப்ரிக்கா/ஹராரெ"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "ஆப்ரிக்கா/ஜொஹானெஸ்பர்க்"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "ஆப்ரிக்கா/கம்பாலா"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "ஆப்ரிக்கா/கார்டொம்"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "ஆப்ரிக்கா/கிகாலி"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "ஆப்ரிக்கா/கிண்"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "மேற்கு டெம். குடியரசு காங்கோ"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "ஆப்ரிக்கா/லாகொஸ்"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "ஆப்ரிக்கா/லிபர்வில்லி"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "ஆப்ரிக்கா/லோம்"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "ஆப்ரிக்கா/லுவாண்டா"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "ஆப்ரிக்கா/லும்பும்ப்ஹஷி"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "கிழக்கு டெம். குடியரசு காங்கோ"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "ஆப்ரிக்கா/லுசகா"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "ஆப்ரிக்கா/மலாபோ"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "ஆப்ரிக்கா/மபுட்டொ"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "ஆப்ரிக்கா/மசீரொ"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "ஆப்ரிக்கா/எம்பபேன்"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "ஆப்ரிக்கா/மொகடிஷு"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "ஆப்ரிக்கா/மொன்ரொவியா"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "ஆப்ரிக்கா/னைரோபி"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "ஆப்ரிக்கா/எண்டிஜமீனா"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "ஆப்ரிக்கா/னெஇமெயி"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "ஆப்ரிக்கா/நௌகொசோட்"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "ஆப்ரிக்கா/ஔவகாடொகு"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "ஆப்ரிக்கா/போர்டோ-னோவோ"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "ஆப்ரிக்கா/சாவோ_டோம்"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "ஆப்ரிக்கா/திம்புக்குது"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "ஆப்ரிக்கா/ட்ரிபோலி"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "ஆப்ரிக்கா/டுனிஸ்"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "ஆப்ரிக்கா/விதோவெக்"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "அமெரிக்காக்கா/அடாக்"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "அலுய்டியன் தீவுகள்"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "அமெரிக்கா/அன்ஷொரேஜ்"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "அலாஸ்கா நேரம்"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "அமேரிக்கா/அனுகில்லா"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "அமேரிக்கா/ஆண்டிகுவா"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "அமேரிக்கா/அரகுவேஐனா"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "டோகான்டின்ஸ்"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "அமெரிக்கா/அர்ஜென்டினா/பியுனஸ்_ஏரீஸ்"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "ப்யூனஸ் ஐரெஸ் (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "அமெரிக்கா/அர்ஜென்டினா/கட்மர்க்கா"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "கடாமார்கா (CT), ச்சுபட் (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "அமெரிக்கா/அர்ஜென்டினா/கமோட்ரிவாடையா"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "அமெரிக்கா/அர்ஜென்டினா/கொர்டொபா"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "நிறைய இடங்கள் (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "அமெரிக்கா/அர்ஜென்டினா/ஜஜுய்"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "ஜுஜுய் (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "அமெரிக்கா/அர்ஜென்டினா/லாரியோஜோ"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "லா ரியோஜா (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "அமெரிக்கா/அர்ஜென்டினா/மெண்டோஸா"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "மென்டோஸா (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "அமெரிக்கா/அர்ஜென்டினா/ரியோ_கேல்கோஸ்"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "சான்டா குரூஸ் (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "அமெரிக்கா/அர்ஜென்டினா/சால்டா"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "அமெரிக்கா/அர்ஜென்டினா/சான்_ஜுயான்"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "சான் ஜுயன் (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "அமெரிக்கா/அர்ஜென்டினா/சான்_லூய்ஸ்"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "சான் லூயிஸ் (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "அமெரிக்கா/அர்ஜென்டினா/டுயுகுமன்"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "துகுமென் (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "அமெரிக்கா/அர்ஜென்டினா/யுஷியேயா"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "டைர்ரிரா டெல் ஃப்யுகோ (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "அமெரிக்கா/அரூபா"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "அமேரிக்கா/அஸுன்சியான்"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "அமெரிக்கா/அடிகோகன்"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "கிழக்கத்திய நிலையான நேரம் - அதிகோகான், ஆன்டரியோ மற்றும் சவுதம்ப்டோன் I, நுனாவுட்"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "அமெரிக்கா/அட்கா"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "அமெரிக்கா/பஹியா"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "பஹியா"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "அமெரிக்கா/பஹியா_பான்டிராஸ்"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "மெக்சிகள் சென்ட்ரல் நேரம் - பாஹியா டி பான்டிராஸ்"
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "அமேரிக்கா/பார்பேலாஸ்"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "அமேரிக்கா/பேலெம்"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "அமாபா, E பாரா"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "அமேரிக்கா/பெல்சி"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "அமெரிக்கா/ப்ளாங்-சேப்லான்"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "அட்லாண்டிக் நிலையான நேரம் - குறைந்த கிழக்கு ஷோர்"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "அமெரிக்கா/போவா_விஸ்டா"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "ரோராய்மா"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "அமேரிக்கா/பொகோடா"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "அமேரிக்கா/போஇஸ்"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "மவுண்டெய்ன் நேரம் - தெற்கு அதாஹோ & கிழக்கு ஒரேகான்"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "அமெரிக்கா/பிஔனஸ்_ஏரீஸ்"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "அமெரிக்கா/கேம்ப்ரிட்ஜ்_பே"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "மவுண்டெய்ன் நேரம் - மேற்கு நுனாவுட்"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "அமெரிக்கா/கேம்போ_கிராண்டே"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "மாடோ க்ரோஸ்ஸா டு சுல்"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "அமெரிக்கா/கன்குன்"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "சென்ட்ரல் நேரம் - க்யுன்டானா ரோ"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "அமெரிக்கா/கரகாஸ்"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "அமெரிக்கா/கட்மர்க்கா"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "அமெரிக்கா/கய்யீன்"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "அமெரிக்கா/கேமன்"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "அமெரிக்கா/சிகாகோ"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "சென்ட்ரல் நேரம்"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "அமெரிக்கா/சிஹுஹயுஹா"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "மவுண்டெய்ன் நேரம் - சிஹுயாஹுயா யுஎஸ் எல்லைக்கு வெளியே"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "அமெரிக்கா/கோரல்_ஹார்பர்"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "அமெரிக்கா/கொர்டொபா"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "அமெரிக்கா/காஸ்டா_ரிகா"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "அமெரிக்கா/குஇபா"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "மாடோ க்ரோஸ்ஸா"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "அமெரிக்கா/குராகவ்"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "அமெரிக்கா/தென்மார்க்ஷ்வன்"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "கிழக்கு காஸ்ட், வடக்கு ஸ்கோரெஸ்பைசன்டு"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "அமெரிக்கா/டாவ்சன்"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "பசிபிக் நேரம் - வடக்கு யுகோன்"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "அமெரிக்கா/டாவ்ச்ன்_ஸ்ரீக்"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid "Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr "மவுண்டெய்ன் நிலையான நேரம் - டாவ்சன் கிரீக் & ஃபோர்ட் செயின்ட் ஜான், பிரிட்டீஷ் கொலாம்பியா"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "அமெரிக்கா/டெனிவெர்"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "ஏறும் நேரம்"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "அமெரிக்கா/டெட்ராஐட்"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "கிழக்கத்திய நேரம் - மிக்சிகன் - நிறைய இடங்கள்"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "அமெரிக்கா/டாமினிக்கா"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "அமெரிக்கா/எட்மாந்டொன்"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "மவுண்டெய்ன் நேரம் - அல்பெர்டா, கிழக்கு பிரிட்டீஷ் கொலாம்பியா & மேற்கு சாஸ்கட்சேவன்"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "அமெரிக்கா/எய்ருனெபி"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "W அமாஸொனாஸ்"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "அமெரிக்கா/ எல்_சால்வாடொர்"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "அமெரிக்கா/என்சென்னடா"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "அமெரிக்கா/ஃபோடலீஸா"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "NE ப்ரேசில் (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "அமெரிக்கா/ஃபோர்டு_வேன்"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "அமெரிக்கா/க்லேஸ்_பே"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr "அட்லாண்டிக் நேரம் - நோவா ஸ்கோடியா - இடங்கள் DST 1966-1971ஐ கவனிக்க முடியவில்லை"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "அமெரிக்கா/காஹாப்"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195
+#: timezones.h:364
+#: timezones.h:453
+#: timezones.h:591
+#: timezones.h:754
+#: timezones.h:852
+#: timezones.h:894
+msgid "most locations"
+msgstr "நிறைய இடங்கள்"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "அமெரிக்கா/கூஸ்_பே"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "அட்லாண்டிக் நேரம் - நிறைய அடங்கள்"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "அமெரிக்கா/க்ராண்டு_ட்ரன்க்"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "அமெரிக்கா/க்ரெனேடா"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "அமெரிக்கா/க்குவாடெலோப்"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "அமெரிக்கா/க்குவாடெமாலா"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "அமெரிக்கா/குயாஃகுயில்"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205
+#: timezones.h:757
+#: timezones.h:763
+msgid "mainland"
+msgstr "மையின்லாண்ட்"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "அமெரிக்கா/குயானா"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "அமெரிக்கா/ஹெல்ஃபாஸ்"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "அட்லாண்டிக் நேரம் - நோவா ஸ்கோடியா(நிறைய இடங்கள்), PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "அமெரிக்கா/ஹவானா"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "அமெரிக்கா/ஹெர்மோசிலோ"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "மவுண்டெய்ன் நிலையான நேரம் - சோனோரா"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "அமெரிக்கா/இந்தியானா/இந்தியானாபோல்ஸ்"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "கிழக்கத்திய நேரம் - இன்டியானா - நிறைய இடங்கள்"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "அமெரிக்கா/இந்தியானா/க்னாஸ்"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "சென்ட்ரல் நேரம் - இன்டியானா - ஸ்டார்கீ கவுண்டி"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "அமெரிக்கா/இந்தியானா/மரேன்கோ"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "கிழக்கத்திய நேரம் - இன்டியானா - க்ராவ்ஃபோர்ட் கவுண்டி"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "அமெரிக்கா/இந்தியானா/பீட்டர்ஸ்பெர்க்"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "கிழக்கத்திய நேரம் - இன்டியானா - பிக் கவுண்டி"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "அமெரிக்கா/இந்தியானாபோலிஸ்"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "அமெரிக்கா/இந்தியானா/Tell_City"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "சென்ட்ரல் நேரம் - இன்டியானா - பெர்ரி கவுண்டி"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "அமெரிக்கா/இந்தியானா/விவேயை"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "கிழக்கத்திய நேரம் - இன்டியானா - சுவிடுஸெர்லாண்ட் கவுண்டி"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "அமெரிக்கா/இந்தியானா/வின்சினெஸ்"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "கிழக்கத்திய நேரம் - இன்டியானா - டாவிய்ஸ், டுபோய்ஸ், கனோஸ் & மார்டின் கவுண்டிஸ்"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "அமெரிக்கா/இந்தியானா/வின்னாமேக்"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "கிழக்கத்திய நேரம் - இன்டியானா - புலாஸ்கி கவுண்டி"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "அமெரிக்கா/இனுவிக்"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "மவுண்டெய்ன் நேரம் - மேற்கு வடமேற்கு டெர்டோரியஸ்"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "அமெரிக்கா/இக்கலுயிட்"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "கிழக்கத்திய நேரம் - கிழக்கு நுனாவுட் - நிறைய இடங்கள்"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "அமெரிக்கா/ஜமேக்கா"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "அமெரிக்கா/ஜுஜுவி"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "அமெரிக்கா/ஜுனேயு"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "அலாஸ்கா நேரம் - அலாஸ்கா பான்ஹான்டில்"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "அமெரிக்கா/கெண்டக்கி/லூயிஸ்விலீ"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "கிழகத்திய நேரம் - கெண்டக்கி - லூயிஸ்விலீப் பகுதி"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "அமெரிக்கா/கெண்டக்கி/மாந்திசெல்லோ"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "கிழக்கத்திய நேரம் - கென்துக்கை - வைய்ன் கவுண்டி"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "அமெரிக்கா/க்னாக்ஸ்_இன்"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "அமெரிக்கா/லா_பாஸ்"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "அமரிக்கா/லிமா"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "அமெரிக்கா/லாஸ்_ஏஜலெஸ்"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "பசிபிக் நேரம்"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "அமெரிக்கா/லூயிஸ்விலீ"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "அமெரிக்கா/மகய்யோ"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "அலாகோயஸ், செர்கிபீ"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "அமெரிக்கா/மானகுவா"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "அமெரிக்கா/மனௌஸ்"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "E அமாஸோனாஸ்"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "அமெரிக்கா/மாரிகோட்"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "அமெரிக்கா/மார்டினிக்"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "அமெரிக்கா/மட்டாமோரோஸ்"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid "US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr "யுஎஸ் சென்ட்ரல் நேரம் - கோஹுய்லா, துரன்கோ, நியுவோ லியோன், தாமுலிபாஸ் யுஎஸ் எல்லை அருகே"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "அமெரிக்கா/மஸடலன்"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "மவுண்டெய்ன் நேரம் - S பாஜா, நயாரிட், சினாலௌவ்"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "அமெரிக்கா/மெண்டோஸா"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "அமெரிக்கா/மெமோமினீ"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "சென்ட்ரல் நேரம் - மிசிகன் - டிக்கின்சன், கோஜ்பிக், ஐயன்& மெனோமின்னீ கவுண்டீஸ்"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "அமெரிக்கா/மெரிடா"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "சென்ட்ரல் நேரம் - காம்பெக்சே, யுகாதன்"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "அமெரிக்கா/மெக்சிகோ_சிடி"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "சென்ட்ரல் நேரம் - நிறைய இடங்கள்"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "அமெரிக்கா/மிகுவெலொன்"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "அமெரிக்கா/மாங்க்டான்"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "அட்லாண்டிக் நேரம் - நியூ ஃப்ரூன்ஸ்விக்"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "அமெரிக்கா/மோந்டெரி"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid "Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from US border"
+msgstr "மெக்ஸிகன் சென்ட்ரல் நேரம் - கோஹுய்லா, துரன்கோ, நியுவோ லியோன், தாமுலிபாஸ் யுஎஸ் எல்லையிலிருந்து வெளியே"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "அமெரிக்கா/மாந்டேவீடியோ"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "அமெரிக்கா/மாந்ட்ரியல்"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "கிழக்கத்திய நேரம் - க்யூபெக் -நிறைய இடங்கள்"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "அமெரிக்கா/மாந்த்சேராட்"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "அமெரிக்கா/நாசாவ்"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "அமெரிக்கா/நியூ_யார்க்"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "கிழக்கத்திய நேரம்"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "அமெரிக்கா/நெப்பிக்கிவான்"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid "Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr "கிழக்கத்திய நேரம் - ஆண்டரியோ & க்யூபெக் - இடங்கள் இதை DST 1967-1973 கவனிக்கவில்லை"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "அமெரிக்கா/நேமி"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "அலாஸ்கா நேரம் - மேற்கு அலாஸ்கா"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "அமெரிக்கா/நொரொன்ஹ"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "அட்லாண்டிக் தீவுகள்"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "அமெரிக்கா/நார்த்_டக்கோடா/மையம்"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "சென்ட்ரல் நேரம் - வடக்கு டகோடா - ஒலிவெர் கவுண்டி"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "அமெரிக்கா/வட_டக்கோடா/புது_சலீம்"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "சென்ட்ரல் நேரம் - வடக்கு டகோடா - மார்தான் கவுண்டி (மன்டன் பகுதியைத் தவிர)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "அமெரிக்கா/மானகுவா"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "யுஎஸ் மவுண்டெய்ன் நேரம் - சிஹுயாஹுயா யுஎஸ் எல்லை அருகே"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "அமெரிக்கா/பனாமா"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "அமெரிக்கா/பன்கினிருட்டங்"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "கிழக்கத்திய நேரம் - பங்னிர்துங், நுனாவுட்"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "அமெரிக்கா/பரமரிபொ"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "அமெரிக்கா/ஃபோனிக்ஸ்"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "மவுண்டெயின் நிலையான நேரம் - அரிஸோனா"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "அமெரிக்கா/போர்டு_ஔ_ப்ரிஸ்"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "அமெரிக்கா/போர்டொ_எக்ரெ"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "அமெரிக்கா/போர்டு_ஆஃப்_ஸ்பேய்ன்"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "அமெரிக்கா/போர்டோ_வெல்ஹோ"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "ரோன்டோனியா"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "அமெரிக்கா/புயெர்டோ_ரிகொ"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "அமெரிக்கா/ராய்னி_ரிவர்"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "சென்ட்ரல் நேரம் - ரெய்னி ரிவர் & ஃபோர்ட் ஃப்ரான்செஸ், ஆன்டாரியோ"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "அமெரிக்கா/ரான்கின்_இன்லெட்"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "சென்ட்ரல் நேரம் - சென்ட்ரல் நுனாவுட்"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "அமெரிக்கா/ரெகிப்ஹி"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "பெர்னாம்புகோ"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "அமெரிக்கா/ரிஜினா"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "சென்ட்ரல் நிலையான நேரம் - சாஸ்கட்சேவன் - நிறைய இடங்கள் "
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "அமெரிக்கா/ரிசோல்ட்"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "கிழக்கத்திய நிலையான நேரம் - ரீசோலுட், நுனாவுட் "
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "அமெரிக்கா/ரியொ_ப்ரான்கோ"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "ஏக்கர்"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "அமெரிக்கா/ரோசாரியோ"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "அமெரிக்கா/சான்டா_இசபெல்"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "மெக்சிகன் பசிபிக் நேரம் - பாஜா கலிஃபோர்னியா யுஸ் எல்லைக்கு வெளியே"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "அமெரிக்கா/சான்டரெம்"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "W பாரா"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "அமெரிக்கா/சாந்டியாகொ"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "அமெரிக்கா/சாண்டோ_டாமின்கொ"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "அமெரிக்கா/சவொ_பாடொ"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "S & SE ஃப்ரேசில் (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "அமெரிக்கா/ஸ்கோர்ஸ்பைசண்டு"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "ஸ்கோரெஸ்பைசன்டு / இட்டோக்கோர்டூர்மிட்"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "அமெரிக்கா/ஷிப்ராக்"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "மவுண்டெய்ன் நேரம் - நவாஜோ"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "அமெரிக்கா/St_Barthelemy"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "அமெரிக்கா/St_ஜான்ஸ்"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "நியூபவன்டுலாண்ட் நேரம், SE லப்ராடரும் சேர்த்து"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "அமெரிக்கா/"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "அமெரிக்கா/St_லூசிய"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "அமெரிக்கா/St_தாமஸ்"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "அமெரிக்கா/St_விண்செந்ட்"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "அமெரிக்கா/ஸ்விஃப்ட்_கரண்டு"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "சென்ட்ரல் நிலையான நேரம் - சாஸ்கட்சேவன் - மத்தியமேற்கு"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "அமெரிக்கா/"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "அமெரிக்கா/துளி"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "தூலீ / பிதுஃபிக்"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "அமெரிக்கா/தண்டர்_பே"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "கிழக்கத்திய நேரம் - தன்டர் பெய், அன்டாரியோ"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "அமெரிக்கா/டைஜுனா"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "யுஎஸ் பசிபிக் நேரம் - பாஜா கலிஃபோர்னியா யுஎஸ் எல்லை அருகே"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "அமெரிக்கா/டெரண்டோ"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "கிழக்கத்திய நேரம் - அன்டாரியோ - நிறைய இடங்கள்"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "அமெரிக்கா/டார்டோலா"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "அமெரிக்கா/வென்கோவர்"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "கசிபிக் நேரம் - மேற்கு பிரிட்டீஷ் கொலாம்பியா"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "அமெரிக்கா/விர்ஜின்"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "அமெரிக்கா/வெள்ளைகுதிரை"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "பசிபிக் நேரம் - தென் யுகோன்"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "அமெரிக்கா/வின்னிபெக்"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "சென்ட்ரல் நேரம் - மணிடோபா & மேற்கு ஆன்டரியோ"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "அமெரிக்கா/யகுடாட்"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "அலாஸ்கா நேரம் - அலாஸ்கா பான்ஹான்டில் நெக்"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "அமெரிக்கா/எல்லோநைப்பு"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "மவுண்டெய்ன் நேரம் - சென்ட்ரல் வடமேற்கு டெர்டோரியஸ்"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "அண்டார்டிகா/காசே"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "காசே ஸ்டேஷன், பாய்லெ பெனின்சூலா"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "அண்டார்டிகா/டேவிஸ்"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "டாவிஸ் ஸ்டேஷன், வெஸ்ட்போல்ட் ஹில்ஸ்"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "அண்டார்டிகா/டுமௌந்ட்டிஉர்விலி"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "துமோன்ட்-டி'உர்வில்லீ ஸ்டேஷன், டெர்ரீ அடேலை"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "அண்டார்டிகா/மெக்க்யுரே"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "மெக்க்ரேயி தீவு ஸ்டேஷன், மெக்க்ரேயி தீவு"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "அண்டார்டிகா/மாவ்சன்"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "மாவ்சன் ஸ்டேஷன், ஹோல்ம் மெய்"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "அண்டார்டிகா/மெக்முர்டோ"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "மெக்முர்டோ ஸ்டேஷன், ரோஸ் தீவு"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "அண்டார்டிகா/பால்மேர்"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "பால்மெர் ஸ்டேஷன், அன்வெர்ஸ் தீவு"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "அண்டார்டிகா/ரூத்தரா"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "ரோதெரா ஸ்டேஷன், அடேலாய்டே தீவு"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "அண்டார்டிகா/சவுத்_பொல்"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "அமுன்ட்சென்-ஸ்கோட் ஸ்டேஷன், தெற்கு போல்"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "அண்டார்டிகா/ஸ்யொவா"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "சையோவா ஸ்டேஷன், E ஆன்குல் I"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "அண்டார்டிகா/வாஸ்டாக்"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "வோஸ்டோக் ஸ்டேஷன், S மெக்னெடிக் போல்"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "ஆர்டிக்/லாங்யியர்பயன்"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "ஆசியா/அடின்"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "ஆசியா/அல்மடி"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "ஆசியா/அமான்"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "ஆசியா/அனாடையர்"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "மாஸ்கோ+08 - பெரிங் கடல்"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "ஆசியா/அக்டுவா"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "அடைராவ் (அடிராவ், குர்'யேவ்), மாங்கைஸ்டவ் (மன்கிஸ்டவ்)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "ஆசியா/அக்டோபி"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "அக்டோப் (அக்டோப்)"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "ஆசியா/ஆஹகாபாட்"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "ஆசியா/அஷ்ஹாபாட்"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "ஆசியா/பாக்தாத்"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "ஆசியா/பாஹ்ரேயின்"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "ஆசியா/பாகு"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "ஆசியா/பாங்காக்"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "ஆசியா/பெயிரட்"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "ஆசியா/பிஷெக்"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "ஆசியா/ப்டூனை"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "ஆசியா/கல்கட்டா"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "ஆசியா/சொயிபால்சான்"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "டோர்னோட், சுக்ஹ்பாட்டர்"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "ஆசியா/சோன்ங்கின்ங்"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "மத்திய சீனா - சிசுயன், யுனான், குயன்ங்ஸி, ஷான்ஸி, குய்ஸ்ஹொவ், மற்றும்."
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "ஆசியா/சாங்கிங்"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "ஆசியா/கொழும்பு"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "ஆசியா/டாகா"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "ஆசியா/டமாஸ்கஸ்"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "ஆசியா/டாகா"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "ஆசியா/டில்லி"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "ஆசியா/துபாய்"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "ஆசியா/துஸ்சன்பி"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "ஆசியா/காசா"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "ஆசியா/ஹ்ர்பின்"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "ஹெய்லோங்ஷியங் (மோஹீ தவிர), ஜிலின்"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "ஆசியா/சோ_சி_மின்ங்"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "ஆசியா/ஹாங்காங்"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "ஆசியா/ஹோவ்டு"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "பாயன்-ஒலிக்ய், கோவி-அல்தாய், ஹோவ்ட், உவ்ஸ், ஸாவ்க்ஹான்"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "ஆசியா/இர்குட்ஸ்க்"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "மாஸ்கோ+05 - லேக் பாய்கல்"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "ஆசியா/இஸ்டான்புல்"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "ஆசியா/ஜகார்டா"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "ஜாவா & சுமத்ரா"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "ஆசியா/ஜயபூரா"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "இரியன் ஜாயா & த மோலுக்காஸ்"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "ஆசியா/ஜெருசலெம்"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "ஆசியா/காபுல்"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "ஆசியா/கம்சட்கா"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "மாஸ்கோ+08 - கமாச்ஹெட்கா"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "ஆசியா/கராச்சி"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "ஆசியா/கஷ்கர்"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "மேற்கு திபெத் & ஸிங்ஜியங்"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "ஆசியா/காட்மாண்டு"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "ஆசியா/காட்மாண்டு"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "ஆசியா/கொல்கத்தா"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "ஆசியா/கர்ஸ்னோயார்ஸ்க்"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "மாஸ்கோ+04 - யேனிசெய் ரிவர்"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "ஆசியா/"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "பெனின்சுலார் மலேஷியா"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "ஆசியா/குசிங்"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "சாபாஹ் & சராவாக்"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "ஆசியா/குவேயித்"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "ஆசியா/மசாவோ"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "ஆசியா/மகாவோ"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "ஆசியா/மகாடன்"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "மாஸ்கோ+08 - மகாடன்"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "ஆசியா/மகசார்"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "கிழக்கு & தெற்கு போர்நியோ, செலெபெஸ், பாலி, நுசா டெங்கார்ரா, மேற்கு திமோர்"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "ஆசியா/மனிலா"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "ஆசியா/மஸ்கட்"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "ஆசியா/நிகோசியா"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "ஆசியா/நோவோகுஸ்நெட்ஸ்க்"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "மாஸ்கோ+03 - நோவோகுஸ்நெட்ஸ்க்"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "ஆசியா/னொவோசிபிர்ஸ்க்"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "மாஸ்கோவ்+03 - நொவோசிபிர்ஸ்க்"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "ஆசியா/ஓம்ஸ்க்"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "மாஸ்கோ+03 - மேற்கு சிபெரியா"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "ஆசியா/ஓரல்"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "மேற்கு கஸாக்ஹிஸ்தான்"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "ஆசியா/ஃபொம்_ஃபென்"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "ஆசியா/பாந்டினாக்"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "மேற்கு & சென்ட்ரல் போர்நியோ"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "ஆசியா/பயாங்யாங்"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "ஆசியா/கடார்"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "ஆசியா/க்சைலோர்டா"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "க்யுஸைலோர்டா (பைஸைலோர்டா, கஸைல்-ஓர்டா)"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "ஆசியா/ரங்கோன்"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "ஆசியா/ரியாத்"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "ஆசியா/ரியாத்87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "ஆசியா/ரியாத்88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "ஆசியா/ரியாத்89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "ஆசியா/சைகான்"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "ஆசியா/சகாலின்"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "மாஸ்கோ+07 - சாக்ஹாலின் தீவு"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "ஆசியா/சமர்கண்ட்"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "மேற்கு உஸ்பெகிஸ்தான்"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "ஆசியா/சியோல்"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "ஆசியா/ஷாங்க்ஹை"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "கிழக்கு சீனா - பெய்ஜிங், குயங்டோங், ஷாங்ஹாய், மற்றும்."
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "ஆசியா/சிங்கப்பூர்"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "ஆசியா/டாயிபேயி"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "ஆசியா/டாஷ்கெண்ட்"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "கிழக்கு உஸ்பெகிஸ்தான்"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "ஆசியா/டிபில்சி"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "ஆசியா/டெஹ்ரான்"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "ஆசியா/டெல்_அவிவ்"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "ஆசியா/திம்பு"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "ஆசியா/திம்ப்ஹு"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "ஆசியா/டோக்கியோ"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "ஆசியா/உஜன்க்_பாண்டங்"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "ஆசியா/உலான்பாடர்"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "ஆசியா/உலான்_படார்"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "ஆசியா/உரும்கி"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "நிறைய திபெத்தாகும் & ஸிங்ஜியங்"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "ஆசியா/வியந்டியேன்"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "ஆசியா/வலாடிவாஸ்டொக்"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "மாஸ்கோ+07 - அமுர் ரிவர்"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "ஆசியா/யகுட்ஸ்க்"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "மாஸ்கோ+06 - லெனா ரிவர்"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "ஆசியா/யெகடெரின்பெர்க்"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "மாஸ்கோ+02 - உரால்ஸ்"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "ஆசியா/எரீவான்"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "அட்லாந்டிக்/அசோர்ஸ்"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "அஸோரெஸ்"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "அட்லாந்டிக்/பெர்முடா"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "அட்லாந்டிக்/கனேரி"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "கனாரி தீவுகள்"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "அட்லாந்டிக்/கேப்_வேர்டி"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "அட்லாந்டிக்/ஃபெரோரெ"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "அட்லாந்டிக்/ஃபெரோ"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "அட்லாந்டிக்/ஜான்_மாயென்"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "அட்லாந்டிக்/மடெரியா"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "மடெய்ரா தீவுகள்"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "அட்லாந்டிக்/ரெக்ஜவிக்"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "அட்லாந்டிக்/சௌத்_ஜார்கியா"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "அட்லாந்டிக்/ஸ்டான்லீ"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "அட்லாந்டிக்/St_ஹெலேனா"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "ஆஸ்ட்ரேலியா/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "ஆஸ்ட்ரேலியா/அடிலேட்"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "தென் ஆஸ்ட்ரேலியா"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "ஆஸ்ட்ரேலியா/ப்ரிஸ்பேன்"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "குயின்ஸ்லாண்ட் - நிறைய இடங்கள்"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "ஆஸ்ட்ரேலியா/ப்ரோக்கன்_ஹில்"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "நியூ தெற்கு வேல்ஸ் - யான்கோவின்னா"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "ஆஸ்ட்ரேலியா/கான்பெரா"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "ஆஸ்ட்ரேலியா/கரி"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "தாஸ்மானியா - கிங் தீவு"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "ஆஸ்ட்ரேலியா/டார்வின்"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "வடக்கத்திய டெர்டோரி"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "ஆஸ்ட்ரேலியா/யூக்லா"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "மேற்கத்திய ஆஸ்ட்ரேலியா - யூக்லாப் பகுதி"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "ஆஸ்ட்ரேலியா/ஹோபார்ட்"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "தாஸ்மானியா - நிறைய இடங்கள்"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "ஆஸ்ட்ரேலியா/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "ஆஸ்ட்ரேலியா/லிண்டிமன்"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "குயின்ஸ்லாண்ட் - ஹாலிடே தீவுகள்"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "ஆஸ்ட்ரேலியா/லோர்ட்_ஹோவ்"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "லார்டு ஹோவ் தீவு"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "ஆஸ்ட்ரேலியா/மெல்போர்ன்"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "விக்டோரியா"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "ஆஸ்ட்ரேலியா/நார்த்"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "ஆஸ்ட்ரேலியா/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "ஆஸ்ட்ரேலியா/பெர்த்"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "மேற்கத்திய ஆஸ்ட்ரேலியா - நிறைய இடங்கள்"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "ஆஸ்ட்ரேலியா/க்வீன்ஸ்லாண்டு"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "ஆஸ்ட்ரேலியா/சௌத்"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "ஆஸ்ட்ரேலியா/சிட்னி"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "நியூ தென் வேல்ஸ் - நிறைய இடங்கள்"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "ஆஸ்ட்ரேலியா/டாஸ்மானியா"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "ஆஸ்ட்ரேலியா/விக்டோரியா"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "ஆஸ்ட்ரேலியா/வெஸ்டு"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "ஆஸ்ட்ரேலியா/யான்கோவினா"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "பிரேஸில்/எக்ரெ"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "பிரேஸில்/டினொரோன்ஹா"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "பிரேஸில்/ஈஸ்ட்"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "பிரேஸில்/வெஸ்ட்"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "கானடா/அட்லாந்டிக்"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "கானடா/செந்ட்ரல்"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "கானடா/ஈஸ்டர்ன்"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "கானடா/ஈஸ்ட்-சச்கட்செவான்"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "கானடா/மௌந்டன்"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "கானடா/நியூஃபௌண்ட்லாந்து"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "கானடா/பஸிபிக்"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "கானடா/சஸ்கட்செவான்"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "கானடா/யுகொன்"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "சைல்/காண்டினெந்ட்ல்"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "சைல்/ஈஸ்டெர்னைலாண்டு"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "க்க்யூபா"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "எக்யுப்த்"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "ஐர்"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/கிரீன்விட்ச்"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/யூனிவேர்சல்"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/சுலூ"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "ஈரோப்/அம்ஸ்டர்டம்"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "ஈரோப்/அண்டேர்ரா"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "ஈரோப்/அதென்ஸ்"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "ஈரோப்/பெல்பாஸ்ட்"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "ஈரோப்/பெல்கிரேடு"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "ஈரோப்/பெர்லின்"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "ஈரோப்/பிராடிஸ்லவா"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "ஈரோப்/புருஸ்சல்ஸ்"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "ஈரோப்/புயுஅரஸ்ட்"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "ஈரோப்/புடாபெஸ்டு"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "ஈரோப்/கிறிஸ்சினவு"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "ஈரோப்/கொபென்ஹஜன்"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "இந்தியன்/டுபிலின்"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "ஈரோப்/கிபிரால்டர்"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "ஐரோப்பா/க்யுர்ன்சே"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "ஈரோப்/ஹெல்சிங்கி"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "ஐரோப்பா/ஸ்லே_ஆஃப்_மேன்"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "ஈரோப்/ஸ்டான்புல்"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "ஐரோப்பா/ஜெர்சி"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "ஈரோப்/கலின்ன்கிராடு"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "மாஸ்கோ-01 - கலின்யிங்ரட்"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "ஈரோப்/கிய்வி"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "ஈரோப்/லிஸ்பான்"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "ஈரோப்/ஜியுபில்ஜனா"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "ஈரோப்/லண்டன்"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "ஈரோப்/லக்ஸெம்பொர்க்"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "ஈரோப்/மாடிரிட்"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "ஈரோப்/மால்டா"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "ஐரோப்பிய/மாரிஹம்ன்"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "ஈரோப்/மின்ஸ்க்"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "ஈரோப்/மானாகோ"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "ஈரோப்/மாஸ்கோ"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "மாஸ்கோ+00 - மேற்கு ருஷ்யா"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "ஈரோப்/நிகோசிய"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "ஈரோப்/ஒஸ்லொ"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "ஈரோப்/பாரிஸ்"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "ஐரோப்பா/போட்கோர்கா"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "ஈரோப்/பிராகியு"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "ஈரோப்/ரிகா"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "ஈரோப்/ரோம்"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "ஈரோப்/சாமாரா"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "மாஸ்கோ - சமாரா, உட்முர்டியா"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "ஈரோப்/சான்_மாரினோ"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "ஈரோப்/சரஜிவொ"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "ஈரோப்/சிம்பெராபொல்"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "சென்ட்ரல் க்ரிமியா"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "ஈரோப்/ஸ்கோபிஜி"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "ஈரோப்/சோபிய"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "ஈரோப்/ஸ்டாக்ஓலம்"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "ஈரோப்/டால்லின்"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "ஈரோப்/டிர்ரானி"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "ஈரோப்/டிராபொல்"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "ஈரோப்/உஸ்கொரொடு"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "ருதெனியா"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "ஈரோப்/வாடுஸ்"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "ஈரோப்/வாட்டிகன்"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "ஈரோப்/வீன்னா"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "ஈரோப்/வில்லினியஸ்"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "ஐரோப்பா/வால்கோக்ரேட்"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "மாஸ்கோ+00 - காஸ்பியன் கடல்"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "ஈரோப்/வார்சாவ்"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "ஈரோப்/சாகிரிப்"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "ஈரோப்/சாபோரோசியி"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "ஸபோரோஸ்'யே, E லுகன்ஸ்க்/ ஸபோரிஸியா, E லுஹன்ஸ்க்"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "ஈரோப்/சுயுரிச்"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "தொழிற்சாலை"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-இரிய்"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "கீரின்விச்"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "ஹாங்காங்"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "ஜஸ்லாந்து"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "இந்தியன்/அண்டானனரிஓ"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "இந்தியன்/சாகோஸ்"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "இந்தியன்/கிறிஸ்துமஸ்"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "இந்தியன்/கொகொஸ்"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "இந்தியன்/கொமொரொ"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "இந்தியன்/கர்கியுஇலின்"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "இந்தியன்/மாகி"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "இந்தியன்/மால்டிவியல்"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "இந்தியன்/மாயுரிடிஅஸ்"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "இந்தியன்/மாயொடிடிய்"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "இந்தியன்/மறுஇணைப்பி"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "ஈரான்"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "ஸ்ரேல்"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "ஜமாய்கா"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "ஜப்பான்"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835
+#: timezones.h:891
+msgid "Kwajalein"
+msgstr "கவாஜலீன்"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "லிபியா"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "மெக்சிகோ/பாஜானார்டி"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "மெக்சிகோ/பாஜாசுர்"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "மெக்சிகோ/படைப் பெருந்தலைவர்"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "மிட்"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "நடுகிழக்கு/ரியாட்88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "நடுகிழக்கு/ரியாட்89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "னவாஜஒ"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "பசிபிக்/அபிய"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "பசிபிக்/ஆக்லண்டு"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "பசிபிக்/சத்தம்"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "சாட்தம் தீவுகள்"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "பசிபிக்/சுய்க்"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "சுய்க் (துருக்) மற்றும் யாப்"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "பசிபிக்/ஈஸ்டர்"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "ஈஸ்டர் தீவு & சாலா ஒய் கோமெஸ்"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "பசிபிக்/ஈபெஃப்ட்"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "பசிபிக்/எண்டர்பரி"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "போனிக்ஸ் தீவுகள்"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "பசிபிக்/பகோபோ"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "பசிபிக்/பிஜி"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "பசிபிக்/புனாப்புடி"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "பசிபிக்/களாபாகஸ்"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "கலாபாகோஸ் தீவுகள்"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "பசிபிக்/கெம்லர்"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "காம்பியர் தீவுகள்"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "பசிபிக்/குடால்கானல்"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "பசிபிக்/கும்"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "பசிபிக்/ஹொனொலுலு"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "ஹவாய்"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "பசிபிக்/ஜான்ஸ்டான்"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "ஜான்ஸ்டோன் அடோல்"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "பசிபிக்/கிர்திமடி"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "லைன் தீவுகள்"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "பசிபிக்/கோஸ்ரே"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "கோஸ்ரேய்"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "பசிபிக்/வாஜாலீன்"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "பசிபிக்/மாஜுரோ"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "பசிபிக்/மார்க்குயுசாஸ்"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "மார்க்யுசாஸ் தீவுகள்"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "பசிபிக்/மிட்வே"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "மிட்வே தீவுகள்"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "பசிபிக்/நவ்ரு"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "பசிபிக்/நியு"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "பசிபிக்/நார்பொல்க்"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "பசிபிக்/நோமியா"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "பசிபிக்/பாகோ_பாகோ"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "பசிபிக்/பலோ"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "பசிபக்/பிட்கெர்ன்"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "பசிபிக்/புனாப்பி"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "போன்பெய் (பொனேப்)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "பசிபிக்/புனாப்பி"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "பசிபிக்/போர்ட்_மோர்ஸ்பை"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "பசிபிக்/ரரோடாங்கா"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "பசிபிக்/"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "பசிபிக்/சமோ"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "பசிபிக்/தாஹிடி"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "சொச்ட்டி தீவுகள்"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "பசிபிக்/டாரவா"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "கில்பெர்ட் தீவுகள்"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "பசிபிக்/டொகடபு"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "பசிபிக்/டிரகு"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "பசிபிக்/வேக்"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "வேக் தீவுகள்"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "பசிபிக்/கோஸ்ரே"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "பசிபிக்/யாபு"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "பொலந்து"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "பொர்ச்சிகல்"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "போஸிக்ஸ்ரூல்ஸ்"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "சிங்கபூர்"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "துர்கி"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "உலகம்"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "யுஎஸ்/அலாஸ்கா"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "யுஎஸ்/அலி"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "யுஎஸ்/அரிசோனா"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "யுஎஸ்/சென்டரல்"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "யுஎஸ்/கிழக்கு"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "யுஎஸ்/கிழக்கு-இண்டியான"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "யுஎஸ்/ஹவாய்"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "யுஎஸ்/இண்டினா-ஸ்டாகி"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "யுஎஸ்/மிஷிகன்"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "யுஎஸ்/"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "யுஎஸ்/பசிபிக்"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "யுஎஸ்/சமோ"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "சுலு"
+
diff --git a/panels/datetime/po-timezones/te.po b/panels/datetime/po-timezones/te.po
new file mode 100644
index 0000000..35caddc
--- /dev/null
+++ b/panels/datetime/po-timezones/te.po
@@ -0,0 +1,3245 @@
+# translation of te.po to Telugu
+# Sree Ganesh <sthottem@redhat.com>, 2006.
+# Krishna Babu K <kkrothap@redhat.com>, 2008, 2009, 2010.
+# translation of te.po to
+# translation of te1.po to
+# translation of te.po to
+msgid ""
+msgstr ""
+"Project-Id-Version: te\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-04-26 13:33+0530\n"
+"Last-Translator: Krishna Babu K <kkrothap@redhat.com>\n"
+"Language-Team: Telugu <en@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: te\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: nplurals=2; plural=(n!=1);\n"
+"\n"
+"\n"
+"\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "ఆఫ్రిక/అడ్జన్"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "ఆఫ్రిక/అక్కర"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "ఆఫ్రిక/అడ్డిస్ ఆబబ (_A)"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "ఆఫ్రిక/అల్గిరీస్"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "ఆఫ్రిక/అస్మరా"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "ఆఫ్రిక/అస్మేరా"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "ఆఫ్రిక/బమకో"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "ఆఫ్రిక/బంగుయి"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "ఆఫ్రిక/బంగుల్"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "ఆఫ్రిక/బిస్సూ"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "ఆఫ్రిక/బ్లాంట్రే"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "ఆఫ్రిక/బ్రజ్విల్లే"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "ఆఫ్రిక/బుజుంబుర"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "ఆఫ్రిక/కైరో"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "ఆఫ్రిక/కసబ్లంక"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "ఆఫ్రిక/చెయుట"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "సియుట & మెలిలా"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "ఆఫ్రిక/కొనక్రే"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "ఆఫ్రిక/డకర్"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "ఆఫ్రిక/డర్ ఏస్స లాం (_S)"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "ఆఫ్రిక/డజ్బోటి"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "ఆఫ్రిక/డౌల"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "ఆఫ్రిక/ఈల్అయూన్ (_A)"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "ఆఫ్రిక/ఫ్రీటౌన్"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "ఆఫ్రిక/గబోర్వన్"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "ఆఫ్రిక/హరరే"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "ఆఫ్రిక/జోన్నెస్బర్గు"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "ఆఫ్రిక/కంపల"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "ఆఫ్రిక/ఖర్టోం"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "ఆఫ్రిక/కిగలి"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "ఆఫ్రిక/కిన్షాష్"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "కాంగో వెస్ట్ డెమ్. రెప్."
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "ఆఫ్రిక/లాగోస్"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "ఆఫ్రిక/లిబ్రేవిల్లే"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "ఆఫ్రిక/లోమే"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "ఆఫ్రిక/లుఆండా"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "ఆఫ్రిక/లుబుంబషి"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "కాంగో ఈస్ట్ డెమ్. రెప్."
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "ఆఫ్రిక/లుసక"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "ఆఫ్రిక/మల్బో"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "ఆఫ్రిక/మపుటో"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "ఆఫ్రిక/మసేరు"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "ఆఫ్రిక/మబబనే"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "ఆఫ్రిక/మొగడిషు"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "ఆఫ్రిక/మొనోరోవియ"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "ఆఫ్రిక/నైరోబీ"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "ఆఫ్రిక/న్డ్జమేనా"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "ఆఫ్రిక/నిమేయే"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "ఆఫ్రిక/నుర్కుచోట్ట"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "ఆఫ్రిక/ఒగడుగో"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "ఆఫ్రిక/పోర్టో-నోవో"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "ఆఫ్రిక/సవోటోమే (_T)"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "ఆఫ్రిక/టింబుక్టు"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "ఆఫ్రిక/త్రిపోలి"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "ఆఫ్రిక/టునిష్"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "ఆఫ్రిక/విన్ఢోక్"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "ఆఫ్రిక/అడక్"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "అలెయుటైన్ ఐలాండ్స్"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "అమెరిక/అంకోర్గే"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "అలస్కా సమయం"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "అమెరిక/అంగుల్ల"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "అమెరిక/ఆంటిగువ"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "అమెరిక/అర్గూనియా"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "టొకాన్టిన్స్"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "అమెరిక/అర్జెంటైనా/బియేన్సుఎయిరీస్ (_A)"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "బెనోస్ ఐర్స్ (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "అమెరిక/అర్జెంటైనా/కట్మార్కా"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "కెటమార్కా (CT), చుబట్ (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "అమెరిక/అర్జెంటైనా/కోండ్రివడయా"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "అమెరిక/అర్జెంటైనా/కోర్డోబా"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "చాలా స్థానములు (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "అమెరిక/అర్జెంటైనా/జుజూయ్"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "జుజుయ్ (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "అమెరిక/అర్జెంటైనా/లరియోజ (_R)"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "లా రియోజ (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "అమెరిక/అర్జెంటైనా/మెన్డోజ్"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "మెండోజా (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "అమెరిక/అర్జెంటైనా/రియోగల్లేగోస్ (_G)"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "సాంతా క్రజ్ (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "అమెరికా/అర్జెంటైనా/సల్టా"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "అమెరిక/అర్జెంటైనా/సన్జుఅన్ (_J)"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "సాన్ జువాన్ (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "అమెరికా/అర్జెంటైనా/సాన్‌లుయిన్ (_L)"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "సాన్ లుయిస్ (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "అమెరిక/అర్జెంటైనా/టచ్మన్"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "టుకుమాన్ (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "అమెరిక/అర్జెంటైనా/ఉషుయియ"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "టైరా డెల్ ఫుయిగో (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "అమెరిక/అరుబ"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "అమెరిక/అసున్కోన్"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "అమెరిక/అటికోకాన్"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "ఈ స్ట్రన్ స్టాండర్డ్ టైమ్ - అటికొకన్, ఆన్టారియో మరియు సౌతామ్టన్ ఐ, నునావుత్"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "అమెరిక/అట్క"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "అమెరిక/బహియ"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "బాహియా"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "అమెరిక/బహియబాండరాస్ (_B)"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "మెక్సికన్ సెంట్రల్ టైమ్ - బహియా డె బండెరాస్"
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "అమెరిక/బ్రబడోస్"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "అమెరిక/బెలేమ్"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "ఆంపా, ఈ పరా"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "అమెరిక/బెల్జే"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "అమెరిక/బ్లన్-సబ్లోన్"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "అట్లాంటిక్ స్టాన్డర్డ్ టైమ్ - క్యూబెక్ - లోయర్ నార్త్ షోర్"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "అమెరిక/బోఆవిస్ట (_V)"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "రొరైమా"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "అమెరిక/బొగోటా"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "అమెరిక/బోయిసే"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "మౌంటైన్ టైమ్ - సౌత్ యిడాహొ & ఈస్ట్ ఒరెగాన్"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "అమెరిక/బుఎనోస్ఐరేస్ (_A)"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "అమెరిక/కేంబ్రిడ్జిబే (_B)"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "మౌంటైన్ టైమ్ - వెస్ట్ నునావత్"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "అమెరిక/కంపోగన్డే (_G)"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "మటొ గ్రొస్సో డొ సల్"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "అమెరిక/కన్కున్"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "సెంట్రల్ టైమ్ - క్వింతానా రొ"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "అమెరిక/కరకస్"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "అమెరిక/కటమ్రాక్"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "అమెరిక/సెయేన్నే"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "అమెరిక/సెయ్మన్"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "అమెరిక/చికాగో"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "సెంట్రల్ టైమ్"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "అమెరిక/చిహుచిహా"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "మెక్సికన్ మౌంటైన్ సమయం - చిహువాహువా US సరిహద్దునుండి దూరంగా"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "అమెరిక/కోరల్హర్బోర్ (_H)"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "అమెరిక/కొర్డోబా"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "అమెరిక/కోస్టారిక (_R)"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "అమెరిక/కుయ్బా"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "మేటో గ్రోస్సో"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "అమెరిక/కురకఓ"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "అమెరిక/డెన్మార్కుషవ్న"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "ఈస్ట్ కోస్ట్, స్కోర్సుబైసండ్ యొక్క నార్త్"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "అమెరిక/డవోస్"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "పసిఫిక్ టైమ్ - నార్త్ యుకాన్"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "అమెరిక/డవోస్క్రీక్ (_C)"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr "మౌంటైన్ స్టాండర్డు టైమ్ - డాసన్ గ్రీక్ & ఫోర్ట్ సెయింట్ జాన్, బ్రిటీష్ కొలంబియా"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "అమెరిక/డెన్వేర్"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "మౌంటెయిన్ టైమ్"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "అమెరిక/డెట్రోయిడ్"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "ఈస్ట్రన్ టైమ్ - మిచిగన్ - చాలా స్థానములు"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "అమెరిక/డొమినిక"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "అమెరిక/ఎడ్మోంటోన్"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "మౌంటైన్ టైమ్ - ఆల్బెర్టా, ఈస్ట్ బ్రిటిష్ కొలంబియా & వెస్ట్ సాస్కెచెవాన్"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "అమెరిక/ఐరూనేప్"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "W అమెజొనాస్"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "అమెరిక/ఏల్సల్వడోర్ (_S)"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "అమెరిక/ఏన్సేనడ"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "అమెరిక/ఫోర్టాలేజ"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "NE బ్రెజిల్ (MA, PI, CE, RN, PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "అమెరిక/ఫోర్టువయేన్ (_W)"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "అమెరిక/గ్లేసేబే (_B)"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr "అట్లాంటిక్ సమయం - నొవాస్కోటియా - DST 1966-1971 గమనించని స్థలములు"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "అమెరిక/గోడ్థాబ్"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "చాలా స్థానములు"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "అమెరిక/గోస్బే (_B)"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "అట్లాంటిక్ సమయం - లాబ్రాడర్ - చాలా స్థానములు"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "అమెరిక/గ్రాండ్టర్క్ (_T)"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "అమెరిక/గ్రన్డ"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "అమెరిక/గుడేలోపే"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "అమెరిక/గుటేమల్"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "అమెరిక/గుయేక్విల్"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "మెయిన్‌లాండ్"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "అమెరిక/గుయన్న"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "అమెరిక/హలిఫాక్స్"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "అట్లాంటిక్ సమయం - నొవా స్కాటియా (చాలా స్థలములు), PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "అమెరిక/హవన్న"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "అమెరిక/హెర్మోసిల్లో"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "మౌంటైన్ స్టాండర్డ్ సమయం - సొనొరా"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "అమెరిక/ఇండియన/ఇండీయానాపోలిస్"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "ఈస్ట్రన్ సమయం - ఇండియానా - చాలా స్థానములు"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "అమెరిక/ఇండియన/క్నోక్స్"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "సెంట్రల్ సమయం - యిండియానా - స్టార్కే కౌంటి"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "అమెరిక/ఇండియన/మరెన్గో"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "ఈస్ట్రన్ సమయం - ఇండియానా - క్రాఫోర్డు కౌంటి"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "అమెరిక/ఇండియన/పీటర్సుబర్గు"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "ఈస్ట్రన్ సమయం - యిండియానా - పైక్ కౌంటి"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "అమెరిక/ఇండియానాపోలిస్"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "అమెరికా/ఇండియానా/టెల్ సిటీ(_C)"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "సెంట్రల్ టైమ్ - ఇండియానా - పెర్రి కౌంటి"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "అమెరిక/ఇండియన/వేవేయ్"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "ఈస్ట్రన్ టైమ్ - ఇండియానా - స్విడ్జర్లాండ్ కౌంటి"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "అమెరిక/ఇండియన/విన్సెన్నీస్"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "ఈస్ట్రన్ టైమ్ - ఇండియానా - డవైస్, డుబొయిస్, నాక్స్ & మార్టిన్ కౌంటీస్"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "అమెరికా/ఇండియానా/వినామేక్"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "ఈస్ట్రన్ టైమ్ - ఇండియానా - పులస్కి కౌంటి"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "అమెరిక/ఇన్విక్"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "మౌంటైన్ టైమ్ - వెస్ట్ నార్త్‌వెస్ట్ టెర్రిటొరీస్"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "అమెరిక/లుల్టు"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "ఈస్ట్రన్ టైమ్ - ఈస్ట్ నునావత్ - చాలా స్థానములు"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "అమెరిక/జమైకా"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "అమెరిక/జుజుయే"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "అమెరిక/జునేయూ"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "అలస్కా టైమ్ - అలస్కా పాన్‌హాండిల్"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "అమెరిక/కెన్టుస్కి/లూయీస్విల్లే"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "ఈస్ట్రన్ టైమ్ - కెంటకీ - లూయిస్‌విల్లీ ప్రాంతము"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "అమెరిక/కెన్టుస్కి/మోంటిసెల్లో"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "ఈస్ట్రన్ టైమ్ - కెంటకి - వెనె కౌంటి"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "అమెరిక/క్నోక్స్ఇన్ (_I)"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "అమెరిక/లఫ్జ (_P)"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "అమెరిక/లిమ"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "అమెరిక/లాసాంగిల్"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "పసిఫిక్ టైమ్"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "అమెరిక/లోయిస్విల్లే"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "అమెరిక/మచేయో"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "అలగోస్, సెర్జెపె"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "అమెరిక/మనగుఆ"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "అమెరిక/మననూస్"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "E అమెజొనాస్"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "అమెరికా/మారిగాట్"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "అమెరిక/మర్టీనిక్వే"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "అమెరిక/మటామొరాస్"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr "US సెంట్రల్ టైమ్ - కౌహుయిలా, డురాంగో, న్యువో లియాన్, US సరిహద్దుకు దగ్గరగా టమౌలిపాస్"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "అమెరిక/మజట్లన్"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "మౌంటైన్ టైమ్ - S బాజా, నయరిట్, సినాలౌ"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "అమెరిక/మెండోజా"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "అమెరిక/మెనోమిన్నే"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "సెంట్రల్ టైమ్ - మిచిగన్ - డికిన్సన్, గొగెబిక్, ఐరన్ & మెనోమిని కౌంటీలు"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "అమెరిక/మెరీడా"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "సెంట్రల్ టైమ్ - కాంపెచె, యుకటన్"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "అమెరిక/మెక్సికోసిటీ"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "సెంట్రల్ టైమ్ - చాలా స్థానములు"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "అమెరిక/మిక్విలోన్"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "అమెరిక/మోన్క్టోన్"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "అట్లాంటిక్ సమయం - న్యూ బ్రున్సివిక్"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "అమెరిక/మోంటెర్రే"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr "మెక్సికన్ సెంట్రల్ సమయం - కౌహుయిలా, డురాంగో, న్యువో లియాన్, టమౌలిపస్ US సరిహద్దుకు దూరంగా"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "అమెరిక/మోంటేవిడో"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "అమెరిక/మోంట్రెల్"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "ఈస్ట్రన్ టైమ్ - క్యుబెక్ - చాలా స్థానములు"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "అమెరిక/మోన్టేర్రట్"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "అమెరిక/నస్సుఆ"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "అమెరిక/న్యూయార్కు"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "ఈస్ట్రన్ టైమ్"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "అమెరిక/నిపిగోన్"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr "ఈస్ట్రన్ టైమ్ - ఆన్టారియో & క్యుబెక్ - DST 1967-1973 గమనించని స్థలములు"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "అమెరిక/నోమే"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "అలస్కా సమయం - పశ్చిమ అలస్కా"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "అమెరిక/నొరోన్హ"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "అట్లాంటిక్ ద్వీపాలు"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "అమెరిక/నార్తుడకోట/సెంటర్"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "సెంట్రల్ సమయం - నార్త్ డకోటా - ఆలీవర్ కౌంటీ"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "అమెరిక/నార్తుడకోట/న్యూసలేమ్"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "సెంట్రల్ టైమ్ - నార్త్ డకోటా - మార్టాన్ కౌంటీ (మాండన్ ప్రాంతము తప్పించి)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "అమెరిక/వొజినగ"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "US మౌంటైన్ సమయం - చిహువాహువా US సరిహద్దుకు దగ్గరగా"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "అమెరిక/పనామా"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "అమెరిక/పన్గిటుంగ్"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "ఈస్ట్రన్ సమయం - పాంగ్నిర్టంగ్, న్యునావత్"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "అమెరిక/పరమొరేబో"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "అమెరిక/ఫొనెక్సి"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "మౌంటైన్ స్టాండర్డ్ టైమ్ - అరిజోనా"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "అమెరిక/పోర్టు-ఉ-ప్రిన్సే"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "అమెరిక/పోర్టోఆక్రే"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "అమెరిక/పోర్టోఆఫ్ స్ఫెయిన్"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "అమెరిక/పోర్టో వెల్హో"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "రాండోనియా"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "అమెరిక/పోర్టో రికో"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "అమెరిక/రైని రివర్"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "సెంట్రల్ టైమ్ - రైనీ రివర్ & ఫోర్ట్ ఫ్రాన్సెస్, ఆన్టారియో"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "అమెరిక/రంకిన్ ఇన్లెట్"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "సెంట్రల్ టైమ్ - సెంట్రల్ న్యునావత్"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "అమెరిక/రిసిఫె"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "పెర్నాంబుకొ"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "అమెరిక/రేజిన"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "సెంట్రల్ స్టాండర్డ్ టైమ్ - సాస్కెట్చివాన్ - చాలా స్థానములు"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "అమెరికా/రెసోల్యూట్"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "ఈస్ట్రన్ స్టాండర్డ్ టైమ్ - రిజొల్యూట్, న్యునావత్"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "అమెరిక/రియోబ్రాంకో"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "ఆక్రె"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "అమెరిక/రోసారియో"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "అమెరికా/సాంటా యిజబెల్"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "మెక్సికన్ పసిఫిక్ సమయం - బడా కాలిఫోర్నియా US సరిహద్దునుండి దూరంగా"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "అమెరికా/సాంటారెమ్"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "W పరా"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "అమెరికా/సంటైగో"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "అమెరిక/సంటోడొమింగో"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "అమెరిక/సాఓపౌలో"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "S & SE బ్రెజిల్ (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "అమెరిక/స్కోరెస్బిసండ్"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "Scoresbysund / Ittoqqortoormiit"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "అమెరిక/షిప్రోక్"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "మౌంటైన్ టైమ్ - నవాజో"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "అమెరికా/ఎస్‌టి బర్తెలెమి"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "అమెరిక/ఎస్టీజోన్సు"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "న్యూఫౌండ్‌లాండ్ టైమ్, SE లాబ్రాడర్ కలిపి"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "అమెరిక/ఎస్టీకిట్ట్సు"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "అమెరిక/ఎస్టీలుసిఅ"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "అమెరిక/ఎస్టీథోమస్"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "అమెరిక/ఎస్టీవిన్సెంట్"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "అమెరిక/స్విఫ్టుకరంట్"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "సెంట్రల్ స్టాండర్డ్ టైమ్ - సాస్కట్చవాన్ - మిడ్‌వెస్ట్"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "అమెరిక/టెగుచిగల్ప"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "అమెరిక/తులే"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "థులే / పిటుఫిక్"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "అమెరిక/థండర్బే"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "ఈస్ట్రన్ టైమ్ - థండర్ బే, ఆన్టారియో"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "అమెరిక/తిజున్న"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "US పసిఫిక్ సమయం - బజ కాలిఫోర్నియా US సరిహద్దుకు దగ్గరగా"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "అమెరిక/టొరొంటో"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "ఈస్ట్రన్ టైమ్ - ఆన్టారియో - చాలా స్థానములు"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "అమెరిక/టొర్టోల"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "అమెరిక/వన్కోవేర్"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "పసిఫిక్ టైమ్ - వెస్ట్ బ్రిటీష్ కొలంబియా"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "అమెరిక/విర్గిన్"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "అమెరిక/వైట్ హార్సు"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "పసిఫిక్ టైమ్ - సౌత్ యుకాన్"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "అమెరిక/విన్నీపేజ్"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "సెంట్రల్ టైమ్ - మినిటోబా & వెస్ట్ ఆన్టారియో"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "అమెరిక/యాకుటక్"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "అలస్కా టైమ్ - అలస్కా పాన్‌హాండిల్ నెక్"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "అమెరిక/యల్లోనైఫ్"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "మౌంటైన్ టైమ్ - సెంట్రల్ నార్తువెస్ట్ టెర్రిటొరీస్"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "అమెరిక/ససేయ్"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "కసే స్టేషన్, బైలీ పెనిన్‌సుల్వా"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "అమెరిక/డవిస్"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "డేవిస్ స్టేషన్, వెస్ట్‌ఫోల్డ్ హిల్స్"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "అంటార్కిటిక/డుమౌంటుడుర్విల్లే"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "డ్యుమాంట్-డ్రువిల్లే స్టేషన్, టెర్రీ ఎడెలి"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "అంటార్కిటిక/మెక్వారి"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "మెక్వారి ఐలాండ్ స్టేషన్, మెక్వారి ఐలాండ్"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "అంటార్కిటిక/మావ్సన్"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "మాసాన్ స్టేషన్, హాల్మే బే"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "అంటార్కిటిక/ముమ్రుడో"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "మెక్‌ముర్డో స్టేషన్, రాస్ ఐలాండ్"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "అంటార్కిటిక/పాల్మర్"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "పామర్ స్టేషన్, ఏన్వర్స్ ఐలాండ్"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "అంటార్కిటిక/రోథేరా"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "రొథెరా స్టేషన్, అడెలైడ్ ఐలాండ్"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "అంటార్కిటిక/సౌత్పోలే"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "అముండ్‌సెన్-స్కాట్ స్టేషన్, సౌత్ పొలె"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "అంటార్కిటిక/స్యోవ"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "స్యోవా స్టేషన్, E ఆన్గుల్ ఐ"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "అంటార్కిటిక/వోస్టోక్"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "వాస్టోక్ స్టేషన్, దక్షిణ అయిస్కాంత ధృవము"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "ఆర్కిటిక్/లాంగేర్బేయిన్"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "ఆసియా/ఆడేన్"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "ఆసియా/ఆల్మటే"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "ఆసియా/అమ్మన్"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "ఆసియా/అండ్ర"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "మాస్కో+08 - బేరింగ్ సముద్రము"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "ఆసియా/అక్టూ"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "అటిరౌ (అటిరు, గురివ్), మాన్గిస్టౌ (మాన్కిస్టౌ)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "ఆసియా/అక్టోబే"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "ఆక్టొబె (ఆక్టొబె)"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "ఆసియా/ఆస్ఘబత్"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "ఆసియా/ఆస్కాబద్"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "ఆసియా/బాగ్దాద్"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "ఆసియా/బహ్రెయిన్"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "ఆసియా/బకు"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "ఆసియా/బ్యాంకాంగ్"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "ఆసియా/బీరట్"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "ఆసియా/భిష్కేక్"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "ఆసియా/బ్రునేయ్"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "ఆసియా/కలకత్తా"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "ఆసియా/చొయ్బల్సన్"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "డొనాడ్, సుఖ్‌బాతర్"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "ఆసియా/చోన్కింగ్"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "సెంట్రల్ చైనా - సిచువాన్, యునాన్, గువాగ్జి, షాంగ్జి, గుయిజౌ, మొదలగు."
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "ఆసియా/చుంకింగ్"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "ఆసియా/కొలంబో"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "ఆసియా/డక్క"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "ఆసియా/డెమాస్కస్"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "ఆసియా/ఢాక"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "ఆసియా/దిలి"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "ఆసియా/దుబాయ్"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "ఆసియా/దుషన్బే"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "ఆసియా/గాజా"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "ఆసియా/హర్బిన్"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "హైలాంగ్‌జియాంగ్ (మొహె తప్పించి), జిలిన్"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "ఆసియా/హొచిమిన్హ్"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "ఆసియా/హాంకాంగ్"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "ఆసియా/హోవ్డ"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "బెయాన్-అల్గె, గొవి-ఆల్టై, హోవ్డ్, Uvs, జ్వఖాన్"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "ఆసియా/ఇర్కుత్సక్"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "మాస్కో+05 - లేక్ బైకల్"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "ఆసియా/ఇస్తాన్బుల్"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "ఆసియా/జకర్తా"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "జావా & సుమత్రా"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "ఆసియా/జయపూర్"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "ఐరియన్ జయా & మొలుక్కస్"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "ఆసియా/జెరూసలేమ్"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "ఆసియా/కాబూల్"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "ఆసియా/కంచట్క"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "మాస్కో+08 - కమ్చత్కా"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "ఆసియా/కరాచీ"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "ఆసియా/కష్గర్"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "పశ్చిమ టిబెట్ & గ్జింజియంగ్"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "ఆసియా/కాట్మాండు"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "ఆసియా/కాట్మాండు"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "ఆసియా/కోల్‌కటా"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "ఆసియా/కస్నోయర్స్కు"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "మాస్కో+04 - యెనిసై నది"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "ఆసియా/కోలాలంపూర్"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "పెనిన్‌సులార్ మలేసియా"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "ఆసియా/కూచింగ్"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "సభాహ్ & సరావక్"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "ఆసియా/కువైట్"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "ఆసియా/మాచో"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "ఆసియా/మాచు"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "ఆసియా/మగ్డన్"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "మాస్కో+08 - మగడన్"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "ఆసియా/మకస్సర్"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "తూర్పు & దక్షిణ బొర్నియో, సెలెబెస్, బలి, నుసా టెంగర్రా, పశ్చిమ టిమోర్"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "ఆసియా/మనీల"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "ఆసియా/మస్కట్"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "ఆసియా/నికొసియ"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "ఆసియా/నోవొకుజ్నాస్క్"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "మాస్కో+03 - నొవొకుజ్నాస్క్"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "ఆసియా/నొవోసిబ్రిస్కు"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "మాస్కో+03 - నొవొసిబిర్‌స్క్"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "ఆసియా/ఓంస్క"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "మాస్కో+03 - పశ్చిమ సైబీరియా"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "ఆసియా/ఓరల్"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "పశ్చిమ కజఖస్తాన్"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "ఆసియా/ఫ్నోమ్ఫేన్"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "ఆసియా/ఫొన్టంక్"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "పశ్చిమ & కేంద్ర బొర్నౌ"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "ఆసియా/ప్యోంగాంగ్"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "ఆసియా/క్వాత్రా"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "ఆసియా/క్యూజ్లోడా"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "క్విజిలోర్డా (క్విజిలోర్డా, జిల్-ఓర్డా)"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "ఆసియా/రంగోన్"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "ఆసియా/రియాధ"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "ఆసియా/రియాధ87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "ఆసియా/రియాధ88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "ఆసియా/రియాధ88"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "ఆసియా/సైగోన్"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "ఆసియా/శఖలిన్"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "మాస్కో+07 - సఖలిన్ ఐలాండ్"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "ఆసియా/సమఖండ్"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "పశ్చిమ వుజ్బెకిస్తాన్"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "ఆసియా/సేఉల్"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "ఆసియా/షాంఘై"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "ఈస్ట్ చైనా - బీజింగ్, గువాంగ్‌డాంగ్, షాంఘై, మొదలగునవి."
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "ఆసియా/సింగపూర్"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "ఆసియా/థైపేయ్"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "ఆసియా/థాష్కంట్"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "తూర్పు ఉజ్బెకిస్తాన్"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "ఆసియా/ట్బిలిసి"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "ఆసియా/తెహ్రాన్"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "ఆసియా/తెలావివ్"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "ఆసియా/థింబు"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "ఆసియా/థింపు"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "ఆసియా/టోక్యో"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "ఆసియా/ఊజుంగ్పండంగ్"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "ఆసియా/ఉల్లన్బట్ర"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "ఆసియా/ఉలన్బటోర్"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "ఆసియా/ఉరుముకి"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "టిబెట్ & క్సిన్‌జియాంగ్ లో చాలా"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "ఆసియా/వియెంటియానే"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "ఆసియా/వ్లాడివోస్టోక్"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "మాస్కో+07 - అముర్ నది"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "ఆసియా/యాకుట్స్క"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "మాస్కో+06 - లెనా నది"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "ఆసియా/యెక్టేరియబర్గు"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "మాస్కో+02 - ఉర్లాస్"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "ఆసియా/యెరేవన్"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "అట్లాంటిక్/అజోరేస్"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "ఎజోరెస్"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "అట్లాంటిక్/బెర్బుడా"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "అట్లాంటిక్/కనరే"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "కెనరీ ద్వీపాలు"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "అట్లాంటిక్/కపేవెర్డే"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "అట్లాంటిక్/ఫేరోఏ"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "అట్లాంటిక్/ఫరోయ్"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "అట్లాంటిక్/జన్మయేన్"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "అట్లాంటిక్/మడేయ్రా"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "మెడైర ద్వీపాలు"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "అట్లాంటిక్/రెక్జావిక్"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "అట్లాంటిక్/సౌత్ జియోర్గియా"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "అట్లాంటిక్/స్టాన్లే"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "అట్లాంటిక్/ఎస్టీహెలేనా"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "ఆస్టేలియా/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "ఆస్టేలియా/అడెలడె"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "దక్షిణ ఆస్ట్రేలియా"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "ఆస్టేలియా/బ్రిస్బిన్"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "క్వీన్స్‌లాండ్ - చాలా స్థానములు"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "ఆస్టేలియా/బ్రోకెన్హిల్"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "కొత్త సౌత్ వేల్స్ - యాన్కొవిన్నా"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "ఆస్టేలియా/కాన్బెర్రా"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "ఆస్టేలియా/కుర్రే"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "తస్మానియా - కింగ్ ద్వీపము"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "ఆస్టేలియా/డర్విన్"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "నార్త్రన్ టెర్రిటొరి"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "ఆస్టేలియా/యుక్లా"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "పశ్చిమ ఆస్ట్రేలియా - యుక్లా ప్రాంతము"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "ఆస్టేలియా/హోబర్టు"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "తస్మానియా - చాలా ప్రాంతములు"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "ఆస్టేలియా/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "ఆస్టేలియా/లిండెమన్"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "క్వీన్స్‌లాండ్ - హాలిడే ద్వీపాలు"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "ఆస్టేలియా/లార్డుహోవే"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "లార్డ్ హోవె ద్వీపము"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "ఆస్టేలియా/మెల్బోర్నే"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "విక్టోరియా"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "ఆస్టేలియా/నార్తు"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "ఆస్టేలియా/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "ఆస్టేలియా/పేర్తు"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "పశ్చిమ ఆస్ట్రేలియా - చాలా స్థానములు"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "ఆస్టేలియా/క్వీన్స్లాండ్"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "ఆస్టేలియా/సౌత్"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "ఆస్టేలియా/సిడ్నీ"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "కొత్త సౌత్ వేల్స్ - చాలా స్థానములు"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "ఆస్టేలియా/టస్మానియ"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "ఆస్టేలియా/విక్టోరియా"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "ఆస్టేలియా/వెస్టు"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "ఆస్టేలియా/యన్కొవిన్న"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "బ్రజిల్/ఆక్రే"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "ఆస్టేలియా/డెనెరోన్హ"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "ఆస్టేలియా/ఈస్టు"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "ఆస్టేలియా/వెస్టు"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "కెనడా/అట్లాంటిక్"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "కెనడా/సెంట్రల్"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "కెనడా/ఈస్ట్రన్"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "కెనడా/ఈస్టుసస్కత్చ్వన్"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "కెనడా/మౌటెయిన్"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "కెనడా/న్యూఫౌండ్లాండ్"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "కెనడా/పస్ఫిక్"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "కెనడా/సస్కచ్వేన్"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "కెనడా/యూకోన్"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "చీలే/కంటినెంటల్"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "చీలే/ఈస్టరైస్లాండ్"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "క్యూబ"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "ఈజిప్టు"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "ఐరే"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/గ్రీన్విచ్"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/యూనివర్సల్"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/జూలు"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "యూరప్/ఆంస్టర్డం"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "యూరప్/అండోరా"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "యూరప్/ఏధెన్సు"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "యూరప్/బెల్ఫస్టు"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "యూరప్/బెల్గ్రేడ్"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "యూరప్/బెర్లిన్"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "యూరప్/బ్రటిస్లవ"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "యూరప్/బ్రుస్సెల్సు"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "యూరప్/బుచరెస్టు"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "యూరప్/బుదపేస్టు"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "యూరప్/చిసినఊ"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "యూరప్/కోపెన్హంగేన్"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "యూరప్/డుబ్లిన్"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "యూరప్/జిబ్రాల్టర్"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "యూరప్/గుర్న్సేయ్"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "యూరప్/హెల్సిన్కి"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "యూరప్/ఇస్లేసాఫ్మన్"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "యూరప్/ఇస్తాన్బుల్"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "యూరప్/జెర్సేస్"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "యూరప్/కలినిన్గార్డు"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "మాస్కో-01 - కలినిన్‌గార్డ్"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "యూరప్/కివె"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "యూరప్/లిస్బోన్"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "యూరప్/జుబ్లిజానా"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "యూరప్/లండన్"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "యూరప్/లుక్సెంబర్గు"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "యూరప్/మాడ్రిడ్"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "యూరప్/మల్త"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "యూరప్/మెరియేహ్మన్"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "యూరప్/మిన్స్క"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "యూరప్/మొనాకో"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "యూరప్/మాస్కో"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "మాస్కో+00 - పశ్చిమ రష్యా"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "యూరప్/నికోసియా"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "యూరప్/ఓస్లో"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "యూరప్/పారిస్"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "యూరప్/పొడ్గోరికా"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "యూరప్/పర్గుయే"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "యూరప్/రిగ"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "యూరప్/రోమే"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "యూరప్/సమర"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "మాస్కో - సమరా,ఉడ్ముర్టియా"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "యూరప్/సన్మెరినో"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "యూరప్/సరజేవో"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "యూరప్/సింఫెరెఫోల్"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "కేంద్ర క్రిమియా"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "యూరప్/స్కోప్జే"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "యూరప్/సోఫియా"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "యూరప్/స్ట్లోఖోం"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "యూరప్/టల్లిన్న్"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "యూరప్/టిరానే"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "యూరప్/టిరస్పోల్"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "యూరప్/ఉజ్గోరోడ్"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "రుథేనియా"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "యూరప్/వాడుజ్"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "యూరప్/వాటికన్"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "యూరప్/వియెన్నా"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "యూరప్/విల్నీయస్"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "యూరప్/వోల్గోగార్డు"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "మాస్కో+00 - కాప్సియన్ సముద్రము"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "యూరప్/వర్సావ్"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "యూరప్/జగ్రేబ్"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "యూరప్/జపోరోజేయే"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "జపొరొఝే, E లుగన్‌స్క్ / జపొరోఝియా, E లుహాన్‌స్క్"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "యూరప్/జూరిc"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "ఫ్యాక్టరీ"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-ఈయర్"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "గ్రీన్విచ్"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "హాంకాంగ్"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "ఐస్లాండ్"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "ఇండియన్/ఆంటనానరివో"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "ఇండియన్/చాగోస్"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "ఇండియన్/క్రిస్ట్మస్"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "ఇండియన్/కొకోస్"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "ఇండియన్/కొమోరో"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "ఇండియన్/కెర్గులేలేన్"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "ఇండియన్/మహే"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "ఇండియన్/మాళీవ్సు"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "ఇండియన్/మౌరితీయస్"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "ఇండియన్/మయోట్టే"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "ఇండియన్/రెయునినో"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "ఇరాన్"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "ఇజ్రాయేల్"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "జమైకా"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "జపాన్"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "క్వజలేని"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "లిబియా"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "మెక్సికో/బజనోర్టే"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "మెక్సికో/బజసూర్"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "మెక్సికో/జనరల్"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "మీడెస్టు/రియాధ్87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "మీడెస్టు/రియాధ్88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "మీడెస్టు/రియాధ్89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "నవజో"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "పస్ఫిక్/అపియ"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "పస్ఫిక్/ఔక్లాండ్"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "పస్ఫిక్/చథం"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "చతమ్ ద్వీపాలు"
+
+#: timezones.h:856
+
+msgid "Pacific/Chuuk"
+msgstr "పస్ఫిక్/చుక్"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+
+msgid "Chuuk (Truk) and Yap"
+msgstr "చుక్ (ట్రక్) మరియు యప్"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "ఫసిఫిక్/ఈస్ట్రర్"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "ఈస్టర్ ద్వీపము & సలా వై గొమెజ్"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "పస్ఫిక్/ఈఫటే"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "పస్ఫిక్/ఎండేర్బరి"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "ఫినిక్స్ ద్వీపాలు"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "పస్ఫిక్/ఫకోఫో"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "పస్ఫిక్/ఫిజి"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "పస్ఫిక్/ఫునఫుటి"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "పస్ఫిక్/గలపగోస్"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "గలాపగాస్ ద్వీపాలు"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "పస్ఫిక్/గంబియేర్"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "గాంబియర్ ద్వీపాలు"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "పస్ఫిక్/గుడల్కనాల్"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "పస్ఫిక్/గుం"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "పస్ఫిక్/హోనోలూలు"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "హవాయి"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "పస్ఫిక్/జాన్స్టోన్"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "జాన్‌స్టన్ అటోల్"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "పస్ఫిక్/కిరీటిమటి"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "లైన్ ఐలాండ్స్"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "పస్ఫిక్/కోస్రే"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "కొస్రాయ్"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "పస్ఫిక్/క్వజలేని"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "పస్ఫిక్/మజురో"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "పస్ఫిక్/మ్రేసస్"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "మార్క్వెసాస్ ద్వీపాలు"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "పస్ఫిక్/మిడ్వే"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "మిడ్వే ద్వీపాలు"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "పస్ఫిక్/నురు"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "పస్ఫిక్/నియే"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "పస్ఫిక్/నోర్ఫోల్కు"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "పస్ఫిక్/నుమేయా"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "పస్ఫిక్/పాగోపాగో"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "పస్ఫిక్/పాలఊ"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "పస్ఫిక్/ఫిట్కేరియన్"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "పస్ఫిక్/పోనాపే"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "పాన్‌పై (పొనాపె)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "పస్ఫిక్/పోనపే"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "పస్ఫిక్/పోర్టుమోరెస్బే"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "పస్ఫిక్/రరోటోంగ"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "పస్ఫిక్/సైఫన్"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "పస్ఫిక్/సమోఆ"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "పస్ఫిక్/తాహితి"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "సొసైటీ ద్వీపాలు"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "పస్ఫిక్/తరవ"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "గిల్బర్ట్ ద్వీపాలు"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "పస్ఫిక్/తొంగతపు"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "పస్ఫిక్/ట్రక్"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "పస్ఫిక్/వకే"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "వేక్ ద్వీపము"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "పస్ఫిక్/వల్లిస్"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "పస్ఫిక్/యప్"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "పస్ఫిక్/పోలాండ్"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "పోర్చుగల్"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "పొసిక్స్‌రూల్స్"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "సింగపూర్"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "టుర్కే"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "యూనివర్సల్"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "యుఎస్/అలస్కా"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "యుఎస్/అలేయుటిఅన్"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "యుఎస్/అరిజోన"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "యుఎస్/సెంట్రల్"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "యుఎస్/ఈస్ట్రన్"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "యుఎస్/ఈస్టు-ఇండియన్"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "యుఎస్/హవాయి"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "యుఎస్/ఇండియన్-స్ట్రేకే"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "యుఎస్/మిచిగన్"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "యుఎస్/మౌంటెయిన్"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "యుఎస్/పస్ఫిక్"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "యుఎస్/సమోఆ"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "జూలు"
diff --git a/panels/datetime/po-timezones/tr.po b/panels/datetime/po-timezones/tr.po
new file mode 100644
index 0000000..abba0d7
--- /dev/null
+++ b/panels/datetime/po-timezones/tr.po
@@ -0,0 +1,3246 @@
+# translation of tr.po to Turkish
+# Bahadir Yagan <bahadir.yagan@mentorsystem.com>, 2004.
+# Egemen Metin Turan <mturan@aegee-ankara.org>, 2006, 2007.
+msgid ""
+msgstr ""
+"Project-Id-Version: system-config-date-timezones\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-11-01 10:58+0200\n"
+"Last-Translator: Hasan Alp iNAN <hasanalpinan@gmail.com>\n"
+"Language-Team: Turkish <none>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: tr\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Afrika/Abidyan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Afrika/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Afrika/Adisababa"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Afrika/Cezayir"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "Afrika/Asmara"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Afrika/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Afrika/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Afrika/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Afrika/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Afrika/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Afrika/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Afrika/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Afrika/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Afrika/Kahire"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Afrika/Kazablanka"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Afrika/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Afrika/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Afrika/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Afrika/DarüsSelam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Afrika/Cibuti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Afrika/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Afrika/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Afrika/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Afrika/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Afrika/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Afrika/Yohanesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Afrika/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Afrika/Hartum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Afrika/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Afrika/Kinşasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Afrika/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Afrika/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Afrika/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Afrika/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Afrika/Lubumbaşi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Afrika/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Afrika/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Afrika/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Afrika/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Afrika/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Afrika/Mogadişu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Afrika/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Afrika/Nayrobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Afrika/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Afrika/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Afrika/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Afrika/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Afrika/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Afrika/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Afrika/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Afrika/Trablus"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Afrika/Tunus"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Afrika/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Amerika/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Aleutian Adaları"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Amerika/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Alaska Zamanı"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Amerika/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Amerika/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Amerika/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Amerika/Arjantin/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Buenos Aires (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Amerika/Arjantin/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Amerika/Arjantin/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Amerika/Arjantin/Kordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Amerika/Arjantin/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Jujuy (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Amerika//Arjantin/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Amerika/Arjantin/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Amerika/Arjantin/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "Amerika/Arjantin/Salta"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Amerika/Arjantin/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "San Juan (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "Amerika/Arjantin/San_Luis"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "San Luis (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Amerika/Arjantin/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Amerika/Arjantin/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Amerika/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Amerika/Asuncion"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Amerika/Atikokan"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Amerika/Atka"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Amerika/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "Amerika/Bahia_Banderas"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Amerika/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Amerika/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Amerika/Belize"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "Amerika/Blanc-Sablon"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Amerika/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Amerika/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Amerika/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Amerika/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Amerika/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "Amerika/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Amerika/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Amerika/Karakas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Amerika/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Amerika/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Amerika/Kayman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Amerika/Şikago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+#, fuzzy
+msgid "Central Time"
+msgstr "ABD/Merkez"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Amerika/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "Amerika/Coral_Limanı"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Amerika/Kordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Amerika/Kosta_Rika"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Amerika/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Amerika/Kurakao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Amerika/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Amerika/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "Pasifik Zamanı - Kuzey Yukon"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Amerika/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid "Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Amerika/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+#, fuzzy
+msgid "Mountain Time"
+msgstr "ABD/Mountain"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Amerika/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Amerika/Dominik"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Amerika/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "America/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Amerika/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Amerika/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Amerika/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Amerika/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Amerika/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Amerika/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195
+#: timezones.h:364
+#: timezones.h:453
+#: timezones.h:591
+#: timezones.h:754
+#: timezones.h:852
+#: timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Amerika/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Amerika/Türk_Adaları"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Amerika/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Amerika/Guadalup"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Amerika/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Amerika/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205
+#: timezones.h:757
+#: timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Amerika/Guyana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Amerika/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Amerika/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Amerika/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Amerika/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Amerika/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Amerika/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "Amerika/Indiana/Petersburg"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Amerika/Indianapolis"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "Amerika/Indiana/Tell_City"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Amerika/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "Amerika/Indiana/Vincennes"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "Amerika/Indiana/Winamac"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Amerika/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Amerika/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Amerika/Jameika"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Amerika/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Amerika/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Amerika/Kentucy/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Doğu Zamanı - Kentucky - Louisville bölgesi"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Amerika/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Amerika/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Amerika/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Amerika/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Amerika/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "Pasifik Zamanı"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Amerika/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Amerika/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Amerika/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Amerika/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "Amerika/Marigot"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Amerika/Martinik"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "Amerika/Matamoros"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid "US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Amerika/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Amerika/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Amerika/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Amerika/Mendoza"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Amerika/Meksiko"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Amerika/Miquelon"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "Amerika/Moncton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Amerika/Montserrat"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid "Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Amerika/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Amerika/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Amerika/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Amerika/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Amerika/New_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "Doğu Zamanı"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Amerika/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid "Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Amerika/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Amerika/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "Atlantik adaları"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Amerika/Kuzey_Dakota/Merkez"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "Amerika/Kuzey_Dakota/New_salem"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "Amerika/Ojinaga"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Amerika/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Amerika/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Amerika/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Amerika/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Amerika/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Amerika/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Amerika/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Amerika/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Amerika/Porto_Riko"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Amerika/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Amerika/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "America/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Amerika/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "Amerika/Resolute"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Amerika/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Amerika/Rosario"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "Amerika/Santa_Isabel"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "Amerika/Santarem"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Amerika/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Amerika/Santo_Dominyo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Amerika/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Amerika/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Amerika/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "Amerika/St_Barthelemy"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Amerika/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Amerika/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Amerika/St_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Amerika/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Amerika/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Amerika/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Amerika/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Amerika/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Amerika/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Amerika/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "Amerika/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Amerika/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Amerika/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Amerika/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Amerika/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Amerika/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Amerika/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Amerika/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "Antartika/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "Antartika/Davis"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "Antartika/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "Antartika/Macquarie"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "Antartika/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "Antartika/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "Antartika/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "Antartika/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "Antartika/Güney_Kutbu"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "Antartika/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "Antartika/Vostok"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "Arctic/Longyearbyen"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Asya/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Asya/Almaata"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Asya/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Asya/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "Moskova+08 - Bering Denizi"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Asya/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Asya/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Asya/Aşkabad"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Asya/Aşkabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Asya/Bağdat"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Asya/Bahreyn"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Asya/Bakü"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Asya/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Asya/Beyrut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Asya/Bişkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Asya/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Asya/Kalküta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Asya/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Asya/Chngqking"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Asya/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Asya/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Asya/Dakka"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Asya/Şam"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Asya/Daka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Asya/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Asya/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Asya/Duşanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Asya/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Asya/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Asya/Ho_Chi_Minh"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Asya/Hong_Kong"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Asya/Aden"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Asya/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Moskova+05 - Baykal Gölü"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Asya/İstanbul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Asya/Jakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Asya/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Asya/Kudüs"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Asya/Kabil"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Asya/Kamçatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "Moskova+08 - Kamchatka"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Asya/Karaçi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Asya/Kaşgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "batı Tibet & Xinjiang"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "Asya/Katmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Asya/Katmandu"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "Asya/Kalküta"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Asya/Krasnoyarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "Moskova+04 - Yenisey Nehri"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Asya/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Asya/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Asya/Kuveyt"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Asya/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Asya/Macau"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Asya/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "Moskova+08 - Magadan"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Asya/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Asya/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Asya/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Asya/Lefkoşa"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "Asya/Novokuznetsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Moskova+03 - Novokuznetsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Asya/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Moskova+03 - Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Asya/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "Moskova+03 - batı Sibirya"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Asya/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "Batı Kazakistan"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Asya/Pnom_Pen"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Asya/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Asya/Piongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Asya/Katar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Asya/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Asya/Rangoon"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Asya/Riyad"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Asya/Riyad87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Asya/Riyad88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Asya/Riyad89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Asya/Saygon"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Asya/Sakhalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "Moskova+07 - Sakhalin Adası"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Asya/Semerkant"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Asya/Seul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Asya/Şanghay"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Asya/Singapur"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Asya/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Asya/Taşkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "doğu Özbekistan"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Asya/Tiflis"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Asya/Tahran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Asya/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Asya/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Asya/Thimbu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Asya/Tokyo"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Asya/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Asya/Ulan_Bator"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Asya/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Asya/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Asya/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Asya/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "Moskova+07 - Amur Nehri"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Asya/Yakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "Moskova+06 - Lena Nehri"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Asya/Yekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "Moskova+02 - Urallar"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Asya/Erivan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Atlantik/Azorlar"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Atlantik/Bermuda"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Atlantik/Kanarya"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Atlantik/Cape_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Atlantik/Faroe"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "Atlantik/Faroe"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Atlantik/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Atlantik/Madeyra"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Atlantik/Reykjavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Atlantik/Güney_Georgia"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Atlantik/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Atlantik/St_Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Avustralya/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Avustralya/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "Güney Avustralya"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Avustralya/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Avustralya/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Avustralya/Canberra"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "Avustralya/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Avustralya/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "Avustralya/Eucla"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "Batı Avustralya - Eucla bölgesi"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Avustralya/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Avustralya/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Avustralya/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Avustralya/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Avustralya/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "Viktoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Avustralya/Kuzey"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Avustralya/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Avustralya/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Avustralya/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Avustralya/Güney"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Avustralya/Sidney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Avustralya/Tazmanya"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Avustralya/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Avustralya/Batı"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Avustralya/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brezilya/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brezilya/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brezilya/Doğu"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brezilya/Batı"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Kanada/Atlantik"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Kanada/Orta"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Kanada/Doğu"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Kanada/East-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Kanada/Dağlık"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Kanada/Newfoundland"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Kanada/Pasifik"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Kanada/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Kanada/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Şili/Kıta"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Şili/EasterAdaları"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Küba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Mısır"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "Eire"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Evrensel"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Sıfır"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Avrupa/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Avrupa/Andorra"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Avrupa/Atina"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Avrupa/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Avrupa/Belgrat"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Avrupa/Berlin"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Avrupa/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Avrupa/Brüksel"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Avrupa/Bükreş"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Avrupa/Budapeşte"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Avrupa/Kişinev"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Avrupa/Kopenhag"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Avrupa/Dublin"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Avrupa/Cebelitarık"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "Avrupa/Guernsey"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Avrupa/Helsinki"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "Avrupa/Man_Adası"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Avrupa/İstanbul"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "Avrupa/Jersey"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Avrupa/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Moskova-01 - Kaliningrad"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Avrupa/Kiev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Avrupa/Lizbon"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Avrupa/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Avrupa/Londra"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Avrupa/Lüksemburg"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Avrupa/Madrit"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Avrupa/Malta"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "Avrupa/Mariehamn"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Avrupa/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Avrupa/Monako"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Avrupa/Moskova"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "Moskova+00 - batı Rusya"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Avrupa/Lefkoşa"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Avrupa/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Avrupa/Paris"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "Avrupa/Podgorica"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Avrupa/Prag"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Avrupa/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Avrupa/Roma"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Avrupa/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Moskova - Samara, Udmurtia"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Avrupa/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Avrupa/Saray_Bosna"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Avrupa/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Avrupa/Üsküp"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Avrupa/Sofya"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Avrupa/Stokholm"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Avrupa/Tallinn"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Avrupa/Tiran"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Avrupa/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Avrupa/Uzhgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Avrupa/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Avrupa/Vatikan"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Avrupa/Viyana"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Avrupa/Vilnius"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "Avrupa/Volgograd"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "Moskova+00 - Hazar Denizi"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Avrupa/Varşova"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Avrupa/Zagrep"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Avrupa/Zaporozya"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Avrupa/Zürih"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "Factory"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "GB-Eire"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hongkong"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "İzlanda"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Hint_Okyanusu/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Hint_Okyanusu/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Hint_Okyanusu/Christmas"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Hint_Okyanusu/Cocos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Hint_Okyanusu/Comoro"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Hint_Okyanusu/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Hint_Okyanusu/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Hint_Okyanusu/Maldives"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Hint_Okyanusu/Mauritius"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Hint_Okyanusu/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Hint_Okyanusu/Reunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "İran"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "İsrail"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jameika"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Japonya"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835
+#: timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Libya"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Meksika/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Meksika/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Meksika/Genel"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "OrtaDoğu/Riyad87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "OrtaDoğu/Riyad88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "OrtaDoğu/Riyad89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Pasifik/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Pasifik/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Pasifik/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+#, fuzzy
+msgid "Chatham Islands"
+msgstr "Şili/EasterAdaları"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "Pasifik/Chuuk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "Pasifik/Easter"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Pasifik/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Pasifik/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Pasifik/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Pasifik/Fiji"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Pasifik/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Pasifik/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "Galapagos Adaları"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Pasifik/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Pasifik/Guadalkanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Pasifik/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Pasifik/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "Hawaii"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Pasifik/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Pasifik/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Pasifik/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "Kosrae"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Pasifik/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Pasifik/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Pasifik/Markiz"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Pasifik/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Pasifik/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Pasifik/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Pasifik/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Pasifik/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Pasifik/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Pasifik/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Pasifik/Pitcairn"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "Pasifik/Pohnpei"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "Pohnpei (Ponape)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Pasifik/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Pasifik/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Pasifik/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Pasifik/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Pasifik/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Pasifik/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Pasifik/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+#, fuzzy
+msgid "Gilbert Islands"
+msgstr "Şili/EasterAdaları"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Pasifik/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Pasifik/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Pasifik/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Pasifik/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Pasifik/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "Polonya"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "Portekiz"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapur"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "Türkiye"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Evrensel"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "ABD/Alaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "ABD/Aleutian"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "ABD/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "ABD/Merkez"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "ABD/Doğu"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "ABD/East-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "ABD/Hawaii"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "ABD/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "ABD/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "ABD/Mountain"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "ABD/Pasifik"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "ABD/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
+
+#~ msgid "US/Pacific-New"
+#~ msgstr "ABD/Pasifik-Yeni"
diff --git a/panels/datetime/po-timezones/uk.po b/panels/datetime/po-timezones/uk.po
new file mode 100644
index 0000000..ca8ff5e
--- /dev/null
+++ b/panels/datetime/po-timezones/uk.po
@@ -0,0 +1,3239 @@
+# Ukrainian translation to system-config-boot.
+# Copyright (C) Free Software Foundation
+# This file is distributed under the same license as the system-config-boot package.
+# Alex Lobas <soft@cw.comizdat.com>
+#
+# Maxim Dziumanenko <dziumanenko@gmail.com>, 2003.
+# Yuri Chornoivan <yurchor@ukr.net>, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: 1.1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-04-20 16:04+0200\n"
+"PO-Revision-Date: 2010-08-20 18:38+0300\n"
+"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
+"Language-Team: Ukrainian <uk@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Lokalize 1.1\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Африка/Абіджан"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Африка/Аккра"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Африка/Адіс-Абеба"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Африка/Алжир"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "Африка/Асмара"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Африка/Асмера"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Африка/Бомако"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Африка/Бангі"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Африка/Банджул"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Африка/Біссау"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Африка/Блантайр"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Африка/Браззавіль"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Африка/Бужумбура"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Африка/Каїр"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Африка/Касабланка"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Африка/Сеута"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "Сеута та Мелілла"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Африка/Конакрі"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Африка/Дакар"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Африка/Дар ес Салаам"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Африка/Джибуті"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Африка/Доуала"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Африка/Ель Ааюн"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Африка/Фрітаун"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Африка/Габероне"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Африка/Хараре"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Африка/Йоганнесбург"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Африка/Кампала"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Африка/Хартоум"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Африка/Кігалі"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Африка/Кіншаса"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "Захід Дем. Республіка Конго"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Африка/Лагос"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Африка/Лібревіль"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Африка/Ломе"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Африка/Луанда"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Африка/Лумумбаши"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "сіхд Дем. Республіки Конго"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Африка/Лусака"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Африка/Малабо"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Африка/Мапуто"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Африка/Масеру"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Африка/Мбабане"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Африка/Могадішу"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Африка/Монровія"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Африка/Найробі"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Африка/Нджамена"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Африка/Ніамей"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Африка/Нуакчотт"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Африка/Уагадугу"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Африка/Порто-Ново"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Африка/Сао Томе"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Африка/Тимбукту"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Африка/Тріполі"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Африка/Туніс"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Африка/Віндхук"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Америка/Адак"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "Алеутські острови"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Америка/Анкорідж"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "Аляска час"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Америка/Ангілла"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Америка/Антігуа"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Америка/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "Токантінс"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Америка/Аргентина/Буенос-Айрос"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "Буенос-Айрес (BA, CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "Америка/Аргентина/Катамарка"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "Катамарка (CT), Чубут (CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Америка/Аргентина/ComodRivadavia"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "Америка/Аргентина/Кордоба"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "основна частина (CB, CC, CN, ER, FM, MN, SE, SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "Америка/Аргентина/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "Жужуй (JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "Америка/Аргентина/La_Rioja"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "Ла-Ріоха (LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "Америка/Аргентина/Мендоза"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "Мендоза (MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Америка/Аргентина/Rio_Gallegos"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "Санта-Круз (SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "Америка/Аргентина/Сальта"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA, LP, NQ, RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "Америка/Аргентина/San_Juan"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "Сан-Хуан (SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "Америка/Аргентина/Сан-Луіс"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "Сан-Луїс (SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "Америка/Аргентина/Tucuman"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "Тукуман (TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "Америка/Аргентина/Ushuaia"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "Архіпелаг Вогненна Земля (TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Америка/Аруба"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Америка/Асунсьйон"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "Америка/Атикокан"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "Східний стандартний час - Атикокан, Онтаріо та Саутгемптон, Нунавут"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Америка/Атка"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "Америка/Bahia"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "Бахія"
+
+#: timezones.h:117
+msgid "America/Barbados"
+msgstr "Америка/Барбадос"
+
+#: timezones.h:118
+msgid "America/Belem"
+msgstr "Америка/Белен"
+
+#. comment for time zone America/Belem
+#: timezones.h:120
+msgid "Amapa, E Para"
+msgstr "Амапа, схід Пара"
+
+#: timezones.h:121
+msgid "America/Belize"
+msgstr "Америка/Ѓеліза"
+
+#: timezones.h:122
+msgid "America/Blanc-Sablon"
+msgstr "Америка/Бланк-Саблон"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:124
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "Атлантичний стандартний час - Квебек - Північний берег"
+
+#: timezones.h:125
+msgid "America/Boa_Vista"
+msgstr "Америка/Боа-Віста"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:127
+msgid "Roraima"
+msgstr "Рорайма"
+
+#: timezones.h:128
+msgid "America/Bogota"
+msgstr "Америка/Богота"
+
+#: timezones.h:129
+msgid "America/Boise"
+msgstr "Америка/Бойсе"
+
+#. comment for time zone America/Boise
+#: timezones.h:131
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "Гірський час - південний Айдахо та східний Орегон"
+
+#: timezones.h:132
+msgid "America/Buenos_Aires"
+msgstr "Америка/Буенос-Айрос"
+
+#: timezones.h:133
+msgid "America/Cambridge_Bay"
+msgstr "Америка/Кембридж Бей"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:135
+msgid "Mountain Time - west Nunavut"
+msgstr "Гірський час - західний Нунавут"
+
+#: timezones.h:136
+msgid "America/Campo_Grande"
+msgstr "Америка/Campo_Grande"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:138
+msgid "Mato Grosso do Sul"
+msgstr "Мато-Гроссо-ду-Сул"
+
+#: timezones.h:139
+msgid "America/Cancun"
+msgstr "Америка/Канкан"
+
+#. comment for time zone America/Cancun
+#: timezones.h:141
+msgid "Central Time - Quintana Roo"
+msgstr "Центральний час - Квінтана-Роо"
+
+#: timezones.h:142
+msgid "America/Caracas"
+msgstr "Америка/Каракас"
+
+#: timezones.h:143
+msgid "America/Catamarca"
+msgstr "Америка/Катамарка"
+
+#: timezones.h:144
+msgid "America/Cayenne"
+msgstr "Америка/Каєна"
+
+#: timezones.h:145
+msgid "America/Cayman"
+msgstr "Америка/Кайман"
+
+#: timezones.h:146
+msgid "America/Chicago"
+msgstr "Америка/Чикаго"
+
+#. comment for time zone America/Chicago
+#: timezones.h:148
+msgid "Central Time"
+msgstr "Центральний час"
+
+#: timezones.h:149
+msgid "America/Chihuahua"
+msgstr "Америка/Чиуауа"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:151
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "Мексиканський гірський час — Чіуауа на віддалі від кордону з США"
+
+#: timezones.h:152
+msgid "America/Coral_Harbour"
+msgstr "Америка/Coral_Harbour"
+
+#: timezones.h:153
+msgid "America/Cordoba"
+msgstr "Америка/Кордоба"
+
+#: timezones.h:154
+msgid "America/Costa_Rica"
+msgstr "Америка/Коста-Ріка"
+
+#: timezones.h:155
+msgid "America/Cuiaba"
+msgstr "Америка/Куяба"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:157
+msgid "Mato Grosso"
+msgstr "Мато-Гроссо"
+
+#: timezones.h:158
+msgid "America/Curacao"
+msgstr "Америка/Куракао"
+
+#: timezones.h:159
+msgid "America/Danmarkshavn"
+msgstr "Америка/Данмаркхавн"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:161
+msgid "east coast, north of Scoresbysund"
+msgstr "східний беріг, північ Скорсбізунд"
+
+#: timezones.h:162
+msgid "America/Dawson"
+msgstr "Америка/Доусон"
+
+#. comment for time zone America/Dawson
+#: timezones.h:164
+msgid "Pacific Time - north Yukon"
+msgstr "Тихоокеанський час - північний Юкон"
+
+#: timezones.h:165
+msgid "America/Dawson_Creek"
+msgstr "Америка/Бухта Доусона"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:167
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+"Гірський стандартний час - Досон крик, Форт Сен-Джон, Британська Колумбія"
+
+#: timezones.h:168
+msgid "America/Denver"
+msgstr "Америка/Денвер"
+
+#. comment for time zone America/Denver
+#: timezones.h:170
+msgid "Mountain Time"
+msgstr "Гірський час"
+
+#: timezones.h:171
+msgid "America/Detroit"
+msgstr "Америка/Детройт"
+
+#. comment for time zone America/Detroit
+#: timezones.h:173
+msgid "Eastern Time - Michigan - most locations"
+msgstr "Східний час - Мічіган - основна частина"
+
+#: timezones.h:174
+msgid "America/Dominica"
+msgstr "Америка/Домініка"
+
+#: timezones.h:175
+msgid "America/Edmonton"
+msgstr "Америка/Едмонтон"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:177
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+"Гірський час - Альберта, схід Британської Колумбії та західний Саскачеван"
+
+#: timezones.h:178
+msgid "America/Eirunepe"
+msgstr "Америка/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:180
+msgid "W Amazonas"
+msgstr "Амазонас, захід"
+
+#: timezones.h:181
+msgid "America/El_Salvador"
+msgstr "Америка/Ель-Сальвадор"
+
+#: timezones.h:182
+msgid "America/Ensenada"
+msgstr "Америка/Ensenada"
+
+#: timezones.h:183
+msgid "America/Fortaleza"
+msgstr "Америка/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:185
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "Північний-схід Бразилии (MA, PI, CE, RN, PB)"
+
+#: timezones.h:186
+msgid "America/Fort_Wayne"
+msgstr "Америка/Fort_Wayne"
+
+#: timezones.h:187
+msgid "America/Glace_Bay"
+msgstr "Америка/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:189
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+"Атлантичний час - Нова Шотландія - де не враховується денний стандарт 1966-"
+"1971"
+
+#: timezones.h:190
+msgid "America/Godthab"
+msgstr "Америка/Готхоб"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:192 timezones.h:361 timezones.h:450 timezones.h:588
+#: timezones.h:751 timezones.h:849 timezones.h:888
+msgid "most locations"
+msgstr "основна частина"
+
+#: timezones.h:193
+msgid "America/Goose_Bay"
+msgstr "Америка/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:195
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "Атлантичний час - Лабрадор - основна частина"
+
+#: timezones.h:196
+msgid "America/Grand_Turk"
+msgstr "Америка/Grand_Turk"
+
+#: timezones.h:197
+msgid "America/Grenada"
+msgstr "Америка/Гренада"
+
+#: timezones.h:198
+msgid "America/Guadeloupe"
+msgstr "Америка/Гваделупа"
+
+#: timezones.h:199
+msgid "America/Guatemala"
+msgstr "Америка/Гватемала"
+
+#: timezones.h:200
+msgid "America/Guayaquil"
+msgstr "Америка/Гуянакіль"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:202 timezones.h:754 timezones.h:760
+msgid "mainland"
+msgstr "материк"
+
+#: timezones.h:203
+msgid "America/Guyana"
+msgstr "Америка/Гаяна"
+
+#: timezones.h:204
+msgid "America/Halifax"
+msgstr "Америка/Халіфакс"
+
+#. comment for time zone America/Halifax
+#: timezones.h:206
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "Атлантичний час - Нова Шотландія (основна частина)"
+
+#: timezones.h:207
+msgid "America/Havana"
+msgstr "Америка/Гавана"
+
+#: timezones.h:208
+msgid "America/Hermosillo"
+msgstr "Америка/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:210
+msgid "Mountain Standard Time - Sonora"
+msgstr "Гірський стандартний час - Сонора"
+
+#: timezones.h:211
+msgid "America/Indiana/Indianapolis"
+msgstr "Америка/Індіана/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:213
+msgid "Eastern Time - Indiana - most locations"
+msgstr "Східний час - Індіана - основна частина"
+
+#: timezones.h:214
+msgid "America/Indiana/Knox"
+msgstr "Америка/Індіана/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:216
+msgid "Central Time - Indiana - Starke County"
+msgstr "Центральний час - Індіана - округ Старк"
+
+#: timezones.h:217
+msgid "America/Indiana/Marengo"
+msgstr "Америка/Індіана/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:219
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "Східний час - Індіана - округ Кроуфорд"
+
+#: timezones.h:220
+msgid "America/Indiana/Petersburg"
+msgstr "Америка/Індіана/Петербург"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "Східний час - Індіана - округ Пайк"
+
+#: timezones.h:223
+msgid "America/Indianapolis"
+msgstr "Америка/Індіанаполіс"
+
+#: timezones.h:224
+msgid "America/Indiana/Tell_City"
+msgstr "Америка/Індіана/Tell_City"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:226
+msgid "Central Time - Indiana - Perry County"
+msgstr "Центральний час - Індіана - округ Перрі"
+
+#: timezones.h:227
+msgid "America/Indiana/Vevay"
+msgstr "Америка/Індіана/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:229
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "Східний час - Індіана - округ Швейцарія"
+
+#: timezones.h:230
+msgid "America/Indiana/Vincennes"
+msgstr "Америка/Індіана/Вінсеннес"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "Східний час - Індіана - округ Дейвес, Дюбуа, Нокс, Мартін"
+
+#: timezones.h:233
+msgid "America/Indiana/Winamac"
+msgstr "Америка/Індіана/Winamac"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "Східний час - Індіана - округ Пуласкі"
+
+#: timezones.h:236
+msgid "America/Inuvik"
+msgstr "Америка/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:238
+msgid "Mountain Time - west Northwest Territories"
+msgstr "Гірський час - західна частина Східно-західних Територій"
+
+#: timezones.h:239
+msgid "America/Iqaluit"
+msgstr "Америка/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:241
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "Східний час - східний Нунавут - основна частина"
+
+#: timezones.h:242
+msgid "America/Jamaica"
+msgstr "Америка/Ямайка"
+
+#: timezones.h:243
+msgid "America/Jujuy"
+msgstr "Америка/Jujuy"
+
+#: timezones.h:244
+msgid "America/Juneau"
+msgstr "Америка/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:246
+msgid "Alaska Time - Alaska panhandle"
+msgstr "Аляска"
+
+#: timezones.h:247
+msgid "America/Kentucky/Louisville"
+msgstr "Америка/Кентуккі/Луїзвіль"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:249
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Східний час - Кентуккі - Луїзвіль"
+
+#: timezones.h:250
+msgid "America/Kentucky/Monticello"
+msgstr "Америка/Кентуккі/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "Східний час - Кентуккі - округ Уэйн"
+
+#: timezones.h:253
+msgid "America/Knox_IN"
+msgstr "Америка/Knox_IN"
+
+#: timezones.h:254
+msgid "America/La_Paz"
+msgstr "Америка/La_Paz"
+
+#: timezones.h:255
+msgid "America/Lima"
+msgstr "Америка/Ліма"
+
+#: timezones.h:256
+msgid "America/Los_Angeles"
+msgstr "Америка/Лос Анжелес"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:258
+msgid "Pacific Time"
+msgstr "Тихоокеанський час"
+
+#: timezones.h:259
+msgid "America/Louisville"
+msgstr "Америка/Луїзвіль"
+
+#: timezones.h:260
+msgid "America/Maceio"
+msgstr "Америка/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:262
+msgid "Alagoas, Sergipe"
+msgstr "Алагоас, Серджпайп"
+
+#: timezones.h:263
+msgid "America/Managua"
+msgstr "Америка/Манагуа"
+
+#: timezones.h:264
+msgid "America/Manaus"
+msgstr "Америка/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:266
+msgid "E Amazonas"
+msgstr "Амазонас, схід"
+
+#: timezones.h:267
+msgid "America/Marigot"
+msgstr "Америка/Marigot"
+
+#: timezones.h:268
+msgid "America/Martinique"
+msgstr "Америка/Мартиніка"
+
+#: timezones.h:269
+msgid "America/Matamoros"
+msgstr "Америка/Матаморос"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:271
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+"Мексиканський центральний час - Коауїла, Дуранго, Нуево-Леон, Тамауліпас "
+"поблизу від кордону з США"
+
+#: timezones.h:272
+msgid "America/Mazatlan"
+msgstr "Америка/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:274
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "Гірський час - Байя, Наяріт, Сіналоа"
+
+#: timezones.h:275
+msgid "America/Mendoza"
+msgstr "Америка/Мендоза"
+
+#: timezones.h:276
+msgid "America/Menominee"
+msgstr "Америка/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:278
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "Центральний час - Мічіган - округ Дікінсон, Годжебик, Айрон, Меноміні"
+
+#: timezones.h:279
+msgid "America/Merida"
+msgstr "Америка/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:281
+msgid "Central Time - Campeche, Yucatan"
+msgstr "Центральний час - Кампече, Юкатан"
+
+#: timezones.h:282
+msgid "America/Mexico_City"
+msgstr "Америка/Mexico_City"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:284
+msgid "Central Time - most locations"
+msgstr "Центральний час - основна частина"
+
+#: timezones.h:285
+msgid "America/Miquelon"
+msgstr "Америка/Miquelon"
+
+#: timezones.h:286
+msgid "America/Moncton"
+msgstr "Америка/Монктон"
+
+#. comment for time zone America/Moncton
+#: timezones.h:288
+msgid "Atlantic Time - New Brunswick"
+msgstr "Атлантичний час - Новий Брансвік"
+
+#: timezones.h:289
+msgid "America/Monterrey"
+msgstr "Америка/Монтеррей"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:291
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+"Мексиканський центральний час - Коауїла, Дуранго, Нуево-Леон, Тамауліпас на "
+"віддалі від кордону з США"
+
+#: timezones.h:292
+msgid "America/Montevideo"
+msgstr "Америка/Монтевідео"
+
+#: timezones.h:293
+msgid "America/Montreal"
+msgstr "Америка/Монреаль"
+
+#. comment for time zone America/Montreal
+#: timezones.h:295
+msgid "Eastern Time - Quebec - most locations"
+msgstr "Східний час - Квебек - основна частина"
+
+#: timezones.h:296
+msgid "America/Montserrat"
+msgstr "Америка/Монсерат"
+
+#: timezones.h:297
+msgid "America/Nassau"
+msgstr "Америка/Нассау"
+
+#: timezones.h:298
+msgid "America/New_York"
+msgstr "Америка/Нью-Йорк"
+
+#. comment for time zone America/New_York
+#: timezones.h:300
+msgid "Eastern Time"
+msgstr "Східний час"
+
+#: timezones.h:301
+msgid "America/Nipigon"
+msgstr "Америка/Ніпігон"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:303
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+"Східний час - Онтаріо та Квебек - де не враховується денний стандарт 1967-"
+"1973"
+
+#: timezones.h:304
+msgid "America/Nome"
+msgstr "Америка/Номе"
+
+#. comment for time zone America/Nome
+#: timezones.h:306
+msgid "Alaska Time - west Alaska"
+msgstr "Аляска час - західна Аляска"
+
+#: timezones.h:307
+msgid "America/Noronha"
+msgstr "Америка/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:309
+msgid "Atlantic islands"
+msgstr "Острови Атлантичного океану"
+
+#: timezones.h:310
+msgid "America/North_Dakota/Center"
+msgstr "Америка/Північна Дакота/Центр"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:312
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "Центральний час - Північна Дакота - Округ Олівер"
+
+#: timezones.h:313
+msgid "America/North_Dakota/New_Salem"
+msgstr "Америка/Північна Дакота/Нью_Салем"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:315
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "Центральний час - Північна Дакота - Округ Мортон (окрім Мандэн)"
+
+#: timezones.h:316
+msgid "America/Ojinaga"
+msgstr "Америка/Охінага"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:318
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "Гірський час США — Чіуауа поблизу кордону з США"
+
+#: timezones.h:319
+msgid "America/Panama"
+msgstr "Америка/Панама"
+
+#: timezones.h:320
+msgid "America/Pangnirtung"
+msgstr "Америка/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:322
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "Східний час - Паніртанг, Нунавут"
+
+#: timezones.h:323
+msgid "America/Paramaribo"
+msgstr "Америка/Paramaribo"
+
+#: timezones.h:324
+msgid "America/Phoenix"
+msgstr "Америка/Фенікс"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:326
+msgid "Mountain Standard Time - Arizona"
+msgstr "Гірський час - Аризона"
+
+#: timezones.h:327
+msgid "America/Port-au-Prince"
+msgstr "Америка/Port-au-Prince"
+
+#: timezones.h:328
+msgid "America/Porto_Acre"
+msgstr "Америка/Porto_Acre"
+
+#: timezones.h:329
+msgid "America/Port_of_Spain"
+msgstr "Америка/Port_of_Spain"
+
+#: timezones.h:330
+msgid "America/Porto_Velho"
+msgstr "Америка/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:332
+msgid "Rondonia"
+msgstr "Рондонія"
+
+#: timezones.h:333
+msgid "America/Puerto_Rico"
+msgstr "Америка/Пуерто-Ріко"
+
+#: timezones.h:334
+msgid "America/Rainy_River"
+msgstr "Америка/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:336
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "Центральний час - Рейні Рівер та Форт Франсіс, Онтаріо"
+
+#: timezones.h:337
+msgid "America/Rankin_Inlet"
+msgstr "Америка/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:339
+msgid "Central Time - central Nunavut"
+msgstr "Центральний час - центральний Нунавут"
+
+#: timezones.h:340
+msgid "America/Recife"
+msgstr "Америка/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:342
+msgid "Pernambuco"
+msgstr "Пернамбуку"
+
+#: timezones.h:343
+msgid "America/Regina"
+msgstr "Америка/Регіна"
+
+#. comment for time zone America/Regina
+#: timezones.h:345
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "Центральний стандартний час - Саскачеван - основна частина"
+
+#: timezones.h:346
+msgid "America/Resolute"
+msgstr "Америка/Resolute"
+
+#. comment for time zone America/Resolute
+#: timezones.h:348
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "Східний стандартний час - Резолют, Нунавут"
+
+#: timezones.h:349
+msgid "America/Rio_Branco"
+msgstr "Америка/Ріо Бранко"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:351
+msgid "Acre"
+msgstr "Акре"
+
+#: timezones.h:352
+msgid "America/Rosario"
+msgstr "Америка/Розаріо"
+
+#: timezones.h:353
+msgid "America/Santa_Isabel"
+msgstr "Америка/Санта-Ісабель"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:355
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+"Мексиканський тихоокеанський час — Нижня Каліфорнія на віддалі від кордону з "
+"США"
+
+#: timezones.h:356
+msgid "America/Santarem"
+msgstr "Америка/Сантарем"
+
+#. comment for time zone America/Santarem
+#: timezones.h:358
+msgid "W Para"
+msgstr "Захід Пара"
+
+#: timezones.h:359
+msgid "America/Santiago"
+msgstr "Америка/Сант'яго"
+
+#: timezones.h:362
+msgid "America/Santo_Domingo"
+msgstr "Америка/Санто-Домінго"
+
+#: timezones.h:363
+msgid "America/Sao_Paulo"
+msgstr "Америка/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:365
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+"Південь та південний схід Бразилії (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+
+#: timezones.h:366
+msgid "America/Scoresbysund"
+msgstr "Америка/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:368
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "Скорсбізунд / Ітокортурмііт"
+
+#: timezones.h:369
+msgid "America/Shiprock"
+msgstr "Америка/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:371
+msgid "Mountain Time - Navajo"
+msgstr "Гірський час - Навахо"
+
+#: timezones.h:372
+msgid "America/St_Barthelemy"
+msgstr "Америка/St_Barthelemy"
+
+#: timezones.h:373
+msgid "America/St_Johns"
+msgstr "Америка/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:375
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "Ньюфаундленд, південний схід Лабрадора"
+
+#: timezones.h:376
+msgid "America/St_Kitts"
+msgstr "Америка/St_Kitts"
+
+#: timezones.h:377
+msgid "America/St_Lucia"
+msgstr "Америка/St_Lucia"
+
+#: timezones.h:378
+msgid "America/St_Thomas"
+msgstr "Америка/St_Thomas"
+
+#: timezones.h:379
+msgid "America/St_Vincent"
+msgstr "Америка/St_Vincent"
+
+#: timezones.h:380
+msgid "America/Swift_Current"
+msgstr "Америка/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:382
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "Центральний стандартний час - Саскачеван - середній захід"
+
+#: timezones.h:383
+msgid "America/Tegucigalpa"
+msgstr "Америка/Tegucigalpa"
+
+#: timezones.h:384
+msgid "America/Thule"
+msgstr "Америка/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:386
+msgid "Thule / Pituffik"
+msgstr "Туле / Пітуфік"
+
+#: timezones.h:387
+msgid "America/Thunder_Bay"
+msgstr "Америка/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:389
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "Східний час - Тандер-Бей, Онтаріо"
+
+#: timezones.h:390
+msgid "America/Tijuana"
+msgstr "Америка/Тігуана"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:392
+msgid "US Pacific Time - Baja California near US border"
+msgstr "Тихоокеанський час США — Нижня Каліфорнія поблизу кордону з США"
+
+#: timezones.h:393
+msgid "America/Toronto"
+msgstr "Америка/Торонто"
+
+#. comment for time zone America/Toronto
+#: timezones.h:395
+msgid "Eastern Time - Ontario - most locations"
+msgstr "Східний час - Онтаріо - основна частина"
+
+#: timezones.h:396
+msgid "America/Tortola"
+msgstr "Америка/Тортола"
+
+#: timezones.h:397
+msgid "America/Vancouver"
+msgstr "Америка/Ванкувер"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:399
+msgid "Pacific Time - west British Columbia"
+msgstr "Тихоокеанський час - західна частина Британської Колумбії"
+
+#: timezones.h:400
+msgid "America/Virgin"
+msgstr "Америка/Virgin"
+
+#: timezones.h:401
+msgid "America/Whitehorse"
+msgstr "Америка/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:403
+msgid "Pacific Time - south Yukon"
+msgstr "Тихоокеанський час - південний Юкон"
+
+#: timezones.h:404
+msgid "America/Winnipeg"
+msgstr "Америка/Вінніпег"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:406
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "Центральний час - Манітоба та західний Онтаріо"
+
+#: timezones.h:407
+msgid "America/Yakutat"
+msgstr "Америка/Якутат"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:409
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "Аляска час - Аляска, перешийок"
+
+#: timezones.h:410
+msgid "America/Yellowknife"
+msgstr "Америка/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:412
+msgid "Mountain Time - central Northwest Territories"
+msgstr "Гірський час - центральна частина Північно-західних Територій"
+
+#: timezones.h:413
+msgid "Antarctica/Casey"
+msgstr "Антарктида/Casey"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:415
+msgid "Casey Station, Bailey Peninsula"
+msgstr "Кейсі, станція Кейсі, півострів Бейлі"
+
+#: timezones.h:416
+msgid "Antarctica/Davis"
+msgstr "Антарктида/Девіс"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:418
+msgid "Davis Station, Vestfold Hills"
+msgstr "Дейвіс, станція Дейвис, Вестфолд Хіллс"
+
+#: timezones.h:419
+msgid "Antarctica/DumontDUrville"
+msgstr "Антарктида/DumontDUrville"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:421
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "Дюмон-д-Юрвіль, станція Дюмон-д-Юрвіль, Терра-Аделі"
+
+#: timezones.h:422
+msgid "Antarctica/Macquarie"
+msgstr "Антарктида/Маккуорі"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:424
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "Острівна станція Маккуорі, острів Маккуорі"
+
+#: timezones.h:425
+msgid "Antarctica/Mawson"
+msgstr "Антарктида/Mawson"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:427
+msgid "Mawson Station, Holme Bay"
+msgstr "Моусон, станція Моусон, бух. Холме"
+
+#: timezones.h:428
+msgid "Antarctica/McMurdo"
+msgstr "Антарктида/McMurdo"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:430
+msgid "McMurdo Station, Ross Island"
+msgstr "Мак-Мердо, станція Мак-Мердо, острів Росс"
+
+#: timezones.h:431
+msgid "Antarctica/Palmer"
+msgstr "Антарктида/Palmer"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:433
+msgid "Palmer Station, Anvers Island"
+msgstr "Палмер, станція Палмер, острів Анверс"
+
+#: timezones.h:434
+msgid "Antarctica/Rothera"
+msgstr "Антарктида/Rothera"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:436
+msgid "Rothera Station, Adelaide Island"
+msgstr "Ротера, станція Ротера, острів Аделаїди"
+
+#: timezones.h:437
+msgid "Antarctica/South_Pole"
+msgstr "Антарктида/South_Pole"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:439
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "Амудсен-Скотт, станція Амудсен-Скотт, Південний полюс"
+
+#: timezones.h:440
+msgid "Antarctica/Syowa"
+msgstr "Антарктида/Syowa"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:442
+msgid "Syowa Station, E Ongul I"
+msgstr "Сева, станція Сева"
+
+#: timezones.h:443
+msgid "Antarctica/Vostok"
+msgstr "Антарктида/Восток"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:445
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "Станція Восток, південний полюс"
+
+#: timezones.h:446
+msgid "Arctic/Longyearbyen"
+msgstr "Арктика/Longyearbyen"
+
+#: timezones.h:447
+msgid "Asia/Aden"
+msgstr "Азія/Аден"
+
+#: timezones.h:448
+msgid "Asia/Almaty"
+msgstr "Азія/Алма-Ата"
+
+#: timezones.h:451
+msgid "Asia/Amman"
+msgstr "Азія/Амман"
+
+#: timezones.h:452
+msgid "Asia/Anadyr"
+msgstr "Азія/Анадир"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:454
+msgid "Moscow+08 - Bering Sea"
+msgstr "Москва +8 — Берингове море"
+
+#: timezones.h:455
+msgid "Asia/Aqtau"
+msgstr "Азія/Актау"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:457
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "Атирау (колишній Гур'єв), Мангистау"
+
+#: timezones.h:458
+msgid "Asia/Aqtobe"
+msgstr "Азія/Актобе"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:460
+msgid "Aqtobe (Aktobe)"
+msgstr "Актюбінськ"
+
+#: timezones.h:461
+msgid "Asia/Ashgabat"
+msgstr "Азія/Ashgabat"
+
+#: timezones.h:462
+msgid "Asia/Ashkhabad"
+msgstr "Азія/Ашхабад"
+
+#: timezones.h:463
+msgid "Asia/Baghdad"
+msgstr "Азія/Багдад"
+
+#: timezones.h:464
+msgid "Asia/Bahrain"
+msgstr "Азія/Bahrain"
+
+#: timezones.h:465
+msgid "Asia/Baku"
+msgstr "Азія/Баку"
+
+#: timezones.h:466
+msgid "Asia/Bangkok"
+msgstr "Азія/Бангкок"
+
+#: timezones.h:467
+msgid "Asia/Beirut"
+msgstr "Азія/Бейрут"
+
+#: timezones.h:468
+msgid "Asia/Bishkek"
+msgstr "Азія/Бішкек"
+
+#: timezones.h:469
+msgid "Asia/Brunei"
+msgstr "Азія/Брунеї"
+
+#: timezones.h:470
+msgid "Asia/Calcutta"
+msgstr "Азія/Калькутта"
+
+#: timezones.h:471
+msgid "Asia/Choibalsan"
+msgstr "Азія/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:473
+msgid "Dornod, Sukhbaatar"
+msgstr "Дорнод, Сухбатаар"
+
+#: timezones.h:474
+msgid "Asia/Chongqing"
+msgstr "Азія/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:476
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+"Центральна частина Китаю - Сичуань, Юннань, Гуансі, Шеньсі, Гуанчжоу та ін."
+
+#: timezones.h:477
+msgid "Asia/Chungking"
+msgstr "Азія/Chungking"
+
+#: timezones.h:478
+msgid "Asia/Colombo"
+msgstr "Азія/Коломбо"
+
+#: timezones.h:479
+msgid "Asia/Dacca"
+msgstr "Азія/Дакка"
+
+#: timezones.h:480
+msgid "Asia/Damascus"
+msgstr "Азія/Дамаск"
+
+#: timezones.h:481
+msgid "Asia/Dhaka"
+msgstr "Азія/Dhaka"
+
+#: timezones.h:482
+msgid "Asia/Dili"
+msgstr "Азія/Dili"
+
+#: timezones.h:483
+msgid "Asia/Dubai"
+msgstr "Азія/Дубай"
+
+#: timezones.h:484
+msgid "Asia/Dushanbe"
+msgstr "Азія/Душанбе"
+
+#: timezones.h:485
+msgid "Asia/Gaza"
+msgstr "Азія/Газа"
+
+#: timezones.h:486
+msgid "Asia/Harbin"
+msgstr "Азія/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:488
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "Хэйлунцзян (окріс Мохе), Цзилинь"
+
+#: timezones.h:489
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Азія/Хо-Чі-Мін"
+
+#: timezones.h:490
+msgid "Asia/Hong_Kong"
+msgstr "Азія/Гонг-Конг"
+
+#: timezones.h:491
+msgid "Asia/Hovd"
+msgstr "Азія/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:493
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "Байан-Олги, Гові-Алтай, Ховд, Увс, Завхан"
+
+#: timezones.h:494
+msgid "Asia/Irkutsk"
+msgstr "Азія/Іркутськ"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:496
+msgid "Moscow+05 - Lake Baikal"
+msgstr "Москва+05 - Байкал"
+
+#: timezones.h:497
+msgid "Asia/Istanbul"
+msgstr "Азія/Стамбул"
+
+#: timezones.h:498
+msgid "Asia/Jakarta"
+msgstr "Азія/Джакарта"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:500
+msgid "Java & Sumatra"
+msgstr "Ява та Суматра"
+
+#: timezones.h:501
+msgid "Asia/Jayapura"
+msgstr "Азія/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:503
+msgid "Irian Jaya & the Moluccas"
+msgstr "Іріан Джайя та Молуккські острови"
+
+#: timezones.h:504
+msgid "Asia/Jerusalem"
+msgstr "Азія/Єрусалим"
+
+#: timezones.h:505
+msgid "Asia/Kabul"
+msgstr "Азія/Кабул"
+
+#: timezones.h:506
+msgid "Asia/Kamchatka"
+msgstr "Азія/Камчатка"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:508
+msgid "Moscow+08 - Kamchatka"
+msgstr "Москва +08 — Камчатка"
+
+#: timezones.h:509
+msgid "Asia/Karachi"
+msgstr "Азія/Карачі"
+
+#: timezones.h:510
+msgid "Asia/Kashgar"
+msgstr "Азія/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:512
+msgid "west Tibet & Xinjiang"
+msgstr "східний Тибет та Синцзян"
+
+#: timezones.h:513
+msgid "Asia/Kathmandu"
+msgstr "Азія/Катманду"
+
+#: timezones.h:514
+msgid "Asia/Katmandu"
+msgstr "Азія/Катманду"
+
+#: timezones.h:515
+msgid "Asia/Kolkata"
+msgstr "Азія/Калькутта"
+
+#: timezones.h:516
+msgid "Asia/Krasnoyarsk"
+msgstr "Азія/Красноярськ"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:518
+msgid "Moscow+04 - Yenisei River"
+msgstr "Москва+04 - Єнісей"
+
+#: timezones.h:519
+msgid "Asia/Kuala_Lumpur"
+msgstr "Азія/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:521
+msgid "peninsular Malaysia"
+msgstr "Малайзія, півострівна"
+
+#: timezones.h:522
+msgid "Asia/Kuching"
+msgstr "Азія/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:524
+msgid "Sabah & Sarawak"
+msgstr "Саба та Саравак"
+
+#: timezones.h:525
+msgid "Asia/Kuwait"
+msgstr "Азія/Кувейт"
+
+#: timezones.h:526
+msgid "Asia/Macao"
+msgstr "Азія/Макао"
+
+#: timezones.h:527
+msgid "Asia/Macau"
+msgstr "Азія/Macau"
+
+#: timezones.h:528
+msgid "Asia/Magadan"
+msgstr "Азія/Магадан"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:530
+msgid "Moscow+08 - Magadan"
+msgstr "Москва+08 - Магадан"
+
+#: timezones.h:531
+msgid "Asia/Makassar"
+msgstr "Азія/Макассар"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:533
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+"Південний та східний Борнео, Целебес, Бали, Нуса Тенгара, західний Тимор"
+
+#: timezones.h:534
+msgid "Asia/Manila"
+msgstr "Азія/Маніла"
+
+#: timezones.h:535
+msgid "Asia/Muscat"
+msgstr "Азія/Muscat"
+
+#: timezones.h:536
+msgid "Asia/Nicosia"
+msgstr "Азія/Нікосія"
+
+#: timezones.h:537
+msgid "Asia/Novokuznetsk"
+msgstr "Азія/Новокузнецьк"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:539
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Москва +03 — Новокузнецьк"
+
+#: timezones.h:540
+msgid "Asia/Novosibirsk"
+msgstr "Азія/Новосибірськ"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:542
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Москва+03 - Новосибірськ"
+
+#: timezones.h:543
+msgid "Asia/Omsk"
+msgstr "Азія/Омськ"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:545
+msgid "Moscow+03 - west Siberia"
+msgstr "Москва+03 - захід Сибіру"
+
+#: timezones.h:546
+msgid "Asia/Oral"
+msgstr "Азія/Орал"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:548
+msgid "West Kazakhstan"
+msgstr "Західний Казахстан"
+
+#: timezones.h:549
+msgid "Asia/Phnom_Penh"
+msgstr "Азія/Phnom_Penh"
+
+#: timezones.h:550
+msgid "Asia/Pontianak"
+msgstr "Азія/Понтіанак"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:552
+msgid "west & central Borneo"
+msgstr "Західний та центральний Борнео"
+
+#: timezones.h:553
+msgid "Asia/Pyongyang"
+msgstr "Азія/Pyongyang"
+
+#: timezones.h:554
+msgid "Asia/Qatar"
+msgstr "Азія/Катар"
+
+#: timezones.h:555
+msgid "Asia/Qyzylorda"
+msgstr "Азія/Кизилорда"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:557
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "Кизилорда"
+
+#: timezones.h:558
+msgid "Asia/Rangoon"
+msgstr "Азія/Rangoon"
+
+#: timezones.h:559
+msgid "Asia/Riyadh"
+msgstr "Азія/Riyadh"
+
+#: timezones.h:560
+msgid "Asia/Riyadh87"
+msgstr "Азія/Riyadh87"
+
+#: timezones.h:561
+msgid "Asia/Riyadh88"
+msgstr "Азія/Riyadh88"
+
+#: timezones.h:562
+msgid "Asia/Riyadh89"
+msgstr "Азія/Riyadh89"
+
+#: timezones.h:563
+msgid "Asia/Saigon"
+msgstr "Азія/Сайгон"
+
+#: timezones.h:564
+msgid "Asia/Sakhalin"
+msgstr "Азія/Сахалін"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:566
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "Москва+07 - Сахалін, острів"
+
+#: timezones.h:567
+msgid "Asia/Samarkand"
+msgstr "Азія/Самарканд"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:569
+msgid "west Uzbekistan"
+msgstr "Західний Узбекистан"
+
+#: timezones.h:570
+msgid "Asia/Seoul"
+msgstr "Азія/Сеул"
+
+#: timezones.h:571
+msgid "Asia/Shanghai"
+msgstr "Азія/Шанхай"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:573
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "Східний Китай - Пекин, Гуандун, Шанхай та ін."
+
+#: timezones.h:574
+msgid "Asia/Singapore"
+msgstr "Азія/Сінгапур"
+
+#: timezones.h:575
+msgid "Asia/Taipei"
+msgstr "Азія/Тайпей"
+
+#: timezones.h:576
+msgid "Asia/Tashkent"
+msgstr "Азія/Ташкент"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:578
+msgid "east Uzbekistan"
+msgstr "східний Узбекистан"
+
+#: timezones.h:579
+msgid "Asia/Tbilisi"
+msgstr "Азія/Тбілісі"
+
+#: timezones.h:580
+msgid "Asia/Tehran"
+msgstr "Азія/Tehran"
+
+#: timezones.h:581
+msgid "Asia/Tel_Aviv"
+msgstr "Азія/Тель-Авів"
+
+#: timezones.h:582
+msgid "Asia/Thimbu"
+msgstr "Азія/Thimbu"
+
+#: timezones.h:583
+msgid "Asia/Thimphu"
+msgstr "Азія/Thimphu"
+
+#: timezones.h:584
+msgid "Asia/Tokyo"
+msgstr "Азія/Токіо"
+
+#: timezones.h:585
+msgid "Asia/Ujung_Pandang"
+msgstr "Азія/Ujung_Pandang"
+
+#: timezones.h:586
+msgid "Asia/Ulaanbaatar"
+msgstr "Азія/Ulaanbaatar"
+
+#: timezones.h:589
+msgid "Asia/Ulan_Bator"
+msgstr "Азія/Ulan_Bator"
+
+#: timezones.h:590
+msgid "Asia/Urumqi"
+msgstr "Азія/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:592
+msgid "most of Tibet & Xinjiang"
+msgstr "Основна частина Тибету та Синцзян"
+
+#: timezones.h:593
+msgid "Asia/Vientiane"
+msgstr "Азія/В'єнт'ян"
+
+#: timezones.h:594
+msgid "Asia/Vladivostok"
+msgstr "Азія/Владивосток"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:596
+msgid "Moscow+07 - Amur River"
+msgstr "Москва+07 - Амур"
+
+#: timezones.h:597
+msgid "Asia/Yakutsk"
+msgstr "Азія/Якутськ"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:599
+msgid "Moscow+06 - Lena River"
+msgstr "Москва+06 - ріка Лена"
+
+#: timezones.h:600
+msgid "Asia/Yekaterinburg"
+msgstr "Азія/Єкатеринбург"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:602
+msgid "Moscow+02 - Urals"
+msgstr "Москва+02 - Урал"
+
+#: timezones.h:603
+msgid "Asia/Yerevan"
+msgstr "Азія/Yerevan"
+
+#: timezones.h:604
+msgid "Atlantic/Azores"
+msgstr "Атлантика/Азорські о-ви"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:606
+msgid "Azores"
+msgstr "Азорські острови"
+
+#: timezones.h:607
+msgid "Atlantic/Bermuda"
+msgstr "Атлантика/Бермудські о-ви"
+
+#: timezones.h:608
+msgid "Atlantic/Canary"
+msgstr "Атлантика/Канарські о-ви"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:610
+msgid "Canary Islands"
+msgstr "Канарські острови"
+
+#: timezones.h:611
+msgid "Atlantic/Cape_Verde"
+msgstr "Атлантика/Капе Верде"
+
+#: timezones.h:612
+msgid "Atlantic/Faeroe"
+msgstr "Атлантика/Фарерскі о-ви"
+
+#: timezones.h:613
+msgid "Atlantic/Faroe"
+msgstr "Атлантика/Фарерскі о-ви"
+
+#: timezones.h:614
+msgid "Atlantic/Jan_Mayen"
+msgstr "Атлантика/Jan_Mayen"
+
+#: timezones.h:615
+msgid "Atlantic/Madeira"
+msgstr "Атлантика/Мадейра"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:617
+msgid "Madeira Islands"
+msgstr "Мадейра, острови"
+
+#: timezones.h:618
+msgid "Atlantic/Reykjavik"
+msgstr "Атлантика/Рейк'явік"
+
+#: timezones.h:619
+msgid "Atlantic/South_Georgia"
+msgstr "Атлантика/South_Georgia"
+
+#: timezones.h:620
+msgid "Atlantic/Stanley"
+msgstr "Атлантика/Стенлі"
+
+#: timezones.h:621
+msgid "Atlantic/St_Helena"
+msgstr "Атлантика/о-в Св.Олени"
+
+#: timezones.h:622
+msgid "Australia/ACT"
+msgstr "Австралія/ACT"
+
+#: timezones.h:623
+msgid "Australia/Adelaide"
+msgstr "Австралія/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:625
+msgid "South Australia"
+msgstr "Південна Австралія"
+
+#: timezones.h:626
+msgid "Australia/Brisbane"
+msgstr "Австралія/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:628
+msgid "Queensland - most locations"
+msgstr "Квінсленд - основна частина"
+
+#: timezones.h:629
+msgid "Australia/Broken_Hill"
+msgstr "Австралія/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:631
+msgid "New South Wales - Yancowinna"
+msgstr "Новий Південний Уельс - Янковінна"
+
+#: timezones.h:632
+msgid "Australia/Canberra"
+msgstr "Австралія/Canberra"
+
+#: timezones.h:633
+msgid "Australia/Currie"
+msgstr "Австралія/Currie"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:635
+msgid "Tasmania - King Island"
+msgstr "Тасманія - острів Кінг"
+
+#: timezones.h:636
+msgid "Australia/Darwin"
+msgstr "Австралія/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:638
+msgid "Northern Territory"
+msgstr "Північна територія"
+
+#: timezones.h:639
+msgid "Australia/Eucla"
+msgstr "Австралія/Юкла"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:641
+msgid "Western Australia - Eucla area"
+msgstr "Західна Австралія - Юкла"
+
+#: timezones.h:642
+msgid "Australia/Hobart"
+msgstr "Австралія/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:644
+msgid "Tasmania - most locations"
+msgstr "Тасманія - основна частина"
+
+#: timezones.h:645
+msgid "Australia/LHI"
+msgstr "Австралія/LHI"
+
+#: timezones.h:646
+msgid "Australia/Lindeman"
+msgstr "Австралія/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:648
+msgid "Queensland - Holiday Islands"
+msgstr "Квінсленд - острови Холидей"
+
+#: timezones.h:649
+msgid "Australia/Lord_Howe"
+msgstr "Австралія/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:651
+msgid "Lord Howe Island"
+msgstr "Лорд Хау, острів"
+
+#: timezones.h:652
+msgid "Australia/Melbourne"
+msgstr "Австралія/Мельбурн"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:654
+msgid "Victoria"
+msgstr "Вікторія"
+
+#: timezones.h:655
+msgid "Australia/North"
+msgstr "Австралія/Північ"
+
+#: timezones.h:656
+msgid "Australia/NSW"
+msgstr "Австралія/NSW"
+
+#: timezones.h:657
+msgid "Australia/Perth"
+msgstr "Австралія/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:659
+msgid "Western Australia - most locations"
+msgstr "Західна Австралія - основна частина"
+
+#: timezones.h:660
+msgid "Australia/Queensland"
+msgstr "Австралія/Queensland"
+
+#: timezones.h:661
+msgid "Australia/South"
+msgstr "Австралія/Південь"
+
+#: timezones.h:662
+msgid "Australia/Sydney"
+msgstr "Австралія/Сідней"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:664
+msgid "New South Wales - most locations"
+msgstr "Новий Південний Уельс - основна частина"
+
+#: timezones.h:665
+msgid "Australia/Tasmania"
+msgstr "Австралія/Тасманія"
+
+#: timezones.h:666
+msgid "Australia/Victoria"
+msgstr "Австралія/Вікторія"
+
+#: timezones.h:667
+msgid "Australia/West"
+msgstr "Австралія/Захід"
+
+#: timezones.h:668
+msgid "Australia/Yancowinna"
+msgstr "Австралія/Yancowinna"
+
+#: timezones.h:669
+msgid "Brazil/Acre"
+msgstr "Бразилія/Acre"
+
+#: timezones.h:670
+msgid "Brazil/DeNoronha"
+msgstr "Бразилія/DeNoronha"
+
+#: timezones.h:671
+msgid "Brazil/East"
+msgstr "Бразилія/Схід"
+
+#: timezones.h:672
+msgid "Brazil/West"
+msgstr "Бразилія/Захід"
+
+#: timezones.h:673
+msgid "Canada/Atlantic"
+msgstr "Канада/Атлантика"
+
+#: timezones.h:674
+msgid "Canada/Central"
+msgstr "Канада/Центральна частина"
+
+#: timezones.h:675
+msgid "Canada/Eastern"
+msgstr "Канада/Східна частина"
+
+#: timezones.h:676
+msgid "Canada/East-Saskatchewan"
+msgstr "Канада/East-Saskatchewan"
+
+#: timezones.h:677
+msgid "Canada/Mountain"
+msgstr "Канада/Mountain"
+
+#: timezones.h:678
+msgid "Canada/Newfoundland"
+msgstr "Канада/Newfoundland"
+
+#: timezones.h:679
+msgid "Canada/Pacific"
+msgstr "Канада/Pacific"
+
+#: timezones.h:680
+msgid "Canada/Saskatchewan"
+msgstr "Канада/Саскачевань"
+
+#: timezones.h:681
+msgid "Canada/Yukon"
+msgstr "Канада/Юкон"
+
+#: timezones.h:682
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:683
+msgid "Chile/Continental"
+msgstr "Chile/Continental"
+
+#: timezones.h:684
+msgid "Chile/EasterIsland"
+msgstr "Chile/EasterIsland"
+
+#: timezones.h:685
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:686
+msgid "Cuba"
+msgstr "Куба"
+
+#: timezones.h:687
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:688
+msgid "Egypt"
+msgstr "Єгипет"
+
+#: timezones.h:689
+msgid "Eire"
+msgstr "Eire"
+
+#: timezones.h:690
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:691
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:692
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:693
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:694
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:695
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:696
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:697
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:698
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:699
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:700
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:701
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:702
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:703
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:704
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:705
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:706
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:707
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:708
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:709
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:710
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:711
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:712
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:713
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:714
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:715
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:716
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:717
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:718
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:719
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:720
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:721
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:722
+msgid "Etc/Greenwich"
+msgstr "Etc/Грінвич"
+
+#: timezones.h:723
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:724
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:725
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:726
+msgid "Etc/Zulu"
+msgstr "Etc/Зулу"
+
+#: timezones.h:727
+msgid "Europe/Amsterdam"
+msgstr "Європа/Амстердам"
+
+#: timezones.h:728
+msgid "Europe/Andorra"
+msgstr "Європа/Андорра"
+
+#: timezones.h:729
+msgid "Europe/Athens"
+msgstr "Європа/Афіни"
+
+#: timezones.h:730
+msgid "Europe/Belfast"
+msgstr "Європа/Белфаст"
+
+#: timezones.h:731
+msgid "Europe/Belgrade"
+msgstr "Європа/Белград"
+
+#: timezones.h:732
+msgid "Europe/Berlin"
+msgstr "Європа/Берлін"
+
+#: timezones.h:733
+msgid "Europe/Bratislava"
+msgstr "Європа/Братислава"
+
+#: timezones.h:734
+msgid "Europe/Brussels"
+msgstr "Європа/Брюссель"
+
+#: timezones.h:735
+msgid "Europe/Bucharest"
+msgstr "Європа/Бухарест"
+
+#: timezones.h:736
+msgid "Europe/Budapest"
+msgstr "Європа/Будапешт"
+
+#: timezones.h:737
+msgid "Europe/Chisinau"
+msgstr "Європа/Кишинів"
+
+#: timezones.h:738
+msgid "Europe/Copenhagen"
+msgstr "Європа/Копенгаген"
+
+#: timezones.h:739
+msgid "Europe/Dublin"
+msgstr "Європа/Дублін"
+
+#: timezones.h:740
+msgid "Europe/Gibraltar"
+msgstr "Європа/Гібралтар"
+
+#: timezones.h:741
+msgid "Europe/Guernsey"
+msgstr "Європа/Гернси"
+
+#: timezones.h:742
+msgid "Europe/Helsinki"
+msgstr "Європа/Хельсінкі"
+
+#: timezones.h:743
+msgid "Europe/Isle_of_Man"
+msgstr "Європа/Острів_Мен"
+
+#: timezones.h:744
+msgid "Europe/Istanbul"
+msgstr "Європа/Стамбул"
+
+#: timezones.h:745
+msgid "Europe/Jersey"
+msgstr "Європа/Джерсі"
+
+#: timezones.h:746
+msgid "Europe/Kaliningrad"
+msgstr "Європа/Калінінград"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:748
+msgid "Moscow-01 - Kaliningrad"
+msgstr "Москва-01 - Калінінград"
+
+#: timezones.h:749
+msgid "Europe/Kiev"
+msgstr "Європа/Київ"
+
+#: timezones.h:752
+msgid "Europe/Lisbon"
+msgstr "Європа/Лісабон"
+
+#: timezones.h:755
+msgid "Europe/Ljubljana"
+msgstr "Європа/Любляна"
+
+#: timezones.h:756
+msgid "Europe/London"
+msgstr "Європа/Лондон"
+
+#: timezones.h:757
+msgid "Europe/Luxembourg"
+msgstr "Європа/Люксембург"
+
+#: timezones.h:758
+msgid "Europe/Madrid"
+msgstr "Європа/Мадрид"
+
+#: timezones.h:761
+msgid "Europe/Malta"
+msgstr "Європа/Мальта"
+
+#: timezones.h:762
+msgid "Europe/Mariehamn"
+msgstr "Європа/Mariehamn"
+
+#: timezones.h:763
+msgid "Europe/Minsk"
+msgstr "Європа/Мінськ"
+
+#: timezones.h:764
+msgid "Europe/Monaco"
+msgstr "Європа/Монако"
+
+#: timezones.h:765
+msgid "Europe/Moscow"
+msgstr "Європа/Москва"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:767
+msgid "Moscow+00 - west Russia"
+msgstr "Москва+00 - Східна частина Россії"
+
+#: timezones.h:768
+msgid "Europe/Nicosia"
+msgstr "Європа/Нікосія"
+
+#: timezones.h:769
+msgid "Europe/Oslo"
+msgstr "Європа/Осло"
+
+#: timezones.h:770
+msgid "Europe/Paris"
+msgstr "Європа/Париж"
+
+#: timezones.h:771
+msgid "Europe/Podgorica"
+msgstr "Європа/Подгориця"
+
+#: timezones.h:772
+msgid "Europe/Prague"
+msgstr "Європа/Прага"
+
+#: timezones.h:773
+msgid "Europe/Riga"
+msgstr "Європа/Рига"
+
+#: timezones.h:774
+msgid "Europe/Rome"
+msgstr "Європа/Рим"
+
+#: timezones.h:775
+msgid "Europe/Samara"
+msgstr "Європа/Самара"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:777
+msgid "Moscow - Samara, Udmurtia"
+msgstr "Москва — Самара, Удмуртія"
+
+#: timezones.h:778
+msgid "Europe/San_Marino"
+msgstr "Європа/Сан Мартіно"
+
+#: timezones.h:779
+msgid "Europe/Sarajevo"
+msgstr "Європа/Сараєво"
+
+#: timezones.h:780
+msgid "Europe/Simferopol"
+msgstr "Європа/Сімферополь"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:782
+msgid "central Crimea"
+msgstr "Центральний Крим"
+
+#: timezones.h:783
+msgid "Europe/Skopje"
+msgstr "Європа/Скопьє"
+
+#: timezones.h:784
+msgid "Europe/Sofia"
+msgstr "Європа/Софія"
+
+#: timezones.h:785
+msgid "Europe/Stockholm"
+msgstr "Європа/Стокгольм"
+
+#: timezones.h:786
+msgid "Europe/Tallinn"
+msgstr "Європа/Таллін"
+
+#: timezones.h:787
+msgid "Europe/Tirane"
+msgstr "Європа/Тирана"
+
+#: timezones.h:788
+msgid "Europe/Tiraspol"
+msgstr "Європа/Тирасполь"
+
+#: timezones.h:789
+msgid "Europe/Uzhgorod"
+msgstr "Європа/Ужгород"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:791
+msgid "Ruthenia"
+msgstr "Зах.Україна"
+
+#: timezones.h:792
+msgid "Europe/Vaduz"
+msgstr "Європа/Вадуц"
+
+#: timezones.h:793
+msgid "Europe/Vatican"
+msgstr "Європа/Ватикан"
+
+#: timezones.h:794
+msgid "Europe/Vienna"
+msgstr "Європа/Вєна"
+
+#: timezones.h:795
+msgid "Europe/Vilnius"
+msgstr "Європа/Вільнюс"
+
+#: timezones.h:796
+msgid "Europe/Volgograd"
+msgstr "Європа/Волгоград"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:798
+msgid "Moscow+00 - Caspian Sea"
+msgstr "Москва+00 - Каспійське море"
+
+#: timezones.h:799
+msgid "Europe/Warsaw"
+msgstr "Європа/Варшава"
+
+#: timezones.h:800
+msgid "Europe/Zagreb"
+msgstr "Європа/Загреб"
+
+#: timezones.h:801
+msgid "Europe/Zaporozhye"
+msgstr "Європа/Запоріжжя"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:803
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "Запоріжжя, Луганськ"
+
+#: timezones.h:804
+msgid "Europe/Zurich"
+msgstr "Європа/Цюріх"
+
+#: timezones.h:805
+msgid "Factory"
+msgstr "Factory"
+
+#: timezones.h:806
+msgid "GB"
+msgstr "Британія"
+
+#: timezones.h:807
+msgid "GB-Eire"
+msgstr "GB-Eire"
+
+#: timezones.h:808
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:809
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:810
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:811
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:812
+msgid "Greenwich"
+msgstr "Грінвіч"
+
+#: timezones.h:813
+msgid "Hongkong"
+msgstr "Гонг-Конг"
+
+#: timezones.h:814
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:815
+msgid "Iceland"
+msgstr "Ісландія"
+
+#: timezones.h:816
+msgid "Indian/Antananarivo"
+msgstr "Індійський океан/Antananarivo"
+
+#: timezones.h:817
+msgid "Indian/Chagos"
+msgstr "Індійський океан/Chagos"
+
+#: timezones.h:818
+msgid "Indian/Christmas"
+msgstr "Індійський океан/Christmas"
+
+#: timezones.h:819
+msgid "Indian/Cocos"
+msgstr "Індійський океан/Cocos"
+
+#: timezones.h:820
+msgid "Indian/Comoro"
+msgstr "Індійський океан/Comoro"
+
+#: timezones.h:821
+msgid "Indian/Kerguelen"
+msgstr "Індійський океан/Kerguelen"
+
+#: timezones.h:822
+msgid "Indian/Mahe"
+msgstr "Індійський океан/Mahe"
+
+#: timezones.h:823
+msgid "Indian/Maldives"
+msgstr "Індійський океан/Мальдівські о-ви"
+
+#: timezones.h:824
+msgid "Indian/Mauritius"
+msgstr "Індійський океан/Mauritius"
+
+#: timezones.h:825
+msgid "Indian/Mayotte"
+msgstr "Індійський океан/Mayotte"
+
+#: timezones.h:826
+msgid "Indian/Reunion"
+msgstr "Індійський океан/Reunion"
+
+#: timezones.h:827
+msgid "Iran"
+msgstr "Іран"
+
+#: timezones.h:828
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:829
+msgid "Israel"
+msgstr "Ізраїль"
+
+#: timezones.h:830
+msgid "Jamaica"
+msgstr "Ямайка"
+
+#: timezones.h:831
+msgid "Japan"
+msgstr "Японія"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:832 timezones.h:885
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:833
+msgid "Libya"
+msgstr "Лівія"
+
+#: timezones.h:834
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:835
+msgid "Mexico/BajaNorte"
+msgstr "Мексика/BajaNorte"
+
+#: timezones.h:836
+msgid "Mexico/BajaSur"
+msgstr "Мексика/BajaSur"
+
+#: timezones.h:837
+msgid "Mexico/General"
+msgstr "Мексика/General"
+
+#: timezones.h:838
+msgid "Mideast/Riyadh87"
+msgstr "Mideast/Riyadh87"
+
+#: timezones.h:839
+msgid "Mideast/Riyadh88"
+msgstr "Mideast/Riyadh88"
+
+#: timezones.h:840
+msgid "Mideast/Riyadh89"
+msgstr "Mideast/Riyadh89"
+
+#: timezones.h:841
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:842
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:843
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:844
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:845
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:846
+msgid "Pacific/Apia"
+msgstr "Тихий океан/Apia"
+
+#: timezones.h:847
+msgid "Pacific/Auckland"
+msgstr "Тихий океан/Auckland"
+
+#: timezones.h:850
+msgid "Pacific/Chatham"
+msgstr "Тихий океан/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:852
+msgid "Chatham Islands"
+msgstr "Чатем, острови"
+
+#: timezones.h:853
+msgid "Pacific/Easter"
+msgstr "Тихий океан/Острів Пасхи"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:855
+msgid "Easter Island & Sala y Gomez"
+msgstr "Острів Пасхи та Сала-і-Гомес"
+
+#: timezones.h:856
+msgid "Pacific/Efate"
+msgstr "Тихий океан/Efate"
+
+#: timezones.h:857
+msgid "Pacific/Enderbury"
+msgstr "Тихий океан/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:859
+msgid "Phoenix Islands"
+msgstr "Фенікс, острови"
+
+#: timezones.h:860
+msgid "Pacific/Fakaofo"
+msgstr "Тихий океан/Fakaofo"
+
+#: timezones.h:861
+msgid "Pacific/Fiji"
+msgstr "Тихий океан/Fiji"
+
+#: timezones.h:862
+msgid "Pacific/Funafuti"
+msgstr "Тихий океан/Funafuti"
+
+#: timezones.h:863
+msgid "Pacific/Galapagos"
+msgstr "Тихий океан/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:865
+msgid "Galapagos Islands"
+msgstr "Галапагоські острови"
+
+#: timezones.h:866
+msgid "Pacific/Gambier"
+msgstr "Тихий океан/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:868
+msgid "Gambier Islands"
+msgstr "Острови Гамб'є"
+
+#: timezones.h:869
+msgid "Pacific/Guadalcanal"
+msgstr "Тихий океан/Guadalcanal"
+
+#: timezones.h:870
+msgid "Pacific/Guam"
+msgstr "Тихий океан/Guam"
+
+#: timezones.h:871
+msgid "Pacific/Honolulu"
+msgstr "Тихий океан/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:873
+msgid "Hawaii"
+msgstr "Гаваї"
+
+#: timezones.h:874
+msgid "Pacific/Johnston"
+msgstr "Тихий океан/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:876
+msgid "Johnston Atoll"
+msgstr "Атол Джонстон"
+
+#: timezones.h:877
+msgid "Pacific/Kiritimati"
+msgstr "Тихий океан/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:879
+msgid "Line Islands"
+msgstr "Лайн, острови"
+
+#: timezones.h:880
+msgid "Pacific/Kosrae"
+msgstr "Тихий океан/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:882
+msgid "Kosrae"
+msgstr "Косрае"
+
+#: timezones.h:883
+msgid "Pacific/Kwajalein"
+msgstr "Тихий океан/Kwajalein"
+
+#: timezones.h:886
+msgid "Pacific/Majuro"
+msgstr "Тихий океан/Majuro"
+
+#: timezones.h:889
+msgid "Pacific/Marquesas"
+msgstr "Тихий океан/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:891
+msgid "Marquesas Islands"
+msgstr "Маркізські острови"
+
+#: timezones.h:892
+msgid "Pacific/Midway"
+msgstr "Тихий океан/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:894
+msgid "Midway Islands"
+msgstr "Мідуей, острови"
+
+#: timezones.h:895
+msgid "Pacific/Nauru"
+msgstr "Тихий океан/Nauru"
+
+#: timezones.h:896
+msgid "Pacific/Niue"
+msgstr "Тихий океан/Niue"
+
+#: timezones.h:897
+msgid "Pacific/Norfolk"
+msgstr "Тихий океан/Norfolk"
+
+#: timezones.h:898
+msgid "Pacific/Noumea"
+msgstr "Тихий океан/Noumea"
+
+#: timezones.h:899
+msgid "Pacific/Pago_Pago"
+msgstr "Тихий океан/Pago_Pago"
+
+#: timezones.h:900
+msgid "Pacific/Palau"
+msgstr "Тихий океан/Palau"
+
+#: timezones.h:901
+msgid "Pacific/Pitcairn"
+msgstr "Тихий океан/Pitcairn"
+
+#: timezones.h:902
+msgid "Pacific/Ponape"
+msgstr "Тихий океан/Ponape"
+
+#. comment for time zone Pacific/Ponape
+#: timezones.h:904
+msgid "Ponape (Pohnpei)"
+msgstr "Понапе (Понпеї)"
+
+#: timezones.h:905
+msgid "Pacific/Port_Moresby"
+msgstr "Тихий океан/Port_Moresby"
+
+#: timezones.h:906
+msgid "Pacific/Rarotonga"
+msgstr "Тихий океан/Rarotonga"
+
+#: timezones.h:907
+msgid "Pacific/Saipan"
+msgstr "Тихий океан/Saipan"
+
+#: timezones.h:908
+msgid "Pacific/Samoa"
+msgstr "Тихий океан/Samoa"
+
+#: timezones.h:909
+msgid "Pacific/Tahiti"
+msgstr "Тихий океан/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:911
+msgid "Society Islands"
+msgstr "Острови Спільноти"
+
+#: timezones.h:912
+msgid "Pacific/Tarawa"
+msgstr "Тихий океан/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:914
+msgid "Gilbert Islands"
+msgstr "Гільберта, острови"
+
+#: timezones.h:915
+msgid "Pacific/Tongatapu"
+msgstr "Тихий океан/Tongatapu"
+
+#: timezones.h:916
+msgid "Pacific/Truk"
+msgstr "Тихий океан/Truk"
+
+#. comment for time zone Pacific/Truk
+#: timezones.h:918
+msgid "Truk (Chuuk) and Yap"
+msgstr "Трук та Яп"
+
+#: timezones.h:919
+msgid "Pacific/Wake"
+msgstr "Тихий океан/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:921
+msgid "Wake Island"
+msgstr "Уейк, острів"
+
+#: timezones.h:922
+msgid "Pacific/Wallis"
+msgstr "Тихий океан/Wallis"
+
+#: timezones.h:923
+msgid "Pacific/Yap"
+msgstr "Тихий океан/Yap"
+
+#: timezones.h:924
+msgid "Poland"
+msgstr "Польща"
+
+#: timezones.h:925
+msgid "Portugal"
+msgstr "Португалія"
+
+#: timezones.h:926
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:927
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:928
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:929
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:930
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:931
+msgid "Singapore"
+msgstr "Сінгапур"
+
+#: timezones.h:932
+msgid "Turkey"
+msgstr "Туреччина"
+
+#: timezones.h:933
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:934
+msgid "Universal"
+msgstr "Universal"
+
+#: timezones.h:935
+msgid "US/Alaska"
+msgstr "США/Аляска"
+
+#: timezones.h:936
+msgid "US/Aleutian"
+msgstr "США/Aleutian"
+
+#: timezones.h:937
+msgid "US/Arizona"
+msgstr "США/Арізона"
+
+#: timezones.h:938
+msgid "US/Central"
+msgstr "США/Центральна частина"
+
+#: timezones.h:939
+msgid "US/Eastern"
+msgstr "США/Східна частина"
+
+#: timezones.h:940
+msgid "US/East-Indiana"
+msgstr "США/Східна-Індіана"
+
+#: timezones.h:941
+msgid "US/Hawaii"
+msgstr "США/Гаваї"
+
+#: timezones.h:942
+msgid "US/Indiana-Starke"
+msgstr "США/Індіана-Старкі"
+
+#: timezones.h:943
+msgid "US/Michigan"
+msgstr "США/Мічіган"
+
+#: timezones.h:944
+msgid "US/Mountain"
+msgstr "США/Mountain"
+
+#: timezones.h:945
+msgid "US/Pacific"
+msgstr "США/Тихий_океан"
+
+#: timezones.h:946
+msgid "US/Samoa"
+msgstr "США/Самоа"
+
+#: timezones.h:947
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:948
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:949
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:950
+msgid "Zulu"
+msgstr "Зулу"
+
diff --git a/panels/datetime/po-timezones/ur.po b/panels/datetime/po-timezones/ur.po
new file mode 100644
index 0000000..a5afce2
--- /dev/null
+++ b/panels/datetime/po-timezones/ur.po
@@ -0,0 +1,3237 @@
+# Urdu translations for PACKAGE package.
+# Copyright (C) 2004 THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# Automatically generated, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2002-04-12 17:04-0400\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ASCII\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr ""
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr ""
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr ""
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr ""
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr ""
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr ""
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr ""
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr ""
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr ""
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr ""
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr ""
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr ""
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr ""
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr ""
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr ""
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr ""
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr ""
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr ""
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr ""
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr ""
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr ""
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr ""
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr ""
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr ""
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr ""
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr ""
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr ""
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr ""
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr ""
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr ""
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr ""
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr ""
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr ""
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr ""
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr ""
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr ""
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr ""
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr ""
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr ""
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr ""
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr ""
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr ""
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr ""
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr ""
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr ""
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr ""
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr ""
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr ""
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr ""
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr ""
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr ""
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr ""
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr ""
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr ""
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr ""
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr ""
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr ""
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr ""
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr ""
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr ""
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr ""
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr ""
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr ""
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr ""
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr ""
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr ""
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr ""
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr ""
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr ""
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr ""
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr ""
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr ""
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr ""
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr ""
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr ""
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr ""
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr ""
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr ""
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr ""
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr ""
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr ""
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr ""
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr ""
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr ""
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr ""
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr ""
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr ""
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr ""
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr ""
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr ""
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr ""
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr ""
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr ""
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr ""
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr ""
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr ""
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr ""
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr ""
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr ""
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr ""
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr ""
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr ""
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr ""
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr ""
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr ""
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr ""
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr ""
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr ""
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr ""
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr ""
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr ""
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr ""
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr ""
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr ""
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr ""
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr ""
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr ""
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr ""
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr ""
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr ""
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr ""
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr ""
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr ""
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr ""
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr ""
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr ""
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr ""
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr ""
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr ""
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr ""
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr ""
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr ""
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr ""
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr ""
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr ""
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr ""
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr ""
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr ""
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr ""
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr ""
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr ""
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr ""
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr ""
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr ""
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr ""
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr ""
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr ""
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr ""
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr ""
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr ""
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr ""
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr ""
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr ""
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr ""
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr ""
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr ""
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr ""
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr ""
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr ""
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr ""
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr ""
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr ""
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr ""
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr ""
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr ""
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr ""
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr ""
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr ""
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr ""
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr ""
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr ""
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr ""
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr ""
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr ""
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr ""
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr ""
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr ""
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr ""
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr ""
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr ""
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr ""
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr ""
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr ""
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr ""
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr ""
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr ""
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr ""
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr ""
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr ""
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr ""
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr ""
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr ""
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr ""
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr ""
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr ""
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr ""
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr ""
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr ""
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr ""
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr ""
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr ""
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr ""
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr ""
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr ""
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr ""
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr ""
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr ""
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr ""
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr ""
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr ""
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr ""
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr ""
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr ""
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr ""
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr ""
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr ""
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr ""
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr ""
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr ""
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr ""
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr ""
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr ""
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr ""
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr ""
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr ""
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr ""
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr ""
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr ""
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr ""
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr ""
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr ""
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr ""
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr ""
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr ""
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr ""
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr ""
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr ""
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr ""
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr ""
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr ""
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr ""
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr ""
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr ""
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr ""
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr ""
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr ""
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr ""
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr ""
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr ""
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr ""
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr ""
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr ""
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr ""
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr ""
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr ""
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr ""
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr ""
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr ""
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr ""
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr ""
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr ""
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr ""
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr ""
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr ""
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr ""
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr ""
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr ""
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr ""
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr ""
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr ""
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr ""
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr ""
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr ""
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr ""
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr ""
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr ""
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr ""
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr ""
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr ""
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr ""
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr ""
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr ""
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr ""
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr ""
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr ""
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr ""
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr ""
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr ""
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr ""
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr ""
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr ""
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr ""
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr ""
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr ""
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr ""
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr ""
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr ""
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr ""
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr ""
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr ""
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr ""
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr ""
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr ""
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr ""
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr ""
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr ""
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr ""
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr ""
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr ""
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr ""
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr ""
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr ""
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr ""
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr ""
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr ""
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr ""
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr ""
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr ""
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr ""
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr ""
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr ""
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr ""
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr ""
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr ""
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr ""
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr ""
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr ""
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr ""
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr ""
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr ""
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr ""
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr ""
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr ""
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr ""
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr ""
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr ""
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr ""
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr ""
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr ""
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr ""
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr ""
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr ""
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr ""
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr ""
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr ""
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr ""
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr ""
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr ""
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr ""
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr ""
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr ""
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr ""
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr ""
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr ""
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr ""
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr ""
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr ""
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr ""
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr ""
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr ""
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr ""
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr ""
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr ""
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr ""
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr ""
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr ""
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr ""
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr ""
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr ""
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr ""
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr ""
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr ""
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr ""
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr ""
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr ""
+
+#: timezones.h:685
+msgid "CET"
+msgstr ""
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr ""
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr ""
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr ""
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr ""
+
+#: timezones.h:690
+msgid "EET"
+msgstr ""
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr ""
+
+#: timezones.h:692
+msgid "Eire"
+msgstr ""
+
+#: timezones.h:693
+msgid "EST"
+msgstr ""
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr ""
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr ""
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr ""
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr ""
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr ""
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr ""
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr ""
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr ""
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr ""
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr ""
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr ""
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr ""
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr ""
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr ""
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr ""
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr ""
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr ""
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr ""
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr ""
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr ""
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr ""
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr ""
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr ""
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr ""
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr ""
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr ""
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr ""
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr ""
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr ""
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr ""
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr ""
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr ""
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr ""
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr ""
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr ""
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr ""
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr ""
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr ""
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr ""
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr ""
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr ""
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr ""
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr ""
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr ""
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr ""
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr ""
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr ""
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr ""
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr ""
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr ""
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr ""
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr ""
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr ""
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr ""
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr ""
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr ""
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr ""
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr ""
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr ""
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr ""
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr ""
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr ""
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr ""
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr ""
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr ""
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr ""
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr ""
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr ""
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr ""
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr ""
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr ""
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr ""
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr ""
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr ""
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr ""
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr ""
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr ""
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr ""
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr ""
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr ""
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr ""
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr ""
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr ""
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr ""
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr ""
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr ""
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr ""
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr ""
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr ""
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr ""
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr ""
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr ""
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr ""
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr ""
+
+#: timezones.h:808
+msgid "Factory"
+msgstr ""
+
+#: timezones.h:809
+msgid "GB"
+msgstr ""
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr ""
+
+#: timezones.h:811
+msgid "GMT"
+msgstr ""
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr ""
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr ""
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr ""
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr ""
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr ""
+
+#: timezones.h:817
+msgid "HST"
+msgstr ""
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr ""
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr ""
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr ""
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr ""
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr ""
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr ""
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr ""
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr ""
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr ""
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr ""
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr ""
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr ""
+
+#: timezones.h:830
+msgid "Iran"
+msgstr ""
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr ""
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr ""
+
+#: timezones.h:834
+msgid "Japan"
+msgstr ""
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr ""
+
+#: timezones.h:836
+msgid "Libya"
+msgstr ""
+
+#: timezones.h:837
+msgid "MET"
+msgstr ""
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr ""
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr ""
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr ""
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr ""
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr ""
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr ""
+
+#: timezones.h:844
+msgid "MST"
+msgstr ""
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr ""
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr ""
+
+#: timezones.h:847
+msgid "NZ"
+msgstr ""
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr ""
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr ""
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr ""
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr ""
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr ""
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr ""
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr ""
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr ""
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr ""
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr ""
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr ""
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr ""
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr ""
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr ""
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr ""
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr ""
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr ""
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr ""
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr ""
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr ""
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr ""
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr ""
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr ""
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr ""
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr ""
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr ""
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr ""
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr ""
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr ""
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr ""
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr ""
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr ""
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr ""
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr ""
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr ""
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr ""
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr ""
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr ""
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr ""
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr ""
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr ""
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr ""
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr ""
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr ""
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr ""
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr ""
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr ""
+
+#: timezones.h:929
+msgid "Poland"
+msgstr ""
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr ""
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr ""
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr ""
+
+#: timezones.h:934
+msgid "ROC"
+msgstr ""
+
+#: timezones.h:935
+msgid "ROK"
+msgstr ""
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr ""
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr ""
+
+#: timezones.h:938
+msgid "UCT"
+msgstr ""
+
+#: timezones.h:939
+msgid "Universal"
+msgstr ""
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr ""
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr ""
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr ""
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr ""
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr ""
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr ""
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr ""
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr ""
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr ""
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr ""
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr ""
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr ""
+
+#: timezones.h:952
+msgid "UTC"
+msgstr ""
+
+#: timezones.h:953
+msgid "WET"
+msgstr ""
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr ""
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr ""
diff --git a/panels/datetime/po-timezones/vi.po b/panels/datetime/po-timezones/vi.po
new file mode 100644
index 0000000..96ee13e
--- /dev/null
+++ b/panels/datetime/po-timezones/vi.po
@@ -0,0 +1,3349 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2002 THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# pclouds <pclouds@gmx.net>, 2002.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: timezones VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2003-07-27 00:05+0700\n"
+"Last-Translator: pclouds <pclouds@gmx.net>\n"
+"Language-Team: GnomeVI <gnomevi-list@lists.sourceforge.net>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "Châu Phi/Abidjan"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "Châu Phi/Accra"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "Châu Phi/Addis_Ababa"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "Châu Phi/Algiers"
+
+#: timezones.h:5
+#, fuzzy
+msgid "Africa/Asmara"
+msgstr "Châu Phi/Asmera"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "Châu Phi/Asmera"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "Châu Phi/Bamako"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "Châu Phi/Bangui"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "Châu Phi/Banjul"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "Châu Phi/Bissau"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "Châu Phi/Blantyre"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "Châu Phi/Brazzaville"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "Châu Phi/Bujumbura"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "Châu Phi/Cairo"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "Châu Phi/Casablanca"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "Châu Phi/Ceuta"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr ""
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "Châu Phi/Conakry"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "Châu Phi/Dakar"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "Châu Phi/Dar_es_Salaam"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "Châu Phi/Djibouti"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "Châu Phi/Douala"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "Châu Phi/El_Aaiun"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "Châu Phi/Freetown"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "Châu Phi/Gaborone"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "Châu Phi/Harare"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "Châu Phi/Johannesburg"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "Châu Phi/Kampala"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "Châu Phi/Khartoum"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "Châu Phi/Kigali"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "Châu Phi/Kinshasa"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "Châu Phi/Lagos"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "Châu Phi/Libreville"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "Châu Phi/Lome"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "Châu Phi/Luanda"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "Châu Phi/Lubumbashi"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr ""
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "Châu Phi/Lusaka"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "Châu Phi/Malabo"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "Châu Phi/Maputo"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "Châu Phi/Maseru"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "Châu Phi/Mbabane"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "Châu Phi/Mogadishu"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "Châu Phi/Monrovia"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "Châu Phi/Nairobi"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "Châu Phi/Ndjamena"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "Châu Phi/Niamey"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "Châu Phi/Nouakchott"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "Châu Phi/Ouagadougou"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "Châu Phi/Porto-Novo"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "Châu Phi/Sao_Tome"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "Châu Phi/Timbuktu"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "Châu Phi/Tripoli"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "Châu Phi/Tunis"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "Châu Phi/Windhoek"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "Châu Mỹ/Adak"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+#, fuzzy
+msgid "Aleutian Islands"
+msgstr "Châu Úc/Queensland"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "Châu Mỹ/Anchorage"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+#, fuzzy
+msgid "Alaska Time"
+msgstr "Mỹ/Alaska"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "Châu Mỹ/Anguilla"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "Châu Mỹ/Antigua"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "Châu Mỹ/Araguaina"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr ""
+
+#: timezones.h:71
+#, fuzzy
+msgid "America/Argentina/Buenos_Aires"
+msgstr "Châu Mỹ/Buenos_Aires"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr ""
+
+#: timezones.h:74
+#, fuzzy
+msgid "America/Argentina/Catamarca"
+msgstr "Châu Mỹ/Catamarca"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr ""
+
+#: timezones.h:77
+#, fuzzy
+msgid "America/Argentina/ComodRivadavia"
+msgstr "Châu Mỹ/Indiana/Indianapolis"
+
+#: timezones.h:78
+#, fuzzy
+msgid "America/Argentina/Cordoba"
+msgstr "Châu Mỹ/Cordoba"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr ""
+
+#: timezones.h:81
+#, fuzzy
+msgid "America/Argentina/Jujuy"
+msgstr "Châu Mỹ/Jujuy"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr ""
+
+#: timezones.h:84
+#, fuzzy
+msgid "America/Argentina/La_Rioja"
+msgstr "Châu Mỹ/Araguaina"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr ""
+
+#: timezones.h:87
+#, fuzzy
+msgid "America/Argentina/Mendoza"
+msgstr "Châu Mỹ/Mendoza"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr ""
+
+#: timezones.h:90
+#, fuzzy
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "Châu Mỹ/Indiana/Marengo"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr ""
+
+#: timezones.h:93
+#, fuzzy
+msgid "America/Argentina/Salta"
+msgstr "Châu Mỹ/Antigua"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr ""
+
+#: timezones.h:96
+#, fuzzy
+msgid "America/Argentina/San_Juan"
+msgstr "Châu Mỹ/Antigua"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr ""
+
+#: timezones.h:99
+#, fuzzy
+msgid "America/Argentina/San_Luis"
+msgstr "Châu Mỹ/Antigua"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr ""
+
+#: timezones.h:102
+#, fuzzy
+msgid "America/Argentina/Tucuman"
+msgstr "Châu Mỹ/Antigua"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr ""
+
+#: timezones.h:105
+#, fuzzy
+msgid "America/Argentina/Ushuaia"
+msgstr "Châu Mỹ/Araguaina"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr ""
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "Châu Mỹ/Aruba"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "Châu Mỹ/Asuncion"
+
+#: timezones.h:110
+#, fuzzy
+msgid "America/Atikokan"
+msgstr "Châu Mỹ/Atka"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr ""
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "Châu Mỹ/Atka"
+
+#: timezones.h:114
+#, fuzzy
+msgid "America/Bahia"
+msgstr "Châu Mỹ/Boa_Vista"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr ""
+
+#: timezones.h:117
+#, fuzzy
+msgid "America/Bahia_Banderas"
+msgstr "Châu Mỹ/Boa_Vista"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr ""
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "Châu Mỹ/Barbados"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "Châu Mỹ/Belem"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr ""
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "Châu Mỹ/Belize"
+
+#: timezones.h:125
+#, fuzzy
+msgid "America/Blanc-Sablon"
+msgstr "Châu Mỹ/Cancun"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr ""
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "Châu Mỹ/Boa_Vista"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr ""
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "Châu Mỹ/Bogota"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "Châu Mỹ/Boise"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr ""
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "Châu Mỹ/Buenos_Aires"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "Châu Mỹ/Cambridge_Bay"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr ""
+
+#: timezones.h:139
+#, fuzzy
+msgid "America/Campo_Grande"
+msgstr "Châu Mỹ/Cayman"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr ""
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "Châu Mỹ/Cancun"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr ""
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "Châu Mỹ/Caracas"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "Châu Mỹ/Catamarca"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "Châu Mỹ/Cayenne"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "Châu Mỹ/Cayman"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "Châu Mỹ/Chicago"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+#, fuzzy
+msgid "Central Time"
+msgstr "Mỹ/Central"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "Châu Mỹ/Chihuahua"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr ""
+
+#: timezones.h:155
+#, fuzzy
+msgid "America/Coral_Harbour"
+msgstr "Châu Mỹ/Curacao"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "Châu Mỹ/Cordoba"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "Châu Mỹ/Costa_Rica"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "Châu Mỹ/Cuiaba"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr ""
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "Châu Mỹ/Curacao"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "Châu Mỹ/Danmarkshavn"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr ""
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "Châu Mỹ/Dawson"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr ""
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "Châu Mỹ/Dawson_Creek"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid ""
+"Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr ""
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "Châu Mỹ/Denver"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+#, fuzzy
+msgid "Mountain Time"
+msgstr "Mỹ/Mountain"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "Châu Mỹ/Detroit"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr ""
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "Châu Mỹ/Dominica"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "Châu Mỹ/Edmonton"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr ""
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "Châu Mỹ/Eirunepe"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr ""
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "Châu Mỹ/El_Salvador"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "Châu Mỹ/Ensenada"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "Châu Mỹ/Fortaleza"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr ""
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "Châu Mỹ/Fort_Wayne"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "Châu Mỹ/Glace_Bay"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr ""
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "Châu Mỹ/Godthab"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr ""
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "Châu Mỹ/Goose_Bay"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr ""
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "Châu Mỹ/Grand_Turk"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "Châu Mỹ/Grenada"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "Châu Mỹ/Guadeloupe"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "Châu Mỹ/Guatemala"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "Châu Mỹ/Guayaquil"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr ""
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "Châu Mỹ/Guyana"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "Châu Mỹ/Halifax"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr ""
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "Châu Mỹ/Havana"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "Châu Mỹ/Hermosillo"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr ""
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "Châu Mỹ/Indiana/Indianapolis"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr ""
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "Châu Mỹ/Indiana/Knox"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr ""
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "Châu Mỹ/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr ""
+
+#: timezones.h:223
+#, fuzzy
+msgid "America/Indiana/Petersburg"
+msgstr "Châu Mỹ/Indiana/Marengo"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr ""
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "Châu Mỹ/Indianapolis"
+
+#: timezones.h:227
+#, fuzzy
+msgid "America/Indiana/Tell_City"
+msgstr "Châu Mỹ/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr ""
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "Châu Mỹ/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr ""
+
+#: timezones.h:233
+#, fuzzy
+msgid "America/Indiana/Vincennes"
+msgstr "Châu Mỹ/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr ""
+
+#: timezones.h:236
+#, fuzzy
+msgid "America/Indiana/Winamac"
+msgstr "Châu Mỹ/Indiana/Vevay"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr ""
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "Châu Mỹ/Inuvik"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr ""
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "Châu Mỹ/Iqaluit"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr ""
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "Châu Mỹ/Jamaica"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "Châu Mỹ/Jujuy"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "Châu Mỹ/Juneau"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr ""
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "Châu Mỹ/Kentucky/Louisville"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+#, fuzzy
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "Châu Mỹ/Kentucky/Louisville"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "Châu Mỹ/Kentucky/Monticello"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr ""
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "Châu Mỹ/Knox_IN"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "Châu Mỹ/La_Paz"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "Châu Mỹ/Lima"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "Châu Mỹ/Los_Angeles"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+#, fuzzy
+msgid "Pacific Time"
+msgstr "Thái Bình Dương/Niue"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "Châu Mỹ/Louisville"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "Châu Mỹ/Maceio"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr ""
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "Châu Mỹ/Managua"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "Châu Mỹ/Manaus"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr ""
+
+#: timezones.h:270
+#, fuzzy
+msgid "America/Marigot"
+msgstr "Châu Mỹ/Maceio"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "Châu Mỹ/Martinique"
+
+#: timezones.h:272
+#, fuzzy
+msgid "America/Matamoros"
+msgstr "Châu Mỹ/Manaus"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid ""
+"US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr ""
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "Châu Mỹ/Mazatlan"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr ""
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "Châu Mỹ/Mendoza"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "Châu Mỹ/Menominee"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr ""
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "Châu Mỹ/Merida"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr ""
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "Châu Mỹ/Mexico_City"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr ""
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "Châu Mỹ/Miquelon"
+
+#: timezones.h:289
+#, fuzzy
+msgid "America/Moncton"
+msgstr "Châu Mỹ/Edmonton"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr ""
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "Châu Mỹ/Monterrey"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr ""
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "Châu Mỹ/Montevideo"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "Châu Mỹ/Montreal"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr ""
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "Châu Mỹ/Montserrat"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "Châu Mỹ/Nassau"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "Châu Mỹ/New_York"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+#, fuzzy
+msgid "Eastern Time"
+msgstr "Mỹ/Eastern"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "Châu Mỹ/Nipigon"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid ""
+"Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr ""
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "Châu Mỹ/Nome"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr ""
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "Châu Mỹ/Noronha"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+#, fuzzy
+msgid "Atlantic islands"
+msgstr "Đại Tây Dương/Canary"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "Châu Mỹ/North_Dakota/Center"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr ""
+
+#: timezones.h:316
+#, fuzzy
+msgid "America/North_Dakota/New_Salem"
+msgstr "Châu Mỹ/North_Dakota/Center"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr ""
+
+#: timezones.h:319
+#, fuzzy
+msgid "America/Ojinaga"
+msgstr "Châu Mỹ/Managua"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr ""
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "Châu Mỹ/Panama"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "Châu Mỹ/Pangnirtung"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr ""
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "Châu Mỹ/Paramaribo"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "Châu Mỹ/Phoenix"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr ""
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "Châu Mỹ/Port-au-Prince"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "Châu Mỹ/Porto_Acre"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "Châu Mỹ/Port_of_Spain"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "Châu Mỹ/Porto_Velho"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr ""
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "Châu Mỹ/Puerto_Rico"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "Châu Mỹ/Rainy_River"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr ""
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "Châu Mỹ/Rankin_Inlet"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr ""
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "Châu Mỹ/Recife"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr ""
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "Châu Mỹ/Regina"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr ""
+
+#: timezones.h:349
+#, fuzzy
+msgid "America/Resolute"
+msgstr "Châu Mỹ/Belem"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr ""
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "Châu Mỹ/Rio_Branco"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr ""
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "Châu Mỹ/Rosario"
+
+#: timezones.h:356
+#, fuzzy
+msgid "America/Santa_Isabel"
+msgstr "Châu Mỹ/Santiago"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr ""
+
+#: timezones.h:359
+#, fuzzy
+msgid "America/Santarem"
+msgstr "Châu Mỹ/Santiago"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr ""
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "Châu Mỹ/Santiago"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "Châu Mỹ/Santo_Domingo"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "Châu Mỹ/Sao_Paulo"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr ""
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "Châu Mỹ/Scoresbysund"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr ""
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "Châu Mỹ/Shiprock"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr ""
+
+#: timezones.h:375
+#, fuzzy
+msgid "America/St_Barthelemy"
+msgstr "Châu Mỹ/Belem"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "Châu Mỹ/St_Johns"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr ""
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "Châu Mỹ/St_Kitts"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "Châu Mỹ/St_Lucia"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "Châu Mỹ/St_Thomas"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "Châu Mỹ/St_Vincent"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "Châu Mỹ/Swift_Current"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr ""
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "Châu Mỹ/Tegucigalpa"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "Châu Mỹ/Thule"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr ""
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "Châu Mỹ/Thunder_Bay"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr ""
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "Châu Mỹ/Tijuana"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr ""
+
+#: timezones.h:396
+#, fuzzy
+msgid "America/Toronto"
+msgstr "Châu Mỹ/Toronto"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr ""
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "Châu Mỹ/Tortola"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "Châu Mỹ/Vancouver"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr ""
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "Châu Mỹ/Virgin"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "Châu Mỹ/Whitehorse"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr ""
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "Châu Mỹ/Winnipeg"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr ""
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "Châu Mỹ/Yakutat"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr ""
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "Châu Mỹ/Yellowknife"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr ""
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr ""
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr ""
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr ""
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr ""
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr ""
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr ""
+
+#: timezones.h:425
+#, fuzzy
+msgid "Antarctica/Macquarie"
+msgstr "Đại Tây Dương/South_Georgia"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr ""
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr ""
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr ""
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr ""
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr ""
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr ""
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr ""
+
+#: timezones.h:437
+#, fuzzy
+msgid "Antarctica/Rothera"
+msgstr "Đại Tây Dương/South_Georgia"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr ""
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr ""
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr ""
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr ""
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr ""
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr ""
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr ""
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr ""
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "Châu Á/Aden"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "Châu Á/Almaty"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "Châu Á/Amman"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "Châu Á/Anadyr"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr ""
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "Châu Á/Aqtau"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr ""
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "Châu Á/Aqtobe"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr ""
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "Châu Á/Ashgabat"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "Châu Á/Ashkhabad"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "Châu Á/Baghdad"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "Châu Á/Bahrain"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "Châu Á/Baku"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "Châu Á/Bangkok"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "Châu Á/Beirut"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "Châu Á/Bishkek"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "Châu Á/Brunei"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "Châu Á/Calcutta"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "Châu Á/Choibalsan"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr ""
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "Châu Á/Chongqing"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr ""
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "Châu Á/Chungking"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "Châu Á/Colombo"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "Châu Á/Dacca"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "Châu Á/Damascus"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "Châu Á/Dhaka"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "Châu Á/Dili"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "Châu Á/Dubai"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "Châu Á/Dushanbe"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "Châu Á/Gaza"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "Châu Á/Harbin"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr ""
+
+#: timezones.h:492
+#, fuzzy
+msgid "Asia/Ho_Chi_Minh"
+msgstr "Châu Á/Chongqing"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "Châu Á/Hồng Kông"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "Châu Á/Hovd"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr ""
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "Châu Á/Irkutsk"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr ""
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "Châu Á/Istanbul"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "Châu Á/Jakarta"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr ""
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "Châu Á/Jayapura"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr ""
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "Châu Á/Jerusalem"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "Châu Á/Kabul"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "Châu Á/Kamchatka"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr ""
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "Châu Á/Karachi"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "Châu Á/Kashgar"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:516
+#, fuzzy
+msgid "Asia/Kathmandu"
+msgstr "Châu Á/Katmandu"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "Châu Á/Katmandu"
+
+#: timezones.h:518
+#, fuzzy
+msgid "Asia/Kolkata"
+msgstr "Châu Á/Jakarta"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "Châu Á/Krasnoyarsk"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr ""
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "Châu Á/Kuala_Lumpur"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr ""
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "Châu Á/Kuching"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr ""
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "Châu Á/Kuwait"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "Châu Á/Macao"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "Châu Á/Macau"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "Châu Á/Magadan"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr ""
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "Châu Á/Makassar"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr ""
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "Châu Á/Manila"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "Châu Á/Muscat"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "Châu Á/Nicosia"
+
+#: timezones.h:540
+#, fuzzy
+msgid "Asia/Novokuznetsk"
+msgstr "Châu Á/Irkutsk"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+#, fuzzy
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "Châu Á/Novosibirsk"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "Châu Á/Novosibirsk"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+#, fuzzy
+msgid "Moscow+03 - Novosibirsk"
+msgstr "Châu Á/Novosibirsk"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "Châu Á/Omsk"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr ""
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "Châu Á/Oral"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr ""
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "Châu Á/Phnom_Penh"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "Châu Á/Pontianak"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr ""
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "Châu Á/Pyongyang"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "Châu Á/Qatar"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "Châu Á/Qyzylorda"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr ""
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "Châu Á/Rangoon"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "Châu Á/Riyadh"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "Châu Á/Riyadh87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "Châu Á/Riyadh88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "Châu Á/Riyadh89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "Châu Á/Sài Gòn"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "Châu Á/Sakhalin"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr ""
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "Châu Á/Samarkand"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr ""
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "Châu Á/Seoul"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "Châu Á/Shanghai"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr ""
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "Châu Á/Singapore"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "Châu Á/Taipei"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "Châu Á/Tashkent"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr ""
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "Châu Á/Tbilisi"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "Châu Á/Tehran"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "Châu Á/Tel_Aviv"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "Châu Á/Thimbu"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "Châu Á/Thimphu"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "Châu Á/Tokyo"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "Châu Á/Ujung_Pandang"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "Châu Á/Ulaanbaatar"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "Châu Á/Ulan_Bator"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "Châu Á/Urumqi"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr ""
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "Châu Á/Vientiane"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "Châu Á/Vladivostok"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr ""
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "Châu Á/Yakutsk"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr ""
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "Châu Á/Yekaterinburg"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr ""
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "Châu Á/Yerevan"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "Đại Tây Dương/Azores"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr ""
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "Đại Tây Dương/Bermuda"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "Đại Tây Dương/Canary"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr ""
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "Đại Tây Dương/Cape_Verde"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "Đại Tây Dương/Faeroe"
+
+#: timezones.h:616
+#, fuzzy
+msgid "Atlantic/Faroe"
+msgstr "Đại Tây Dương/Faeroe"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "Đại Tây Dương/Jan_Mayen"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "Đại Tây Dương/Madeira"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr ""
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "Đại Tây Dương/Reykjavik"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "Đại Tây Dương/South_Georgia"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "Đại Tây Dương/Stanley"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "Đại Tây Dương/St_Helena"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "Châu Úc/ACT"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "Châu Úc/Adelaide"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+#, fuzzy
+msgid "South Australia"
+msgstr "Châu Úc/ACT"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "Châu Úc/Brisbane"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr ""
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "Châu Úc/Broken_Hill"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr ""
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "Châu Úc/Canberra"
+
+#: timezones.h:636
+#, fuzzy
+msgid "Australia/Currie"
+msgstr "Châu Úc/Canberra"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr ""
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "Châu Úc/Darwin"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr ""
+
+#: timezones.h:642
+#, fuzzy
+msgid "Australia/Eucla"
+msgstr "Châu Úc/Queensland"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+#, fuzzy
+msgid "Western Australia - Eucla area"
+msgstr "Châu Úc/Queensland"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "Châu Úc/Hobart"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr ""
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "Châu Úc/LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "Châu Úc/Lindeman"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr ""
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "Châu Úc/Lord_Howe"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr ""
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "Châu Úc/Melbourne"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+#, fuzzy
+msgid "Victoria"
+msgstr "Châu Úc/Victoria"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "Châu Úc/North"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "Châu Úc/NSW"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "Châu Úc/Perth"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr ""
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "Châu Úc/Queensland"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "Châu Úc/South"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "Châu Úc/Sydney"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr ""
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "Châu Úc/Tasmania"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "Châu Úc/Victoria"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "Châu Úc/West"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "Châu Úc/Yancowinna"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "Brazil/Acre"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "Brazil/DeNoronha"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "Brazil/East"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "Brazil/West"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "Canada/Atlantic"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "Canada/Central"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "Canada/Eastern"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "Canada/East-Saskatchewan"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "Canada/Mountain"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "Canada/Newfoundland"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "Canada/Pacific"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "Canada/Saskatchewan"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "Canada/Yukon"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "Chi Lê/Continental"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "Chi Lê/EasterIsland"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "Cuba"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "Ai Cập"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr ""
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/Greenwich"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/Universal"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/Zulu"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "Châu Âu/Amsterdam"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "Châu Âu/Andorra"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "Châu Âu/Athens"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "Châu Âu/Belfast"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "Châu Âu/Belgrade"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "Châu Âu/Berlin"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "Châu Âu/Bratislava"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "Châu Âu/Brussels"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "Châu Âu/Bucharest"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "Châu Âu/Budapest"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "Châu Âu/Chisinau"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "Châu Âu/Copenhagen"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "Châu Âu/Dublin"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "Châu Âu/Gibraltar"
+
+#: timezones.h:744
+#, fuzzy
+msgid "Europe/Guernsey"
+msgstr "Châu Âu/Athens"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "Châu Âu/Helsinki"
+
+#: timezones.h:746
+#, fuzzy
+msgid "Europe/Isle_of_Man"
+msgstr "Châu Âu/Oslo"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "Châu Âu/Istanbul"
+
+#: timezones.h:748
+#, fuzzy
+msgid "Europe/Jersey"
+msgstr "Châu Âu/Paris"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "Châu Âu/Kaliningrad"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr ""
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "Châu Âu/Kiev"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "Châu Âu/Lisbon"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "Châu Âu/Ljubljana"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "Châu Âu/London"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "Châu Âu/Luxembourg"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "Châu Âu/Madrid"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "Châu Âu/Malta"
+
+#: timezones.h:765
+#, fuzzy
+msgid "Europe/Mariehamn"
+msgstr "Châu Âu/Madrid"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "Châu Âu/Minsk"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "Châu Âu/Monaco"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "Châu Âu/Moscow"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr ""
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "Châu Âu/Nicosia"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "Châu Âu/Oslo"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "Châu Âu/Paris"
+
+#: timezones.h:774
+#, fuzzy
+msgid "Europe/Podgorica"
+msgstr "Châu Âu/Andorra"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "Châu Âu/Prague"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "Châu Âu/Riga"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "Châu Âu/Rome"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "Châu Âu/Samara"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr ""
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "Châu Âu/San_Marino"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "Châu Âu/Sarajevo"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "Châu Âu/Simferopol"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr ""
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "Châu Âu/Skopje"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "Châu Âu/Sofia"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "Châu Âu/Stockholm"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "Châu Âu/Tallinn"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "Châu Âu/Tirane"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "Châu Âu/Tiraspol"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "Châu Âu/Uzhgorod"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr ""
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "Châu Âu/Vaduz"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "Châu Âu/Vatican"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "Châu Âu/Vienna"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "Châu Âu/Vilnius"
+
+#: timezones.h:799
+#, fuzzy
+msgid "Europe/Volgograd"
+msgstr "Châu Âu/Belgrade"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr ""
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "Châu Âu/Warsaw"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "Châu Âu/Zagreb"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "Châu Âu/Zaporozhye"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr ""
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "Châu Âu/Zurich"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr ""
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr ""
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "Greenwich"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "Hồng Kông"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr ""
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "Ấn Độ Dương/Antananarivo"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "Ấn Độ Dương/Chagos"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "Ấn Độ Dương/Christmas"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "Ấn Độ Dương/Cocos"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "Ấn Độ Dương/Comoro"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "Ấn Độ Dương/Kerguelen"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "Ấn Độ Dương/Mahe"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "Ấn Độ Dương/Maldives"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "Ấn Độ Dương/Mauritius"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "Ấn Độ Dương/Mayotte"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "Ấn Độ Dương/Reunion"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "Iran"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr ""
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "Israel"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "Jamaica"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "Nhật Bản"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "Kwajalein"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "Li Bi"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "Mê Hi Cô/BajaNorte"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "Mê Hi Cô/BajaSur"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "Mê Hi Cô/General"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "Trung Đông/Riyadh87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "Trung Đông/Riyadh88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "Trung Đông/Riyadh89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "Navajo"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "Thái Bình Dương/Apia"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "Thái Bình Dương/Auckland"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "Thái Bình Dương/Chatham"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+#, fuzzy
+msgid "Chatham Islands"
+msgstr "Chi Lê/EasterIsland"
+
+#: timezones.h:856
+#, fuzzy
+msgid "Pacific/Chuuk"
+msgstr "Thái Bình Dương/Truk"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr ""
+
+#: timezones.h:859
+#, fuzzy
+msgid "Pacific/Easter"
+msgstr "Thái Bình Dương/Easter"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr ""
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "Thái Bình Dương/Efate"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "Thái Bình Dương/Enderbury"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr ""
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "Thái Bình Dương/Fakaofo"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "Thái Bình Dương/Fiji"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "Thái Bình Dương/Funafuti"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "Thái Bình Dương/Galapagos"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr ""
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "Thái Bình Dương/Gambier"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr ""
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "Thái Bình Dương/Guadalcanal"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "Thái Bình Dương/Guam"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "Thái Bình Dương/Honolulu"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+#, fuzzy
+msgid "Hawaii"
+msgstr "Mỹ/Hawaii"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "Thái Bình Dương/Johnston"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr ""
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "Thái Bình Dương/Kiritimati"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr ""
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "Thái Bình Dương/Kosrae"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+#, fuzzy
+msgid "Kosrae"
+msgstr "Israel"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "Thái Bình Dương/Kwajalein"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "Thái Bình Dương/Majuro"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "Thái Bình Dương/Marquesas"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr ""
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "Thái Bình Dương/Midway"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr ""
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "Thái Bình Dương/Nauru"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "Thái Bình Dương/Niue"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "Thái Bình Dương/Norfolk"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "Thái Bình Dương/Noumea"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "Thái Bình Dương/Pago_Pago"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "Thái Bình Dương/Palau"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "Thái Bình Dương/Pitcairn"
+
+#: timezones.h:908
+#, fuzzy
+msgid "Pacific/Pohnpei"
+msgstr "Thái Bình Dương/Ponape"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr ""
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "Thái Bình Dương/Ponape"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "Thái Bình Dương/Port_Moresby"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "Thái Bình Dương/Rarotonga"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "Thái Bình Dương/Saipan"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "Thái Bình Dương/Samoa"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "Thái Bình Dương/Tahiti"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr ""
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "Thái Bình Dương/Tarawa"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+#, fuzzy
+msgid "Gilbert Islands"
+msgstr "Chi Lê/EasterIsland"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "Thái Bình Dương/Tongatapu"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "Thái Bình Dương/Truk"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "Thái Bình Dương/Wake"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr ""
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "Thái Bình Dương/Wallis"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "Thái Bình Dương/Yap"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr ""
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr ""
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr ""
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "Singapore"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr ""
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "Toàn Cầu"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "Mỹ/Alaska"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "Mỹ/Aleutian"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "Mỹ/Arizona"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "Mỹ/Central"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "Mỹ/Eastern"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "Mỹ/East-Indiana"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "Mỹ/Hawaii"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "Mỹ/Indiana-Starke"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "Mỹ/Michigan"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "Mỹ/Mountain"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "Mỹ/Pacific"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "Mỹ/Samoa"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "Zulu"
+
+#, fuzzy
+#~ msgid "US/Pacific-New"
+#~ msgstr "Mỹ/Pacific"
+
+#~ msgid "SystemV/AST4"
+#~ msgstr "SystemV/AST4"
+
+#~ msgid "SystemV/AST4ADT"
+#~ msgstr "SystemV/AST4ADT"
+
+#~ msgid "SystemV/CST6"
+#~ msgstr "SystemV/CST6"
+
+#~ msgid "SystemV/CST6CDT"
+#~ msgstr "SystemV/CST6CDT"
+
+#~ msgid "SystemV/EST5"
+#~ msgstr "SystemV/EST5"
+
+#~ msgid "SystemV/EST5EDT"
+#~ msgstr "SystemV/EST5EDT"
+
+#~ msgid "SystemV/HST10"
+#~ msgstr "SystemV/HST10"
+
+#~ msgid "SystemV/MST7"
+#~ msgstr "SystemV/MST7"
+
+#~ msgid "SystemV/MST7MDT"
+#~ msgstr "SystemV/MST7MDT"
+
+#~ msgid "SystemV/PST8"
+#~ msgstr "SystemV/PST8"
+
+#~ msgid "SystemV/PST8PDT"
+#~ msgstr "SystemV/PST8PDT"
+
+#~ msgid "SystemV/YST9"
+#~ msgstr "SystemV/YST9"
+
+#~ msgid "SystemV/YST9YDT"
+#~ msgstr "SystemV/YST9YDT"
diff --git a/panels/datetime/po-timezones/zh_CN.po b/panels/datetime/po-timezones/zh_CN.po
new file mode 100644
index 0000000..38b053f
--- /dev/null
+++ b/panels/datetime/po-timezones/zh_CN.po
@@ -0,0 +1,3244 @@
+# translation of system-config-date.master-timezones.po to Wei Liu
+# Ben Wu <hpwu@redhat.com>, 2002,2003.
+# Chester Cheng <ccheng@redhat.com>, 2004, 2005, 2006, 2007.
+# Waika Liu <wliu@redhat.com>, 2005.
+# Leah Liu <weliu@redhat.com>, 2005.
+# Walter Cheuk <wwycheuk@netvigator.com>, 2005.
+# Terry Chuang <tchuang@redhat.com>, 2008.
+# Terry Chuang <tchuang@redhat.com>, 2009.
+# pingman <pingman@fedoraproject.org>, 2009.
+# Leah Liu <lliu@redhat.com>, 2010.
+# Huan Chen <chenhuan.gt@gmail.com>, 2010.
+# Copyright (C) 2002 Red Hat Inc.
+msgid ""
+msgstr ""
+"Project-Id-Version: system-config-date.master-timezones\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-12-07 15:19+1000\n"
+"Last-Translator: Leah Liu <lliu@redhat.com>\n"
+"Language-Team: Wei Liu\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: zh_CN\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "非洲/阿比让"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "非洲/阿克拉"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "非洲/亚的斯亚贝巴"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "非洲/阿尔及尔"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "非洲/阿斯马拉"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "非洲/阿斯马拉"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "非洲/巴马科"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "非洲/班吉"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "非洲/班珠"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "非洲/比绍"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "非洲/布兰太尔"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "非洲/布拉扎维"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "非洲/布琼布拉"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "非洲/开罗"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "非洲/卡萨布兰卡"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "非洲/休达"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "休达和梅利利亚"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "非洲/科纳克里"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "非洲/达喀尔"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "非洲/达累斯萨拉姆"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "非洲/吉布提"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "非洲/杜阿拉"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "非洲/阿尤恩"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "非洲/弗里敦"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "非洲/哈博罗内"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "非洲/哈拉雷"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "非洲/约翰内斯堡"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "非洲/坎帕拉"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "非洲/喀土穆"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "非洲/基加利"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "非洲/金沙萨"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "刚果民主共和国西部"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "非洲/拉各斯"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "非洲/利伯维尔"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "非洲/洛美"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "非洲/罗安达"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "非洲/卢本巴希"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "刚果民主共和国东部"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "非洲/卢萨卡"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "非洲/马拉博"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "非洲/马普托"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "非洲/马塞卢"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "非洲/姆巴巴内"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "非洲/摩加迪沙"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "非洲/蒙罗维亚"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "非洲/内罗比"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "非洲/恩贾梅纳"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "非洲/尼亚美"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "非洲/努瓦克肖特"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "非洲/瓦加杜古"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "非洲/波多诺伏"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "非洲/圣多美"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "非洲/通布图"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "非洲/的黎波里"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "非洲/突尼斯"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "非洲/温得和克"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "美洲/阿达克"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "阿留申群岛"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "美洲/安克雷奇"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "阿拉斯加时间"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "美洲/安圭拉"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "美洲/安提瓜"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "美洲/阿拉瓜伊那"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "托坎廷斯"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "美洲/阿根廷/布宜诺斯艾利斯"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "布宜诺斯艾利斯(BA,CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "美洲/阿根廷/卡塔马卡"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "卡塔马卡(CT),丘布特(CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "美洲∕阿根廷∕科莫多罗里瓦达维亚"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "美洲/阿根廷/科尔多瓦"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "大部分地区(CB,CC,CN,ER,FM,MN,SE,SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "美洲/阿根廷/胡惠"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "胡惠(JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "美洲/阿根廷/拉里奥哈"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "拉里奥哈(LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "美洲/阿根廷/门多萨"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "门多萨(MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "美洲∕阿根廷∕里奥加耶戈斯"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "圣克鲁斯(SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "美洲/阿根廷/萨尔塔"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA,LP,NQ,RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "美洲/阿根廷/圣胡安"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "圣胡安(SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "美洲/阿根廷/圣路易斯"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "圣路易斯(SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "美洲/阿根廷/图库曼"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "图库曼(TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "美洲/阿根廷/乌斯怀亚"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "火地岛(TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "美洲/阿鲁巴"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "美洲/阿孙西翁"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "美洲∕阿蒂科肯"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "东部标准时间——阿蒂科肯,安大略和南安普敦岛,纽纳瓦特"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "美洲/阿特卡"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "美洲/巴伊亚"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "巴伊亚"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "美洲/巴伊亚_班德拉斯"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "墨西哥支部时间 - 巴伊亚德班德拉斯 "
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "美洲/巴巴多斯"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "美洲/贝伦"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "阿马帕,巴拉东部"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "美洲/伯利茲"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "美洲∕布朗萨布隆"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "大西洋标准时间——魁北克——下北岸"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "美洲/博阿维斯塔"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "罗赖马"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "美洲/波哥大"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "美洲/博伊西"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "山地时间——爱达荷南部和俄勒冈东部"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "美洲/布宜诺斯艾利斯"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "美洲/剑桥湾"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "山地时间——纽纳瓦特西部"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "美洲/大坎普"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "马托格罗索南部"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "美洲/坎昆"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "中部时间——金塔纳罗奥"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "美洲/加拉加斯"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "美洲/卡塔马卡"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "美洲/卡宴"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "美洲/开曼"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "美洲/芝加哥"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "中部时间"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "美洲/奇瓦瓦"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "墨西哥山地时间——美国边境的奇瓦瓦"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "美洲/科勒尔哈伯(珊瑚港)"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "美洲/科尔多瓦"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "美洲/哥斯达黎加"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "美洲/库亚巴"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "马托格罗索"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "美洲/库拉索岛"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "美洲/丹麦沙文"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "东海岸,斯科斯比松北部"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "美洲/道森"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "太平洋时间——育空北部"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "美洲/道森克里克"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid "Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr "山地标准时间——道生克里克和圣约翰堡,不列颠哥伦比亚"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "美洲/丹佛"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "山地时间"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "美洲/底特律"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "东部时间——密歇根——大部分地区"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "美洲/多米尼加"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "美洲/埃德蒙顿"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "山地时间——艾伯塔,不列颠哥伦比亚东部和萨斯喀彻温西部"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "美洲/埃鲁内佩"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "亚马孙西部"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "美洲/萨尔瓦多"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "美洲/恩塞纳达"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "美洲/福塔莱萨"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "巴西东北部(MA,PI,CE,RN,PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "美洲/韦恩堡"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "美洲/格莱斯湾"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr "大西洋时间——新斯科舍——不遵守DST1966——1971的地方"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "美洲/高特哈"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "大部分地区"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "美洲/古斯湾"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "大西洋时间——拉布拉多——大部分地区"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "美洲/大特克"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "美洲/格林纳达"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "美洲/瓜德卢普"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "美洲/危地马拉"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "美洲/瓜亚基尔"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "大陆"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "美洲/圭亚那"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "美洲/哈利法克斯"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "大西洋时间——新斯科舍(大部分地区),爱德华王子岛"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "美洲/哈瓦那"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "美洲/哈模斯罗"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "山地标准时间——索诺拉"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "美洲/印第安纳/印第安纳波利斯"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "东部时间——印地安纳——大部分地区"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "美洲/印第安纳/诺克斯"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "中部时间——印地安纳——斯塔克县"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "美洲/印第安纳/马伦戈"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "东部时间——印地安那——克劳福德县"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "美洲∕印第安那∕彼得斯堡"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "东部时间——印地安那——派克县"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "美洲/印第安纳波利斯"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "美洲∕印第安纳∕特尔城"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "中部时间——印地安纳——佩里县"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "美洲/印第安那/韦韦"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "东部时间——印地安纳——瑞士县"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "美洲∕印第安纳∕温森斯"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "东部时间——印地安纳——戴维斯,杜波依斯,诺克斯和马丁县"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "美洲∕印第安纳∕威纳马克"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "东部时间——印地安纳——珀拉斯凯县"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "美洲/伊努维克"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "山地时间——西西北区"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "美洲/伊卡卢伊特"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "东部时间——纽纳瓦特东部——大部分地区"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "美洲/牙买加"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "美洲/胡惠"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "美洲/朱诺"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "阿拉斯加时间——阿拉斯加“锅柄”(狭长地带)"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "美洲/肯塔基/路易斯维尔"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "东部时间——肯塔基——路易斯维尔地区"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "美洲/肯塔基/蒙蒂塞洛"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "东部时间——肯塔基——韦恩县"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "美洲∕诺克斯(印第安纳)"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "美洲/拉巴斯"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "美洲/利马"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "美洲/洛杉矶"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "太平洋时间"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "美洲/路易斯维尔"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "美洲/马塞约"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "阿拉戈斯,塞尔希培"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "美洲/马那瓜"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "美洲/马瑙斯"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "亚马逊东部"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "美洲∕马里戈特"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "美洲/马蒂尼克"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "美洲/马塔莫罗斯"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid "US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr "美国中部时间——靠近美国边境的科阿韦拉,杜兰戈,新莱昂,塔毛利帕斯"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "美洲/马萨特兰"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "山地时间——巴哈南部,纳亚里特,锡那罗亚"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "美洲/门多萨"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "美洲/梅诺米尼"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "中部时间——密歇根——迪金森,戈吉比克,艾恩和梅诺米尼县"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "美洲/梅里达"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "中部时间——康佩什,尤卡坦"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "美洲/墨西哥城"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "中部时间——大部分地区"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "美洲/密克隆"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "美洲∕蒙克顿"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "大西洋时间——新不伦瑞克"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "美洲/蒙特雷"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid ""
+"Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from "
+"US border"
+msgstr "墨西哥中部时间——远离美国边境的科阿韦拉,杜兰戈,新莱昂,塔毛利帕斯"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "美洲/蒙特维的亚"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "美洲/蒙特利尔"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "东部时间——魁北克——大部分地区"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "美洲/蒙塞拉特"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "美洲/拿骚"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "美洲/纽约"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "东部时间"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "美洲/尼皮贡"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid "Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr "东部时间——安大略和魁北克——不遵守DST1967——1973的地方"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "美洲/诺姆"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "阿拉斯加时间——阿拉斯加西部"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "美洲/诺罗尼亚"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "大西洋群岛"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "美洲∕北达科他∕中部"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "中部时间——北达科他——奥利弗县"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "美洲∕北达科他∕纽沙伦"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "中部时间——北达科他——莫顿县(曼丹地区除外)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "美洲/奥希纳加"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "美国山地时间——靠近美国边境的奇瓦瓦"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "美洲/巴拿马"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "美洲/庞纳唐"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "东部时间——庞纳唐,纽纳瓦特"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "美洲/帕拉马里博"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "美洲/凤凰城"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "山地标准时间——亚利桑那"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "美洲/太子港"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "美洲∕阿克里港"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "美洲/西班牙港"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "美洲/韦柳港"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "朗多尼亚"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "美洲/波多黎各"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "美洲/雷尼里弗"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "中部时间——雷尼河和弗朗西斯堡,安大略"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "美洲/兰金因莱特"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "中部时间——纽纳瓦特中部"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "美洲/雷西腓"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "伯南布哥"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "美洲/里贾那"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "中部标准时间——萨斯喀彻温——大部分地区"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "美洲∕雷索卢特"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "东部标准时间——雷索卢特,纽纳瓦特"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "美洲/里奥布朗库"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "阿克里"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "美洲/罗萨里奥"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "美国/圣伊莎贝尔"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "墨西哥太平洋地区时间——远离美国边境的下加利福尼亚"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "美国/圣塔伦"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "巴拉西部"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "美洲/圣地亚哥"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "美洲/圣多明戈"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "美洲/圣保罗"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "巴西南部和东南部(GO,DF,MG,ES,RJ,SP,PR,SC,RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "美洲/斯科斯比松"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "斯科斯比松/伊托科尔托米特"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "美洲/希普罗克"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "山地时间——纳瓦霍"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "美洲∕圣巴泰勒米"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "美洲/圣约翰斯"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "纽芬兰时间,包括拉布拉多东南部"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "美洲/圣基茨"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "美洲/圣卢西亚"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "美洲/圣托马斯"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "美洲/圣文森特"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "美洲/斯威夫特卡伦特"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "中部标准时间——萨斯喀彻温——中西部"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "美洲/特古西加尔巴"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "美洲/图勒"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "图勒/皮图菲克"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "美洲/桑德湾"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "东部时间——桑德湾,安大略"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "美洲/提华纳"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "美国太平洋地区时间——靠近美国边境的下加利福尼亚"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "美洲/多伦多"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "东部时间——安大略——大部分地区"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "美洲/托尔托拉"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "美洲/温哥华"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "太平洋时间——不列颠哥伦比亚西部"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "美洲∕维尔京"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "美洲/怀特霍斯"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "太平洋时间——育空南部"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "美洲/温尼伯"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "中部时间——马尼托巴和安大略西部"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "美洲/亚库塔特"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "阿拉斯加时间——阿拉斯加“锅柄”(狭长地带)颈"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "美洲/耶洛奈夫"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "山地时间——西北区中部"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "南极洲/凯西"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "凯西站,贝利半岛"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "南极洲/戴维斯"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "戴维斯站,韦斯特福尔德丘陵"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "南极洲/杜蒙特迪维尔"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "杜蒙特迪维尔站,特雷阿德利"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "南极洲/麦夸里"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "麦夸利岛站,麦夸利岛"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "南极洲/莫森"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "莫森站,霍姆湾"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "南极洲/麦克默多"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "麦克默多站,罗斯岛"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "南极洲/帕默"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "帕默站,安弗斯岛"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "南极洲∕罗瑟拉"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "罗瑟拉站,阿德莱德岛"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "南极洲/南极"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "阿蒙德森——斯科特站,南极"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "南极洲/昭和"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "昭和站,翁古尔岛东部"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "南极洲/东方"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "东方站,南极寒极"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "北极/朗伊尔城"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "亚洲/亚丁"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "亚洲/阿拉木图"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "亚洲/安曼"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "亚洲/阿纳德尔"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "莫斯科+08——白令海"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "亚洲/阿克套"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "阿特劳(阿特劳,古里耶夫),曼格斯套(曼吉斯陶)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "亚洲/阿克托比"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "阿克托比(阿克托别)"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "亚洲/阿什哈巴德"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "亚洲∕阿什哈巴德"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "亚洲/巴格达"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "亚洲/巴林"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "亚洲/巴库"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "亚洲/曼谷"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "亚洲/贝鲁特"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "亚洲/比什凯克"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "亚洲/文莱"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "亚洲/加尔各答"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "亚洲∕乔巴山"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "东方,苏赫巴托尔"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "亚洲∕重庆"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "中国中部——四川,云南,广西,陕西,贵州等。"
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "亚洲∕重庆"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "亚洲/科伦坡"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "亚洲∕达卡"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "亚洲/大马士革"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "亚洲/达卡"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "亚洲/帝力"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "亚洲/迪拜"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "亚洲/杜尚別"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "亚洲/加沙"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "亚洲/哈尔滨"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "黑龙江(漠河除外),吉林"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "亚洲∕胡志明"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "亚洲/香港"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "亚洲/科布多"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "巴彦——乌列盖,戈壁阿尔泰,科布多,乌布苏,扎布汗"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "亚洲/伊尔库次克"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "莫斯科+05——贝加尔湖"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "亚洲/伊斯坦布尔"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "亚洲/雅加达"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "爪哇和苏门答腊"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "亚洲/查亚普拉"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "伊里安查亚和摩鹿加"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "亚洲/耶路撒冷"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "亚洲/喀布尔"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "亚洲/堪察加"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "莫斯科+08——堪察加"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "亚洲/卡拉奇"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "亚洲/喀什"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "西藏和新疆西部"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "亚洲/加德满都"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "亚洲/加德满都"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "亚洲/加尔各答"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "亚洲/克拉斯诺亚尔斯克"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "莫斯科+04——叶尼塞河"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "亚洲/吉隆坡"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "马来西亚半岛"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "亚洲/古晋"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "萨巴赫和萨拉瓦克"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "亚洲/科威特"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "亚洲/澳门"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "亚洲/澳门"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "亚洲/马加丹"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "莫斯科+08——马加丹"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "亚洲∕望加锡"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "婆罗洲东部和南部,苏拉威西,巴厘,努沙登加拉,帝汶西部"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "亚洲/马尼拉"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "亚洲/马斯喀特"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "亚洲/尼科西亚"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "亚洲/新库兹涅茨克"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "莫斯科+03——新库兹涅茨克"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "亚洲/新西伯利亚"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "莫斯科+03——新西伯利亚"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "亚洲/鄂木斯克"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "莫斯科+03——西伯利亚西部"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "亚洲∕奥勒尔"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "哈萨克斯坦西部"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "亚洲/金边"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "亚洲/坤甸"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "婆罗洲西和中部"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "亚洲/平壤"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "亚洲/卡塔尔"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "亚洲∕克孜勒奥尔达"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "克孜勒奥尔达(克孜勒奥尔达)"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "亚洲/仰光"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "亚洲/利雅得"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "亚洲/利雅得87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "亚洲/利雅得88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "亚洲/利雅得89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "亚洲/西贡"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "亚洲∕萨哈林"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "莫斯科+07——萨哈林岛"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "亚洲/撒马尔罕"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "乌兹别克斯坦西部"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "亚洲/首尔"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "亚洲/上海"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "中国东部——北京,广东,上海等。"
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "亚洲/新加坡"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "亚洲/台北"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "亚洲/塔什干"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "乌兹别克斯坦东部"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "亚洲/第比利斯"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "亚洲/德黑兰"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "亚洲∕特拉维夫"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "亚洲/廷布"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "亚洲/廷布"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "亚洲/东京"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "亚洲/乌戎潘当"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "亚洲/乌兰巴托"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "亚洲/乌兰巴托"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "亚洲/乌鲁木齐"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "新疆和西藏大部分地区"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "亚洲/万象"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "亚洲/海参崴"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "莫斯科+07——阿穆尔河"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "亚洲/雅库茨克"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "莫斯科+06——勒拿河"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "亚洲/叶卡杰琳堡"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "莫斯科+02——乌拉尔山脉"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "亚洲/埃里温"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "大西洋/阿索雷斯"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "阿索雷斯"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "大西洋/百慕达"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "大西洋/加那利"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "加那利群岛"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "大西洋/佛得角"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "大西洋/法罗"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "大西洋/法罗"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "大西洋/扬马延"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "大西洋/马德拉"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "马德拉群岛"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "大西洋/雷克雅未克"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "大西洋/南乔治亚"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "大西洋/斯坦利"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "大西洋/圣海伦纳"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "澳洲∕澳大利亚首都地区"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "澳洲∕阿德莱德"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "南澳大利亚"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "澳洲/布里斯班"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "昆士兰——大部分地区"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "澳洲∕布罗肯希尔"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "新南威尔士——扬科维纳"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "澳洲∕堪培拉"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "澳洲∕柯里"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "塔斯马尼亚——金岛"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "澳洲/达尔文"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "北区"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "澳洲/尤克拉"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "澳大利亚西部——尤克拉地区"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "澳洲/霍巴特"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "塔斯马尼亚——大部分地区"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "澳洲∕豪勋爵岛"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "澳洲/林德曼"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "昆士兰——假日群岛"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "澳洲/豪勋爵"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "豪勋爵岛"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "澳洲/墨尔本"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "维多利亚"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "澳洲∕北部"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "澳洲∕新南威尔士"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "澳洲/珀斯"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "澳大利亚西部——大部分地区"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "澳洲/昆士兰"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "澳洲∕南部"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "澳洲/悉尼"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "新南威尔士——大部分地区"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "澳洲∕塔斯马尼亚"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "澳洲∕维多利亚"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "澳洲∕西部"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "澳洲∕扬科维纳"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "巴西∕阿克里"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "巴西∕迪诺罗尼亚"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "巴西∕东部"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "巴西∕西部"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "加拿大∕大西洋沿岸"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "加拿大∕中部"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "加拿大∕东部"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "加拿大∕萨斯喀彻温东部"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "加拿大∕山地"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "加拿大∕纽芬兰"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "加拿大∕太平洋沿岸"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "加拿大∕萨斯喀彻温"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "加拿大∕育空"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET(欧洲中部时间)"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "智利∕大陆"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "智利∕复活节岛"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST(美国中部标准时间)6CDT(美国中部夏令时间)"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "古巴"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET(欧洲东部时间)"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "埃及"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "爱尔兰"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST(美国东部标准时间)"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT(美国东部夏令时间)"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT(格林尼治标准时间)"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/格林尼治时"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT(协调世界时)"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/世界时"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/协调世界时"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/祖鲁"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "欧洲/阿姆斯特丹"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "欧洲/安道尔"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "欧洲/雅典"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "欧洲/贝尔法斯特"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "欧洲/贝尔格莱德"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "欧洲/柏林"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "欧洲/布拉迪斯拉发"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "欧洲/布鲁塞尔"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "欧洲/布加勒斯特"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "欧洲/布达佩斯"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "欧洲/基希讷乌"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "欧洲/哥本哈根"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "欧洲/都柏林"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "欧洲/直布罗陀"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "欧洲∕根西"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "欧洲/赫尔辛基"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "欧洲∕马恩岛"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "欧洲/伊斯坦布尔"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "欧洲∕耶尔赛"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "欧洲/加里宁格勒"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "莫斯科—01——加里宁格勒"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "欧洲/基辅"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "欧洲/里斯本"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "欧洲/卢布尔雅那"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "欧洲/伦敦"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "欧洲/卢森堡"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "欧洲/马德里"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "欧洲/马尔他"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "欧洲∕玛丽港"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "欧洲/明思克"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "欧洲/摩纳哥"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "欧洲/莫斯科"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "莫斯科+00——俄罗斯西部"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "欧洲/尼科西亚"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "欧洲/奥斯陆"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "欧洲/巴黎"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "欧洲/波德戈里察"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "欧洲/布拉格"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "欧洲/里察"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "欧洲/罗马"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "欧洲/萨马拉"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "莫斯科——萨马拉,乌德穆尔特共和国"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "欧洲/圣马力诺"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "欧洲/萨拉热窝"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "欧洲/辛菲罗波尔"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "克里梅中部"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "欧洲/斯科普里"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "欧洲/索非亚"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "欧洲/斯德哥尔摩"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "欧洲/塔林"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "欧洲/地拉那"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "欧洲∕蒂拉斯波尔"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "欧洲/乌日戈罗德"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "罗塞尼亚"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "欧洲/瓦杜兹"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "欧洲/梵蒂冈"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "欧洲/维也纳"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "欧洲/维尔纽斯"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "欧洲∕伏尔加格勒"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "莫斯科+00——里海"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "欧洲/华沙"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "欧洲/萨格勒布"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "欧洲/扎波罗热"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "扎波罗热,卢甘斯克东部/扎波罗热,卢甘斯克东部"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "欧洲/苏黎世"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "工厂"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "英国"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "英国——爱尔兰"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "格林尼治"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "香港"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "HST(美国夏威夷标准时间)"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "冰岛"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "印度洋/安塔那那利佛"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "印度洋/查戈斯"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "印度洋/圣诞"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "印度洋/可可斯"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "印度洋/科摩罗"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "印度洋/凯尔格朗"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "印度洋/马埃"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "印度洋/马尔代夫"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "印度洋/毛里求斯"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "印度洋/马约特"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "印度洋/留尼旺"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "伊朗"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "以色列"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "牙买加"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "日本"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "夸贾莱因"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "利比亚"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET(欧洲中部时间)"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "墨西哥∕下北加州"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "墨西哥∕下南加州"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "墨西哥∕普通地区"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "中东∕利雅德87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "中东∕利雅德88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "中东∕利雅德89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "MST(山地标准时间)"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT(山地夏令时间)"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "纳瓦霍"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "新西兰"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "太平洋/阿皮亚"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "太平洋/奥克兰"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "太平洋/查塔姆"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "查塔姆群岛"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "太平洋/楚克"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "楚克(特鲁克)和雅普"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "太平洋/复活节"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "复活节岛和萨拉戈麦斯"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "太平洋/埃法特"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "太平洋/恩德伯里"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "菲尼克斯群岛"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "太平洋/法考福"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "太平洋/斐济"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "太平洋/富那富提"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "太平洋/加拉帕戈斯"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "加拉帕戈斯群岛"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "太平洋/甘比尔"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "甘比尔群岛"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "太平洋/瓜达尔卡纳尔"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "太平洋/关岛"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "太平洋/火奴鲁鲁(檀香山)"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "夏威夷岛"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "太平洋/约翰斯顿"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "约翰斯顿环礁"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "太平洋/基里马斯岛"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "莱恩群岛"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "太平洋/科斯雷"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "科斯雷岛"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "太平洋/夸贾莱因"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "太平洋/马朱罗岛"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "太平洋/马克萨斯"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "马克萨斯群岛"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "太平洋/中途"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "中途群岛"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "太平洋/瑙鲁"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "太平洋/纽埃"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "太平洋/诺福克岛"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "太平洋/努美阿"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "太平洋/帕果帕果"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "太平洋/帕劳"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "太平洋/皮特凯恩"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "太平洋/波纳佩"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "波纳佩(波纳佩岛)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "太平洋/波纳普"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "太平洋/莫尔兹比港"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "太平洋/拉罗汤加"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "太平洋/塞班"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "太平洋∕萨摩亚"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "太平洋/塔希提岛"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "社会群岛"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "太平洋/塔拉瓦环礁"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "吉尔伯特群岛"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "太平洋/汤加塔布"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "太平洋/特鲁克"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "太平洋/威克"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "威克岛"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "太平洋/瓦利斯"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "太平洋/雅浦"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "波兰"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "葡萄牙"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "PRC"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "ROC"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "ROK"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "新加坡"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "土耳其"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT(协调世界时)"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "全球"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "美国/阿拉斯加"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "美国/阿留申"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "美国/亚利桑纳"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "美国/中部"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "美国/东部"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "美国/东印第安那"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "美国/夏威夷"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "美国/印第安那——斯塔克"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "美国/密歇根"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "美国/山地时间"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "美国/太平洋"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "美国/萨摩亚"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC(协调世界时)"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET(欧洲西部时间)"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "祖鲁"
+
diff --git a/panels/datetime/po-timezones/zh_TW.po b/panels/datetime/po-timezones/zh_TW.po
new file mode 100644
index 0000000..ebad04a
--- /dev/null
+++ b/panels/datetime/po-timezones/zh_TW.po
@@ -0,0 +1,3243 @@
+# translation of system-config-date.master-timezones.po to Traditional Chinese
+# Copyright (C) 2002 Red Hat Inc.
+# This file is distributed under the same license as the x package.
+#
+#
+# Ben Wu <hpwu@redhat.com>, 2002,2003.
+# Chester Cheng <ccheng@redhat.com>, 2004, 2005, 2006, 2007.
+# Waika Liu <wliu@redhat.com>, 2005.
+# Leah Liu <weliu@redhat.com>, 2005.
+# Walter Cheuk <wwycheuk@netvigator.com>, 2005.
+# Terry Chuang <tchuang@redhat.com>, 2008.
+# Terry Chuang <tchuang@redhat.com>, 2009.
+# pingman <pingman@fedoraproject.org>, 2009.
+# Chester Cheng <ccheng@紅帽子>, 2010.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: x \n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-16 14:02+0200\n"
+"PO-Revision-Date: 2010-09-28 00:53+0800\n"
+"Last-Translator: root <root@localdomain>\n"
+"Language-Team: Chinese (traditional) <zh-l10n@linux.org.tw>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: timezones.h:1
+msgid "Africa/Abidjan"
+msgstr "非洲/阿必尚"
+
+#: timezones.h:2
+msgid "Africa/Accra"
+msgstr "非洲/阿克拉"
+
+#: timezones.h:3
+msgid "Africa/Addis_Ababa"
+msgstr "非洲/阿迪斯阿貝巴"
+
+#: timezones.h:4
+msgid "Africa/Algiers"
+msgstr "非洲/阿爾及爾"
+
+#: timezones.h:5
+msgid "Africa/Asmara"
+msgstr "非洲/阿斯馬拉"
+
+#: timezones.h:6
+msgid "Africa/Asmera"
+msgstr "非洲/阿斯馬拉"
+
+#: timezones.h:7
+msgid "Africa/Bamako"
+msgstr "非洲/巴馬科"
+
+#: timezones.h:8
+msgid "Africa/Bangui"
+msgstr "非洲/班基"
+
+#: timezones.h:9
+msgid "Africa/Banjul"
+msgstr "非洲/班竹"
+
+#: timezones.h:10
+msgid "Africa/Bissau"
+msgstr "非洲/比索"
+
+#: timezones.h:11
+msgid "Africa/Blantyre"
+msgstr "非洲/布蘭泰爾"
+
+#: timezones.h:12
+msgid "Africa/Brazzaville"
+msgstr "非洲/布拉薩"
+
+#: timezones.h:13
+msgid "Africa/Bujumbura"
+msgstr "非洲/布瓊布拉"
+
+#: timezones.h:14
+msgid "Africa/Cairo"
+msgstr "非洲/開羅"
+
+#: timezones.h:15
+msgid "Africa/Casablanca"
+msgstr "非洲/卡薩布蘭卡"
+
+#: timezones.h:16
+msgid "Africa/Ceuta"
+msgstr "非洲/休達"
+
+#. comment for time zone Africa/Ceuta
+#: timezones.h:18
+msgid "Ceuta & Melilla"
+msgstr "休達及梅利利亞"
+
+#: timezones.h:19
+msgid "Africa/Conakry"
+msgstr "非洲/科納克里"
+
+#: timezones.h:20
+msgid "Africa/Dakar"
+msgstr "非洲/達喀爾"
+
+#: timezones.h:21
+msgid "Africa/Dar_es_Salaam"
+msgstr "非洲/三蘭港"
+
+#: timezones.h:22
+msgid "Africa/Djibouti"
+msgstr "非洲/吉布地"
+
+#: timezones.h:23
+msgid "Africa/Douala"
+msgstr "非洲/杜瓦拉"
+
+#: timezones.h:24
+msgid "Africa/El_Aaiun"
+msgstr "非洲/艾拉蘊"
+
+#: timezones.h:25
+msgid "Africa/Freetown"
+msgstr "非洲/自由城"
+
+#: timezones.h:26
+msgid "Africa/Gaborone"
+msgstr "非洲/嘉伯帕里"
+
+#: timezones.h:27
+msgid "Africa/Harare"
+msgstr "非洲/哈拉雷"
+
+#: timezones.h:28
+msgid "Africa/Johannesburg"
+msgstr "非洲/約翰尼斯堡"
+
+#: timezones.h:29
+msgid "Africa/Kampala"
+msgstr "非洲/坎帕拉"
+
+#: timezones.h:30
+msgid "Africa/Khartoum"
+msgstr "非洲/喀土穆"
+
+#: timezones.h:31
+msgid "Africa/Kigali"
+msgstr "非洲/奇佳利"
+
+#: timezones.h:32
+msgid "Africa/Kinshasa"
+msgstr "非洲/金夏沙"
+
+#. comment for time zone Africa/Kinshasa
+#: timezones.h:34
+msgid "west Dem. Rep. of Congo"
+msgstr "west Dem. 剛果民主共和國"
+
+#: timezones.h:35
+msgid "Africa/Lagos"
+msgstr "非洲/拉哥斯"
+
+#: timezones.h:36
+msgid "Africa/Libreville"
+msgstr "非洲/自由市"
+
+#: timezones.h:37
+msgid "Africa/Lome"
+msgstr "非洲/洛梅"
+
+#: timezones.h:38
+msgid "Africa/Luanda"
+msgstr "非洲/盧安達"
+
+#: timezones.h:39
+msgid "Africa/Lubumbashi"
+msgstr "非洲/盧本巴希"
+
+#. comment for time zone Africa/Lubumbashi
+#: timezones.h:41
+msgid "east Dem. Rep. of Congo"
+msgstr "east Dem. 剛果民主共和國"
+
+#: timezones.h:42
+msgid "Africa/Lusaka"
+msgstr "非洲/路沙卡"
+
+#: timezones.h:43
+msgid "Africa/Malabo"
+msgstr "非洲/馬拉博"
+
+#: timezones.h:44
+msgid "Africa/Maputo"
+msgstr "非洲/馬普托"
+
+#: timezones.h:45
+msgid "Africa/Maseru"
+msgstr "非洲/馬塞魯"
+
+#: timezones.h:46
+msgid "Africa/Mbabane"
+msgstr "非洲/墨巴本"
+
+#: timezones.h:47
+msgid "Africa/Mogadishu"
+msgstr "非洲/摩加迪休"
+
+#: timezones.h:48
+msgid "Africa/Monrovia"
+msgstr "非洲/蒙羅維亞"
+
+#: timezones.h:49
+msgid "Africa/Nairobi"
+msgstr "非洲/奈羅比"
+
+#: timezones.h:50
+msgid "Africa/Ndjamena"
+msgstr "非洲/恩嘉美納"
+
+#: timezones.h:51
+msgid "Africa/Niamey"
+msgstr "非洲/尼亞美"
+
+#: timezones.h:52
+msgid "Africa/Nouakchott"
+msgstr "非洲/諾克少"
+
+#: timezones.h:53
+msgid "Africa/Ouagadougou"
+msgstr "非洲/瓦加杜古"
+
+#: timezones.h:54
+msgid "Africa/Porto-Novo"
+msgstr "非洲/新港"
+
+#: timezones.h:55
+msgid "Africa/Sao_Tome"
+msgstr "非洲/聖多美"
+
+#: timezones.h:56
+msgid "Africa/Timbuktu"
+msgstr "非洲/堤巴土"
+
+#: timezones.h:57
+msgid "Africa/Tripoli"
+msgstr "非洲/的黎波里"
+
+#: timezones.h:58
+msgid "Africa/Tunis"
+msgstr "非洲/突尼斯"
+
+#: timezones.h:59
+msgid "Africa/Windhoek"
+msgstr "非洲/文德霍克"
+
+#: timezones.h:60
+msgid "America/Adak"
+msgstr "美洲/艾達克"
+
+#. comment for time zone America/Adak
+#: timezones.h:62
+msgid "Aleutian Islands"
+msgstr "阿留申群島"
+
+#: timezones.h:63
+msgid "America/Anchorage"
+msgstr "美洲/安克里治"
+
+#. comment for time zone America/Anchorage
+#: timezones.h:65
+msgid "Alaska Time"
+msgstr "阿拉斯加時區"
+
+#: timezones.h:66
+msgid "America/Anguilla"
+msgstr "美洲/安圭拉"
+
+#: timezones.h:67
+msgid "America/Antigua"
+msgstr "美洲/安堤瓜"
+
+#: timezones.h:68
+msgid "America/Araguaina"
+msgstr "美洲/阿拉瓜因那"
+
+#. comment for time zone America/Araguaina
+#: timezones.h:70
+msgid "Tocantins"
+msgstr "托肯丁斯"
+
+#: timezones.h:71
+msgid "America/Argentina/Buenos_Aires"
+msgstr "美洲/阿根廷/布宜諾斯艾利斯"
+
+#. comment for time zone America/Argentina/Buenos_Aires
+#: timezones.h:73
+msgid "Buenos Aires (BA, CF)"
+msgstr "布埃諾斯艾雷斯(BA,CF)"
+
+#: timezones.h:74
+msgid "America/Argentina/Catamarca"
+msgstr "美洲/阿根廷/卡達馬魯卡"
+
+#. comment for time zone America/Argentina/Catamarca
+#: timezones.h:76
+msgid "Catamarca (CT), Chubut (CH)"
+msgstr "卡塔馬卡省(CT),丘布特省(CH)"
+
+#: timezones.h:77
+msgid "America/Argentina/ComodRivadavia"
+msgstr "美洲∕阿根廷∕科木多洛"
+
+#: timezones.h:78
+msgid "America/Argentina/Cordoba"
+msgstr "美洲/阿根廷/哥多華"
+
+#. comment for time zone America/Argentina/Cordoba
+#: timezones.h:80
+msgid "most locations (CB, CC, CN, ER, FM, MN, SE, SF)"
+msgstr "大部分地區(CB、CC、CN、ER、FM、MN、SE、SF)"
+
+#: timezones.h:81
+msgid "America/Argentina/Jujuy"
+msgstr "美洲/阿根廷/胡胡伊"
+
+#. comment for time zone America/Argentina/Jujuy
+#: timezones.h:83
+msgid "Jujuy (JY)"
+msgstr "夫夫伊(JY)"
+
+#: timezones.h:84
+msgid "America/Argentina/La_Rioja"
+msgstr "美洲/阿根廷/拉裏奧哈"
+
+#. comment for time zone America/Argentina/La_Rioja
+#: timezones.h:86
+msgid "La Rioja (LR)"
+msgstr "拉裡奧哈(LR)"
+
+#: timezones.h:87
+msgid "America/Argentina/Mendoza"
+msgstr "美洲/阿根廷/門多薩"
+
+#. comment for time zone America/Argentina/Mendoza
+#: timezones.h:89
+msgid "Mendoza (MZ)"
+msgstr "曼多薩(MZ)"
+
+#: timezones.h:90
+msgid "America/Argentina/Rio_Gallegos"
+msgstr "美洲∕阿根廷∕里奧加耶戈斯"
+
+#. comment for time zone America/Argentina/Rio_Gallegos
+#: timezones.h:92
+msgid "Santa Cruz (SC)"
+msgstr "聖克魯茲(SC)"
+
+#: timezones.h:93
+msgid "America/Argentina/Salta"
+msgstr "美洲/阿根廷/薩撻省"
+
+#. comment for time zone America/Argentina/Salta
+#: timezones.h:95
+msgid "(SA, LP, NQ, RN)"
+msgstr "(SA、LP、NQ、RN)"
+
+#: timezones.h:96
+msgid "America/Argentina/San_Juan"
+msgstr "美洲/阿根廷/聖胡安"
+
+#. comment for time zone America/Argentina/San_Juan
+#: timezones.h:98
+msgid "San Juan (SJ)"
+msgstr "聖胡安(SJ)"
+
+#: timezones.h:99
+msgid "America/Argentina/San_Luis"
+msgstr "美洲/阿根廷/聖路易士"
+
+#. comment for time zone America/Argentina/San_Luis
+#: timezones.h:101
+msgid "San Luis (SL)"
+msgstr "聖路易士(SL)"
+
+#: timezones.h:102
+msgid "America/Argentina/Tucuman"
+msgstr "美洲/阿根廷/圖庫曼"
+
+#. comment for time zone America/Argentina/Tucuman
+#: timezones.h:104
+msgid "Tucuman (TM)"
+msgstr "圖庫曼(TM)"
+
+#: timezones.h:105
+msgid "America/Argentina/Ushuaia"
+msgstr "美洲/阿根廷/烏斯懷亞"
+
+#. comment for time zone America/Argentina/Ushuaia
+#: timezones.h:107
+msgid "Tierra del Fuego (TF)"
+msgstr "火地島(TF)"
+
+#: timezones.h:108
+msgid "America/Aruba"
+msgstr "美洲/阿盧巴"
+
+#: timezones.h:109
+msgid "America/Asuncion"
+msgstr "美洲/亞松森"
+
+#: timezones.h:110
+msgid "America/Atikokan"
+msgstr "美洲∕阿蒂科肯"
+
+#. comment for time zone America/Atikokan
+#: timezones.h:112
+msgid "Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut"
+msgstr "東部標準時間 - 阿提科坎、安大略以及南安普頓、努那福"
+
+#: timezones.h:113
+msgid "America/Atka"
+msgstr "美洲/阿提卡"
+
+#: timezones.h:114
+msgid "America/Bahia"
+msgstr "美洲/巴伊亞"
+
+#. comment for time zone America/Bahia
+#: timezones.h:116
+msgid "Bahia"
+msgstr "巴伊亞"
+
+#: timezones.h:117
+msgid "America/Bahia_Banderas"
+msgstr "美洲/巴伊亞班德拉斯"
+
+#. comment for time zone America/Bahia_Banderas
+#: timezones.h:119
+msgid "Mexican Central Time - Bahia de Banderas"
+msgstr "墨西哥中央時間 - 巴伊亞班德拉斯"
+
+#: timezones.h:120
+msgid "America/Barbados"
+msgstr "美洲/巴貝多"
+
+#: timezones.h:121
+msgid "America/Belem"
+msgstr "美洲/巴連姆"
+
+#. comment for time zone America/Belem
+#: timezones.h:123
+msgid "Amapa, E Para"
+msgstr "阿瑪帕"
+
+#: timezones.h:124
+msgid "America/Belize"
+msgstr "美洲/貝里斯"
+
+#: timezones.h:125
+msgid "America/Blanc-Sablon"
+msgstr "美洲∕布朗克沙伯倫"
+
+#. comment for time zone America/Blanc-Sablon
+#: timezones.h:127
+msgid "Atlantic Standard Time - Quebec - Lower North Shore"
+msgstr "大西洋標準時間 - 魁北克 - 低北岸"
+
+#: timezones.h:128
+msgid "America/Boa_Vista"
+msgstr "美洲/波亞維斯塔"
+
+#. comment for time zone America/Boa_Vista
+#: timezones.h:130
+msgid "Roraima"
+msgstr "羅賴馬"
+
+#: timezones.h:131
+msgid "America/Bogota"
+msgstr "美洲/波哥大"
+
+#: timezones.h:132
+msgid "America/Boise"
+msgstr "美洲/波伊西"
+
+#. comment for time zone America/Boise
+#: timezones.h:134
+msgid "Mountain Time - south Idaho & east Oregon"
+msgstr "山脈時間 - 南愛達荷與東俄勒岡"
+
+#: timezones.h:135
+msgid "America/Buenos_Aires"
+msgstr "美洲/布宜諾斯艾利斯"
+
+#: timezones.h:136
+msgid "America/Cambridge_Bay"
+msgstr "美洲/劍橋灣"
+
+#. comment for time zone America/Cambridge_Bay
+#: timezones.h:138
+msgid "Mountain Time - west Nunavut"
+msgstr "山脈時間 - 西努那福"
+
+#: timezones.h:139
+msgid "America/Campo_Grande"
+msgstr "美洲/坎普格蘭"
+
+#. comment for time zone America/Campo_Grande
+#: timezones.h:141
+msgid "Mato Grosso do Sul"
+msgstr "馬托格羅索州"
+
+#: timezones.h:142
+msgid "America/Cancun"
+msgstr "美洲/坎庫恩"
+
+#. comment for time zone America/Cancun
+#: timezones.h:144
+msgid "Central Time - Quintana Roo"
+msgstr "中央時間 - 金塔納羅奧"
+
+#: timezones.h:145
+msgid "America/Caracas"
+msgstr "美洲/卡拉卡斯"
+
+#: timezones.h:146
+msgid "America/Catamarca"
+msgstr "美洲/卡它馬爾卡"
+
+#: timezones.h:147
+msgid "America/Cayenne"
+msgstr "美洲/卡宴"
+
+#: timezones.h:148
+msgid "America/Cayman"
+msgstr "美洲/開曼"
+
+#: timezones.h:149
+msgid "America/Chicago"
+msgstr "美洲/芝加哥"
+
+#. comment for time zone America/Chicago
+#: timezones.h:151
+msgid "Central Time"
+msgstr "中央時間"
+
+#: timezones.h:152
+msgid "America/Chihuahua"
+msgstr "美洲/徹瓦瓦"
+
+#. comment for time zone America/Chihuahua
+#: timezones.h:154
+msgid "Mexican Mountain Time - Chihuahua away from US border"
+msgstr "墨西哥山脈時間 - 離美國邊界較遠的奇瓦瓦"
+
+#: timezones.h:155
+msgid "America/Coral_Harbour"
+msgstr "美洲/珊瑚港"
+
+#: timezones.h:156
+msgid "America/Cordoba"
+msgstr "美洲/科多巴"
+
+#: timezones.h:157
+msgid "America/Costa_Rica"
+msgstr "美洲/哥斯大黎加"
+
+#: timezones.h:158
+msgid "America/Cuiaba"
+msgstr "美洲/圭亞巴"
+
+#. comment for time zone America/Cuiaba
+#: timezones.h:160
+msgid "Mato Grosso"
+msgstr "馬托格羅索州"
+
+#: timezones.h:161
+msgid "America/Curacao"
+msgstr "美洲/庫拉桑"
+
+#: timezones.h:162
+msgid "America/Danmarkshavn"
+msgstr "美洲/丹馬沙文"
+
+#. comment for time zone America/Danmarkshavn
+#: timezones.h:164
+msgid "east coast, north of Scoresbysund"
+msgstr "東岸、司廓爾比桑北部"
+
+#: timezones.h:165
+msgid "America/Dawson"
+msgstr "美洲/道森"
+
+#. comment for time zone America/Dawson
+#: timezones.h:167
+msgid "Pacific Time - north Yukon"
+msgstr "太平洋時間 - 育空北部"
+
+#: timezones.h:168
+msgid "America/Dawson_Creek"
+msgstr "美洲/道森克里克"
+
+#. comment for time zone America/Dawson_Creek
+#: timezones.h:170
+msgid "Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia"
+msgstr "山脈標準時間 - 道森克里克以及福聖約翰,英屬哥倫比亞"
+
+#: timezones.h:171
+msgid "America/Denver"
+msgstr "美洲/丹佛"
+
+#. comment for time zone America/Denver
+#: timezones.h:173
+msgid "Mountain Time"
+msgstr "山脈時間"
+
+#: timezones.h:174
+msgid "America/Detroit"
+msgstr "美洲/底特律"
+
+#. comment for time zone America/Detroit
+#: timezones.h:176
+msgid "Eastern Time - Michigan - most locations"
+msgstr "東部時間 - 密西根州 - 大部分地區"
+
+#: timezones.h:177
+msgid "America/Dominica"
+msgstr "美洲/多明尼加"
+
+#: timezones.h:178
+msgid "America/Edmonton"
+msgstr "美洲/艾德蒙頓"
+
+#. comment for time zone America/Edmonton
+#: timezones.h:180
+msgid "Mountain Time - Alberta, east British Columbia & west Saskatchewan"
+msgstr "山脈時間 - 艾伯塔,英屬哥倫比亞東部以及薩克其萬省西部"
+
+#: timezones.h:181
+msgid "America/Eirunepe"
+msgstr "美洲/艾魯內佩"
+
+#. comment for time zone America/Eirunepe
+#: timezones.h:183
+msgid "W Amazonas"
+msgstr "亞馬遜西部"
+
+#: timezones.h:184
+msgid "America/El_Salvador"
+msgstr "美洲/薩爾瓦多"
+
+#: timezones.h:185
+msgid "America/Ensenada"
+msgstr "美洲/恩森那達"
+
+#: timezones.h:186
+msgid "America/Fortaleza"
+msgstr "美洲/福塔雷薩"
+
+#. comment for time zone America/Fortaleza
+#: timezones.h:188
+msgid "NE Brazil (MA, PI, CE, RN, PB)"
+msgstr "巴西東北部(MA、PI、CE、RN、PB)"
+
+#: timezones.h:189
+msgid "America/Fort_Wayne"
+msgstr "美洲/韋恩堡"
+
+#: timezones.h:190
+msgid "America/Glace_Bay"
+msgstr "美洲/葛雷斯灣"
+
+#. comment for time zone America/Glace_Bay
+#: timezones.h:192
+msgid "Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971"
+msgstr "大西洋時間 - 新斯科細亞省 - 未遵照 DST 1966-1971 的地區"
+
+#: timezones.h:193
+msgid "America/Godthab"
+msgstr "美洲/高特哈"
+
+#. comment for time zone America/Godthab
+#. comment for time zone America/Santiago
+#. comment for time zone Asia/Almaty
+#. comment for time zone Asia/Ulaanbaatar
+#. comment for time zone Europe/Kiev
+#. comment for time zone Pacific/Auckland
+#. comment for time zone Pacific/Majuro
+#: timezones.h:195 timezones.h:364 timezones.h:453 timezones.h:591
+#: timezones.h:754 timezones.h:852 timezones.h:894
+msgid "most locations"
+msgstr "大部分地區"
+
+#: timezones.h:196
+msgid "America/Goose_Bay"
+msgstr "美洲/鵝灣"
+
+#. comment for time zone America/Goose_Bay
+#: timezones.h:198
+msgid "Atlantic Time - Labrador - most locations"
+msgstr "大西洋時間 - 拉布多爾 - 大部分地區"
+
+#: timezones.h:199
+msgid "America/Grand_Turk"
+msgstr "美洲/大特克"
+
+#: timezones.h:200
+msgid "America/Grenada"
+msgstr "美洲/格瑞納達"
+
+#: timezones.h:201
+msgid "America/Guadeloupe"
+msgstr "美洲/瓜德洛佩"
+
+#: timezones.h:202
+msgid "America/Guatemala"
+msgstr "美洲/瓜地馬拉"
+
+#: timezones.h:203
+msgid "America/Guayaquil"
+msgstr "美洲/瓜亞基爾"
+
+#. comment for time zone America/Guayaquil
+#. comment for time zone Europe/Lisbon
+#. comment for time zone Europe/Madrid
+#: timezones.h:205 timezones.h:757 timezones.h:763
+msgid "mainland"
+msgstr "大陸"
+
+#: timezones.h:206
+msgid "America/Guyana"
+msgstr "美洲/蓋亞那"
+
+#: timezones.h:207
+msgid "America/Halifax"
+msgstr "美洲/哈利法克斯"
+
+#. comment for time zone America/Halifax
+#: timezones.h:209
+msgid "Atlantic Time - Nova Scotia (most places), PEI"
+msgstr "大西洋時間 - 新斯科細亞省(大部分地區),PEI"
+
+#: timezones.h:210
+msgid "America/Havana"
+msgstr "美洲/哈瓦那"
+
+#: timezones.h:211
+msgid "America/Hermosillo"
+msgstr "美洲/艾爾莫西歐"
+
+#. comment for time zone America/Hermosillo
+#: timezones.h:213
+msgid "Mountain Standard Time - Sonora"
+msgstr "山脈標準時間 - 索諾拉"
+
+#: timezones.h:214
+msgid "America/Indiana/Indianapolis"
+msgstr "美洲/印第安那州/印第安納波里"
+
+#. comment for time zone America/Indiana/Indianapolis
+#: timezones.h:216
+msgid "Eastern Time - Indiana - most locations"
+msgstr "東部時間 - 印地安納州 - 大部分地區"
+
+#: timezones.h:217
+msgid "America/Indiana/Knox"
+msgstr "美洲/印第安那州/納克斯"
+
+#. comment for time zone America/Indiana/Knox
+#: timezones.h:219
+msgid "Central Time - Indiana - Starke County"
+msgstr "中央時間 - 印地安納州 - 史塔克郡"
+
+#: timezones.h:220
+msgid "America/Indiana/Marengo"
+msgstr "美洲/印第安那州/馬倫戈"
+
+#. comment for time zone America/Indiana/Marengo
+#: timezones.h:222
+msgid "Eastern Time - Indiana - Crawford County"
+msgstr "東部時間 - 印地安納州 - 克勞福郡"
+
+#: timezones.h:223
+msgid "America/Indiana/Petersburg"
+msgstr "美洲∕印第安那州∕彼得堡"
+
+#. comment for time zone America/Indiana/Petersburg
+#: timezones.h:225
+msgid "Eastern Time - Indiana - Pike County"
+msgstr "東部時間 - 印地安納州 - 派克郡"
+
+#: timezones.h:226
+msgid "America/Indianapolis"
+msgstr "美洲/印第安納波里"
+
+#: timezones.h:227
+msgid "America/Indiana/Tell_City"
+msgstr "美洲∕印第安那州∕泰爾城"
+
+#. comment for time zone America/Indiana/Tell_City
+#: timezones.h:229
+msgid "Central Time - Indiana - Perry County"
+msgstr "中央時間 - 印地安納州 - 佩裡郡"
+
+#: timezones.h:230
+msgid "America/Indiana/Vevay"
+msgstr "美洲/印第安那州/偉威"
+
+#. comment for time zone America/Indiana/Vevay
+#: timezones.h:232
+msgid "Eastern Time - Indiana - Switzerland County"
+msgstr "東部時間 - 印地安納州 - 瑞士郡"
+
+#: timezones.h:233
+msgid "America/Indiana/Vincennes"
+msgstr "美洲∕印第安那州∕溫森斯"
+
+#. comment for time zone America/Indiana/Vincennes
+#: timezones.h:235
+msgid "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties"
+msgstr "東部時間 - 印地安納州 - 戴維斯、杜保斯、納克斯以及馬丁郡"
+
+#: timezones.h:236
+msgid "America/Indiana/Winamac"
+msgstr "美洲∕印第安那州∕威納馬克"
+
+#. comment for time zone America/Indiana/Winamac
+#: timezones.h:238
+msgid "Eastern Time - Indiana - Pulaski County"
+msgstr "東部時間 - 印地安納 - 普拉斯基郡"
+
+#: timezones.h:239
+msgid "America/Inuvik"
+msgstr "美洲/伊紐維克"
+
+#. comment for time zone America/Inuvik
+#: timezones.h:241
+msgid "Mountain Time - west Northwest Territories"
+msgstr "山脈時間 - 西北地區西部"
+
+#: timezones.h:242
+msgid "America/Iqaluit"
+msgstr "美洲/伊卡魯伊特"
+
+#. comment for time zone America/Iqaluit
+#: timezones.h:244
+msgid "Eastern Time - east Nunavut - most locations"
+msgstr "東部時間 - 努那福東部 - 大部分地區"
+
+#: timezones.h:245
+msgid "America/Jamaica"
+msgstr "美洲/牙買加"
+
+#: timezones.h:246
+msgid "America/Jujuy"
+msgstr "美洲/胡卉"
+
+#: timezones.h:247
+msgid "America/Juneau"
+msgstr "美洲/朱諾"
+
+#. comment for time zone America/Juneau
+#: timezones.h:249
+msgid "Alaska Time - Alaska panhandle"
+msgstr "阿拉斯加時間 - 阿拉斯加狹長地"
+
+#: timezones.h:250
+msgid "America/Kentucky/Louisville"
+msgstr "美洲/肯塔基州/路易維爾"
+
+#. comment for time zone America/Kentucky/Louisville
+#: timezones.h:252
+msgid "Eastern Time - Kentucky - Louisville area"
+msgstr "東部時間 - 肯塔基州 - 路易維爾地區"
+
+#: timezones.h:253
+msgid "America/Kentucky/Monticello"
+msgstr "美洲/肯塔基州/蒙地卻羅"
+
+#. comment for time zone America/Kentucky/Monticello
+#: timezones.h:255
+msgid "Eastern Time - Kentucky - Wayne County"
+msgstr "東部時間 - 肯塔基州 - 偉恩郡"
+
+#: timezones.h:256
+msgid "America/Knox_IN"
+msgstr "美洲∕納克斯(印第安那州)"
+
+#: timezones.h:257
+msgid "America/La_Paz"
+msgstr "美洲/拉巴斯"
+
+#: timezones.h:258
+msgid "America/Lima"
+msgstr "美洲/利馬"
+
+#: timezones.h:259
+msgid "America/Los_Angeles"
+msgstr "美洲/洛杉磯"
+
+#. comment for time zone America/Los_Angeles
+#: timezones.h:261
+msgid "Pacific Time"
+msgstr "太平洋時間"
+
+#: timezones.h:262
+msgid "America/Louisville"
+msgstr "美洲/路易維爾"
+
+#: timezones.h:263
+msgid "America/Maceio"
+msgstr "美洲/墨塞歐"
+
+#. comment for time zone America/Maceio
+#: timezones.h:265
+msgid "Alagoas, Sergipe"
+msgstr "阿拉戈斯,賽吉貝"
+
+#: timezones.h:266
+msgid "America/Managua"
+msgstr "美洲/馬拿瓜"
+
+#: timezones.h:267
+msgid "America/Manaus"
+msgstr "美洲/瑪瑙斯"
+
+#. comment for time zone America/Manaus
+#: timezones.h:269
+msgid "E Amazonas"
+msgstr "亞馬遜東部"
+
+#: timezones.h:270
+msgid "America/Marigot"
+msgstr "美洲∕馬利格"
+
+#: timezones.h:271
+msgid "America/Martinique"
+msgstr "美洲/馬汀尼克"
+
+#: timezones.h:272
+msgid "America/Matamoros"
+msgstr "美洲/馬塔莫羅斯"
+
+#. comment for time zone America/Matamoros
+#: timezones.h:274
+msgid "US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border"
+msgstr "美國中央時間 - 科阿韋拉、杜蘭哥、新萊昂、塔毛利帕斯,近美國邊界"
+
+#: timezones.h:275
+msgid "America/Mazatlan"
+msgstr "美洲/馬塞特蘭"
+
+#. comment for time zone America/Mazatlan
+#: timezones.h:277
+msgid "Mountain Time - S Baja, Nayarit, Sinaloa"
+msgstr "山脈時間 - S Baja、納亞里特州、新納娜阿州"
+
+#: timezones.h:278
+msgid "America/Mendoza"
+msgstr "美洲/門多薩"
+
+#: timezones.h:279
+msgid "America/Menominee"
+msgstr "美洲/門諾米尼"
+
+#. comment for time zone America/Menominee
+#: timezones.h:281
+msgid "Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties"
+msgstr "中央時間 - 密西根 - 迪金森、喬治比克、Iron 以及米諾米尼郡"
+
+#: timezones.h:282
+msgid "America/Merida"
+msgstr "美洲/梅里達"
+
+#. comment for time zone America/Merida
+#: timezones.h:284
+msgid "Central Time - Campeche, Yucatan"
+msgstr "中央時間 - 坎佩切、尤卡坦"
+
+#: timezones.h:285
+msgid "America/Mexico_City"
+msgstr "美洲/墨西哥"
+
+#. comment for time zone America/Mexico_City
+#: timezones.h:287
+msgid "Central Time - most locations"
+msgstr "中央時間 - 大部分地區"
+
+#: timezones.h:288
+msgid "America/Miquelon"
+msgstr "美洲/密克朗"
+
+#: timezones.h:289
+msgid "America/Moncton"
+msgstr "美洲∕蒙克頓"
+
+#. comment for time zone America/Moncton
+#: timezones.h:291
+msgid "Atlantic Time - New Brunswick"
+msgstr "大西洋時間 - 新伯倫瑞克"
+
+#: timezones.h:292
+msgid "America/Monterrey"
+msgstr "美洲/蒙特瑞"
+
+#. comment for time zone America/Monterrey
+#: timezones.h:294
+msgid "Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from US border"
+msgstr "墨西哥中央時間 - 科阿韋拉、杜蘭哥、新萊昂、塔毛利帕斯,離美國邊界較遠"
+
+#: timezones.h:295
+msgid "America/Montevideo"
+msgstr "美洲/蒙特維多"
+
+#: timezones.h:296
+msgid "America/Montreal"
+msgstr "美洲/蒙特婁"
+
+#. comment for time zone America/Montreal
+#: timezones.h:298
+msgid "Eastern Time - Quebec - most locations"
+msgstr "東部時間 - 魁北克 - 大部分地區"
+
+#: timezones.h:299
+msgid "America/Montserrat"
+msgstr "美洲/蒙塞拉特"
+
+#: timezones.h:300
+msgid "America/Nassau"
+msgstr "美洲/拿梭"
+
+#: timezones.h:301
+msgid "America/New_York"
+msgstr "美洲/紐約"
+
+#. comment for time zone America/New_York
+#: timezones.h:303
+msgid "Eastern Time"
+msgstr "東部時間"
+
+#: timezones.h:304
+msgid "America/Nipigon"
+msgstr "美洲/尼埤崗"
+
+#. comment for time zone America/Nipigon
+#: timezones.h:306
+msgid "Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973"
+msgstr "東部時間 - 安大略與魁北克 - 未遵照 DST 1967-1973 的地區"
+
+#: timezones.h:307
+msgid "America/Nome"
+msgstr "美洲/諾姆"
+
+#. comment for time zone America/Nome
+#: timezones.h:309
+msgid "Alaska Time - west Alaska"
+msgstr "阿拉斯加時間 - 阿拉斯加西部"
+
+#: timezones.h:310
+msgid "America/Noronha"
+msgstr "美洲/諾若尼亞"
+
+#. comment for time zone America/Noronha
+#: timezones.h:312
+msgid "Atlantic islands"
+msgstr "大西洋群島"
+
+#: timezones.h:313
+msgid "America/North_Dakota/Center"
+msgstr "美洲∕北達科他∕中部"
+
+#. comment for time zone America/North_Dakota/Center
+#: timezones.h:315
+msgid "Central Time - North Dakota - Oliver County"
+msgstr "中央時間 - 北達科他 - 奧利佛郡"
+
+#: timezones.h:316
+msgid "America/North_Dakota/New_Salem"
+msgstr "美洲∕北達科他∕紐沙倫"
+
+#. comment for time zone America/North_Dakota/New_Salem
+#: timezones.h:318
+msgid "Central Time - North Dakota - Morton County (except Mandan area)"
+msgstr "中央時間 - 北達科他 - 摩頓郡(不包含曼丹地區)"
+
+#: timezones.h:319
+msgid "America/Ojinaga"
+msgstr "美洲/Ojinaga"
+
+#. comment for time zone America/Ojinaga
+#: timezones.h:321
+msgid "US Mountain Time - Chihuahua near US border"
+msgstr "美國山脈時間 - 奇瓦瓦,近美國邊界"
+
+#: timezones.h:322
+msgid "America/Panama"
+msgstr "美洲/巴拿馬"
+
+#: timezones.h:323
+msgid "America/Pangnirtung"
+msgstr "美洲/潘尼爾東"
+
+#. comment for time zone America/Pangnirtung
+#: timezones.h:325
+msgid "Eastern Time - Pangnirtung, Nunavut"
+msgstr "東部時間 - 旁尼唐、努納武特"
+
+#: timezones.h:326
+msgid "America/Paramaribo"
+msgstr "美洲/巴拉馬利波"
+
+#: timezones.h:327
+msgid "America/Phoenix"
+msgstr "美洲/鳳凰城"
+
+#. comment for time zone America/Phoenix
+#: timezones.h:329
+msgid "Mountain Standard Time - Arizona"
+msgstr "山脈標準時間 - 亞利桑那"
+
+#: timezones.h:330
+msgid "America/Port-au-Prince"
+msgstr "美洲/太子港"
+
+#: timezones.h:331
+msgid "America/Porto_Acre"
+msgstr "美洲∕波多諾佛"
+
+#: timezones.h:332
+msgid "America/Port_of_Spain"
+msgstr "美洲/西班牙港"
+
+#: timezones.h:333
+msgid "America/Porto_Velho"
+msgstr "美洲/維利尤港"
+
+#. comment for time zone America/Porto_Velho
+#: timezones.h:335
+msgid "Rondonia"
+msgstr "朗多尼亞州"
+
+#: timezones.h:336
+msgid "America/Puerto_Rico"
+msgstr "美洲/波多黎各"
+
+#: timezones.h:337
+msgid "America/Rainy_River"
+msgstr "美洲/瑞尼河"
+
+#. comment for time zone America/Rainy_River
+#: timezones.h:339
+msgid "Central Time - Rainy River & Fort Frances, Ontario"
+msgstr "中央時間 - 瑞尼河與弗朗西斯堡、安大略"
+
+#: timezones.h:340
+msgid "America/Rankin_Inlet"
+msgstr "美洲/朗金灣"
+
+#. comment for time zone America/Rankin_Inlet
+#: timezones.h:342
+msgid "Central Time - central Nunavut"
+msgstr "中央時間 - 努那福中部"
+
+#: timezones.h:343
+msgid "America/Recife"
+msgstr "美洲/瑞西佛"
+
+#. comment for time zone America/Recife
+#: timezones.h:345
+msgid "Pernambuco"
+msgstr "波納姆布柯州"
+
+#: timezones.h:346
+msgid "America/Regina"
+msgstr "美洲/瑞傑那"
+
+#. comment for time zone America/Regina
+#: timezones.h:348
+msgid "Central Standard Time - Saskatchewan - most locations"
+msgstr "中央標準時間 - 薩克其萬省 - 大部分地區"
+
+#: timezones.h:349
+msgid "America/Resolute"
+msgstr "美洲∕羅斯魯特"
+
+#. comment for time zone America/Resolute
+#: timezones.h:351
+msgid "Eastern Standard Time - Resolute, Nunavut"
+msgstr "東部標準時間 - 羅斯魯特、努那福"
+
+#: timezones.h:352
+msgid "America/Rio_Branco"
+msgstr "美洲/布蘭科河"
+
+#. comment for time zone America/Rio_Branco
+#: timezones.h:354
+msgid "Acre"
+msgstr "阿卡"
+
+#: timezones.h:355
+msgid "America/Rosario"
+msgstr "美洲/羅薩里奧"
+
+#: timezones.h:356
+msgid "America/Santa_Isabel"
+msgstr "美洲/聖塔伊莎貝爾"
+
+#. comment for time zone America/Santa_Isabel
+#: timezones.h:358
+msgid "Mexican Pacific Time - Baja California away from US border"
+msgstr "墨西哥太平洋時間 - 離美國邊界較遠的北下加利福尼亞州"
+
+#: timezones.h:359
+msgid "America/Santarem"
+msgstr "美洲/聖塔倫"
+
+#. comment for time zone America/Santarem
+#: timezones.h:361
+msgid "W Para"
+msgstr "W Para"
+
+#: timezones.h:362
+msgid "America/Santiago"
+msgstr "美洲/聖地牙哥"
+
+#: timezones.h:365
+msgid "America/Santo_Domingo"
+msgstr "美洲/聖多明哥"
+
+#: timezones.h:366
+msgid "America/Sao_Paulo"
+msgstr "美洲/聖保羅"
+
+#. comment for time zone America/Sao_Paulo
+#: timezones.h:368
+msgid "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)"
+msgstr "巴西南部與東南部(GO、DF、MG、ES、RJ、SP、PR、SC、RS)"
+
+#: timezones.h:369
+msgid "America/Scoresbysund"
+msgstr "美洲/司廓爾比桑"
+
+#. comment for time zone America/Scoresbysund
+#: timezones.h:371
+msgid "Scoresbysund / Ittoqqortoormiit"
+msgstr "司廓爾比桑/Ittoqqortoormiit"
+
+#: timezones.h:372
+msgid "America/Shiprock"
+msgstr "美洲/船岩"
+
+#. comment for time zone America/Shiprock
+#: timezones.h:374
+msgid "Mountain Time - Navajo"
+msgstr "山脈時間 - 納瓦霍"
+
+#: timezones.h:375
+msgid "America/St_Barthelemy"
+msgstr "美洲∕聖巴托洛繆"
+
+#: timezones.h:376
+msgid "America/St_Johns"
+msgstr "美洲/聖約翰"
+
+#. comment for time zone America/St_Johns
+#: timezones.h:378
+msgid "Newfoundland Time, including SE Labrador"
+msgstr "紐芬蘭標準時間,包括拉布多爾東南部"
+
+#: timezones.h:379
+msgid "America/St_Kitts"
+msgstr "美洲/聖基次"
+
+#: timezones.h:380
+msgid "America/St_Lucia"
+msgstr "美洲/聖露西亞"
+
+#: timezones.h:381
+msgid "America/St_Thomas"
+msgstr "美洲/聖湯馬斯"
+
+#: timezones.h:382
+msgid "America/St_Vincent"
+msgstr "美洲/聖文生"
+
+#: timezones.h:383
+msgid "America/Swift_Current"
+msgstr "美洲/湍水"
+
+#. comment for time zone America/Swift_Current
+#: timezones.h:385
+msgid "Central Standard Time - Saskatchewan - midwest"
+msgstr "中央標準時間 - 薩克其萬省 - 中西部"
+
+#: timezones.h:386
+msgid "America/Tegucigalpa"
+msgstr "美洲/德古斯加巴"
+
+#: timezones.h:387
+msgid "America/Thule"
+msgstr "美洲/圖里"
+
+#. comment for time zone America/Thule
+#: timezones.h:389
+msgid "Thule / Pituffik"
+msgstr "圖里/皮圖非克"
+
+#: timezones.h:390
+msgid "America/Thunder_Bay"
+msgstr "美洲/雷灣"
+
+#. comment for time zone America/Thunder_Bay
+#: timezones.h:392
+msgid "Eastern Time - Thunder Bay, Ontario"
+msgstr "東部時間 - 雷灣、安大略"
+
+#: timezones.h:393
+msgid "America/Tijuana"
+msgstr "美洲/提亞瓦納"
+
+#. comment for time zone America/Tijuana
+#: timezones.h:395
+msgid "US Pacific Time - Baja California near US border"
+msgstr "墨西哥太平洋時間 - 離美國邊界較近的北下加利福尼亞州"
+
+#: timezones.h:396
+msgid "America/Toronto"
+msgstr "美洲/多倫多"
+
+#. comment for time zone America/Toronto
+#: timezones.h:398
+msgid "Eastern Time - Ontario - most locations"
+msgstr "東部時間 - 安大略 - 大部分地區"
+
+#: timezones.h:399
+msgid "America/Tortola"
+msgstr "美洲/托爾托拉"
+
+#: timezones.h:400
+msgid "America/Vancouver"
+msgstr "美洲/溫哥華"
+
+#. comment for time zone America/Vancouver
+#: timezones.h:402
+msgid "Pacific Time - west British Columbia"
+msgstr "太平洋時間 - 英屬哥倫比亞西部"
+
+#: timezones.h:403
+msgid "America/Virgin"
+msgstr "美洲∕維爾京"
+
+#: timezones.h:404
+msgid "America/Whitehorse"
+msgstr "美洲/白馬"
+
+#. comment for time zone America/Whitehorse
+#: timezones.h:406
+msgid "Pacific Time - south Yukon"
+msgstr "太平洋時間 - 育光南部"
+
+#: timezones.h:407
+msgid "America/Winnipeg"
+msgstr "美洲/溫尼伯"
+
+#. comment for time zone America/Winnipeg
+#: timezones.h:409
+msgid "Central Time - Manitoba & west Ontario"
+msgstr "中央時間 - 曼尼托巴以及安大略西部"
+
+#: timezones.h:410
+msgid "America/Yakutat"
+msgstr "美洲/亞庫特"
+
+#. comment for time zone America/Yakutat
+#: timezones.h:412
+msgid "Alaska Time - Alaska panhandle neck"
+msgstr "阿拉斯加時間 - Alaska panhandle neck"
+
+#: timezones.h:413
+msgid "America/Yellowknife"
+msgstr "美洲/黃刀"
+
+#. comment for time zone America/Yellowknife
+#: timezones.h:415
+msgid "Mountain Time - central Northwest Territories"
+msgstr "山脈時間 - 中央西北地區"
+
+#: timezones.h:416
+msgid "Antarctica/Casey"
+msgstr "南極洲/凱西"
+
+#. comment for time zone Antarctica/Casey
+#: timezones.h:418
+msgid "Casey Station, Bailey Peninsula"
+msgstr "凱西站,貝里半島"
+
+#: timezones.h:419
+msgid "Antarctica/Davis"
+msgstr "南極洲/戴維斯"
+
+#. comment for time zone Antarctica/Davis
+#: timezones.h:421
+msgid "Davis Station, Vestfold Hills"
+msgstr "戴維斯站,維斯特福爾得嶺"
+
+#: timezones.h:422
+msgid "Antarctica/DumontDUrville"
+msgstr "南極洲/迪蒙‧迪爾維爾"
+
+#. comment for time zone Antarctica/DumontDUrville
+#: timezones.h:424
+msgid "Dumont-d'Urville Station, Terre Adelie"
+msgstr "迪蒙‧迪爾維爾站,阿黛利地"
+
+#: timezones.h:425
+msgid "Antarctica/Macquarie"
+msgstr "南極洲/麥格理"
+
+#. comment for time zone Antarctica/Macquarie
+#: timezones.h:427
+msgid "Macquarie Island Station, Macquarie Island"
+msgstr "麥格理島站,麥格理島"
+
+#: timezones.h:428
+msgid "Antarctica/Mawson"
+msgstr "南極洲/墨生"
+
+#. comment for time zone Antarctica/Mawson
+#: timezones.h:430
+msgid "Mawson Station, Holme Bay"
+msgstr "墨生站,霍姆灣"
+
+#: timezones.h:431
+msgid "Antarctica/McMurdo"
+msgstr "南極洲/麥克莫多"
+
+#. comment for time zone Antarctica/McMurdo
+#: timezones.h:433
+msgid "McMurdo Station, Ross Island"
+msgstr "麥克莫多站,羅斯島"
+
+#: timezones.h:434
+msgid "Antarctica/Palmer"
+msgstr "南極洲/帕爾莫"
+
+#. comment for time zone Antarctica/Palmer
+#: timezones.h:436
+msgid "Palmer Station, Anvers Island"
+msgstr "帕爾莫站,昂韋爾島"
+
+#: timezones.h:437
+msgid "Antarctica/Rothera"
+msgstr "南極洲∕羅西拉"
+
+#. comment for time zone Antarctica/Rothera
+#: timezones.h:439
+msgid "Rothera Station, Adelaide Island"
+msgstr "羅西拉站,艾特利島"
+
+#: timezones.h:440
+msgid "Antarctica/South_Pole"
+msgstr "南極洲/南極點"
+
+#. comment for time zone Antarctica/South_Pole
+#: timezones.h:442
+msgid "Amundsen-Scott Station, South Pole"
+msgstr "阿慕得森-史考特站,南極"
+
+#: timezones.h:443
+msgid "Antarctica/Syowa"
+msgstr "南極洲/昭和"
+
+#. comment for time zone Antarctica/Syowa
+#: timezones.h:445
+msgid "Syowa Station, E Ongul I"
+msgstr "昭和站,南極釣鉤島東部"
+
+#: timezones.h:446
+msgid "Antarctica/Vostok"
+msgstr "南極洲/東方"
+
+#. comment for time zone Antarctica/Vostok
+#: timezones.h:448
+msgid "Vostok Station, S Magnetic Pole"
+msgstr "沃斯托克站,南 磁點"
+
+#: timezones.h:449
+msgid "Arctic/Longyearbyen"
+msgstr "北極/朗伊爾城"
+
+#: timezones.h:450
+msgid "Asia/Aden"
+msgstr "亞洲/亞丁"
+
+#: timezones.h:451
+msgid "Asia/Almaty"
+msgstr "亞洲/阿拉木圖"
+
+#: timezones.h:454
+msgid "Asia/Amman"
+msgstr "亞洲/安曼"
+
+#: timezones.h:455
+msgid "Asia/Anadyr"
+msgstr "亞洲/阿納德爾"
+
+#. comment for time zone Asia/Anadyr
+#: timezones.h:457
+msgid "Moscow+08 - Bering Sea"
+msgstr "莫斯科+08 - 白令海"
+
+#: timezones.h:458
+msgid "Asia/Aqtau"
+msgstr "亞洲/阿克套"
+
+#. comment for time zone Asia/Aqtau
+#: timezones.h:460
+msgid "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)"
+msgstr "阿特勞(Atirau,Gur'yev)、曼格斯套(Mankistau)"
+
+#: timezones.h:461
+msgid "Asia/Aqtobe"
+msgstr "亞洲/阿克托貝"
+
+#. comment for time zone Asia/Aqtobe
+#: timezones.h:463
+msgid "Aqtobe (Aktobe)"
+msgstr "阿克托貝(Aktobe)"
+
+#: timezones.h:464
+msgid "Asia/Ashgabat"
+msgstr "亞洲/阿什喀巴得"
+
+#: timezones.h:465
+msgid "Asia/Ashkhabad"
+msgstr "亞洲∕阿什哈巴德"
+
+#: timezones.h:466
+msgid "Asia/Baghdad"
+msgstr "亞洲/巴格達"
+
+#: timezones.h:467
+msgid "Asia/Bahrain"
+msgstr "亞洲/巴林"
+
+#: timezones.h:468
+msgid "Asia/Baku"
+msgstr "亞洲/巴庫"
+
+#: timezones.h:469
+msgid "Asia/Bangkok"
+msgstr "亞洲/曼谷"
+
+#: timezones.h:470
+msgid "Asia/Beirut"
+msgstr "亞洲/貝魯特"
+
+#: timezones.h:471
+msgid "Asia/Bishkek"
+msgstr "亞洲/比什凱克"
+
+#: timezones.h:472
+msgid "Asia/Brunei"
+msgstr "亞洲/汶萊"
+
+#: timezones.h:473
+msgid "Asia/Calcutta"
+msgstr "亞洲/加爾各答"
+
+#: timezones.h:474
+msgid "Asia/Choibalsan"
+msgstr "亞洲∕喬巴山"
+
+#. comment for time zone Asia/Choibalsan
+#: timezones.h:476
+msgid "Dornod, Sukhbaatar"
+msgstr "蒙古東方省,蘇赫巴特"
+
+#: timezones.h:477
+msgid "Asia/Chongqing"
+msgstr "亞洲∕重慶"
+
+#. comment for time zone Asia/Chongqing
+#: timezones.h:479
+msgid "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc."
+msgstr "中國大陸中部 - 四川、雲南、廣西、陜西、貴州等等。"
+
+#: timezones.h:480
+msgid "Asia/Chungking"
+msgstr "亞洲∕重慶"
+
+#: timezones.h:481
+msgid "Asia/Colombo"
+msgstr "亞洲/可倫坡"
+
+#: timezones.h:482
+msgid "Asia/Dacca"
+msgstr "亞洲∕達卡"
+
+#: timezones.h:483
+msgid "Asia/Damascus"
+msgstr "亞洲/大馬士革"
+
+#: timezones.h:484
+msgid "Asia/Dhaka"
+msgstr "亞洲/達卡"
+
+#: timezones.h:485
+msgid "Asia/Dili"
+msgstr "亞洲/帝力"
+
+#: timezones.h:486
+msgid "Asia/Dubai"
+msgstr "亞洲/杜拜"
+
+#: timezones.h:487
+msgid "Asia/Dushanbe"
+msgstr "亞洲/杜桑貝"
+
+#: timezones.h:488
+msgid "Asia/Gaza"
+msgstr "亞洲/迦薩"
+
+#: timezones.h:489
+msgid "Asia/Harbin"
+msgstr "亞洲/哈爾濱"
+
+#. comment for time zone Asia/Harbin
+#: timezones.h:491
+msgid "Heilongjiang (except Mohe), Jilin"
+msgstr "黑龍江(漠河除外),吉林"
+
+#: timezones.h:492
+msgid "Asia/Ho_Chi_Minh"
+msgstr "亞洲∕胡志明市"
+
+#: timezones.h:493
+msgid "Asia/Hong_Kong"
+msgstr "亞洲/香港"
+
+#: timezones.h:494
+msgid "Asia/Hovd"
+msgstr "亞洲/科布多"
+
+#. comment for time zone Asia/Hovd
+#: timezones.h:496
+msgid "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan"
+msgstr "巴彥烏列蓋、戈壁阿爾泰、呼布德、烏布蘇、札布汗"
+
+#: timezones.h:497
+msgid "Asia/Irkutsk"
+msgstr "亞洲/伊爾庫茨克"
+
+#. comment for time zone Asia/Irkutsk
+#: timezones.h:499
+msgid "Moscow+05 - Lake Baikal"
+msgstr "莫斯科+05 - 貝加爾湖"
+
+#: timezones.h:500
+msgid "Asia/Istanbul"
+msgstr "亞洲/伊斯坦堡"
+
+#: timezones.h:501
+msgid "Asia/Jakarta"
+msgstr "亞洲/雅加達"
+
+#. comment for time zone Asia/Jakarta
+#: timezones.h:503
+msgid "Java & Sumatra"
+msgstr "爪哇與蘇門答臘"
+
+#: timezones.h:504
+msgid "Asia/Jayapura"
+msgstr "亞洲/嘉雅浦拉"
+
+#. comment for time zone Asia/Jayapura
+#: timezones.h:506
+msgid "Irian Jaya & the Moluccas"
+msgstr "伊利安查亞與摩鹿加"
+
+#: timezones.h:507
+msgid "Asia/Jerusalem"
+msgstr "亞洲/耶路撒冷"
+
+#: timezones.h:508
+msgid "Asia/Kabul"
+msgstr "亞洲/喀布爾"
+
+#: timezones.h:509
+msgid "Asia/Kamchatka"
+msgstr "亞洲/堪察加"
+
+#. comment for time zone Asia/Kamchatka
+#: timezones.h:511
+msgid "Moscow+08 - Kamchatka"
+msgstr "莫斯科+08 - 堪察加"
+
+#: timezones.h:512
+msgid "Asia/Karachi"
+msgstr "亞洲/喀拉蚩"
+
+#: timezones.h:513
+msgid "Asia/Kashgar"
+msgstr "亞洲/喀什噶爾"
+
+#. comment for time zone Asia/Kashgar
+#: timezones.h:515
+msgid "west Tibet & Xinjiang"
+msgstr "西藏與新疆"
+
+#: timezones.h:516
+msgid "Asia/Kathmandu"
+msgstr "亞洲/加德滿都"
+
+#: timezones.h:517
+msgid "Asia/Katmandu"
+msgstr "亞洲/加德滿都"
+
+#: timezones.h:518
+msgid "Asia/Kolkata"
+msgstr "亞洲/加爾各答"
+
+#: timezones.h:519
+msgid "Asia/Krasnoyarsk"
+msgstr "亞洲/克拉斯諾亞爾斯克"
+
+#. comment for time zone Asia/Krasnoyarsk
+#: timezones.h:521
+msgid "Moscow+04 - Yenisei River"
+msgstr "莫斯科+04 - 葉尼塞河"
+
+#: timezones.h:522
+msgid "Asia/Kuala_Lumpur"
+msgstr "亞洲/吉隆坡"
+
+#. comment for time zone Asia/Kuala_Lumpur
+#: timezones.h:524
+msgid "peninsular Malaysia"
+msgstr "馬來西亞半島"
+
+#: timezones.h:525
+msgid "Asia/Kuching"
+msgstr "亞洲/古晉"
+
+#. comment for time zone Asia/Kuching
+#: timezones.h:527
+msgid "Sabah & Sarawak"
+msgstr "沙巴與沙勞越"
+
+#: timezones.h:528
+msgid "Asia/Kuwait"
+msgstr "亞洲/科威特"
+
+#: timezones.h:529
+msgid "Asia/Macao"
+msgstr "亞洲/澳門"
+
+#: timezones.h:530
+msgid "Asia/Macau"
+msgstr "亞洲/澳門"
+
+#: timezones.h:531
+msgid "Asia/Magadan"
+msgstr "亞洲/馬加丹"
+
+#. comment for time zone Asia/Magadan
+#: timezones.h:533
+msgid "Moscow+08 - Magadan"
+msgstr "莫斯科+08 - 馬加丹"
+
+#: timezones.h:534
+msgid "Asia/Makassar"
+msgstr "亞洲∕錫江"
+
+#. comment for time zone Asia/Makassar
+#: timezones.h:536
+msgid "east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor"
+msgstr "婆羅東部與南部、西里貝斯、峇里島、Nusa Tengarra、西帝汶"
+
+#: timezones.h:537
+msgid "Asia/Manila"
+msgstr "亞洲/馬尼拉"
+
+#: timezones.h:538
+msgid "Asia/Muscat"
+msgstr "亞洲/馬斯喀特"
+
+#: timezones.h:539
+msgid "Asia/Nicosia"
+msgstr "亞洲/尼科西亞"
+
+#: timezones.h:540
+msgid "Asia/Novokuznetsk"
+msgstr "亞洲/新庫斯內次"
+
+#. comment for time zone Asia/Novokuznetsk
+#: timezones.h:542
+msgid "Moscow+03 - Novokuznetsk"
+msgstr "莫斯科+03 - 新庫斯內次"
+
+#: timezones.h:543
+msgid "Asia/Novosibirsk"
+msgstr "亞洲/新西伯利亞"
+
+#. comment for time zone Asia/Novosibirsk
+#: timezones.h:545
+msgid "Moscow+03 - Novosibirsk"
+msgstr "莫斯科+03 - 新西伯利亞"
+
+#: timezones.h:546
+msgid "Asia/Omsk"
+msgstr "亞洲/鄂木斯克"
+
+#. comment for time zone Asia/Omsk
+#: timezones.h:548
+msgid "Moscow+03 - west Siberia"
+msgstr "莫斯科+03 - 西伯利亞西部"
+
+#: timezones.h:549
+msgid "Asia/Oral"
+msgstr "亞洲∕歐羅"
+
+#. comment for time zone Asia/Oral
+#: timezones.h:551
+msgid "West Kazakhstan"
+msgstr "哈薩克西部"
+
+#: timezones.h:552
+msgid "Asia/Phnom_Penh"
+msgstr "亞洲/金邊"
+
+#: timezones.h:553
+msgid "Asia/Pontianak"
+msgstr "亞洲/坤甸"
+
+#. comment for time zone Asia/Pontianak
+#: timezones.h:555
+msgid "west & central Borneo"
+msgstr "婆羅西部與中部"
+
+#: timezones.h:556
+msgid "Asia/Pyongyang"
+msgstr "亞洲/平壤"
+
+#: timezones.h:557
+msgid "Asia/Qatar"
+msgstr "亞洲/卡達"
+
+#: timezones.h:558
+msgid "Asia/Qyzylorda"
+msgstr "亞洲∕奎茲羅答"
+
+#. comment for time zone Asia/Qyzylorda
+#: timezones.h:560
+msgid "Qyzylorda (Kyzylorda, Kzyl-Orda)"
+msgstr "克孜勒奧爾達(Kyzylorda、Kzyl-Orda)"
+
+#: timezones.h:561
+msgid "Asia/Rangoon"
+msgstr "亞洲/仰光"
+
+#: timezones.h:562
+msgid "Asia/Riyadh"
+msgstr "亞洲/利雅得"
+
+#: timezones.h:563
+msgid "Asia/Riyadh87"
+msgstr "亞洲/利雅得87"
+
+#: timezones.h:564
+msgid "Asia/Riyadh88"
+msgstr "亞洲/利雅得88"
+
+#: timezones.h:565
+msgid "Asia/Riyadh89"
+msgstr "亞洲/利雅得89"
+
+#: timezones.h:566
+msgid "Asia/Saigon"
+msgstr "亞洲/胡志明市"
+
+#: timezones.h:567
+msgid "Asia/Sakhalin"
+msgstr "亞洲∕庫頁"
+
+#. comment for time zone Asia/Sakhalin
+#: timezones.h:569
+msgid "Moscow+07 - Sakhalin Island"
+msgstr "莫斯科+07 - 庫頁島"
+
+#: timezones.h:570
+msgid "Asia/Samarkand"
+msgstr "亞洲/撒馬爾罕"
+
+#. comment for time zone Asia/Samarkand
+#: timezones.h:572
+msgid "west Uzbekistan"
+msgstr "烏茲別克斯坦西部"
+
+#: timezones.h:573
+msgid "Asia/Seoul"
+msgstr "亞洲/首爾"
+
+#: timezones.h:574
+msgid "Asia/Shanghai"
+msgstr "亞洲/上海"
+
+#. comment for time zone Asia/Shanghai
+#: timezones.h:576
+msgid "east China - Beijing, Guangdong, Shanghai, etc."
+msgstr "中國大陸東部 - 北京、廣東、上海等等"
+
+#: timezones.h:577
+msgid "Asia/Singapore"
+msgstr "亞洲/新加坡"
+
+#: timezones.h:578
+msgid "Asia/Taipei"
+msgstr "亞洲/台北"
+
+#: timezones.h:579
+msgid "Asia/Tashkent"
+msgstr "亞洲/塔什干"
+
+#. comment for time zone Asia/Tashkent
+#: timezones.h:581
+msgid "east Uzbekistan"
+msgstr "烏茲別克斯坦東部"
+
+#: timezones.h:582
+msgid "Asia/Tbilisi"
+msgstr "亞洲/第比利斯"
+
+#: timezones.h:583
+msgid "Asia/Tehran"
+msgstr "亞洲/德黑蘭"
+
+#: timezones.h:584
+msgid "Asia/Tel_Aviv"
+msgstr "亞洲∕特拉維夫"
+
+#: timezones.h:585
+msgid "Asia/Thimbu"
+msgstr "亞洲/辛布"
+
+#: timezones.h:586
+msgid "Asia/Thimphu"
+msgstr "亞洲/辛布"
+
+#: timezones.h:587
+msgid "Asia/Tokyo"
+msgstr "亞洲/東京"
+
+#: timezones.h:588
+msgid "Asia/Ujung_Pandang"
+msgstr "亞洲/烏戎潘當"
+
+#: timezones.h:589
+msgid "Asia/Ulaanbaatar"
+msgstr "亞洲/烏蘭巴托"
+
+#: timezones.h:592
+msgid "Asia/Ulan_Bator"
+msgstr "亞洲/烏蘭巴托"
+
+#: timezones.h:593
+msgid "Asia/Urumqi"
+msgstr "亞洲/烏魯木齊"
+
+#. comment for time zone Asia/Urumqi
+#: timezones.h:595
+msgid "most of Tibet & Xinjiang"
+msgstr "大部分西藏和新疆地區"
+
+#: timezones.h:596
+msgid "Asia/Vientiane"
+msgstr "亞洲/永珍"
+
+#: timezones.h:597
+msgid "Asia/Vladivostok"
+msgstr "亞洲/海參崴"
+
+#. comment for time zone Asia/Vladivostok
+#: timezones.h:599
+msgid "Moscow+07 - Amur River"
+msgstr "莫斯科+07 - 阿姆河"
+
+#: timezones.h:600
+msgid "Asia/Yakutsk"
+msgstr "亞洲/雅庫次克"
+
+#. comment for time zone Asia/Yakutsk
+#: timezones.h:602
+msgid "Moscow+06 - Lena River"
+msgstr "莫斯科+06 - 萊納河"
+
+#: timezones.h:603
+msgid "Asia/Yekaterinburg"
+msgstr "亞洲/葉卡捷琳堡"
+
+#. comment for time zone Asia/Yekaterinburg
+#: timezones.h:605
+msgid "Moscow+02 - Urals"
+msgstr "莫斯科+02 - 烏拉山"
+
+#: timezones.h:606
+msgid "Asia/Yerevan"
+msgstr "亞洲/葉里溫"
+
+#: timezones.h:607
+msgid "Atlantic/Azores"
+msgstr "大西洋/亞速爾群島"
+
+#. comment for time zone Atlantic/Azores
+#: timezones.h:609
+msgid "Azores"
+msgstr "亞速爾群島"
+
+#: timezones.h:610
+msgid "Atlantic/Bermuda"
+msgstr "大西洋/百慕達"
+
+#: timezones.h:611
+msgid "Atlantic/Canary"
+msgstr "大西洋/卡納里群島"
+
+#. comment for time zone Atlantic/Canary
+#: timezones.h:613
+msgid "Canary Islands"
+msgstr "加那利群島"
+
+#: timezones.h:614
+msgid "Atlantic/Cape_Verde"
+msgstr "大西洋/維德角"
+
+#: timezones.h:615
+msgid "Atlantic/Faeroe"
+msgstr "大西洋/法羅群島"
+
+#: timezones.h:616
+msgid "Atlantic/Faroe"
+msgstr "大西洋/法羅群島"
+
+#: timezones.h:617
+msgid "Atlantic/Jan_Mayen"
+msgstr "大西洋/揚馬延島"
+
+#: timezones.h:618
+msgid "Atlantic/Madeira"
+msgstr "大西洋/馬德拉群島"
+
+#. comment for time zone Atlantic/Madeira
+#: timezones.h:620
+msgid "Madeira Islands"
+msgstr "馬德拉群島"
+
+#: timezones.h:621
+msgid "Atlantic/Reykjavik"
+msgstr "大西洋/雷克雅維克"
+
+#: timezones.h:622
+msgid "Atlantic/South_Georgia"
+msgstr "大西洋/南喬治亞"
+
+#: timezones.h:623
+msgid "Atlantic/Stanley"
+msgstr "大西洋/史坦利島"
+
+#: timezones.h:624
+msgid "Atlantic/St_Helena"
+msgstr "大西洋/聖赫勒納島"
+
+#: timezones.h:625
+msgid "Australia/ACT"
+msgstr "澳洲∕澳洲首府"
+
+#: timezones.h:626
+msgid "Australia/Adelaide"
+msgstr "澳洲∕阿德萊德"
+
+#. comment for time zone Australia/Adelaide
+#: timezones.h:628
+msgid "South Australia"
+msgstr "南澳洲"
+
+#: timezones.h:629
+msgid "Australia/Brisbane"
+msgstr "澳洲/布里斯本"
+
+#. comment for time zone Australia/Brisbane
+#: timezones.h:631
+msgid "Queensland - most locations"
+msgstr "昆士蘭 - 大部分地區"
+
+#: timezones.h:632
+msgid "Australia/Broken_Hill"
+msgstr "澳洲∕布羅肯希爾"
+
+#. comment for time zone Australia/Broken_Hill
+#: timezones.h:634
+msgid "New South Wales - Yancowinna"
+msgstr "新南威爾斯 - Yancowinna"
+
+#: timezones.h:635
+msgid "Australia/Canberra"
+msgstr "澳洲∕坎培拉"
+
+#: timezones.h:636
+msgid "Australia/Currie"
+msgstr "澳洲∕卡里"
+
+#. comment for time zone Australia/Currie
+#: timezones.h:638
+msgid "Tasmania - King Island"
+msgstr "塔斯馬尼亞 - 國王島"
+
+#: timezones.h:639
+msgid "Australia/Darwin"
+msgstr "澳洲/達爾文市"
+
+#. comment for time zone Australia/Darwin
+#: timezones.h:641
+msgid "Northern Territory"
+msgstr "澳洲北領地"
+
+#: timezones.h:642
+msgid "Australia/Eucla"
+msgstr "澳洲/尤克拉"
+
+#. comment for time zone Australia/Eucla
+#: timezones.h:644
+msgid "Western Australia - Eucla area"
+msgstr "西澳大利亞 - 尤克拉地區"
+
+#: timezones.h:645
+msgid "Australia/Hobart"
+msgstr "澳洲/哈巴特"
+
+#. comment for time zone Australia/Hobart
+#: timezones.h:647
+msgid "Tasmania - most locations"
+msgstr "塔斯馬尼亞 - 大部分地區"
+
+#: timezones.h:648
+msgid "Australia/LHI"
+msgstr "澳洲∕LHI"
+
+#: timezones.h:649
+msgid "Australia/Lindeman"
+msgstr "澳洲/林德曼"
+
+#. comment for time zone Australia/Lindeman
+#: timezones.h:651
+msgid "Queensland - Holiday Islands"
+msgstr "昆士蘭 - 假日群島"
+
+#: timezones.h:652
+msgid "Australia/Lord_Howe"
+msgstr "澳洲/羅豪"
+
+#. comment for time zone Australia/Lord_Howe
+#: timezones.h:654
+msgid "Lord Howe Island"
+msgstr "羅豪島"
+
+#: timezones.h:655
+msgid "Australia/Melbourne"
+msgstr "澳洲/墨爾本"
+
+#. comment for time zone Australia/Melbourne
+#: timezones.h:657
+msgid "Victoria"
+msgstr "維多利亞"
+
+#: timezones.h:658
+msgid "Australia/North"
+msgstr "澳洲∕北部"
+
+#: timezones.h:659
+msgid "Australia/NSW"
+msgstr "澳洲∕新南威爾斯"
+
+#: timezones.h:660
+msgid "Australia/Perth"
+msgstr "澳洲/伯斯"
+
+#. comment for time zone Australia/Perth
+#: timezones.h:662
+msgid "Western Australia - most locations"
+msgstr "西澳大利亞 - 大部分地區"
+
+#: timezones.h:663
+msgid "Australia/Queensland"
+msgstr "澳洲/昆士蘭"
+
+#: timezones.h:664
+msgid "Australia/South"
+msgstr "澳洲∕南部"
+
+#: timezones.h:665
+msgid "Australia/Sydney"
+msgstr "澳洲/雪梨"
+
+#. comment for time zone Australia/Sydney
+#: timezones.h:667
+msgid "New South Wales - most locations"
+msgstr "新南威爾斯 - 大部分地區"
+
+#: timezones.h:668
+msgid "Australia/Tasmania"
+msgstr "澳洲∕塔斯馬尼亞"
+
+#: timezones.h:669
+msgid "Australia/Victoria"
+msgstr "澳洲∕維多利亞"
+
+#: timezones.h:670
+msgid "Australia/West"
+msgstr "澳洲∕西部"
+
+#: timezones.h:671
+msgid "Australia/Yancowinna"
+msgstr "澳洲∕揚科維納"
+
+#: timezones.h:672
+msgid "Brazil/Acre"
+msgstr "巴西∕阿卡"
+
+#: timezones.h:673
+msgid "Brazil/DeNoronha"
+msgstr "巴西∕迪諾羅尼亞島"
+
+#: timezones.h:674
+msgid "Brazil/East"
+msgstr "巴西∕東岸"
+
+#: timezones.h:675
+msgid "Brazil/West"
+msgstr "巴西∕西部"
+
+#: timezones.h:676
+msgid "Canada/Atlantic"
+msgstr "加拿大∕大西洋岸"
+
+#: timezones.h:677
+msgid "Canada/Central"
+msgstr "加拿大∕中部"
+
+#: timezones.h:678
+msgid "Canada/Eastern"
+msgstr "加拿大∕東岸"
+
+#: timezones.h:679
+msgid "Canada/East-Saskatchewan"
+msgstr "加拿大∕薩客其萬省"
+
+#: timezones.h:680
+msgid "Canada/Mountain"
+msgstr "加拿大∕山脈區"
+
+#: timezones.h:681
+msgid "Canada/Newfoundland"
+msgstr "加拿大∕紐芬蘭"
+
+#: timezones.h:682
+msgid "Canada/Pacific"
+msgstr "加拿大∕太平洋岸"
+
+#: timezones.h:683
+msgid "Canada/Saskatchewan"
+msgstr "加拿大∕薩克斯其萬省"
+
+#: timezones.h:684
+msgid "Canada/Yukon"
+msgstr "加拿大∕育空"
+
+#: timezones.h:685
+msgid "CET"
+msgstr "CET"
+
+#: timezones.h:686
+msgid "Chile/Continental"
+msgstr "智利∕大陸時區"
+
+#: timezones.h:687
+msgid "Chile/EasterIsland"
+msgstr "智利∕復活島"
+
+#: timezones.h:688
+msgid "CST6CDT"
+msgstr "CST6CDT"
+
+#: timezones.h:689
+msgid "Cuba"
+msgstr "古巴"
+
+#: timezones.h:690
+msgid "EET"
+msgstr "EET"
+
+#: timezones.h:691
+msgid "Egypt"
+msgstr "埃及"
+
+#: timezones.h:692
+msgid "Eire"
+msgstr "愛爾蘭"
+
+#: timezones.h:693
+msgid "EST"
+msgstr "EST"
+
+#: timezones.h:694
+msgid "EST5EDT"
+msgstr "EST5EDT"
+
+#: timezones.h:695
+msgid "Etc/GMT"
+msgstr "Etc/GMT"
+
+#: timezones.h:696
+msgid "Etc/GMT0"
+msgstr "Etc/GMT0"
+
+#: timezones.h:697
+msgid "Etc/GMT-0"
+msgstr "Etc/GMT-0"
+
+#: timezones.h:698
+msgid "Etc/GMT+0"
+msgstr "Etc/GMT+0"
+
+#: timezones.h:699
+msgid "Etc/GMT-1"
+msgstr "Etc/GMT-1"
+
+#: timezones.h:700
+msgid "Etc/GMT+1"
+msgstr "Etc/GMT+1"
+
+#: timezones.h:701
+msgid "Etc/GMT-10"
+msgstr "Etc/GMT-10"
+
+#: timezones.h:702
+msgid "Etc/GMT+10"
+msgstr "Etc/GMT+10"
+
+#: timezones.h:703
+msgid "Etc/GMT-11"
+msgstr "Etc/GMT-11"
+
+#: timezones.h:704
+msgid "Etc/GMT+11"
+msgstr "Etc/GMT+11"
+
+#: timezones.h:705
+msgid "Etc/GMT-12"
+msgstr "Etc/GMT-12"
+
+#: timezones.h:706
+msgid "Etc/GMT+12"
+msgstr "Etc/GMT+12"
+
+#: timezones.h:707
+msgid "Etc/GMT-13"
+msgstr "Etc/GMT-13"
+
+#: timezones.h:708
+msgid "Etc/GMT-14"
+msgstr "Etc/GMT-14"
+
+#: timezones.h:709
+msgid "Etc/GMT-2"
+msgstr "Etc/GMT-2"
+
+#: timezones.h:710
+msgid "Etc/GMT+2"
+msgstr "Etc/GMT+2"
+
+#: timezones.h:711
+msgid "Etc/GMT-3"
+msgstr "Etc/GMT-3"
+
+#: timezones.h:712
+msgid "Etc/GMT+3"
+msgstr "Etc/GMT+3"
+
+#: timezones.h:713
+msgid "Etc/GMT-4"
+msgstr "Etc/GMT-4"
+
+#: timezones.h:714
+msgid "Etc/GMT+4"
+msgstr "Etc/GMT+4"
+
+#: timezones.h:715
+msgid "Etc/GMT-5"
+msgstr "Etc/GMT-5"
+
+#: timezones.h:716
+msgid "Etc/GMT+5"
+msgstr "Etc/GMT+5"
+
+#: timezones.h:717
+msgid "Etc/GMT-6"
+msgstr "Etc/GMT-6"
+
+#: timezones.h:718
+msgid "Etc/GMT+6"
+msgstr "Etc/GMT+6"
+
+#: timezones.h:719
+msgid "Etc/GMT-7"
+msgstr "Etc/GMT-7"
+
+#: timezones.h:720
+msgid "Etc/GMT+7"
+msgstr "Etc/GMT+7"
+
+#: timezones.h:721
+msgid "Etc/GMT-8"
+msgstr "Etc/GMT-8"
+
+#: timezones.h:722
+msgid "Etc/GMT+8"
+msgstr "Etc/GMT+8"
+
+#: timezones.h:723
+msgid "Etc/GMT-9"
+msgstr "Etc/GMT-9"
+
+#: timezones.h:724
+msgid "Etc/GMT+9"
+msgstr "Etc/GMT+9"
+
+#: timezones.h:725
+msgid "Etc/Greenwich"
+msgstr "Etc/格林威治"
+
+#: timezones.h:726
+msgid "Etc/UCT"
+msgstr "Etc/UCT"
+
+#: timezones.h:727
+msgid "Etc/Universal"
+msgstr "Etc/通用"
+
+#: timezones.h:728
+msgid "Etc/UTC"
+msgstr "Etc/UTC"
+
+#: timezones.h:729
+msgid "Etc/Zulu"
+msgstr "Etc/祖魯"
+
+#: timezones.h:730
+msgid "Europe/Amsterdam"
+msgstr "歐洲/阿姆斯特丹"
+
+#: timezones.h:731
+msgid "Europe/Andorra"
+msgstr "歐洲/安道爾"
+
+#: timezones.h:732
+msgid "Europe/Athens"
+msgstr "歐洲/雅典"
+
+#: timezones.h:733
+msgid "Europe/Belfast"
+msgstr "歐洲/貝爾發斯特"
+
+#: timezones.h:734
+msgid "Europe/Belgrade"
+msgstr "歐洲/貝爾格勒"
+
+#: timezones.h:735
+msgid "Europe/Berlin"
+msgstr "歐洲/柏林"
+
+#: timezones.h:736
+msgid "Europe/Bratislava"
+msgstr "歐洲/布拉第斯拉瓦"
+
+#: timezones.h:737
+msgid "Europe/Brussels"
+msgstr "歐洲/布魯塞爾"
+
+#: timezones.h:738
+msgid "Europe/Bucharest"
+msgstr "歐洲/布加勒斯特"
+
+#: timezones.h:739
+msgid "Europe/Budapest"
+msgstr "歐洲/布達佩斯"
+
+#: timezones.h:740
+msgid "Europe/Chisinau"
+msgstr "歐洲/基希那烏"
+
+#: timezones.h:741
+msgid "Europe/Copenhagen"
+msgstr "歐洲/哥本哈根"
+
+#: timezones.h:742
+msgid "Europe/Dublin"
+msgstr "歐洲/都柏林"
+
+#: timezones.h:743
+msgid "Europe/Gibraltar"
+msgstr "歐洲/直布羅陀"
+
+#: timezones.h:744
+msgid "Europe/Guernsey"
+msgstr "歐洲∕根西"
+
+#: timezones.h:745
+msgid "Europe/Helsinki"
+msgstr "歐洲/赫爾辛基"
+
+#: timezones.h:746
+msgid "Europe/Isle_of_Man"
+msgstr "歐洲∕曼島"
+
+#: timezones.h:747
+msgid "Europe/Istanbul"
+msgstr "歐洲/伊斯坦堡"
+
+#: timezones.h:748
+msgid "Europe/Jersey"
+msgstr "歐洲∕澤西島"
+
+#: timezones.h:749
+msgid "Europe/Kaliningrad"
+msgstr "歐洲/加里寧格勒"
+
+#. comment for time zone Europe/Kaliningrad
+#: timezones.h:751
+msgid "Moscow-01 - Kaliningrad"
+msgstr "莫斯科-01 - 加里寧格勒"
+
+#: timezones.h:752
+msgid "Europe/Kiev"
+msgstr "歐洲/基輔"
+
+#: timezones.h:755
+msgid "Europe/Lisbon"
+msgstr "歐洲/里斯本"
+
+#: timezones.h:758
+msgid "Europe/Ljubljana"
+msgstr "歐洲/盧布雅那"
+
+#: timezones.h:759
+msgid "Europe/London"
+msgstr "歐洲/倫敦"
+
+#: timezones.h:760
+msgid "Europe/Luxembourg"
+msgstr "歐洲/盧森堡"
+
+#: timezones.h:761
+msgid "Europe/Madrid"
+msgstr "歐洲/馬德里"
+
+#: timezones.h:764
+msgid "Europe/Malta"
+msgstr "歐洲/馬爾他"
+
+#: timezones.h:765
+msgid "Europe/Mariehamn"
+msgstr "歐洲∕瑪麗港"
+
+#: timezones.h:766
+msgid "Europe/Minsk"
+msgstr "歐洲/明斯克"
+
+#: timezones.h:767
+msgid "Europe/Monaco"
+msgstr "歐洲/摩納哥"
+
+#: timezones.h:768
+msgid "Europe/Moscow"
+msgstr "歐洲/莫斯科"
+
+#. comment for time zone Europe/Moscow
+#: timezones.h:770
+msgid "Moscow+00 - west Russia"
+msgstr "莫斯科+00 - 俄羅斯西部"
+
+#: timezones.h:771
+msgid "Europe/Nicosia"
+msgstr "歐洲/尼科西亞"
+
+#: timezones.h:772
+msgid "Europe/Oslo"
+msgstr "歐洲/奧斯陸"
+
+#: timezones.h:773
+msgid "Europe/Paris"
+msgstr "歐洲/巴黎"
+
+#: timezones.h:774
+msgid "Europe/Podgorica"
+msgstr "歐洲∕普哥里卡"
+
+#: timezones.h:775
+msgid "Europe/Prague"
+msgstr "歐洲/布拉格"
+
+#: timezones.h:776
+msgid "Europe/Riga"
+msgstr "歐洲/里加"
+
+#: timezones.h:777
+msgid "Europe/Rome"
+msgstr "歐洲/羅馬"
+
+#: timezones.h:778
+msgid "Europe/Samara"
+msgstr "歐洲/沙馬拉"
+
+#. comment for time zone Europe/Samara
+#: timezones.h:780
+msgid "Moscow - Samara, Udmurtia"
+msgstr "莫斯科 - 沙馬拉、烏德穆爾特"
+
+#: timezones.h:781
+msgid "Europe/San_Marino"
+msgstr "歐洲/聖馬利諾"
+
+#: timezones.h:782
+msgid "Europe/Sarajevo"
+msgstr "歐洲/薩拉耶佛"
+
+#: timezones.h:783
+msgid "Europe/Simferopol"
+msgstr "歐洲/辛菲洛普"
+
+#. comment for time zone Europe/Simferopol
+#: timezones.h:785
+msgid "central Crimea"
+msgstr "克裏米亞半島中部"
+
+#: timezones.h:786
+msgid "Europe/Skopje"
+msgstr "歐洲/史高彼耶"
+
+#: timezones.h:787
+msgid "Europe/Sofia"
+msgstr "歐洲/索非亞"
+
+#: timezones.h:788
+msgid "Europe/Stockholm"
+msgstr "歐洲/斯德哥爾摩"
+
+#: timezones.h:789
+msgid "Europe/Tallinn"
+msgstr "歐洲/塔林"
+
+#: timezones.h:790
+msgid "Europe/Tirane"
+msgstr "歐洲/地拉那"
+
+#: timezones.h:791
+msgid "Europe/Tiraspol"
+msgstr "歐洲∕蒂拉斯波爾"
+
+#: timezones.h:792
+msgid "Europe/Uzhgorod"
+msgstr "歐洲/烏日戈羅德"
+
+#. comment for time zone Europe/Uzhgorod
+#: timezones.h:794
+msgid "Ruthenia"
+msgstr "盧森尼亞"
+
+#: timezones.h:795
+msgid "Europe/Vaduz"
+msgstr "歐洲/瓦杜茲"
+
+#: timezones.h:796
+msgid "Europe/Vatican"
+msgstr "歐洲/梵蒂岡"
+
+#: timezones.h:797
+msgid "Europe/Vienna"
+msgstr "歐洲/維也納"
+
+#: timezones.h:798
+msgid "Europe/Vilnius"
+msgstr "歐洲/維爾拿"
+
+#: timezones.h:799
+msgid "Europe/Volgograd"
+msgstr "歐洲∕伏爾加格勒"
+
+#. comment for time zone Europe/Volgograd
+#: timezones.h:801
+msgid "Moscow+00 - Caspian Sea"
+msgstr "莫斯科+00 - 裏海"
+
+#: timezones.h:802
+msgid "Europe/Warsaw"
+msgstr "歐洲/華沙"
+
+#: timezones.h:803
+msgid "Europe/Zagreb"
+msgstr "歐洲/札格勒布"
+
+#: timezones.h:804
+msgid "Europe/Zaporozhye"
+msgstr "歐洲/扎波羅熱"
+
+#. comment for time zone Europe/Zaporozhye
+#: timezones.h:806
+msgid "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk"
+msgstr "紮波羅熱、盧干斯克/薩波里賈東部、利西昌斯克東部"
+
+#: timezones.h:807
+msgid "Europe/Zurich"
+msgstr "歐洲/蘇黎世"
+
+#: timezones.h:808
+msgid "Factory"
+msgstr "工廠"
+
+#: timezones.h:809
+msgid "GB"
+msgstr "GB"
+
+#: timezones.h:810
+msgid "GB-Eire"
+msgstr "英國-愛爾蘭"
+
+#: timezones.h:811
+msgid "GMT"
+msgstr "GMT"
+
+#: timezones.h:812
+msgid "GMT0"
+msgstr "GMT0"
+
+#: timezones.h:813
+msgid "GMT-0"
+msgstr "GMT-0"
+
+#: timezones.h:814
+msgid "GMT+0"
+msgstr "GMT+0"
+
+#: timezones.h:815
+msgid "Greenwich"
+msgstr "格林威治"
+
+#: timezones.h:816
+msgid "Hongkong"
+msgstr "香港"
+
+#: timezones.h:817
+msgid "HST"
+msgstr "夏威夷標準時間"
+
+#: timezones.h:818
+msgid "Iceland"
+msgstr "冰島"
+
+#: timezones.h:819
+msgid "Indian/Antananarivo"
+msgstr "印度/安塔那那利佛"
+
+#: timezones.h:820
+msgid "Indian/Chagos"
+msgstr "印度/查戈斯"
+
+#: timezones.h:821
+msgid "Indian/Christmas"
+msgstr "印度/查戈斯"
+
+#: timezones.h:822
+msgid "Indian/Cocos"
+msgstr "印度/可可斯"
+
+#: timezones.h:823
+msgid "Indian/Comoro"
+msgstr "印度/葛摩群島"
+
+#: timezones.h:824
+msgid "Indian/Kerguelen"
+msgstr "印度/克爾格倫群島"
+
+#: timezones.h:825
+msgid "Indian/Mahe"
+msgstr "印度/瑪黑"
+
+#: timezones.h:826
+msgid "Indian/Maldives"
+msgstr "印度/馬爾地夫"
+
+#: timezones.h:827
+msgid "Indian/Mauritius"
+msgstr "印度/模里西斯"
+
+#: timezones.h:828
+msgid "Indian/Mayotte"
+msgstr "印度/馬約特島"
+
+#: timezones.h:829
+msgid "Indian/Reunion"
+msgstr "印度/留尼旺島"
+
+#: timezones.h:830
+msgid "Iran"
+msgstr "伊朗"
+
+#: timezones.h:831
+msgid "iso3166.tab"
+msgstr "iso3166.tab"
+
+#: timezones.h:832
+msgid "Israel"
+msgstr "以色列"
+
+#: timezones.h:833
+msgid "Jamaica"
+msgstr "牙買加"
+
+#: timezones.h:834
+msgid "Japan"
+msgstr "日本"
+
+#. comment for time zone Pacific/Kwajalein
+#: timezones.h:835 timezones.h:891
+msgid "Kwajalein"
+msgstr "瓜加林島"
+
+#: timezones.h:836
+msgid "Libya"
+msgstr "利比亞"
+
+#: timezones.h:837
+msgid "MET"
+msgstr "MET"
+
+#: timezones.h:838
+msgid "Mexico/BajaNorte"
+msgstr "墨西哥∕北下加利福尼亞州"
+
+#: timezones.h:839
+msgid "Mexico/BajaSur"
+msgstr "墨西哥∕南下加利福尼亞州"
+
+#: timezones.h:840
+msgid "Mexico/General"
+msgstr "墨西哥∕普通地區"
+
+#: timezones.h:841
+msgid "Mideast/Riyadh87"
+msgstr "中東∕利雅德 87"
+
+#: timezones.h:842
+msgid "Mideast/Riyadh88"
+msgstr "中東∕利雅德 88"
+
+#: timezones.h:843
+msgid "Mideast/Riyadh89"
+msgstr "中東∕利雅德 89"
+
+#: timezones.h:844
+msgid "MST"
+msgstr "山區標準時間"
+
+#: timezones.h:845
+msgid "MST7MDT"
+msgstr "MST7MDT"
+
+#: timezones.h:846
+msgid "Navajo"
+msgstr "納瓦霍"
+
+#: timezones.h:847
+msgid "NZ"
+msgstr "NZ"
+
+#: timezones.h:848
+msgid "NZ-CHAT"
+msgstr "NZ-CHAT"
+
+#: timezones.h:849
+msgid "Pacific/Apia"
+msgstr "太平洋/亞庇"
+
+#: timezones.h:850
+msgid "Pacific/Auckland"
+msgstr "太平洋/奧克蘭"
+
+#: timezones.h:853
+msgid "Pacific/Chatham"
+msgstr "太平洋/占松"
+
+#. comment for time zone Pacific/Chatham
+#: timezones.h:855
+msgid "Chatham Islands"
+msgstr "查塔姆群島"
+
+#: timezones.h:856
+msgid "Pacific/Chuuk"
+msgstr "太平洋/楚克"
+
+#. comment for time zone Pacific/Chuuk
+#: timezones.h:858
+msgid "Chuuk (Truk) and Yap"
+msgstr "楚克(特魯克)與雅浦島"
+
+#: timezones.h:859
+msgid "Pacific/Easter"
+msgstr "太平洋/復活島"
+
+#. comment for time zone Pacific/Easter
+#: timezones.h:861
+msgid "Easter Island & Sala y Gomez"
+msgstr "復活島以及 Sala y Gomez"
+
+#: timezones.h:862
+msgid "Pacific/Efate"
+msgstr "太平洋/伊法提"
+
+#: timezones.h:863
+msgid "Pacific/Enderbury"
+msgstr "太平洋/英德貝里"
+
+#. comment for time zone Pacific/Enderbury
+#: timezones.h:865
+msgid "Phoenix Islands"
+msgstr "費尼克斯群島"
+
+#: timezones.h:866
+msgid "Pacific/Fakaofo"
+msgstr "太平洋/法克奧佛"
+
+#: timezones.h:867
+msgid "Pacific/Fiji"
+msgstr "太平洋/斐濟"
+
+#: timezones.h:868
+msgid "Pacific/Funafuti"
+msgstr "太平洋/福那富提"
+
+#: timezones.h:869
+msgid "Pacific/Galapagos"
+msgstr "太平洋/加拉帕哥群島"
+
+#. comment for time zone Pacific/Galapagos
+#: timezones.h:871
+msgid "Galapagos Islands"
+msgstr "加拉巴戈斯群島"
+
+#: timezones.h:872
+msgid "Pacific/Gambier"
+msgstr "太平洋/甘畢爾"
+
+#. comment for time zone Pacific/Gambier
+#: timezones.h:874
+msgid "Gambier Islands"
+msgstr "甘比爾群島"
+
+#: timezones.h:875
+msgid "Pacific/Guadalcanal"
+msgstr "太平洋/瓜達爾卡納爾島"
+
+#: timezones.h:876
+msgid "Pacific/Guam"
+msgstr "太平洋/關島"
+
+#: timezones.h:877
+msgid "Pacific/Honolulu"
+msgstr "太平洋/檀香山"
+
+#. comment for time zone Pacific/Honolulu
+#: timezones.h:879
+msgid "Hawaii"
+msgstr "夏威夷"
+
+#: timezones.h:880
+msgid "Pacific/Johnston"
+msgstr "太平洋/強斯敦"
+
+#. comment for time zone Pacific/Johnston
+#: timezones.h:882
+msgid "Johnston Atoll"
+msgstr "強斯頓環礁"
+
+#: timezones.h:883
+msgid "Pacific/Kiritimati"
+msgstr "太平洋/聖誕島"
+
+#. comment for time zone Pacific/Kiritimati
+#: timezones.h:885
+msgid "Line Islands"
+msgstr "列嶼群島"
+
+#: timezones.h:886
+msgid "Pacific/Kosrae"
+msgstr "太平洋/科斯萊"
+
+#. comment for time zone Pacific/Kosrae
+#: timezones.h:888
+msgid "Kosrae"
+msgstr "柯斯雷"
+
+#: timezones.h:889
+msgid "Pacific/Kwajalein"
+msgstr "太平洋/夸加連島"
+
+#: timezones.h:892
+msgid "Pacific/Majuro"
+msgstr "太平洋/馬久羅"
+
+#: timezones.h:895
+msgid "Pacific/Marquesas"
+msgstr "太平洋/馬凱薩斯"
+
+#. comment for time zone Pacific/Marquesas
+#: timezones.h:897
+msgid "Marquesas Islands"
+msgstr "馬克薩斯群島"
+
+#: timezones.h:898
+msgid "Pacific/Midway"
+msgstr "太平洋/中途島"
+
+#. comment for time zone Pacific/Midway
+#: timezones.h:900
+msgid "Midway Islands"
+msgstr "中途島"
+
+#: timezones.h:901
+msgid "Pacific/Nauru"
+msgstr "太平洋/諾魯"
+
+#: timezones.h:902
+msgid "Pacific/Niue"
+msgstr "太平洋/紐埃島"
+
+#: timezones.h:903
+msgid "Pacific/Norfolk"
+msgstr "太平洋/諾福克"
+
+#: timezones.h:904
+msgid "Pacific/Noumea"
+msgstr "太平洋/努美雅"
+
+#: timezones.h:905
+msgid "Pacific/Pago_Pago"
+msgstr "太平洋/帕果帕果"
+
+#: timezones.h:906
+msgid "Pacific/Palau"
+msgstr "太平洋/帛琉"
+
+#: timezones.h:907
+msgid "Pacific/Pitcairn"
+msgstr "太平洋/皮特凱恩"
+
+#: timezones.h:908
+msgid "Pacific/Pohnpei"
+msgstr "太平洋/澎貝島"
+
+#. comment for time zone Pacific/Pohnpei
+#: timezones.h:910
+msgid "Pohnpei (Ponape)"
+msgstr "澎貝島(波納佩島)"
+
+#: timezones.h:911
+msgid "Pacific/Ponape"
+msgstr "太平洋/波那佩"
+
+#: timezones.h:912
+msgid "Pacific/Port_Moresby"
+msgstr "太平洋/摩勒斯比港"
+
+#: timezones.h:913
+msgid "Pacific/Rarotonga"
+msgstr "太平洋/拉羅東加島"
+
+#: timezones.h:914
+msgid "Pacific/Saipan"
+msgstr "太平洋/塞班島"
+
+#: timezones.h:915
+msgid "Pacific/Samoa"
+msgstr "太平洋∕薩摩亞群島"
+
+#: timezones.h:916
+msgid "Pacific/Tahiti"
+msgstr "太平洋/大溪地島"
+
+#. comment for time zone Pacific/Tahiti
+#: timezones.h:918
+msgid "Society Islands"
+msgstr "社會群島"
+
+#: timezones.h:919
+msgid "Pacific/Tarawa"
+msgstr "太平洋/塔拉瓦島"
+
+#. comment for time zone Pacific/Tarawa
+#: timezones.h:921
+msgid "Gilbert Islands"
+msgstr "吉爾伯特群島"
+
+#: timezones.h:922
+msgid "Pacific/Tongatapu"
+msgstr "太平洋/東加塔普"
+
+#: timezones.h:923
+msgid "Pacific/Truk"
+msgstr "太平洋/楚克"
+
+#: timezones.h:924
+msgid "Pacific/Wake"
+msgstr "太平洋/威克島"
+
+#. comment for time zone Pacific/Wake
+#: timezones.h:926
+msgid "Wake Island"
+msgstr "美屬威克島"
+
+#: timezones.h:927
+msgid "Pacific/Wallis"
+msgstr "太平洋/沃利斯"
+
+#: timezones.h:928
+msgid "Pacific/Yap"
+msgstr "太平洋/雅浦島"
+
+#: timezones.h:929
+msgid "Poland"
+msgstr "波蘭"
+
+#: timezones.h:930
+msgid "Portugal"
+msgstr "葡萄牙"
+
+#: timezones.h:931
+msgid "posixrules"
+msgstr "posixrules"
+
+#: timezones.h:932
+msgid "PRC"
+msgstr "中華人民共和國"
+
+#: timezones.h:933
+msgid "PST8PDT"
+msgstr "PST8PDT"
+
+#: timezones.h:934
+msgid "ROC"
+msgstr "中華民國"
+
+#: timezones.h:935
+msgid "ROK"
+msgstr "大韓民國"
+
+#: timezones.h:936
+msgid "Singapore"
+msgstr "新加坡"
+
+#: timezones.h:937
+msgid "Turkey"
+msgstr "土耳其"
+
+#: timezones.h:938
+msgid "UCT"
+msgstr "UCT"
+
+#: timezones.h:939
+msgid "Universal"
+msgstr "通用"
+
+#: timezones.h:940
+msgid "US/Alaska"
+msgstr "美國∕阿拉斯加"
+
+#: timezones.h:941
+msgid "US/Aleutian"
+msgstr "美國∕阿留申群島"
+
+#: timezones.h:942
+msgid "US/Arizona"
+msgstr "美國∕亞利桑納州"
+
+#: timezones.h:943
+msgid "US/Central"
+msgstr "美國∕中部"
+
+#: timezones.h:944
+msgid "US/Eastern"
+msgstr "美國∕東部"
+
+#: timezones.h:945
+msgid "US/East-Indiana"
+msgstr "美國∕東-印第安那"
+
+#: timezones.h:946
+msgid "US/Hawaii"
+msgstr "美國∕夏威夷"
+
+#: timezones.h:947
+msgid "US/Indiana-Starke"
+msgstr "美國∕印第安那-史塔克"
+
+#: timezones.h:948
+msgid "US/Michigan"
+msgstr "美國∕密西根"
+
+#: timezones.h:949
+msgid "US/Mountain"
+msgstr "美國∕山脈區"
+
+#: timezones.h:950
+msgid "US/Pacific"
+msgstr "美國∕太平洋岸"
+
+#: timezones.h:951
+msgid "US/Samoa"
+msgstr "美國∕薩摩亞群島"
+
+#: timezones.h:952
+msgid "UTC"
+msgstr "UTC"
+
+#: timezones.h:953
+msgid "WET"
+msgstr "WET"
+
+#: timezones.h:954
+msgid "W-SU"
+msgstr "W-SU"
+
+#: timezones.h:955
+msgid "Zulu"
+msgstr "祖魯"
diff --git a/panels/datetime/timedated1-interface.xml b/panels/datetime/timedated1-interface.xml
new file mode 100644
index 0000000..3370e0e
--- /dev/null
+++ b/panels/datetime/timedated1-interface.xml
@@ -0,0 +1,28 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+ <interface name="org.freedesktop.timedate1">
+ <property name="Timezone" type="s" access="read"/>
+ <property name="LocalRTC" type="b" access="read"/>
+ <property name="CanNTP" type="b" access="read"/>
+ <property name="NTP" type="b" access="read"/>
+ <method name="SetTime">
+ <arg name="usec_utc" type="x" direction="in"/>
+ <arg name="relative" type="b" direction="in"/>
+ <arg name="user_interaction" type="b" direction="in"/>
+ </method>
+ <method name="SetTimezone">
+ <arg name="timezone" type="s" direction="in"/>
+ <arg name="user_interaction" type="b" direction="in"/>
+ </method>
+ <method name="SetLocalRTC">
+ <arg name="local_rtc" type="b" direction="in"/>
+ <arg name="fix_system" type="b" direction="in"/>
+ <arg name="user_interaction" type="b" direction="in"/>
+ </method>
+ <method name="SetNTP">
+ <arg name="use_ntp" type="b" direction="in"/>
+ <arg name="user_interaction" type="b" direction="in"/>
+ </method>
+ </interface>
+</node>
diff --git a/panels/datetime/tz.c b/panels/datetime/tz.c
new file mode 100644
index 0000000..4fe2305
--- /dev/null
+++ b/panels/datetime/tz.c
@@ -0,0 +1,492 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* Generic timezone utilities.
+ *
+ * Copyright (C) 2000-2001 Ximian, Inc.
+ *
+ * Authors: Hans Petter Jansson <hpj@ximian.com>
+ *
+ * Largely based on Michael Fulbright's work on Anaconda.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <math.h>
+#include <string.h>
+#include <ctype.h>
+#include "tz.h"
+#include "cc-datetime-resources.h"
+
+
+/* Forward declarations for private functions */
+
+static float convert_pos (gchar *pos, int digits);
+static int compare_country_names (const void *a, const void *b);
+static void sort_locations_by_country (GPtrArray *locations);
+static gchar * tz_data_file_get (void);
+static void load_backward_tz (TzDB *tz_db);
+
+/* ---------------- *
+ * Public interface *
+ * ---------------- */
+TzDB *
+tz_load_db (void)
+{
+ g_autofree gchar *tz_data_file = NULL;
+ TzDB *tz_db;
+ FILE *tzfile;
+ char buf[4096];
+
+ tz_data_file = tz_data_file_get ();
+ if (!tz_data_file) {
+ g_warning ("Could not get the TimeZone data file name");
+ return NULL;
+ }
+ tzfile = fopen (tz_data_file, "r");
+ if (!tzfile) {
+ g_warning ("Could not open *%s*\n", tz_data_file);
+ return NULL;
+ }
+
+ tz_db = g_new0 (TzDB, 1);
+ tz_db->locations = g_ptr_array_new ();
+
+ while (fgets (buf, sizeof(buf), tzfile))
+ {
+ g_auto(GStrv) tmpstrarr = NULL;
+ g_autofree gchar *latstr = NULL;
+ g_autofree gchar *lngstr = NULL;
+ gchar *p;
+ TzLocation *loc;
+
+ if (*buf == '#') continue;
+
+ g_strchomp(buf);
+ tmpstrarr = g_strsplit(buf,"\t", 6);
+
+ latstr = g_strdup (tmpstrarr[1]);
+ p = latstr + 1;
+ while (*p != '-' && *p != '+') p++;
+ lngstr = g_strdup (p);
+ *p = '\0';
+
+ loc = g_new0 (TzLocation, 1);
+ loc->country = g_strdup (tmpstrarr[0]);
+ loc->zone = g_strdup (tmpstrarr[2]);
+ loc->latitude = convert_pos (latstr, 2);
+ loc->longitude = convert_pos (lngstr, 3);
+
+#ifdef __sun
+ if (tmpstrarr[3] && *tmpstrarr[3] == '-' && tmpstrarr[4])
+ loc->comment = g_strdup (tmpstrarr[4]);
+
+ if (tmpstrarr[3] && *tmpstrarr[3] != '-' && !islower(loc->zone)) {
+ TzLocation *locgrp;
+
+ /* duplicate entry */
+ locgrp = g_new0 (TzLocation, 1);
+ locgrp->country = g_strdup (tmpstrarr[0]);
+ locgrp->zone = g_strdup (tmpstrarr[3]);
+ locgrp->latitude = convert_pos (latstr, 2);
+ locgrp->longitude = convert_pos (lngstr, 3);
+ locgrp->comment = (tmpstrarr[4]) ? g_strdup (tmpstrarr[4]) : NULL;
+
+ g_ptr_array_add (tz_db->locations, (gpointer) locgrp);
+ }
+#else
+ loc->comment = (tmpstrarr[3]) ? g_strdup(tmpstrarr[3]) : NULL;
+#endif
+
+ g_ptr_array_add (tz_db->locations, (gpointer) loc);
+ }
+
+ fclose (tzfile);
+
+ /* now sort by country */
+ sort_locations_by_country (tz_db->locations);
+
+ /* Load up the hashtable of backward links */
+ load_backward_tz (tz_db);
+
+ return tz_db;
+}
+
+static void
+tz_location_free (TzLocation *loc)
+{
+ g_free (loc->country);
+ g_free (loc->zone);
+ g_free (loc->comment);
+
+ g_free (loc);
+}
+
+void
+tz_db_free (TzDB *db)
+{
+ g_ptr_array_foreach (db->locations, (GFunc) tz_location_free, NULL);
+ g_ptr_array_free (db->locations, TRUE);
+ g_hash_table_destroy (db->backward);
+ g_free (db);
+}
+
+GPtrArray *
+tz_get_locations (TzDB *db)
+{
+ return db->locations;
+}
+
+
+gchar *
+tz_location_get_country (TzLocation *loc)
+{
+ return loc->country;
+}
+
+
+gchar *
+tz_location_get_zone (TzLocation *loc)
+{
+ return loc->zone;
+}
+
+
+gchar *
+tz_location_get_comment (TzLocation *loc)
+{
+ return loc->comment;
+}
+
+
+void
+tz_location_get_position (TzLocation *loc, double *longitude, double *latitude)
+{
+ *longitude = loc->longitude;
+ *latitude = loc->latitude;
+}
+
+/* For timezone map display purposes, we try to highlight regions of the
+ * world that keep the same time. There is no reasonable API to discover
+ * this; at the moment we just group timezones by their non-daylight-savings
+ * UTC offset and hope that's good enough. However, in some cases that
+ * produces confusing results. For example, Irish Standard Time is legally
+ * defined as the country's summer time, with a negative DST offset in
+ * winter; but this results in the same observed clock times as countries
+ * that observe Western European (Summer) Time, not those that observe
+ * Central European (Summer) Time, so we should group Ireland with the
+ * former, matching the grouping implied by data/timezone_*.png.
+ *
+ * This is something of a hack, and there remain other problems with
+ * timezone grouping: for example, grouping timezones north and south of the
+ * equator together where DST is observed at different times of the year is
+ * dubious.
+ */
+struct {
+ const char *zone;
+ gint offset;
+} base_offset_overrides[] = {
+ { "Europe/Dublin", 0 },
+};
+
+glong
+tz_location_get_base_utc_offset (TzLocation *loc)
+{
+ g_autoptr(TzInfo) tz_info = NULL;
+ glong offset;
+ guint i;
+
+ tz_info = tz_info_from_location (loc);
+ offset = tz_info->utc_offset + (tz_info->daylight ? -3600 : 0);
+
+ for (i = 0; i < G_N_ELEMENTS (base_offset_overrides); i++) {
+ if (g_str_equal (loc->zone, base_offset_overrides[i].zone)) {
+ offset = base_offset_overrides[i].offset;
+ break;
+ }
+ }
+
+ return offset;
+}
+
+TzInfo *
+tz_info_from_location (TzLocation *loc)
+{
+ TzInfo *tzinfo;
+ time_t curtime;
+ struct tm *curzone;
+ g_autofree gchar *tz_env_value = NULL;
+
+ g_return_val_if_fail (loc != NULL, NULL);
+ g_return_val_if_fail (loc->zone != NULL, NULL);
+
+ tz_env_value = g_strdup (getenv ("TZ"));
+ setenv ("TZ", loc->zone, 1);
+
+#if 0
+ tzset ();
+#endif
+ tzinfo = g_new0 (TzInfo, 1);
+
+ curtime = time (NULL);
+ curzone = localtime (&curtime);
+
+#ifndef __sun
+ tzinfo->tzname = g_strdup (curzone->tm_zone);
+ tzinfo->utc_offset = curzone->tm_gmtoff;
+#else
+ tzinfo->tzname = NULL;
+ tzinfo->utc_offset = 0;
+#endif
+
+ tzinfo->daylight = curzone->tm_isdst;
+
+ if (tz_env_value)
+ setenv ("TZ", tz_env_value, 1);
+ else
+ unsetenv ("TZ");
+
+ return tzinfo;
+}
+
+
+void
+tz_info_free (TzInfo *tzinfo)
+{
+ g_return_if_fail (tzinfo != NULL);
+
+ if (tzinfo->tzname) g_free (tzinfo->tzname);
+ g_free (tzinfo);
+}
+
+struct {
+ const char *orig;
+ const char *dest;
+} aliases[] = {
+ { "Asia/Istanbul", "Europe/Istanbul" }, /* Istanbul is in both Europe and Asia */
+ { "Europe/Nicosia", "Asia/Nicosia" }, /* Ditto */
+ { "EET", "Europe/Istanbul" }, /* Same tz as the 2 above */
+ { "HST", "Pacific/Honolulu" },
+ { "WET", "Europe/Brussels" }, /* Other name for the mainland Europe tz */
+ { "CET", "Europe/Brussels" }, /* ditto */
+ { "MET", "Europe/Brussels" },
+ { "Etc/Zulu", "Etc/GMT" },
+ { "Etc/UTC", "Etc/GMT" },
+ { "GMT", "Etc/GMT" },
+ { "Greenwich", "Etc/GMT" },
+ { "Etc/UCT", "Etc/GMT" },
+ { "Etc/GMT0", "Etc/GMT" },
+ { "Etc/GMT+0", "Etc/GMT" },
+ { "Etc/GMT-0", "Etc/GMT" },
+ { "Etc/Universal", "Etc/GMT" },
+ { "PST8PDT", "America/Los_Angeles" }, /* Other name for the Atlantic tz */
+ { "EST", "America/New_York" }, /* Other name for the Eastern tz */
+ { "EST5EDT", "America/New_York" }, /* ditto */
+ { "CST6CDT", "America/Chicago" }, /* Other name for the Central tz */
+ { "MST", "America/Denver" }, /* Other name for the mountain tz */
+ { "MST7MDT", "America/Denver" }, /* ditto */
+};
+
+static gboolean
+compare_timezones (const char *a,
+ const char *b)
+{
+ if (g_str_equal (a, b))
+ return TRUE;
+ if (strchr (b, '/') == NULL) {
+ g_autofree gchar *prefixed = NULL;
+
+ prefixed = g_strdup_printf ("/%s", b);
+ if (g_str_has_suffix (a, prefixed))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+char *
+tz_info_get_clean_name (TzDB *tz_db,
+ const char *tz)
+{
+ char *ret;
+ const char *timezone;
+ guint i;
+ gboolean replaced;
+
+ /* Remove useless prefixes */
+ if (g_str_has_prefix (tz, "right/"))
+ tz = tz + strlen ("right/");
+ else if (g_str_has_prefix (tz, "posix/"))
+ tz = tz + strlen ("posix/");
+
+ /* Here start the crazies */
+ replaced = FALSE;
+
+ for (i = 0; i < G_N_ELEMENTS (aliases); i++) {
+ if (compare_timezones (tz, aliases[i].orig)) {
+ replaced = TRUE;
+ timezone = aliases[i].dest;
+ break;
+ }
+ }
+
+ /* Try again! */
+ if (!replaced) {
+ /* Ignore crazy solar times from the '80s */
+ if (g_str_has_prefix (tz, "Asia/Riyadh") ||
+ g_str_has_prefix (tz, "Mideast/Riyadh")) {
+ timezone = "Asia/Riyadh";
+ replaced = TRUE;
+ }
+ }
+
+ if (!replaced)
+ timezone = tz;
+
+ ret = g_hash_table_lookup (tz_db->backward, timezone);
+ if (ret == NULL)
+ return g_strdup (timezone);
+ return g_strdup (ret);
+}
+
+/* ----------------- *
+ * Private functions *
+ * ----------------- */
+
+static gchar *
+tz_data_file_get (void)
+{
+ gchar *file;
+
+ file = g_strdup (TZ_DATA_FILE);
+
+ return file;
+}
+
+static float
+convert_pos (gchar *pos, int digits)
+{
+ gchar whole[10];
+ gchar *fraction;
+ gint i;
+ float t1, t2;
+
+ if (!pos || strlen(pos) < 4 || digits > 9) return 0.0;
+
+ for (i = 0; i < digits + 1; i++) whole[i] = pos[i];
+ whole[i] = '\0';
+ fraction = pos + digits + 1;
+
+ t1 = g_strtod (whole, NULL);
+ t2 = g_strtod (fraction, NULL);
+
+ if (t1 >= 0.0) return t1 + t2/pow (10.0, strlen(fraction));
+ else return t1 - t2/pow (10.0, strlen(fraction));
+}
+
+
+#if 0
+
+/* Currently not working */
+static void
+free_tzdata (TzLocation *tz)
+{
+
+ if (tz->country)
+ g_free(tz->country);
+ if (tz->zone)
+ g_free(tz->zone);
+ if (tz->comment)
+ g_free(tz->comment);
+
+ g_free(tz);
+}
+#endif
+
+
+static int
+compare_country_names (const void *a, const void *b)
+{
+ const TzLocation *tza = * (TzLocation **) a;
+ const TzLocation *tzb = * (TzLocation **) b;
+
+ return strcmp (tza->zone, tzb->zone);
+}
+
+
+static void
+sort_locations_by_country (GPtrArray *locations)
+{
+ qsort (locations->pdata, locations->len, sizeof (gpointer),
+ compare_country_names);
+}
+
+static void
+load_backward_tz (TzDB *tz_db)
+{
+ g_auto(GStrv) lines = NULL;
+ g_autoptr(GBytes) bytes = NULL;
+ const char *contents;
+ guint i;
+
+ tz_db->backward = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ bytes = g_resources_lookup_data ("/org/gnome/control-center/datetime/backward",
+ G_RESOURCE_LOOKUP_FLAGS_NONE, NULL);
+ contents = (const char *) g_bytes_get_data (bytes, NULL);
+
+ lines = g_strsplit (contents, "\n", -1);
+
+ for (i = 0; lines[i] != NULL; i++)
+ {
+ g_auto(GStrv) items = NULL;
+ guint j;
+ char *real, *alias;
+
+ if (g_ascii_strncasecmp (lines[i], "Link\t", 5) != 0)
+ continue;
+
+ items = g_strsplit (lines[i], "\t", -1);
+ real = NULL;
+ alias = NULL;
+ /* Skip the "Link<tab>" part */
+ for (j = 1; items[j] != NULL; j++)
+ {
+ if (items[j][0] == '\0')
+ continue;
+ if (real == NULL)
+ {
+ real = items[j];
+ continue;
+ }
+ alias = items[j];
+ break;
+ }
+
+ if (real == NULL || alias == NULL)
+ g_warning ("Could not parse line: %s", lines[i]);
+
+ /* We don't need more than one name for it */
+ if (g_str_equal (real, "Etc/UTC") ||
+ g_str_equal (real, "Etc/UCT"))
+ real = "Etc/GMT";
+
+ g_hash_table_insert (tz_db->backward, g_strdup (alias), g_strdup (real));
+ }
+}
+
diff --git a/panels/datetime/tz.h b/panels/datetime/tz.h
new file mode 100644
index 0000000..feef165
--- /dev/null
+++ b/panels/datetime/tz.h
@@ -0,0 +1,90 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* Generic timezone utilities.
+ *
+ * Copyright (C) 2000-2001 Ximian, Inc.
+ *
+ * Authors: Hans Petter Jansson <hpj@ximian.com>
+ *
+ * Largely based on Michael Fulbright's work on Anaconda.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#ifndef __sun
+# define TZ_DATA_FILE "/usr/share/zoneinfo/zone.tab"
+#else
+# define TZ_DATA_FILE "/usr/share/lib/zoneinfo/tab/zone_sun.tab"
+#endif
+
+typedef struct _TzDB TzDB;
+typedef struct _TzLocation TzLocation;
+typedef struct _TzInfo TzInfo;
+
+
+struct _TzDB
+{
+ GPtrArray *locations;
+ GHashTable *backward;
+};
+
+struct _TzLocation
+{
+ gchar *country;
+ gdouble latitude;
+ gdouble longitude;
+ gchar *zone;
+ gchar *comment;
+
+ gdouble dist; /* distance to clicked point for comparison */
+};
+
+/* see the glibc info page information on time zone information */
+/* tzname is the default name for the timezone */
+/* utc_offset is offset in seconds from utc */
+/* daylight if non-zero then location obeys daylight savings */
+
+struct _TzInfo
+{
+ gchar *tzname;
+ glong utc_offset;
+ gint daylight;
+};
+
+
+TzDB *tz_load_db (void);
+void tz_db_free (TzDB *db);
+char * tz_info_get_clean_name (TzDB *tz_db,
+ const char *tz);
+GPtrArray *tz_get_locations (TzDB *db);
+void tz_location_get_position (TzLocation *loc,
+ double *longitude, double *latitude);
+char *tz_location_get_country (TzLocation *loc);
+gchar *tz_location_get_zone (TzLocation *loc);
+gchar *tz_location_get_comment (TzLocation *loc);
+glong tz_location_get_base_utc_offset (TzLocation *loc);
+gint tz_location_set_locally (TzLocation *loc);
+TzInfo *tz_info_from_location (TzLocation *loc);
+void tz_info_free (TzInfo *tz_info);
+
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (TzDB, tz_db_free)
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (TzInfo, tz_info_free)
+
+G_END_DECLS
diff --git a/panels/default-apps/cc-default-apps-panel.c b/panels/default-apps/cc-default-apps-panel.c
new file mode 100644
index 0000000..5949fab
--- /dev/null
+++ b/panels/default-apps/cc-default-apps-panel.c
@@ -0,0 +1,198 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2017 Mohammed Sadiq <sadiq@sadiqpk.org>
+ * Copyright (C) 2010 Red Hat, Inc
+ * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+
+#include "cc-default-apps-panel.h"
+#include "cc-default-apps-resources.h"
+
+typedef struct
+{
+ const char *content_type;
+ gint label_offset;
+ /* Patterns used to filter supported mime types
+ when changing preferred applications. NULL
+ means no other types should be changed */
+ const char *extra_type_filter;
+} DefaultAppData;
+
+struct _CcDefaultAppsPanel
+{
+ CcPanel parent_instance;
+
+ GtkWidget *default_apps_grid;
+
+ GtkWidget *web_label;
+ GtkWidget *mail_label;
+ GtkWidget *calendar_label;
+ GtkWidget *music_label;
+ GtkWidget *video_label;
+ GtkWidget *photos_label;
+};
+
+
+G_DEFINE_TYPE (CcDefaultAppsPanel, cc_default_apps_panel, CC_TYPE_PANEL)
+
+static void
+default_app_changed (CcDefaultAppsPanel *self,
+ GtkAppChooserButton *button)
+{
+ g_autoptr(GAppInfo) info = NULL;
+ g_autoptr(GError) error = NULL;
+ DefaultAppData *app_data;
+ int i;
+
+ info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (button));
+ app_data = g_object_get_data (G_OBJECT (button), "cc-default-app-data");
+
+ if (g_app_info_set_as_default_for_type (info, app_data->content_type, &error) == FALSE)
+ {
+ g_warning ("Failed to set '%s' as the default application for '%s': %s",
+ g_app_info_get_name (info), app_data->content_type, error->message);
+ }
+ else
+ {
+ g_debug ("Set '%s' as the default handler for '%s'",
+ g_app_info_get_name (info), app_data->content_type);
+ }
+
+ if (app_data->extra_type_filter)
+ {
+ g_auto(GStrv) entries = NULL;
+ const char *const *mime_types;
+ g_autoptr(GPtrArray) patterns = NULL;
+
+ entries = g_strsplit (app_data->extra_type_filter, ";", -1);
+ patterns = g_ptr_array_new_with_free_func ((GDestroyNotify) g_pattern_spec_free);
+ for (i = 0; entries[i] != NULL; i++)
+ {
+ GPatternSpec *pattern = g_pattern_spec_new (entries[i]);
+ g_ptr_array_add (patterns, pattern);
+ }
+
+ mime_types = g_app_info_get_supported_types (info);
+ for (i = 0; mime_types && mime_types[i]; i++)
+ {
+ int j;
+ gboolean matched = FALSE;
+ g_autoptr(GError) local_error = NULL;
+
+ for (j = 0; j < patterns->len; j++)
+ {
+ GPatternSpec *pattern = g_ptr_array_index (patterns, j);
+ if (g_pattern_spec_match_string (pattern, mime_types[i]))
+ matched = TRUE;
+ }
+ if (!matched)
+ continue;
+
+ if (g_app_info_set_as_default_for_type (info, mime_types[i], &local_error) == FALSE)
+ {
+ g_warning ("Failed to set '%s' as the default application for secondary "
+ "content type '%s': %s",
+ g_app_info_get_name (info), mime_types[i], local_error->message);
+ }
+ else
+ {
+ g_debug ("Set '%s' as the default handler for '%s'",
+ g_app_info_get_name (info), mime_types[i]);
+ }
+ }
+ }
+}
+
+#define OFFSET(x) (G_STRUCT_OFFSET (CcDefaultAppsPanel, x))
+#define WIDGET_FROM_OFFSET(x) (G_STRUCT_MEMBER (GtkWidget*, self, x))
+
+static void
+info_panel_setup_default_app (CcDefaultAppsPanel *self,
+ DefaultAppData *data,
+ guint left_attach,
+ guint top_attach)
+{
+ GtkWidget *button;
+ GtkWidget *label;
+
+ button = gtk_app_chooser_button_new (data->content_type);
+ g_object_set_data (G_OBJECT (button), "cc-default-app-data", data);
+
+ gtk_app_chooser_button_set_show_default_item (GTK_APP_CHOOSER_BUTTON (button), TRUE);
+ gtk_grid_attach (GTK_GRID (self->default_apps_grid), button, left_attach, top_attach,
+ 1, 1);
+ g_signal_connect_object (G_OBJECT (button), "changed",
+ G_CALLBACK (default_app_changed), self, G_CONNECT_SWAPPED);
+
+ label = WIDGET_FROM_OFFSET (data->label_offset);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), button);
+}
+
+static DefaultAppData preferred_app_infos[] = {
+ { "x-scheme-handler/http", OFFSET (web_label), "text/html;application/xhtml+xml;x-scheme-handler/https" },
+ { "x-scheme-handler/mailto", OFFSET (mail_label), NULL },
+ { "text/calendar", OFFSET (calendar_label), NULL },
+ { "audio/x-vorbis+ogg", OFFSET (music_label), "audio/*" },
+ { "video/x-ogm+ogg", OFFSET (video_label), "video/*" },
+ { "image/jpeg", OFFSET (photos_label), "image/*" }
+};
+
+static void
+info_panel_setup_default_apps (CcDefaultAppsPanel *self)
+{
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (preferred_app_infos); i++)
+ {
+ info_panel_setup_default_app (self, &preferred_app_infos[i],
+ 1, i);
+ }
+}
+
+static void
+cc_default_apps_panel_class_init (CcDefaultAppsPanelClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/default-apps/cc-default-apps-panel.ui");
+ gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPanel, default_apps_grid);
+ gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPanel, web_label);
+ gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPanel, mail_label);
+ gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPanel, calendar_label);
+ gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPanel, music_label);
+ gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPanel, video_label);
+ gtk_widget_class_bind_template_child (widget_class, CcDefaultAppsPanel, photos_label);
+}
+
+static void
+cc_default_apps_panel_init (CcDefaultAppsPanel *self)
+{
+ g_resources_register (cc_default_apps_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ info_panel_setup_default_apps (self);
+}
+
+GtkWidget *
+cc_default_apps_panel_new (void)
+{
+ return g_object_new (CC_TYPE_DEFAULT_APPS_PANEL,
+ NULL);
+}
diff --git a/panels/default-apps/cc-default-apps-panel.h b/panels/default-apps/cc-default-apps-panel.h
new file mode 100644
index 0000000..4aca17b
--- /dev/null
+++ b/panels/default-apps/cc-default-apps-panel.h
@@ -0,0 +1,31 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2017 Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_DEFAULT_APPS_PANEL (cc_default_apps_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcDefaultAppsPanel, cc_default_apps_panel, CC, DEFAULT_APPS_PANEL, CcPanel)
+
+GtkWidget *cc_default_apps_panel_new (void);
+
+G_END_DECLS
diff --git a/panels/default-apps/cc-default-apps-panel.ui b/panels/default-apps/cc-default-apps-panel.ui
new file mode 100644
index 0000000..ac8db76
--- /dev/null
+++ b/panels/default-apps/cc-default-apps-panel.ui
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcDefaultAppsPanel" parent="CcPanel">
+ <child type="content">
+ <object class="GtkBox">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="margin_top">32</property>
+ <property name="margin_bottom">32</property>
+ <property name="margin_start">24</property>
+ <property name="margin_end">24</property>
+ <property name="halign">center</property>
+ <property name="valign">start</property>
+ <property name="spacing">10</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkGrid" id="default_apps_grid">
+ <property name="column_spacing">12</property>
+ <property name="row_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="web_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Web</property>
+ <property name="use_underline">True</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="mail_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Mail</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="row">1</property>
+ <property name="column">0</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="calendar_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Calendar</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="row">2</property>
+ <property name="column">0</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="music_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">M_usic</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="row">3</property>
+ <property name="column">0</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="video_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Video</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="row">4</property>
+ <property name="column">0</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label25">
+ <property name="label"> </property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label26">
+ <property name="label"> </property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label27">
+ <property name="label"> </property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label28">
+ <property name="label"> </property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label29">
+ <property name="label"> </property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">4</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="photos_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Photos</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="row">5</property>
+ <property name="column">0</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label33">
+ <property name="label"> </property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">5</property>
+ </layout>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/default-apps/default-apps.gresource.xml b/panels/default-apps/default-apps.gresource.xml
new file mode 100644
index 0000000..a2029e7
--- /dev/null
+++ b/panels/default-apps/default-apps.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/default-apps">
+ <file preprocess="xml-stripblanks">cc-default-apps-panel.ui</file>
+ </gresource>
+</gresources>
diff --git a/panels/default-apps/gnome-default-apps-panel.desktop.in.in b/panels/default-apps/gnome-default-apps-panel.desktop.in.in
new file mode 100644
index 0000000..f03c3ee
--- /dev/null
+++ b/panels/default-apps/gnome-default-apps-panel.desktop.in.in
@@ -0,0 +1,18 @@
+[Desktop Entry]
+Name=Default Applications
+Comment=Configure Default Applications
+Exec=gnome-control-center default-apps
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-default-apps-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;X-GNOME-Settings-Panel;X-GNOME-DetailsSettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=info
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: Search terms to find the Default Applications panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=default;application;preferred;media;
diff --git a/panels/default-apps/icons/meson.build b/panels/default-apps/icons/meson.build
new file mode 100644
index 0000000..0e9b7ff
--- /dev/null
+++ b/panels/default-apps/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-default-apps-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/default-apps/icons/scalable/org.gnome.Settings-default-apps-symbolic.svg b/panels/default-apps/icons/scalable/org.gnome.Settings-default-apps-symbolic.svg
new file mode 100644
index 0000000..2dd3fd4
--- /dev/null
+++ b/panels/default-apps/icons/scalable/org.gnome.Settings-default-apps-symbolic.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <path d="m 7.988281 0.0078125 c -0.429687 0 -0.8125 0.2734375 -0.949219 0.6835935 l -1.449218 4.339844 l -4.589844 -0.015625 c -0.9804688 -0.003906 -1.382812 1.257813 -0.582031 1.820313 l 3.625 2.554687 l -1.5 4.285156 c -0.316407 0.902344 0.6875 1.691407 1.492187 1.171875 l 4.003906 -2.59375 l 3.894532 2.585938 c 0.800781 0.53125 1.816406 -0.257813 1.5 -1.160156 l -1.503906 -4.289063 l 3.644531 -2.578125 c 0.789062 -0.5625 0.394531 -1.808594 -0.574219 -1.8125 l -4.660156 -0.015625 l -1.402344 -4.285156 c -0.132812 -0.410157 -0.515625 -0.6875002 -0.949219 -0.6914065 z m 0 0" fill="#2e3436"/>
+</svg>
diff --git a/panels/default-apps/meson.build b/panels/default-apps/meson.build
new file mode 100644
index 0000000..3edf34d
--- /dev/null
+++ b/panels/default-apps/meson.build
@@ -0,0 +1,43 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+sources = files(
+ 'cc-default-apps-panel.c'
+)
+
+resource_data = files(
+ 'cc-default-apps-panel.ui'
+)
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname.underscorify (),
+ dependencies: resource_data,
+ export: true
+)
+
+panels_libs += static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [ top_inc, common_inc ],
+ dependencies: common_deps,
+ c_args: cflags
+)
+
+subdir('icons')
diff --git a/panels/diagnostics/cc-diagnostics-panel.c b/panels/diagnostics/cc-diagnostics-panel.c
new file mode 100644
index 0000000..9aeca6e
--- /dev/null
+++ b/panels/diagnostics/cc-diagnostics-panel.c
@@ -0,0 +1,143 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2018 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#include "cc-diagnostics-panel.h"
+#include "cc-diagnostics-resources.h"
+#include "cc-util.h"
+#include "shell/cc-application.h"
+
+#include <gio/gdesktopappinfo.h>
+#include <glib/gi18n.h>
+
+struct _CcDiagnosticsPanel
+{
+ CcPanel parent_instance;
+
+ AdwPreferencesGroup *diagnostics_group;
+ GtkSwitch *abrt_switch;
+
+ GSettings *privacy_settings;
+};
+
+CC_PANEL_REGISTER (CcDiagnosticsPanel, cc_diagnostics_panel)
+
+/* Static init function */
+
+static void
+set_panel_visibility (CcPanelVisibility visibility)
+{
+ CcApplication *application;
+
+ application = CC_APPLICATION (g_application_get_default ());
+ cc_shell_model_set_panel_visibility (cc_application_get_model (application),
+ "diagnostics",
+ visibility);
+
+}
+
+static void
+abrt_appeared_cb (GDBusConnection *connection,
+ const gchar *name,
+ const gchar *name_owner,
+ gpointer user_data)
+{
+ g_debug ("ABRT appeared");
+ set_panel_visibility (CC_PANEL_VISIBLE);
+}
+
+static void
+abrt_vanished_cb (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ g_debug ("ABRT vanished");
+ set_panel_visibility (CC_PANEL_VISIBLE_IN_SEARCH);
+}
+
+void
+cc_diagnostics_panel_static_init_func (void)
+{
+ g_bus_watch_name (G_BUS_TYPE_SYSTEM,
+ "org.freedesktop.problems.daemon",
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ abrt_appeared_cb,
+ abrt_vanished_cb,
+ NULL,
+ NULL);
+
+ set_panel_visibility (CC_PANEL_VISIBLE_IN_SEARCH);
+}
+
+static void
+cc_diagnostics_panel_finalize (GObject *object)
+{
+ CcDiagnosticsPanel *self = CC_DIAGNOSTICS_PANEL (object);
+
+ g_clear_object (&self->privacy_settings);
+
+ G_OBJECT_CLASS (cc_diagnostics_panel_parent_class)->finalize (object);
+}
+
+static void
+cc_diagnostics_panel_class_init (CcDiagnosticsPanelClass *klass)
+{
+ GObjectClass *oclass = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ oclass->finalize = cc_diagnostics_panel_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/diagnostics/cc-diagnostics-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcDiagnosticsPanel, diagnostics_group);
+ gtk_widget_class_bind_template_child (widget_class, CcDiagnosticsPanel, abrt_switch);
+}
+
+static void
+cc_diagnostics_panel_init (CcDiagnosticsPanel *self)
+{
+ g_autofree gchar *os_name = NULL;
+ g_autofree gchar *url = NULL;
+ g_autofree gchar *msg = NULL;
+ g_autofree gchar *link = NULL;
+
+ g_resources_register (cc_diagnostics_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->privacy_settings = g_settings_new ("org.gnome.desktop.privacy");
+
+ g_settings_bind (self->privacy_settings, "report-technical-problems",
+ self->abrt_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ os_name = g_get_os_info (G_OS_INFO_KEY_NAME);
+ if (!os_name)
+ os_name = g_strdup ("GNOME");
+ url = g_get_os_info (G_OS_INFO_KEY_PRIVACY_POLICY_URL);
+ if (!url)
+ url = g_strdup ("http://www.gnome.org/privacy-policy");
+ /* translators: Text used in link to privacy policy */
+ link = g_strdup_printf ("<a href=\"%s\">%s</a>", url, _("Learn more"));
+ /* translators: The first '%s' is the distributor's name, such as 'Fedora', the second '%s' is a link to the privacy policy */
+ msg = g_strdup_printf (_("Sending reports of technical problems helps us improve %s. Reports "
+ "are sent anonymously and are scrubbed of personal data. %s"),
+ os_name, link);
+ adw_preferences_group_set_description (self->diagnostics_group, msg);
+}
diff --git a/panels/diagnostics/cc-diagnostics-panel.h b/panels/diagnostics/cc-diagnostics-panel.h
new file mode 100644
index 0000000..3875ec5
--- /dev/null
+++ b/panels/diagnostics/cc-diagnostics-panel.h
@@ -0,0 +1,32 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2018 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_DIAGNOSTICS_PANEL (cc_diagnostics_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcDiagnosticsPanel, cc_diagnostics_panel, CC, DIAGNOSTICS_PANEL, CcPanel)
+
+void cc_diagnostics_panel_static_init_func (void);
+
+G_END_DECLS
diff --git a/panels/diagnostics/cc-diagnostics-panel.ui b/panels/diagnostics/cc-diagnostics-panel.ui
new file mode 100644
index 0000000..a08a4ca
--- /dev/null
+++ b/panels/diagnostics/cc-diagnostics-panel.ui
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcDiagnosticsPanel" parent="CcPanel">
+ <child type="content">
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup" id="diagnostics_group">
+ <property name="title" translatable="yes">Problem Reporting</property>
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">_Automatic Problem Reporting</property>
+ <property name="use-underline">True</property>
+ <property name="activatable-widget">abrt_switch</property>
+ <child type="suffix">
+ <object class="GtkSwitch" id="abrt_switch">
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Enable</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/diagnostics/diagnostics.gresource.xml b/panels/diagnostics/diagnostics.gresource.xml
new file mode 100644
index 0000000..541d62c
--- /dev/null
+++ b/panels/diagnostics/diagnostics.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/diagnostics">
+ <file preprocess="xml-stripblanks">cc-diagnostics-panel.ui</file>
+ </gresource>
+</gresources>
diff --git a/panels/diagnostics/gnome-diagnostics-panel.desktop.in.in b/panels/diagnostics/gnome-diagnostics-panel.desktop.in.in
new file mode 100644
index 0000000..68d4cb0
--- /dev/null
+++ b/panels/diagnostics/gnome-diagnostics-panel.desktop.in.in
@@ -0,0 +1,19 @@
+[Desktop Entry]
+Name=Diagnostics
+Comment=Report your problems
+Exec=gnome-control-center diagnostics
+# FIXME
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-diagnostics-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-PrivacySettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=privacy
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: Search terms to find the Diagnostics panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=diagnostics;crash;
diff --git a/panels/diagnostics/icons/meson.build b/panels/diagnostics/icons/meson.build
new file mode 100644
index 0000000..c1b200d
--- /dev/null
+++ b/panels/diagnostics/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-diagnostics-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/diagnostics/icons/scalable/org.gnome.Settings-diagnostics-symbolic.svg b/panels/diagnostics/icons/scalable/org.gnome.Settings-diagnostics-symbolic.svg
new file mode 100644
index 0000000..34e4afc
--- /dev/null
+++ b/panels/diagnostics/icons/scalable/org.gnome.Settings-diagnostics-symbolic.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <g fill="#2e3436">
+ <path d="m 3.011719 1 c -1.644531 0 -3.0000002 1.355469 -3.0000002 3 v 6 c 0 1.644531 1.3554692 3 3.0000002 3 h 1.988281 v -2 h -1.988281 c -0.570313 0 -1 -0.429688 -1 -1 v -6 c 0 -0.570312 0.429687 -1 1 -1 h 8.976562 c 0.570313 0 1 0.429688 1 1 v 1 h 2 v -1 c 0 -1.644531 -1.355469 -3 -3 -3 z m 0 0"/>
+ <path d="m 5.011719 14 c -1.105469 0 -2 0.894531 -2 2 h 10 c 0 -1.105469 -0.894531 -2 -2 -2 z m 0 0"/>
+ <path d="m 9.5 4 c -2.484375 0 -4.5 2.015625 -4.5 4.5 s 2.015625 4.5 4.5 4.5 c 0.847656 0 1.675781 -0.242188 2.390625 -0.695312 l 2.402344 2.402343 c 0.390625 0.390625 1.023437 0.390625 1.414062 0 s 0.390625 -1.023437 0 -1.414062 l -2.398437 -2.398438 c 0.449218 -0.71875 0.691406 -1.546875 0.691406 -2.394531 c 0 -2.484375 -2.015625 -4.5 -4.5 -4.5 z m 0 2 c 1.378906 0 2.5 1.121094 2.5 2.5 s -1.121094 2.5 -2.5 2.5 s -2.5 -1.121094 -2.5 -2.5 s 1.121094 -2.5 2.5 -2.5 z m 0 0"/>
+ </g>
+</svg>
diff --git a/panels/diagnostics/meson.build b/panels/diagnostics/meson.build
new file mode 100644
index 0000000..0061d38
--- /dev/null
+++ b/panels/diagnostics/meson.build
@@ -0,0 +1,41 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+sources = files('cc-diagnostics-panel.c')
+
+resource_data = files('cc-diagnostics-panel.ui')
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname,
+ dependencies: resource_data,
+ export: true
+)
+
+cflags += '-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir)
+
+panels_libs += static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [top_inc, common_inc],
+ dependencies: common_deps,
+ c_args: cflags
+)
+
+subdir('icons')
diff --git a/panels/display/TODO b/panels/display/TODO
new file mode 100644
index 0000000..f09425c
--- /dev/null
+++ b/panels/display/TODO
@@ -0,0 +1,837 @@
+Highlevel overview:
+
+Tablet rotation things
+only when there is a tablet attached.
+
+Here is the OS X Display menu:
+
+ Detect Displays
+ Turn on mirroring
+ --------------------------
+ SyncMaster
+ - 1280 x 1024, 60 Hz, Millions
+ - 1344 x ...
+ --------------------------------
+ Color LCD
+ - 1024 x 1024 ...
+ --------------------------
+ Displays Preferences
+
+ Color LCD means "laptop panel".
+
+- GTK+ work.
+
+ Allow applications to be notified whenever monitors are added
+ or removed. Allow applications to get more detailed
+ information about the connected monitors.
+
+ The main complication is that XRRGetScreenResources() is very
+ slow. We could call it only when the X server sends an event,
+ but it's not desirable to have every application freeze for
+ half a second. And certainly not desirable to have the X
+ server block for n * 0.5 seconds.
+
+ With the X server work below we should be fine just calling
+ XRRGetScreenResources on startup and in response to events.
+
+- X server work:
+
+ X server needs to poll for whether a monitor is plugged
+ in. Whenever it detects a change, it should do an EDID query,
+ and cache the resulting information. That way XRRGetScreenResources()
+ can be the speed of a normal roundtrip. It's desirable that
+ normal client requests can still be processed during the EDID
+ querying, but only a nice-to-have.
+
+ Drivers need to work reliably. There could be substantial work
+ here. For F9, possibly only the Intel driver can be made to
+ work.
+
+ Interrupts and events must be generated whenever something changes
+ about the outputs, if necessary by polling.
+
+ Events must be emitted whenever something changes, including when
+ the reason for the change is a manual change.
+
+ The maximum framebuffer must be dynamically changable.
+
+- Control panel work:
+ Capplet needs to be written. The main complications:
+
+ - It needs to pay attention to events from the X server
+ and update itself, ie., add show new monitors if they become
+ available when the applet is shown.
+
+ - It needs to store information under a key computed
+ from a monitor identifier. The complication here is that
+ it's not completely clear how to do this in GConf.
+
+ - Would probably be worthwhile to drop libgnome/libgnomeui from
+ the craplets.
+
+- Metacity work:
+ - Metacity is already Xinerama aware, but it needs to update itself
+ when monitors come and go.
+
+- GNOME panel work:
+ - Is already Xinerama aware, but needs to listen and update itself
+ when monitors change.
+
+- Evince work:
+ - Make sure it deals sensibly with multiple monitors
+
+- OpenOffice work:
+ - Make sure it deals sensibly with multiple monitors
+
+- An Xlib call to just return all the available information would be
+ useful. At the moment we have to do a bunch of roundtrips to
+ get the information. This is a would-be-nice though.
+
+- A dbus service could be written that pops up the applet whenever a
+ monitor. It should only pop up if the new monitor is unknown. This
+ is at best a nice-to-have, and low priority in my opinion.
+
+
+******************* Metacity
+
+Havoc:
+
+> I was just talking to bryan about this and "helping" him design it ;-)
+
+> But I wanted to be sure and lobby for a fix window managers
+> need. Basically right now the WM can't tell "physical" from
+> "logical" monitors.
+
+> A "logical" monitor is a desktop; it has its own panel, windows
+> maximize to it, etc.
+
+> A "physical" monitor is a piece of hardware.
+
+> Sometimes people want to combine physical monitors into a video wall
+> or just two monitors treated as one. Or at least a couple of noisy
+> people in bugzilla want to do this.
+
+> When people talk about a "Xinerama aware" app or WM they usually
+> mean that all physical monitors are treated as logical monitors,
+> while lack of Xinerama-aware means treating the entire X screen (all
+> physical monitors) as one logical monitor.
+
+> The problem is that the setting for "ignore Xinerama" or "don't be
+> Xinerama aware" should be global to the desktop (GTK, all apps, WM)
+> and should not be a window manager setting.
+
+> Bryan thought people who wanted non-Xinerama-aware should just use
+> fvwm, which may be right, but what I'd say is that if there is any
+> setting for this, it should be desktop-global and in this monitor
+> config dialog.
+
+> It should not be a metacity or Compiz option, but in some way an X
+> option in short. The implementation could be either an X server
+> feature or an EWMH hint or whatever, but it should be controlled by
+> the monitor config dialog and used by apps, GTK, etc. in addition to
+> used by the WM.
+
+> People tend to insist this should be a WM option, but that's just
+> busted, since GTK and apps also have Xinerama-awareness features.
+
+
+******************* EDID
+
+edid-decode enhancements:
+
+- Rejects years <= 0x0f for all versions, but this should only be done
+ for monitors claiming conformance to 1.4 (since 1.4 was released in
+ 2006). A monitor produced in 2005 should have 0x0f - it's the only
+ reasonable thing to do.
+
+- Uses 0x80 as the conformance mask for 1.4, should be 0
+
+- Should read from stdin
+
+- Should parse xrandr -verbose output more robustly
+
+- Color depth computation is wrong. It uses the formula
+
+ (edid[0x14] >> 3) + 2
+
+ The correct formula to use is
+
+ (edid[0x14] & 0x70) >> 3 + 4
+
+-
+
+-=-=-=-
+Computing a display name from EDID information:
+
+ vendor = lookup_vendor (code);
+
+ if (dsc_product && !is_gobbledigook (dsc_product))
+ {
+ if (vendor && !fuzzy_string_search (vendor, dsc_product))
+ prepend (vendor);
+ }
+ else
+ {
+ if (vendor)
+ append (vendor);
+ else
+ append ("Unknown");
+ }
+
+ if (has size)
+ {
+ convert_to_inches()
+
+ append (" %d\"", inches)
+ }
+
+(Does this internationalize at all)?
+
+We also need the ability to get laptop names. The laptop panel may report
+a manufacturer that has nothing to do with the laptop manufacturer.
+
+Needed XRandr output properties:
+
+- Modes that the monitor supports, or enough information that the
+ client can go throught the list of modes for the relevant
+ CRTC/Outputs and filter those out that the monitor can't support.
+
+- The preferred mode, if any. Also useful if we could get a "strongly
+ preferred" indication if it's an LCD with a fixed resolution.
+
+- Sufficient information that a fairly specific identifier can be
+ computed. The algorithm the client should use is:
+
+ 1 Have we seen exactly this monitor before? If yes, use
+ settings for that.
+
+ 2 Have we seen a monitor with similar specs before? If yes,
+ use settings for that. (But don't save, unless the user
+ changes the settings).
+
+ 3 Otherwise, use some reasonable default for the monitor and
+ save it.
+
+ A setting should only be used if the CRTC/Output allows it. Ie,. if
+ a user has installed a new video card, then previously-used settings
+ may no longer apply, so this must be checked every time.
+
+ (1) Implies that we really need a globally unique identifier for
+ monitors. (2) is useful in an enterprise setting, but not absolutely
+ critical, since (3) would still handle the majority of cases.
+
+ There is a question here: Where are machine specific preferences
+ stored? Havoc mentions three possibilities here:
+
+ http://mail.gnome.org/archives/gnomecc-list/2001-October/msg00023.html
+
+ I'm not sure if any of them are implementable at this point. Also
+ (1) may mostly take care of the problem.
+
+
+ Usecases:
+
+ 1. Fixed setup with some number of monitors.
+ - They should be set to the correct mode on login.
+ Note that this involves setting the right position in the
+ framebuffer too.
+
+ What if someone swaps two monitors? Users are going to expect
+ that the images will switch position.
+
+ 2. Laptop being moved between home and work
+ - Setups should be detected and the correct mode set, at least on
+ login, but ideally when you put the laptop into the docking
+ station.
+
+ 3. Laptop gets projector plugged in.
+
+ Note the same model monitor can be used in two different ways. Ie.,
+ at home, it's being used at one resolution, at work the same type of
+ monitor is used at a different resolution.
+
+ Simple solution:
+
+ - The on-disk database is just a list of monitors. Each monitor has an
+ associated mode. This has these problems:
+ - If someone uses the same monitor model in two different ways.
+ - If someone swaps the monitors around
+
+ Better solution
+
+ - The on-disk database is a list of configurations, where a
+ configuration is a list of monitors and what outputs they are
+ connected to, and the position in the framebuffer.
+
+ - Picking a default configuration is then a matter of selecting the
+ closest existing configuration from the database.
+
+ - If the stored configuration is a subset of the existing,
+ then use that - then pick the best mode available for the
+ rest of the monitors
+
+ - If the stored configuration is a superset of the existing,
+ then use the projection of the configuration onto the monitors.
+
+ - Pick the configuration with the most overlap in monitors.
+ Although, if a configuration differs only in what outputs
+ they are connected to, then those outputs should probably
+ get their original modes set.
+
+ - Or maybe simply:
+
+ - If there is an exact match, use it, if not, pick a default.
+
+ - Picking a new default must never change the mode of any existing
+ output.
+
+******************* Capplet
+
+Somehow the applet will find out that a new monitor is plugged in
+(either through notification, or through a refresh button). When this
+happens, this monitor is looked up in a database and if it is found,
+some suitable mode is set.
+
+Restrictions on the modes:
+
+- Monitors that are already plugged in should not get their mode
+ changed just because a new monitor is plugged in.
+
+- If the exact configuration of monitors is known, and all the old
+ monitors have the same mode as the known configuration, then just use
+ the known configuration. Also do this, if the configuration is a
+ subset of something known.
+
+- Otherwise, if the configuration is a subset of a known configuration
+ where the only difference is that existing monitors have different
+ modes, then try and convert that mode to something we can know
+ about. Maybe configurations should be stored in terms of edges that
+ line up.
+
+- Otherwise, just pick some good default for the mode, probably based
+ on the EDID prferred mode if possible. By default cloning is
+ probably best.
+
+- How do virtual desktops interact with this?
+
+
+g-s-d:
+
+- On startup
+
+ - It reads the configuration file into memory
+
+ capplet --configure
+
+ - It gathers the existing configuration from randr
+
+ - If the existing config is in the file, set that mode
+
+- On changes, including changes to the config file [this is crack]
+
+ - Reread configuration file
+
+ - Compare new configuration to database, if it is there, set the
+ mode as appropriate
+
+ - If a monitor was added, pop up a bubble
+
+ capplet --show-bubble
+
+ capplet --set-mode
+
+capplet
+
+- On changes
+
+ - Update GUI
+
+- When user changes something,
+
+ - Write configuration to file
+
+ - Signal gsd somehow
+
+Schemes:
+ - configuration file changes
+ - randr code will have to be shared between gcc and gsd
+
+ - binary installed by gcc
+ - something will still have to listen for changes to pop
+ up the notification bubble.
+
+Structure of capplet:
+
+- There is a database on disk with monitors and their corresponding
+ settings.
+
+- On startup, this database is read into memory. When the user accepts
+ new settings, it is written back to disk.
+
+- When something changes about the settings
+
+ - If new configuration is in the database, use that mode
+
+ - Else, find all outputs that are now connected but weren't before,
+ and set a default mode for them.
+
+ - If GUI is running, update graphics.
+
+
+ - Notification thing:
+ - if
+
+ - if the new configuration is found in the database, use it
+
+ and added if they are not already there. Initial settings are
+ 1 what the output is already doing, if anything
+ 2 based on an existing sufficiently similar monitor, if possible
+ 3 some reasonable default.
+
+- When the user changes settings in the GUI, the corresponding monitor
+ in the database is updated.
+
+- Whenever the GUI settings change, for all displayed monitors the
+ possible modes are recomputed.
+
+- Whenever a new monitor is selected in the GUI, it first gets all its
+ possible modes computed based on the selections on other
+ outputs. Then, if the possible modes include the existing choice of
+ resolution, that is selected.
+
+ Actually,
+
+ - initially, the settings are copied from the current settings
+
+ - whenever a gui setting changes for a monitor, all the other
+ monitors get their list of choices set to whatever is possible
+ given the chocie for the current monitor. A 'desired mode' is
+ maintained, and the closest choice to that is displayed. Whenever
+ the user actively selects something, that becomes the desired mode
+ for that monitor.
+
+- Required
+
+ - Generate all outputs that are newly connected
+
+ foreach_newly_connected (Configuration *before, Configuration *after,
+ OutputFunc);
+
+ - A way to generate the best mode for a connected output
+
+ existing best_mode() can probably be used
+
+ - Given a list of modes, pick the one closest to a given mode.
+
+ (a possibility here is: pick an exact match, if that's
+ impossible, then pick the best one with the same
+ width/height, if that's impossible, then just pick the
+ best mode on the list).
+
+ - For a configuation, fix the mode for a subset of the outputs, then
+ list the combinations for the rest of the outputs.
+
+ An obvious possibility here is to simply list all possibilities,
+ then weed out those that don't work. Is this too expensive?
+ It might be.
+
+Structure of login time program:
+
+- The configuration database is read
+
+- The current hardware configuration is generated
+
+- If the current configuration is found in the database, that mode is set.
+
+- If it isn't found, then nothing changes.
+
+ This could just be gnome-screen-resolution-capplet --reset
+
+******************* Things that need to be done to the xrandr.patch:
+
+===
+
+XRRGetScreenResources() is a roundtrip and very slow (~0.5 s). GTK+
+needs to keep information up-to-date by tracking events rather than
+calling this function. In fact we probably can't call it at all unless
+its performance improves significantly.
+
+If EDID processing really has to be this slow, and we can't get
+interrupts when monitors are plugged in, then we have a problem,
+because we can't do anything this expensive once per second.
+
+
+Detailed notes (but most of the patch should be rewritten):
+
+
+=== FIXME in gdkscreen-x11.c in get_width_mm()
+
+/* monitor pixel width / screen pixel width * screen_physical width */
+
+
+
+=== Check for 1.2 library
+
+The patch should check that the 1.2 version of the XRandR library is
+available before using the functions. A possibility is to not use any
+RandR unless 1.2 is available, another is to conditionalize the code.
+
+The most sane thing is probably to just require 1.2.
+
+On the other hand, installing a newer gtk+ on a system with older X is
+probably not that unusual, so maybe it's better to do the full 1.0,
+vs. 1.1 vs 1.2 check.
+
+For now it just requires 1.2.
+
+Actually, this might be fine because the only place where we make use
+of a 1.1 library is in the _gdk_x11_screen_size_changed() function,
+but there we have a fallback that just updates the variables in the
+Screen struct itself.
+
+So, only defining HAVE_RANDR if we detect 1.2 should be ok.
+
+=== Monitor information available
+
+- Subpixel information. This should be set automatically for the fonts and
+ store under the name of the monitor. If the user changes the font
+ configuration, that change should also be stored under the monitor name.
+
+- When a monitor we don't know about is plugged in, a configuration should
+ be generated:
+
+ - Screen size, computed based on the location of the screens
+
+ - RGBA information
+
+ - Whether the screen has a panel on it
+
+ - If there is a conflict between stored information and EDID,
+ the stored information wins
+
+
+
+New API so far:
+
+(* monitors_changed) signal
+gdk_screen_get_monitor_width_mm()
+gdk_screen_get_monitor_height_mm()
+gdk_screen_get_monitor_name() => Note this is the output (eg. "DVI-0")
+
+We should probably also have
+get_manufacturer()
+get_serial()
+get_resolutions()
+
+etc.
+
+Should there be a GdkMonitor object that would correspond to an
+output? Or maybe GdkOutput?
+
+screen_list_monitors()
+
+
+*************************** Issues XRandR/Xserver
+
+- We need polling in the X server, whenever something changes, X must
+ recompute the information and cache it, then send an event. Note the
+ situation where the user disconnects and reconnects a monitor within
+ the polling interval. The event could missed in that case since the polling
+ cannot do a full EDID query. Difficult to see a way around this.
+
+ Actually, DDC allows random access, so it should be possible to just
+ read theq vendor id and manufacturer codes. This can be done once a
+ second without a problem. The polling should be turned off in power
+ saving mode anyway.
+
+ - Driver work:
+
+ - Intel driver:
+
+ - EDID information is not reported for VGA when the output is not
+ turned on (i945 laptop).
+
+ - Screen size must be dynamically changable. (No xorg.conf changes
+ should be required).
+
+ - Make use of ACPI information when possible.
+
+ Adam has code on his freedesktop page.
+
+ - i830 laptop can be put in a state where XRandr reports that no
+ outputs are connected to a CRTC, but the panel is on.
+
+ - Plug in VGA
+ - xrandr --auto
+ - xrandr --output VGA --off
+ - run chk
+ - xrandr --verbose will now not report any outputs as turned on
+ - run chk again - all screens will be turned off
+
+ - Small Sun monitor - an 1152x921 mode is generated, but the
+ monitor doesn't handle that. The monitor itself only claims to
+ handle 1152x920. It doesn't look to me like there is anything
+ in the EDID information that would indicate that it could handle
+ 1152x921.
+
+ This happens with a radeon as wellso it may be a bug in the
+ generic X server EDID parsing. The X server apparently
+ interpretes the standard timing 1152x920 as 1152x921.
+
+ This happens because the X server uses
+
+ hsize * 4 / 5
+
+ which gives 921 for 1152. By using
+
+ (hsize / 5) * 4
+
+ you get 920. The 66 Hz version can bet set, the 76 Hz mode gets
+ sync out of range. (Would be interesting to find out whether the
+ 1152x920 ModeLine would allow the 76 Hz version to be set).
+
+ This is for the ATI driver as shipped in F8:
+
+ - XRRGetScreenResources() takes half a second.
+
+ - Adam has now removed a workaround that caused some of the slowdown.
+
+ - If a DVI monitor is disconnected, you get "Unknown" for connection
+ status.
+
+ - If a VGA monitor is plugged in, then EDID information is not
+ available, even after running xrandr --verbose. The monitor has
+ to be plugged in at driver startup time, apparently.
+
+ - Logging out and logging back in often results in some random mode being
+ set. We need mode selection to not be completely screwed up.
+ Currently it is.
+
+ - The set up at server startup needs to be fixed. *If* randr actually works,
+ then we might be able to do something sensible.
+
+ - We need to revisit the idea that many monitors have broken EDID data.
+ This may be less widespread than previously believed.
+
+- It may be useful to return the connector names as identifiers instead
+ of relying on UTF-8 strings. Ie., have an enum
+
+ { UNKNOWN, OTHER, DVI, VGA, HDMI, ..., }
+
+ in addition to the string. The difference between UNKNOWN and OTHER is that
+ UNKNOWN means the driver doesn't know, whereas OTHER means it is something
+ not listed in the enum (which could be listed in a later version).
+
+- Mouse cursor should be confined to the visible area. (It is already, I think)
+
+- It looks like EDID information is only available for one output
+ even though it is actually read according to the log file.
+ (nv, intel drivers)
+
+
+*********************************
+
+
+
+DONE:
+
+Server work:
+
+ - i830 laptop incorrectly reports BadMatch when you configure the
+ CRTC to drive both VGA and LVDS with the 1024x768 mode that both
+ outputs can handle. (It should return 'failed' if it can't do
+ that). Same for i945 laptop. It seems as if the same CRTC can't
+ drive more than one output at the same time on Intel.
+
+ This was a client bug, but the documentation for SetCrtcConfig
+ should say that BadMatch will be returned if the outputs aren't
+ clones.
+
+GTK+ patch is in now.
+
+=== Add helper function
+
+
++ if (screen_x11->randr12)
++ {
++ XRRScreenResources *sr;
++ XRROutputInfo *output;
++ gchar *retval;
++
++ sr = XRRGetScreenResources ( screen_x11->xdisplay,
++ screen_x11->xroot_window );
++
++ output = XRRGetOutputInfo ( screen_x11->xdisplay,
++ sr,
++ (RROutput)screen_x11->act_outputs[monitor_num]
+);
+
+ Might be worthwhile to factor this out into a
+ gdk_screen_get_output_info (screen, monitor_num)
+ helper function ?
+
+Instead of cutting and pasting all over creation
+
+* Calling XRRGetScreenResources all the time is not going to fly. It
+ takes hundreds of milliseconds ... Even if it didn't, it wouldn't
+ be acceptable to do all those roundtrips.
+
+
+=== Some g_prints left
+
+
+=== Version check
+
+Should be (maj > 1) || (maj == 1 && min >= 2)
+
+
+=== Grep for TODO
+
+
+=== Setup XRRSelectInput()
+
+ You should call XRRSelectInput() at the same place where you are
+ calling XSelectInput() right now. The right place to handle the
+ XRandr events is the huge switch in gdkevents-x11.c:gdk_event_translate
+ Check out how other extension events are handled there, like
+ XKB, or XFixes.
+
+
+=== Lots of variable naming issues, such as act_output and noutput
+
+=== Needs to select the input, and hook it up to the signal
+
+=== Add version markers to API
+
+=== API to turn monitors on and off?
+
+- DPMS not exposed through randr, maybe should be
+
+ - DPMS is presumably a property of either an
+ output or a CRTC. Logically it's an output.
+
+- Need events when DPMS happens. Exposing the "screen saving on" on
+ dbus may not be good enough.
+
+=== Why does init_multihead_support() start by freeing monitors and
+outputs?
+
+=== Do we disable Xinerama support entirely when 1.2 is in use?
+
+=== We should expose information about what parts of the screen monitors
+are viewing.
+
+=== Make use of the EDID information?
+
+
+-- details for X server --
+
+In nv driver SorSetOutputProperty should return TRUE for unknown
+properties. (Like the Intel driver does).
+
+Detecting plugged in
+
+- Periodically poll
+ -
+
+ - One ddc probe takes 5 ms, according to a comment in the intel
+ driver. Running this twice a second would mean spending 1% of
+ overall time doing ddc polling, which is almost certainly not
+ acceptable.
+
+ 1) Async I2C:
+
+ void I2CProbeAsync(..., callback, data);
+ Bool I2CPending()
+ void I2CUpdate()
+
+ In Dispatch, call I2CUpdate()
+ Before going idle, do
+
+ while (I2CPending())
+ I2CUpdate()
+
+ Would need
+ RegisterDispatchFunction() (Is this called Wakeup?)
+ RegisterIdleFunction()
+
+ Note the idle function should have the option of saying:
+ "check if something else happened; if not, call me again" and
+ "ok, I'm done - go idle". Otherwise, we would be blocking for
+ 5 ms whenever the X server went idle. So actually the idle
+ function should be
+
+ if (I2CPending())
+ {
+ I2CUpdate();
+ return TRUE; /* call me again */
+ }
+ else
+ {
+ return FALSE; /* I'm done */
+ }
+
+ What happens if another I2C requests come in while an async one
+ is pending? Most likely we simply finish whatever is going on,
+ then process the new request.
+
+ What happens if an X request takes so long that we get timeouts on
+ the i2c bus? Good question. Need to read the VESA ddc spec.
+
+ 2) Run the polling in a separate thread.
+
+ Probably crack.
+
+ 3) Run the polling less, maybe once every three seconds.
+
+-- details for control panel --
+Screen changes
+ - Currently it is polling via rw_screen_refresh(), which will always emit
+ a screen-changed event. In reponse to this event the capplet currently
+ checks whether anything changed physically about the setup. This means
+ the capplet can't react to external changes to modes. On the other hand
+ if it didn't
+Disallow combinations that would exceed the screen ranges.
+ - Note rotations
+
+Give rw objects stable positions in memory so that they can be cached
+across screen_changed events.
+
+Add Clone Mode
+
+Drag and drop for the monitors
+ - 2 dimensional layout
+
+Store make and model in monitors.xml, then if serial numbers don't
+match, fall back to a make and model match. Users with an nfs mounted
+home directory should not have to reconfigure for each new system they
+log in to.
+
+Make sure text is scaled correctly
+
+Need to sanitize naming
+ RWOutput vs Output - should probably be OutputInfo
+ rate vs. freq - decide on one
+
+Should probably reconsider the use of null terminated arrays.
+Maybe lists would be better.
+
+Pick a fixed scale, so that two 1024x768 don't look like two 6x4.
+ - An alternative would be to draw a checkerboard pattern
+ below the monitors.
+
+
+
+done:
+
+Add rotation
+
+Disable panel checkbox for now
+
+Patch into gnome-desktop
+
+Find out how to share code between gcc and gsd
+
+Make it assign coordinates correctly
+ - including computing correct screen size
+
diff --git a/panels/display/cc-display-arrangement.c b/panels/display/cc-display-arrangement.c
new file mode 100644
index 0000000..ae3541e
--- /dev/null
+++ b/panels/display/cc-display-arrangement.c
@@ -0,0 +1,978 @@
+/* cc-display-arrangement.c
+ *
+ * Copyright (C) 2007, 2008, 2017 Red Hat, Inc.
+ * Copyright (C) 2013 Intel, Inc.
+ *
+ * Written by: Benjamin Berg <bberg@redhat.com>
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <math.h>
+#include "cc-display-arrangement.h"
+#include "cc-display-config.h"
+
+struct _CcDisplayArrangement
+{
+ GtkDrawingArea object;
+
+ CcDisplayConfig *config;
+
+ cairo_matrix_t to_widget;
+ cairo_matrix_t to_actual;
+
+ gboolean drag_active;
+ CcDisplayMonitor *selected_output;
+ CcDisplayMonitor *prelit_output;
+ /* Starting position of cursor inside the monitor. */
+ gdouble drag_anchor_x;
+ gdouble drag_anchor_y;
+
+ guint major_snap_distance;
+};
+
+typedef struct _CcDisplayArrangement CcDisplayArrangement;
+
+enum {
+ PROP_0,
+ PROP_CONFIG,
+ PROP_SELECTED_OUTPUT,
+ PROP_LAST
+};
+
+typedef enum {
+ SNAP_DIR_NONE = 0,
+ SNAP_DIR_X = 1 << 0,
+ SNAP_DIR_Y = 1 << 1,
+ SNAP_DIR_BOTH = (SNAP_DIR_X | SNAP_DIR_Y),
+} SnapDirection;
+
+typedef struct {
+ cairo_matrix_t to_widget;
+ guint major_snap_distance;
+ gdouble dist_x;
+ gdouble dist_y;
+ gint mon_x;
+ gint mon_y;
+ SnapDirection snapped;
+} SnapData;
+
+#define MARGIN_PX 0
+#define MARGIN_MON 0.66
+#define MAJOR_SNAP_DISTANCE 25
+#define MINOR_SNAP_DISTANCE 5
+#define MIN_OVERLAP 25
+
+G_DEFINE_TYPE (CcDisplayArrangement, cc_display_arrangement, GTK_TYPE_DRAWING_AREA)
+
+static GParamSpec *props[PROP_LAST];
+
+static void
+apply_rotation_to_geometry (CcDisplayMonitor *output,
+ int *w,
+ int *h)
+{
+ CcDisplayRotation rotation;
+
+ rotation = cc_display_monitor_get_rotation (output);
+ if ((rotation == CC_DISPLAY_ROTATION_90) || (rotation == CC_DISPLAY_ROTATION_270))
+ {
+ int tmp;
+ tmp = *h;
+ *h = *w;
+ *w = tmp;
+ }
+}
+
+/* get_geometry */
+static void
+get_scaled_geometry (CcDisplayConfig *config,
+ CcDisplayMonitor *output,
+ int *x,
+ int *y,
+ int *w,
+ int *h)
+{
+ if (cc_display_monitor_is_active (output))
+ {
+ cc_display_monitor_get_geometry (output, x, y, w, h);
+ }
+ else
+ {
+ cc_display_monitor_get_geometry (output, x, y, NULL, NULL);
+ cc_display_mode_get_resolution (cc_display_monitor_get_preferred_mode (output), w, h);
+ }
+
+ if (cc_display_config_is_layout_logical (config))
+ {
+ double scale = cc_display_monitor_get_scale (output);
+ *w = round (*w / scale);
+ *h = round (*h / scale);
+ }
+
+ apply_rotation_to_geometry (output, w, h);
+}
+
+static void
+get_bounding_box (CcDisplayConfig *config,
+ gint *x1,
+ gint *y1,
+ gint *x2,
+ gint *y2,
+ gint *max_w,
+ gint *max_h)
+{
+ GList *outputs, *l;
+
+ g_assert (x1 && y1 && x2 && y2);
+
+ *x1 = *y1 = G_MAXINT;
+ *x2 = *y2 = G_MININT;
+ *max_w = 0;
+ *max_h = 0;
+
+ outputs = cc_display_config_get_monitors (config);
+ for (l = outputs; l; l = l->next)
+ {
+ CcDisplayMonitor *output = l->data;
+ int x, y, w, h;
+
+ if (!cc_display_monitor_is_useful (output))
+ continue;
+
+ get_scaled_geometry (config, output, &x, &y, &w, &h);
+
+ *x1 = MIN (*x1, x);
+ *y1 = MIN (*y1, y);
+ *x2 = MAX (*x2, x + w);
+ *y2 = MAX (*y2, y + h);
+ *max_w = MAX (*max_w, w);
+ *max_h = MAX (*max_h, h);
+ }
+}
+
+static void
+monitor_get_drawing_rect (CcDisplayArrangement *self,
+ CcDisplayMonitor *output,
+ gint *x1,
+ gint *y1,
+ gint *x2,
+ gint *y2)
+{
+ gdouble x, y;
+
+ get_scaled_geometry (self->config, output, x1, y1, x2, y2);
+
+ /* get_scaled_geometry returns the width and height */
+ *x2 = *x1 + *x2;
+ *y2 = *y1 + *y2;
+
+ x = *x1; y = *y1;
+ cairo_matrix_transform_point (&self->to_widget, &x, &y);
+ *x1 = round (x);
+ *y1 = round (y);
+
+ x = *x2; y = *y2;
+ cairo_matrix_transform_point (&self->to_widget, &x, &y);
+ *x2 = round (x);
+ *y2 = round (y);
+}
+
+
+static void
+get_snap_distance (SnapData *snap_data,
+ gint mon_x,
+ gint mon_y,
+ gint new_x,
+ gint new_y,
+ gdouble *dist_x,
+ gdouble *dist_y)
+{
+ gdouble local_dist_x, local_dist_y;
+
+ local_dist_x = ABS (mon_x - new_x);
+ local_dist_y = ABS (mon_y - new_y);
+
+ cairo_matrix_transform_distance (&snap_data->to_widget, &local_dist_x, &local_dist_y);
+
+ if (dist_x)
+ *dist_x = local_dist_x;
+ if (dist_y)
+ *dist_y = local_dist_y;
+}
+
+static void
+maybe_update_snap (SnapData *snap_data,
+ gint mon_x,
+ gint mon_y,
+ gint new_x,
+ gint new_y,
+ SnapDirection snapped,
+ SnapDirection major_axis,
+ gint minor_unlimited)
+{
+ SnapDirection update_snap = SNAP_DIR_NONE;
+ gdouble dist_x, dist_y;
+ gdouble dist;
+
+ get_snap_distance (snap_data, mon_x, mon_y, new_x, new_y, &dist_x, &dist_y);
+ dist = MAX (dist_x, dist_y);
+
+ /* Snap by the variable max snap distance on the major axis, ensure the
+ * minor axis is below the minimum snapping distance (often just zero). */
+ switch (major_axis)
+ {
+ case SNAP_DIR_X:
+ if (dist_x > snap_data->major_snap_distance)
+ return;
+ if (dist_y > MINOR_SNAP_DISTANCE)
+ {
+ if (new_y > mon_y && minor_unlimited <= 0)
+ return;
+ if (new_y < mon_y && minor_unlimited >= 0)
+ return;
+ }
+ break;
+
+ case SNAP_DIR_Y:
+ if (dist_y > snap_data->major_snap_distance)
+ return;
+ if (dist_x > MINOR_SNAP_DISTANCE)
+ {
+ if (new_x > mon_x && minor_unlimited <= 0)
+ return;
+ if (new_x < mon_x && minor_unlimited >= 0)
+ return;
+ }
+ break;
+
+ default:
+ g_assert_not_reached();
+ }
+
+ if (snapped == SNAP_DIR_BOTH)
+ {
+ if (snap_data->snapped == SNAP_DIR_NONE)
+ update_snap = SNAP_DIR_BOTH;
+
+ /* Update, if this is closer on the main axis. */
+ if (((major_axis == SNAP_DIR_X) && (dist_x < snap_data->dist_x)) ||
+ ((major_axis == SNAP_DIR_Y) && (dist_y < snap_data->dist_y)))
+ {
+ update_snap = SNAP_DIR_BOTH;
+ }
+
+ /* Also update if we were only snapping in one direction earlier and it
+ * is better or equally good. */
+ if ((snap_data->snapped == SNAP_DIR_X && (dist <= snap_data->dist_x)) ||
+ (snap_data->snapped == SNAP_DIR_Y && (dist <= snap_data->dist_y)))
+ {
+ update_snap = SNAP_DIR_BOTH;
+ }
+
+ /* Also allow a minor axis to be added if the first axis remains identical. */
+ if (((snap_data->snapped == SNAP_DIR_X) && (major_axis == SNAP_DIR_X) && (new_x == snap_data->mon_x)) ||
+ ((snap_data->snapped == SNAP_DIR_Y) && (major_axis == SNAP_DIR_Y) && (new_y == snap_data->mon_y)))
+ {
+ update_snap = SNAP_DIR_BOTH;
+ }
+ }
+ else if (snapped == SNAP_DIR_X)
+ {
+ if (dist_x < snap_data->dist_x || (snap_data->snapped & SNAP_DIR_X) == SNAP_DIR_NONE)
+ update_snap = SNAP_DIR_X;
+ }
+ else if (snapped == SNAP_DIR_Y)
+ {
+ if (dist_y < snap_data->dist_y || (snap_data->snapped & SNAP_DIR_Y) == SNAP_DIR_NONE)
+ update_snap = SNAP_DIR_Y;
+ }
+ else
+ {
+ g_assert_not_reached ();
+ }
+
+ if (update_snap & SNAP_DIR_X)
+ {
+ snap_data->dist_x = dist_x;
+ snap_data->mon_x = new_x;
+ snap_data->snapped = snap_data->snapped | SNAP_DIR_X;
+ }
+ if (update_snap & SNAP_DIR_Y)
+ {
+ snap_data->dist_y = dist_y;
+ snap_data->mon_y = new_y;
+ snap_data->snapped = snap_data->snapped | SNAP_DIR_Y;
+ }
+}
+
+static void
+find_best_snapping (CcDisplayConfig *config,
+ CcDisplayMonitor *snap_output,
+ SnapData *snap_data)
+{
+ GList *outputs, *l;
+ gint x1, y1, x2, y2;
+ gint w, h;
+
+ g_assert (snap_data != NULL);
+
+ get_scaled_geometry (config, snap_output, &x1, &y1, &w, &h);
+ x2 = x1 + w;
+ y2 = y1 + h;
+
+#define OVERLAP(_s1, _s2, _t1, _t2) ((_s1) <= (_t2) && (_t1) <= (_s2))
+
+ outputs = cc_display_config_get_monitors (config);
+ for (l = outputs; l; l = l->next)
+ {
+ CcDisplayMonitor *output = l->data;
+ gint _x1, _y1, _x2, _y2, _h, _w;
+ gint bottom_snap_pos;
+ gint top_snap_pos;
+ gint left_snap_pos;
+ gint right_snap_pos;
+ gdouble dist_x, dist_y;
+ gdouble tmp;
+
+ if (output == snap_output)
+ continue;
+
+ if (!cc_display_monitor_is_useful (output))
+ continue;
+
+ get_scaled_geometry (config, output, &_x1, &_y1, &_w, &_h);
+ _x2 = _x1 + _w;
+ _y2 = _y1 + _h;
+
+ top_snap_pos = _y1 - h;
+ bottom_snap_pos = _y2;
+ left_snap_pos = _x1 - w;
+ right_snap_pos = _x2;
+
+ dist_y = 9999;
+ /* overlap on the X axis */
+ if (OVERLAP (x1, x2, _x1, _x2))
+ {
+ get_snap_distance (snap_data, x1, y1, x1, top_snap_pos, NULL, &dist_y);
+ get_snap_distance (snap_data, x1, y1, x1, bottom_snap_pos, NULL, &tmp);
+ dist_y = MIN(dist_y, tmp);
+ }
+
+ dist_x = 9999;
+ /* overlap on the Y axis */
+ if (OVERLAP (y1, y2, _y1, _y2))
+ {
+ get_snap_distance (snap_data, x1, y1, left_snap_pos, y1, &dist_x, NULL);
+ get_snap_distance (snap_data, x1, y1, right_snap_pos, y1, &tmp, NULL);
+ dist_x = MIN(dist_x, tmp);
+ }
+
+ /* We only snap horizontally or vertically to an edge of the same monitor */
+ if (dist_y < dist_x)
+ {
+ maybe_update_snap (snap_data, x1, y1, x1, top_snap_pos, SNAP_DIR_Y, SNAP_DIR_Y, 0);
+ maybe_update_snap (snap_data, x1, y1, x1, bottom_snap_pos, SNAP_DIR_Y, SNAP_DIR_Y, 0);
+ }
+ else if (dist_x < 9999)
+ {
+ maybe_update_snap (snap_data, x1, y1, left_snap_pos, y1, SNAP_DIR_X, SNAP_DIR_X, 0);
+ maybe_update_snap (snap_data, x1, y1, right_snap_pos, y1, SNAP_DIR_X, SNAP_DIR_X, 0);
+ }
+
+ /* Left/right edge identical on the top */
+ maybe_update_snap (snap_data, x1, y1, _x1, top_snap_pos, SNAP_DIR_BOTH, SNAP_DIR_Y, 0);
+ maybe_update_snap (snap_data, x1, y1, _x2 - w, top_snap_pos, SNAP_DIR_BOTH, SNAP_DIR_Y, 0);
+
+ /* Left/right edge identical on the bottom */
+ maybe_update_snap (snap_data, x1, y1, _x1, bottom_snap_pos, SNAP_DIR_BOTH, SNAP_DIR_Y, 0);
+ maybe_update_snap (snap_data, x1, y1, _x2 - w, bottom_snap_pos, SNAP_DIR_BOTH, SNAP_DIR_Y, 0);
+
+ /* Top/bottom edge identical on the left */
+ maybe_update_snap (snap_data, x1, y1, left_snap_pos, _y1, SNAP_DIR_BOTH, SNAP_DIR_X, 0);
+ maybe_update_snap (snap_data, x1, y1, left_snap_pos, _y2 - h, SNAP_DIR_BOTH, SNAP_DIR_X, 0);
+
+ /* Top/bottom edge identical on the right */
+ maybe_update_snap (snap_data, x1, y1, right_snap_pos, _y1, SNAP_DIR_BOTH, SNAP_DIR_X, 0);
+ maybe_update_snap (snap_data, x1, y1, right_snap_pos, _y2 - h, SNAP_DIR_BOTH, SNAP_DIR_X, 0);
+
+ /* If snapping is infinite, then add snapping points with minimal overlap
+ * to prevent detachment.
+ * This is similar to the above but simply re-defines the snapping pos
+ * to have only minimal overlap */
+ if (snap_data->major_snap_distance == G_MAXUINT)
+ {
+ /* Hanging over the left/right edge on the top */
+ maybe_update_snap (snap_data, x1, y1, _x1 - w + MIN_OVERLAP, top_snap_pos, SNAP_DIR_BOTH, SNAP_DIR_Y, 1);
+ maybe_update_snap (snap_data, x1, y1, _x2 - MIN_OVERLAP, top_snap_pos, SNAP_DIR_BOTH, SNAP_DIR_Y, -1);
+
+ /* Left/right edge identical on the bottom */
+ maybe_update_snap (snap_data, x1, y1, _x1 - w + MIN_OVERLAP, bottom_snap_pos, SNAP_DIR_BOTH, SNAP_DIR_Y, 1);
+ maybe_update_snap (snap_data, x1, y1, _x2 - MIN_OVERLAP, bottom_snap_pos, SNAP_DIR_BOTH, SNAP_DIR_Y, -1);
+
+ /* Top/bottom edge identical on the left */
+ maybe_update_snap (snap_data, x1, y1, left_snap_pos, _y1 - h + MIN_OVERLAP, SNAP_DIR_BOTH, SNAP_DIR_X, 1);
+ maybe_update_snap (snap_data, x1, y1, left_snap_pos, _y2 - MIN_OVERLAP, SNAP_DIR_BOTH, SNAP_DIR_X, -1);
+
+ /* Top/bottom edge identical on the right */
+ maybe_update_snap (snap_data, x1, y1, right_snap_pos, _y1 - h + MIN_OVERLAP, SNAP_DIR_BOTH, SNAP_DIR_X, 1);
+ maybe_update_snap (snap_data, x1, y1, right_snap_pos, _y2 - MIN_OVERLAP, SNAP_DIR_BOTH, SNAP_DIR_X, -1);
+ }
+ }
+
+#undef OVERLAP
+}
+
+static void
+cc_display_arrangement_update_matrices (CcDisplayArrangement *self)
+{
+ GtkAllocation allocation;
+ gdouble scale, scale_h, scale_w;
+ gint x1, y1, x2, y2, max_w, max_h;
+
+ g_assert (self->config);
+
+ /* Do not update the matrices while the user is dragging things around. */
+ if (self->drag_active)
+ return;
+
+ get_bounding_box (self->config, &x1, &y1, &x2, &y2, &max_w, &max_h);
+ gtk_widget_get_allocation (GTK_WIDGET (self), &allocation);
+
+ scale_h = (gdouble) (allocation.width - 2 * MARGIN_PX) / (x2 - x1 + max_w * 2 * MARGIN_MON);
+ scale_w = (gdouble) (allocation.height - 2 * MARGIN_PX) / (y2 - y1 + max_h * 2 * MARGIN_MON);
+
+ scale = MIN (scale_h, scale_w);
+
+ cairo_matrix_init_identity (&self->to_widget);
+ cairo_matrix_translate (&self->to_widget, allocation.width / 2.0, allocation.height / 2.0);
+ cairo_matrix_scale (&self->to_widget, scale, scale);
+ cairo_matrix_translate (&self->to_widget, - (x1 + x2) / 2.0, - (y1 + y2) / 2.0);
+
+ self->to_actual = self->to_widget;
+ cairo_matrix_invert (&self->to_actual);
+}
+
+static CcDisplayMonitor*
+cc_display_arrangement_find_monitor_at (CcDisplayArrangement *self,
+ gint x,
+ gint y)
+{
+ g_autoptr(GList) outputs = NULL;
+ GList *l;
+
+ outputs = g_list_copy (cc_display_config_get_monitors (self->config));
+
+ if (self->selected_output)
+ outputs = g_list_prepend (outputs, self->selected_output);
+
+ for (l = outputs; l; l = l->next)
+ {
+ CcDisplayMonitor *output = l->data;
+ gint x1, y1, x2, y2;
+
+ if (!cc_display_monitor_is_useful (output))
+ continue;
+
+ monitor_get_drawing_rect (self, output, &x1, &y1, &x2, &y2);
+
+ if (x >= x1 && x <= x2 && y >= y1 && y <= y2)
+ return output;
+ }
+
+ return NULL;
+}
+
+static void
+on_output_changed_cb (CcDisplayArrangement *self,
+ CcDisplayMonitor *output)
+{
+ if (cc_display_config_count_useful_monitors (self->config) > 2)
+ self->major_snap_distance = MAJOR_SNAP_DISTANCE;
+ else
+ self->major_snap_distance = G_MAXUINT;
+
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+}
+
+static void
+cc_display_arrangement_draw (GtkDrawingArea *drawing_area,
+ cairo_t *cr,
+ gint width,
+ gint height,
+ gpointer user_data)
+{
+ CcDisplayArrangement *self = CC_DISPLAY_ARRANGEMENT (drawing_area);
+ GtkStyleContext *context = gtk_widget_get_style_context (GTK_WIDGET (self));
+ g_autoptr(GList) outputs = NULL;
+ GList *l;
+
+ if (!self->config)
+ return;
+
+ cc_display_arrangement_update_matrices (self);
+
+ /* Draw in reverse order so that hit detection matches visual. Also pull
+ * the selected output to the back. */
+ outputs = g_list_copy (cc_display_config_get_monitors (self->config));
+ outputs = g_list_remove (outputs, self->selected_output);
+ if (self->selected_output != NULL)
+ outputs = g_list_prepend (outputs, self->selected_output);
+ outputs = g_list_reverse (outputs);
+
+ for (l = outputs; l; l = l->next)
+ {
+ CcDisplayMonitor *output = l->data;
+ GtkStateFlags state = GTK_STATE_FLAG_NORMAL;
+ GtkBorder border, padding, margin;
+ gint x1, y1, x2, y2;
+ gint w, h;
+ gint num;
+
+ if (!cc_display_monitor_is_useful (output))
+ continue;
+
+ gtk_style_context_save (context);
+ cairo_save (cr);
+
+ gtk_style_context_add_class (context, "monitor");
+
+ if (output == self->selected_output)
+ state |= GTK_STATE_FLAG_SELECTED;
+ if (output == self->prelit_output)
+ state |= GTK_STATE_FLAG_PRELIGHT;
+
+ gtk_style_context_set_state (context, state);
+ if (cc_display_monitor_is_primary (output) || cc_display_config_is_cloning (self->config))
+ gtk_style_context_add_class (context, "primary");
+
+ /* Set in cc-display-panel.c */
+ num = cc_display_monitor_get_ui_number (output);
+
+ monitor_get_drawing_rect (self, output, &x1, &y1, &x2, &y2);
+ w = x2 - x1;
+ h = y2 - y1;
+
+ cairo_translate (cr, x1, y1);
+
+ gtk_style_context_get_margin (context, &margin);
+
+ cairo_translate (cr, margin.left, margin.top);
+
+ w -= margin.left + margin.right;
+ h -= margin.top + margin.bottom;
+
+ gtk_render_background (context, cr, 0, 0, w, h);
+ gtk_render_frame (context, cr, 0, 0, w, h);
+
+ gtk_style_context_get_border (context, &border);
+ gtk_style_context_get_padding (context, &padding);
+
+ w -= border.left + border.right + padding.left + padding.right;
+ h -= border.top + border.bottom + padding.top + padding.bottom;
+
+ cairo_translate (cr, border.left + padding.left, border.top + padding.top);
+
+ if (num > 0)
+ {
+ PangoLayout *layout;
+ g_autofree gchar *number_str = NULL;
+ PangoRectangle extents;
+ GdkRGBA color;
+ gdouble text_width, text_padding;
+
+ gtk_style_context_add_class (context, "monitor-label");
+ gtk_style_context_remove_class (context, "monitor");
+
+ gtk_style_context_get_border (context, &border);
+ gtk_style_context_get_padding (context, &padding);
+
+ cairo_translate (cr, w / 2, h / 2);
+
+ number_str = g_strdup_printf ("%d", num);
+ layout = gtk_widget_create_pango_layout (GTK_WIDGET (self), number_str);
+ pango_layout_get_extents (layout, NULL, &extents);
+
+ h = (extents.height - extents.y) / PANGO_SCALE;
+ text_width = (extents.width - extents.x) / PANGO_SCALE;
+ w = MAX (text_width, h - padding.left - padding.right);
+ text_padding = w - text_width;
+
+ w += border.left + border.right + padding.left + padding.right;
+ h += border.top + border.bottom + padding.top + padding.bottom;
+
+ /* Enforce evenness */
+ if ((w % 2) != 0)
+ w++;
+ if ((h % 2) != 0)
+ h++;
+
+ cairo_translate (cr, - w / 2, - h / 2);
+
+ gtk_render_background (context, cr, 0, 0, w, h);
+ gtk_render_frame (context, cr, 0, 0, w, h);
+
+ cairo_translate (cr, border.left + padding.left, border.top + padding.top);
+ cairo_translate (cr, extents.x + text_padding / 2, 0);
+
+ gtk_style_context_get_color (context, &color);
+ gdk_cairo_set_source_rgba (cr, &color);
+
+ gtk_render_layout (context, cr, 0, 0, layout);
+ g_object_unref (layout);
+ }
+
+ gtk_style_context_restore (context);
+ cairo_restore (cr);
+ }
+}
+
+static gboolean
+on_click_gesture_pressed_cb (GtkGestureClick *click_gesture,
+ gint n_press,
+ gdouble x,
+ gdouble y,
+ CcDisplayArrangement *self)
+{
+ CcDisplayMonitor *output;
+ gdouble event_x, event_y;
+ gint mon_x, mon_y;
+
+ if (!self->config)
+ return FALSE;
+
+ g_return_val_if_fail (self->drag_active == FALSE, FALSE);
+
+ output = cc_display_arrangement_find_monitor_at (self, x, y);
+ if (!output)
+ return FALSE;
+
+ event_x = x;
+ event_y = y;
+
+ cairo_matrix_transform_point (&self->to_actual, &event_x, &event_y);
+ cc_display_monitor_get_geometry (output, &mon_x, &mon_y, NULL, NULL);
+
+ cc_display_arrangement_set_selected_output (self, output);
+
+ if (cc_display_config_count_useful_monitors (self->config) > 1)
+ {
+ self->drag_active = TRUE;
+ self->drag_anchor_x = event_x - mon_x;
+ self->drag_anchor_y = event_y - mon_y;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+on_click_gesture_released_cb (GtkGestureClick *click_gesture,
+ gint n_press,
+ gdouble x,
+ gdouble y,
+ CcDisplayArrangement *self)
+{
+ CcDisplayMonitor *output;
+
+ if (!self->config)
+ return FALSE;
+
+ if (!self->drag_active)
+ return FALSE;
+
+ self->drag_active = FALSE;
+
+ output = cc_display_arrangement_find_monitor_at (self, x, y);
+ gtk_widget_set_cursor_from_name (GTK_WIDGET (self),
+ output != NULL ? "fleur" : NULL);
+
+ /* And queue a redraw to recenter everything */
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+
+ g_signal_emit_by_name (G_OBJECT (self), "updated");
+
+ return TRUE;
+}
+
+static gboolean
+on_motion_controller_motion_cb (GtkEventControllerMotion *motion_controller,
+ gdouble x,
+ gdouble y,
+ CcDisplayArrangement *self)
+{
+ gdouble event_x, event_y;
+ gint mon_x, mon_y;
+ SnapData snap_data;
+
+ if (!self->config)
+ return FALSE;
+
+ if (cc_display_config_count_useful_monitors (self->config) <= 1)
+ return FALSE;
+
+ if (!self->drag_active)
+ {
+ CcDisplayMonitor *output;
+ output = cc_display_arrangement_find_monitor_at (self, x, y);
+
+ gtk_widget_set_cursor_from_name (GTK_WIDGET (self),
+ output != NULL ? "fleur" : NULL);
+ if (self->prelit_output != output)
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+
+ self->prelit_output = output;
+
+ return FALSE;
+ }
+
+ g_assert (self->selected_output);
+
+ event_x = x;
+ event_y = y;
+
+ cairo_matrix_transform_point (&self->to_actual, &event_x, &event_y);
+
+ mon_x = round (event_x - self->drag_anchor_x);
+ mon_y = round (event_y - self->drag_anchor_y);
+
+ /* The monitor is now at the location as if there was no snapping whatsoever. */
+ snap_data.snapped = SNAP_DIR_NONE;
+ snap_data.mon_x = mon_x;
+ snap_data.mon_y = mon_y;
+ snap_data.dist_x = 0;
+ snap_data.dist_y = 0;
+ snap_data.to_widget = self->to_widget;
+ snap_data.major_snap_distance = self->major_snap_distance;
+
+ cc_display_monitor_set_position (self->selected_output, mon_x, mon_y);
+
+ find_best_snapping (self->config, self->selected_output, &snap_data);
+
+ cc_display_monitor_set_position (self->selected_output, snap_data.mon_x, snap_data.mon_y);
+
+ return TRUE;
+}
+
+static void
+cc_display_arrangement_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcDisplayArrangement *self = CC_DISPLAY_ARRANGEMENT (object);
+
+ switch (prop_id)
+ {
+ case PROP_CONFIG:
+ g_value_set_object (value, self->config);
+ break;
+
+ case PROP_SELECTED_OUTPUT:
+ g_value_set_object (value, self->selected_output);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_display_arrangement_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcDisplayArrangement *obj = CC_DISPLAY_ARRANGEMENT (object);
+
+ switch (prop_id)
+ {
+ case PROP_CONFIG:
+ cc_display_arrangement_set_config (obj, g_value_get_object (value));
+ break;
+
+ case PROP_SELECTED_OUTPUT:
+ cc_display_arrangement_set_selected_output (obj, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_display_arrangement_finalize (GObject *object)
+{
+ CcDisplayArrangement *self = CC_DISPLAY_ARRANGEMENT (object);
+
+ g_clear_object (&self->config);
+
+ G_OBJECT_CLASS (cc_display_arrangement_parent_class)->finalize (object);
+}
+
+static void
+cc_display_arrangement_class_init (CcDisplayArrangementClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = cc_display_arrangement_finalize;
+ gobject_class->get_property = cc_display_arrangement_get_property;
+ gobject_class->set_property = cc_display_arrangement_set_property;
+
+ props[PROP_CONFIG] = g_param_spec_object ("config", "Display Config",
+ "The display configuration to work with",
+ CC_TYPE_DISPLAY_CONFIG,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ props[PROP_SELECTED_OUTPUT] = g_param_spec_object ("selected-output", "Selected Output",
+ "The output that is currently selected on the configuration",
+ CC_TYPE_DISPLAY_MONITOR,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (gobject_class,
+ PROP_LAST,
+ props);
+
+ g_signal_new ("updated",
+ CC_TYPE_DISPLAY_ARRANGEMENT,
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+
+ gtk_widget_class_set_css_name (GTK_WIDGET_CLASS (klass), "display-arrangement");
+}
+
+static void
+cc_display_arrangement_init (CcDisplayArrangement *self)
+{
+ GtkEventController *motion_controller;
+ GtkGesture *click_gesture;
+
+ click_gesture = gtk_gesture_click_new ();
+ g_signal_connect (click_gesture, "pressed", G_CALLBACK (on_click_gesture_pressed_cb), self);
+ g_signal_connect (click_gesture, "released", G_CALLBACK (on_click_gesture_released_cb), self);
+ gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (click_gesture));
+
+ motion_controller = gtk_event_controller_motion_new ();
+ g_signal_connect (motion_controller, "motion", G_CALLBACK (on_motion_controller_motion_cb), self);
+ gtk_widget_add_controller (GTK_WIDGET (self), motion_controller);
+
+ gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (self),
+ cc_display_arrangement_draw,
+ self,
+ NULL);
+
+ self->major_snap_distance = MAJOR_SNAP_DISTANCE;
+}
+
+CcDisplayArrangement*
+cc_display_arrangement_new (CcDisplayConfig *config)
+{
+ return g_object_new (CC_TYPE_DISPLAY_ARRANGEMENT, "config", config, NULL);
+}
+
+CcDisplayConfig*
+cc_display_arrangement_get_config (CcDisplayArrangement *self)
+{
+ return self->config;
+}
+
+void
+cc_display_arrangement_set_config (CcDisplayArrangement *self,
+ CcDisplayConfig *config)
+{
+ const gchar *signals[] = { "rotation", "mode", "primary", "active", "scale", "position-changed", "is-usable" };
+ GList *outputs, *l;
+ guint i;
+
+ if (self->config)
+ {
+ outputs = cc_display_config_get_monitors (self->config);
+ for (l = outputs; l; l = l->next)
+ {
+ CcDisplayMonitor *output = l->data;
+
+ g_signal_handlers_disconnect_by_data (output, self);
+ }
+ }
+ g_clear_object (&self->config);
+
+ self->drag_active = FALSE;
+
+ /* Listen to all the signals */
+ if (config)
+ {
+ self->config = g_object_ref (config);
+
+ outputs = cc_display_config_get_monitors (self->config);
+ for (l = outputs; l; l = l->next)
+ {
+ CcDisplayMonitor *output = l->data;
+
+ for (i = 0; i < G_N_ELEMENTS (signals); ++i)
+ g_signal_connect_object (output, signals[i], G_CALLBACK (on_output_changed_cb), self, G_CONNECT_SWAPPED);
+ }
+ }
+
+ cc_display_arrangement_set_selected_output (self, NULL);
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CONFIG]);
+}
+
+CcDisplayMonitor*
+cc_display_arrangement_get_selected_output (CcDisplayArrangement *self)
+{
+ return self->selected_output;
+}
+
+void
+cc_display_arrangement_set_selected_output (CcDisplayArrangement *self,
+ CcDisplayMonitor *output)
+{
+ g_return_if_fail (self->drag_active == FALSE);
+
+ /* XXX: Could check that it actually belongs to the right config object. */
+ self->selected_output = output;
+
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SELECTED_OUTPUT]);
+}
+
+void
+cc_display_config_snap_output (CcDisplayConfig *config,
+ CcDisplayMonitor *output)
+{
+ SnapData snap_data;
+ gint x, y, w, h;
+
+ if (!cc_display_monitor_is_useful (output))
+ return;
+
+ if (cc_display_config_count_useful_monitors (config) <= 1)
+ return;
+
+ get_scaled_geometry (config, output, &x, &y, &w, &h);
+
+ snap_data.snapped = SNAP_DIR_NONE;
+ snap_data.mon_x = x;
+ snap_data.mon_y = y;
+ snap_data.dist_x = 0;
+ snap_data.dist_y = 0;
+ cairo_matrix_init_identity (&snap_data.to_widget);
+ snap_data.major_snap_distance = G_MAXUINT;
+
+ find_best_snapping (config, output, &snap_data);
+
+ cc_display_monitor_set_position (output, snap_data.mon_x, snap_data.mon_y);
+}
diff --git a/panels/display/cc-display-arrangement.h b/panels/display/cc-display-arrangement.h
new file mode 100644
index 0000000..9494c48
--- /dev/null
+++ b/panels/display/cc-display-arrangement.h
@@ -0,0 +1,47 @@
+/* -*- mode: c; style: linux -*-
+ *
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * Written by: Benjamin Berg <bberg@redhat.com>
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include "cc-display-config.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_DISPLAY_ARRANGEMENT cc_display_arrangement_get_type ()
+G_DECLARE_FINAL_TYPE (CcDisplayArrangement, cc_display_arrangement, CC, DISPLAY_ARRANGEMENT, GtkDrawingArea);
+
+CcDisplayArrangement* cc_display_arrangement_new (CcDisplayConfig *config);
+
+CcDisplayConfig* cc_display_arrangement_get_config (CcDisplayArrangement *self);
+void cc_display_arrangement_set_config (CcDisplayArrangement *self,
+ CcDisplayConfig *config);
+
+CcDisplayMonitor* cc_display_arrangement_get_selected_output (CcDisplayArrangement *arr);
+void cc_display_arrangement_set_selected_output (CcDisplayArrangement *arr,
+ CcDisplayMonitor *output);
+
+/* This is a bit of an odd-ball, but it currently makes sense to have it with
+ * the arrangement widget where the snapping code lives. */
+void cc_display_config_snap_output (CcDisplayConfig *config,
+ CcDisplayMonitor *output);
+
+G_END_DECLS
+
diff --git a/panels/display/cc-display-config-dbus.c b/panels/display/cc-display-config-dbus.c
new file mode 100644
index 0000000..c3b269d
--- /dev/null
+++ b/panels/display/cc-display-config-dbus.c
@@ -0,0 +1,2116 @@
+/*
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <float.h>
+#include <math.h>
+#include <gio/gio.h>
+
+#include "cc-display-config-dbus.h"
+
+#define MODE_BASE_FORMAT "siiddad"
+#define MODE_FORMAT "(" MODE_BASE_FORMAT "a{sv})"
+#define MODES_FORMAT "a" MODE_FORMAT
+#define MONITOR_SPEC_FORMAT "(ssss)"
+#define MONITOR_FORMAT "(" MONITOR_SPEC_FORMAT MODES_FORMAT "a{sv})"
+#define MONITORS_FORMAT "a" MONITOR_FORMAT
+
+#define LOGICAL_MONITOR_MONITORS_FORMAT "a" MONITOR_SPEC_FORMAT
+#define LOGICAL_MONITOR_FORMAT "(iidub" LOGICAL_MONITOR_MONITORS_FORMAT "a{sv})"
+#define LOGICAL_MONITORS_FORMAT "a" LOGICAL_MONITOR_FORMAT
+
+#define CURRENT_STATE_FORMAT "(u" MONITORS_FORMAT LOGICAL_MONITORS_FORMAT "a{sv})"
+
+typedef enum _CcDisplayModeFlags
+{
+ MODE_PREFERRED = 1 << 0,
+ MODE_CURRENT = 1 << 1,
+ MODE_INTERLACED = 1 << 2,
+} CcDisplayModeFlags;
+
+struct _CcDisplayModeDBus
+{
+ CcDisplayMode parent_instance;
+ CcDisplayMonitorDBus *monitor;
+
+ char *id;
+ int width;
+ int height;
+ double refresh_rate;
+ double preferred_scale;
+ GArray *supported_scales;
+ guint32 flags;
+};
+
+G_DEFINE_TYPE (CcDisplayModeDBus,
+ cc_display_mode_dbus,
+ CC_TYPE_DISPLAY_MODE)
+
+static gboolean
+cc_display_mode_dbus_equal (const CcDisplayModeDBus *m1,
+ const CcDisplayModeDBus *m2)
+{
+ if (!m1 && !m2)
+ return TRUE;
+ else if (!m1 || !m2)
+ return FALSE;
+
+ return m1->width == m2->width &&
+ m1->height == m2->height &&
+ m1->refresh_rate == m2->refresh_rate &&
+ (m1->flags & MODE_INTERLACED) == (m2->flags & MODE_INTERLACED);
+}
+
+static gboolean
+cc_display_mode_dbus_is_clone_mode (CcDisplayMode *pself)
+{
+ CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (pself);
+
+ return !self->id;
+}
+
+static void
+cc_display_mode_dbus_get_resolution (CcDisplayMode *pself,
+ int *w, int *h)
+{
+ CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (pself);
+
+ if (w)
+ *w = self->width;
+ if (h)
+ *h = self->height;
+}
+
+static GArray * cc_display_mode_dbus_get_supported_scales (CcDisplayMode *pself);
+
+static double
+cc_display_mode_dbus_get_preferred_scale (CcDisplayMode *pself)
+{
+ CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (pself);
+
+ return self->preferred_scale;
+}
+
+static gboolean
+cc_display_mode_dbus_is_supported_scale (CcDisplayMode *pself,
+ double scale)
+{
+ CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (pself);
+
+ guint i;
+ for (i = 0; i < self->supported_scales->len; i++)
+ {
+ double v = g_array_index (self->supported_scales, double, i);
+
+ if (G_APPROX_VALUE (v, scale, DBL_EPSILON))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+static gboolean
+cc_display_mode_dbus_is_interlaced (CcDisplayMode *pself)
+{
+ CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (pself);
+
+ return !!(self->flags & MODE_INTERLACED);
+}
+
+static gboolean
+cc_display_mode_dbus_is_preferred (CcDisplayMode *pself)
+{
+ CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (pself);
+
+ return !!(self->flags & MODE_PREFERRED);
+}
+
+static int
+cc_display_mode_dbus_get_freq (CcDisplayMode *pself)
+{
+ CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (pself);
+
+ return self->refresh_rate;
+}
+
+static double
+cc_display_mode_dbus_get_freq_f (CcDisplayMode *pself)
+{
+ CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (pself);
+
+ return self->refresh_rate;
+}
+
+static void
+cc_display_mode_dbus_init (CcDisplayModeDBus *self)
+{
+ self->supported_scales = g_array_new (FALSE, FALSE, sizeof (double));
+}
+
+static void
+cc_display_mode_dbus_finalize (GObject *object)
+{
+ CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (object);
+
+ g_free (self->id);
+ g_array_free (self->supported_scales, TRUE);
+
+ G_OBJECT_CLASS (cc_display_mode_dbus_parent_class)->finalize (object);
+}
+
+static void
+cc_display_mode_dbus_class_init (CcDisplayModeDBusClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ CcDisplayModeClass *parent_class = CC_DISPLAY_MODE_CLASS (klass);
+
+ gobject_class->finalize = cc_display_mode_dbus_finalize;
+
+ parent_class->is_clone_mode = cc_display_mode_dbus_is_clone_mode;
+ parent_class->get_resolution = cc_display_mode_dbus_get_resolution;
+ parent_class->get_supported_scales = cc_display_mode_dbus_get_supported_scales;
+ parent_class->get_preferred_scale = cc_display_mode_dbus_get_preferred_scale;
+ parent_class->is_interlaced = cc_display_mode_dbus_is_interlaced;
+ parent_class->is_preferred = cc_display_mode_dbus_is_preferred;
+ parent_class->get_freq = cc_display_mode_dbus_get_freq;
+ parent_class->get_freq_f = cc_display_mode_dbus_get_freq_f;
+}
+
+static CcDisplayModeDBus *
+cc_display_mode_dbus_new_virtual (int width,
+ int height,
+ double preferred_scale,
+ GArray *supported_scales)
+{
+ g_autoptr(GVariant) properties_variant = NULL;
+ CcDisplayModeDBus *self;
+
+ self = g_object_new (CC_TYPE_DISPLAY_MODE_DBUS, NULL);
+
+ self->width = width;
+ self->height = height;
+ self->preferred_scale = preferred_scale;
+ self->supported_scales = g_array_ref (supported_scales);
+
+ return self;
+}
+
+static CcDisplayModeDBus *
+cc_display_mode_dbus_new (CcDisplayMonitorDBus *monitor,
+ GVariant *variant)
+{
+ double d;
+ g_autoptr(GVariantIter) scales_iter = NULL;
+ g_autoptr(GVariant) properties_variant = NULL;
+ gboolean is_current;
+ gboolean is_preferred;
+ gboolean is_interlaced;
+ CcDisplayModeDBus *self = g_object_new (CC_TYPE_DISPLAY_MODE_DBUS, NULL);
+
+ self->monitor = monitor;
+
+ g_variant_get (variant, "(" MODE_BASE_FORMAT "@a{sv})",
+ &self->id,
+ &self->width,
+ &self->height,
+ &self->refresh_rate,
+ &self->preferred_scale,
+ &scales_iter,
+ &properties_variant);
+
+ while (g_variant_iter_next (scales_iter, "d", &d))
+ g_array_append_val (self->supported_scales, d);
+
+ if (!g_variant_lookup (properties_variant, "is-current", "b", &is_current))
+ is_current = FALSE;
+ if (!g_variant_lookup (properties_variant, "is-preferred", "b", &is_preferred))
+ is_preferred = FALSE;
+ if (!g_variant_lookup (properties_variant, "is-interlaced", "b", &is_interlaced))
+ is_interlaced = FALSE;
+
+ if (is_current)
+ self->flags |= MODE_CURRENT;
+ if (is_preferred)
+ self->flags |= MODE_PREFERRED;
+ if (is_interlaced)
+ self->flags |= MODE_INTERLACED;
+
+ return self;
+}
+
+
+#define CC_TYPE_DISPLAY_LOGICAL_MONITOR (cc_display_logical_monitor_get_type ())
+G_DECLARE_FINAL_TYPE (CcDisplayLogicalMonitor, cc_display_logical_monitor,
+ CC, DISPLAY_LOGICAL_MONITOR, GObject)
+
+struct _CcDisplayLogicalMonitor
+{
+ GObject parent_instance;
+
+ int x;
+ int y;
+ double scale;
+ CcDisplayRotation rotation;
+ gboolean primary;
+
+ GHashTable *monitors;
+};
+
+G_DEFINE_TYPE (CcDisplayLogicalMonitor,
+ cc_display_logical_monitor,
+ G_TYPE_OBJECT)
+
+static gboolean
+cc_display_logical_monitor_equal (const CcDisplayLogicalMonitor *m1,
+ const CcDisplayLogicalMonitor *m2)
+{
+ if (!m1 && !m2)
+ return TRUE;
+ else if (!m1 || !m2)
+ return FALSE;
+
+ return m1->x == m2->x &&
+ m1->y == m2->y &&
+ G_APPROX_VALUE (m1->scale, m2->scale, DBL_EPSILON) &&
+ m1->rotation == m2->rotation &&
+ m1->primary == m2->primary;
+}
+
+static void
+cc_display_logical_monitor_init (CcDisplayLogicalMonitor *self)
+{
+ self->scale = 1.0;
+ self->monitors = g_hash_table_new (NULL, NULL);
+}
+
+static void
+cc_display_logical_monitor_finalize (GObject *object)
+{
+ CcDisplayLogicalMonitor *self = CC_DISPLAY_LOGICAL_MONITOR (object);
+
+ g_warn_if_fail (g_hash_table_size (self->monitors) == 0);
+ g_clear_pointer (&self->monitors, g_hash_table_destroy);
+
+ G_OBJECT_CLASS (cc_display_logical_monitor_parent_class)->finalize (object);
+}
+
+static void
+cc_display_logical_monitor_class_init (CcDisplayLogicalMonitorClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = cc_display_logical_monitor_finalize;
+}
+
+
+typedef enum _CcDisplayMonitorUnderscanning
+{
+ UNDERSCANNING_UNSUPPORTED = 0,
+ UNDERSCANNING_DISABLED,
+ UNDERSCANNING_ENABLED
+} CcDisplayMonitorUnderscanning;
+
+struct _CcDisplayMonitorDBus
+{
+ CcDisplayMonitor parent_instance;
+ CcDisplayConfigDBus *config;
+
+ gchar *connector_name;
+ gchar *vendor_name;
+ gchar *product_name;
+ gchar *product_serial;
+ gchar *display_name;
+
+ int width_mm;
+ int height_mm;
+ gboolean builtin;
+ CcDisplayMonitorUnderscanning underscanning;
+ CcDisplayMonitorPrivacy privacy_screen;
+ int max_width;
+ int max_height;
+
+ GList *modes;
+ CcDisplayMode *current_mode;
+ CcDisplayMode *preferred_mode;
+
+ CcDisplayLogicalMonitor *logical_monitor;
+};
+
+G_DEFINE_TYPE (CcDisplayMonitorDBus,
+ cc_display_monitor_dbus,
+ CC_TYPE_DISPLAY_MONITOR)
+
+static void
+register_logical_monitor (CcDisplayConfigDBus *self,
+ CcDisplayLogicalMonitor *logical_monitor);
+static void
+cc_display_config_dbus_set_primary (CcDisplayConfigDBus *self,
+ CcDisplayMonitorDBus *new_primary);
+static void
+cc_display_config_dbus_unset_primary (CcDisplayConfigDBus *self,
+ CcDisplayMonitorDBus *old_primary);
+static void
+cc_display_config_dbus_ensure_non_offset_coords (CcDisplayConfigDBus *self);
+static void
+cc_display_config_dbus_append_right (CcDisplayConfigDBus *self,
+ CcDisplayLogicalMonitor *monitor);
+static void
+cc_display_config_dbus_make_linear (CcDisplayConfigDBus *self);
+
+
+static const char *
+cc_display_monitor_dbus_get_display_name (CcDisplayMonitor *pself)
+{
+ CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself);
+
+ if (self->display_name)
+ return self->display_name;
+
+ return self->connector_name;
+}
+
+static const char *
+cc_display_monitor_dbus_get_connector_name (CcDisplayMonitor *pself)
+{
+ CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself);
+
+ return self->connector_name;
+}
+
+static gboolean
+cc_display_monitor_dbus_is_builtin (CcDisplayMonitor *pself)
+{
+ CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself);
+
+ return self->builtin;
+}
+
+static gboolean
+cc_display_monitor_dbus_is_primary (CcDisplayMonitor *pself)
+{
+ CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself);
+
+ if (self->logical_monitor)
+ return self->logical_monitor->primary;
+
+ return FALSE;
+}
+
+static void
+cc_display_monitor_dbus_set_primary (CcDisplayMonitor *pself,
+ gboolean primary)
+{
+ CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself);
+
+ if (primary)
+ cc_display_config_dbus_set_primary (self->config, self);
+ else
+ cc_display_config_dbus_unset_primary (self->config, self);
+}
+
+static gboolean
+cc_display_monitor_dbus_is_active (CcDisplayMonitor *pself)
+{
+ CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself);
+
+ return self->logical_monitor != NULL;
+}
+
+static void
+cc_display_monitor_dbus_set_logical_monitor (CcDisplayMonitorDBus *self,
+ CcDisplayLogicalMonitor *logical_monitor)
+{
+ gboolean was_primary = FALSE;
+
+ if (self->logical_monitor)
+ {
+ was_primary = self->logical_monitor->primary;
+ if (was_primary)
+ cc_display_config_dbus_unset_primary (self->config, self);
+ g_hash_table_remove (self->logical_monitor->monitors, self);
+ g_object_unref (self->logical_monitor);
+ }
+
+ self->logical_monitor = logical_monitor;
+
+ if (self->logical_monitor)
+ {
+ g_hash_table_add (self->logical_monitor->monitors, self);
+ g_object_ref (self->logical_monitor);
+ /* unset primary with NULL will select this monitor if it is the only one.*/
+ if (was_primary)
+ cc_display_config_dbus_set_primary (self->config, self);
+ else
+ cc_display_config_dbus_unset_primary (self->config, NULL);
+ }
+}
+
+static void
+cc_display_monitor_dbus_set_active (CcDisplayMonitor *pself,
+ gboolean active)
+{
+ CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself);
+
+ if (!self->current_mode && active)
+ {
+ if (self->preferred_mode)
+ self->current_mode = self->preferred_mode;
+ else if (self->modes)
+ self->current_mode = (CcDisplayMode *) self->modes->data;
+ else
+ g_warning ("Couldn't find a mode to activate monitor at %s", self->connector_name);
+ }
+
+ if (!self->logical_monitor && active)
+ {
+ CcDisplayLogicalMonitor *logical_monitor;
+ logical_monitor = g_object_new (CC_TYPE_DISPLAY_LOGICAL_MONITOR, NULL);
+ cc_display_monitor_dbus_set_logical_monitor (self, logical_monitor);
+ cc_display_config_dbus_append_right (self->config, logical_monitor);
+ register_logical_monitor (self->config, logical_monitor);
+ }
+ else if (self->logical_monitor && !active)
+ {
+ cc_display_monitor_dbus_set_logical_monitor (self, NULL);
+ }
+
+ g_signal_emit_by_name (self, "active");
+}
+
+static CcDisplayRotation
+cc_display_monitor_dbus_get_rotation (CcDisplayMonitor *pself)
+{
+ CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself);
+
+ if (self->logical_monitor)
+ return self->logical_monitor->rotation;
+
+ return CC_DISPLAY_ROTATION_NONE;
+}
+
+static void
+cc_display_monitor_dbus_set_rotation (CcDisplayMonitor *pself,
+ CcDisplayRotation rotation)
+{
+ CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself);
+
+ if (!self->logical_monitor)
+ return;
+
+ if (self->logical_monitor->rotation != rotation)
+ {
+ self->logical_monitor->rotation = rotation;
+
+ g_signal_emit_by_name (self, "rotation");
+ }
+}
+
+static gboolean
+cc_display_monitor_dbus_supports_rotation (CcDisplayMonitor *pself,
+ CcDisplayRotation rotation)
+{
+ return TRUE;
+}
+
+static void
+cc_display_monitor_dbus_get_physical_size (CcDisplayMonitor *pself,
+ int *w, int *h)
+{
+ CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself);
+
+ if (w)
+ *w = self->width_mm;
+ if (h)
+ *h = self->height_mm;
+}
+
+static void
+cc_display_monitor_dbus_get_geometry (CcDisplayMonitor *pself,
+ int *x, int *y, int *w, int *h)
+{
+ CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself);
+ CcDisplayMode *mode = NULL;
+
+ if (self->logical_monitor)
+ {
+ if (x)
+ *x = self->logical_monitor->x;
+ if (y)
+ *y = self->logical_monitor->y;
+ }
+ else
+ {
+ if (x)
+ *x = -1;
+ if (y)
+ *y = -1;
+ }
+
+ if (self->current_mode)
+ mode = self->current_mode;
+ else if (self->preferred_mode)
+ mode = self->preferred_mode;
+ else if (self->modes)
+ mode = CC_DISPLAY_MODE (self->modes->data);
+
+ if (mode)
+ cc_display_mode_get_resolution (mode, w, h);
+ else
+ {
+ g_warning ("Monitor at %s has no modes?", self->connector_name);
+ if (w)
+ *w = -1;
+ if (h)
+ *h = -1;
+ }
+}
+
+static CcDisplayMode *
+cc_display_monitor_dbus_get_mode (CcDisplayMonitor *pself)
+{
+ CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself);
+
+ return self->current_mode;
+}
+
+static CcDisplayMode *
+cc_display_monitor_dbus_get_preferred_mode (CcDisplayMonitor *pself)
+{
+ CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself);
+
+ return self->preferred_mode;
+}
+
+static guint32
+cc_display_monitor_dbus_get_id (CcDisplayMonitor *pself)
+{
+ return 0;
+}
+
+static GList *
+cc_display_monitor_dbus_get_modes (CcDisplayMonitor *pself)
+{
+ CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself);
+
+ return self->modes;
+}
+
+static gboolean
+cc_display_monitor_dbus_supports_underscanning (CcDisplayMonitor *pself)
+{
+ CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself);
+
+ return self->underscanning != UNDERSCANNING_UNSUPPORTED;
+}
+
+static gboolean
+cc_display_monitor_dbus_get_underscanning (CcDisplayMonitor *pself)
+{
+ CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself);
+
+ return self->underscanning == UNDERSCANNING_ENABLED;
+}
+
+static CcDisplayMonitorPrivacy
+cc_display_monitor_dbus_get_privacy (CcDisplayMonitor *pself)
+{
+ CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself);
+
+ return self->privacy_screen;
+}
+
+static void
+cc_display_monitor_dbus_set_underscanning (CcDisplayMonitor *pself,
+ gboolean underscanning)
+{
+ CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself);
+
+ if (self->underscanning == UNDERSCANNING_UNSUPPORTED)
+ return;
+
+ if (underscanning)
+ self->underscanning = UNDERSCANNING_ENABLED;
+ else
+ self->underscanning = UNDERSCANNING_DISABLED;
+}
+
+static CcDisplayMode *
+cc_display_monitor_dbus_get_closest_mode (CcDisplayMonitorDBus *self,
+ CcDisplayModeDBus *mode)
+{
+ CcDisplayModeDBus *best = NULL;
+ GList *l;
+
+ for (l = self->modes; l != NULL; l = l->next)
+ {
+ CcDisplayModeDBus *similar = l->data;
+
+ if (similar->width != mode->width ||
+ similar->height != mode->height)
+ continue;
+
+ if (similar->refresh_rate == mode->refresh_rate &&
+ (similar->flags & MODE_INTERLACED) == (mode->flags & MODE_INTERLACED))
+ {
+ best = similar;
+ break;
+ }
+
+ /* There might be a better heuristic. */
+ if (!best || best->refresh_rate < similar->refresh_rate)
+ {
+ best = similar;
+ continue;
+ }
+ }
+
+ return CC_DISPLAY_MODE (best);
+}
+
+static void
+cc_display_monitor_dbus_set_mode (CcDisplayMonitor *pself,
+ CcDisplayMode *new_mode)
+{
+ CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself);
+ CcDisplayMode *mode;
+
+ g_return_if_fail (new_mode != NULL);
+
+ mode = cc_display_monitor_dbus_get_closest_mode (self, CC_DISPLAY_MODE_DBUS (new_mode));
+
+ self->current_mode = mode;
+
+ if (!cc_display_mode_dbus_is_supported_scale (mode, cc_display_monitor_get_scale (pself)))
+ cc_display_monitor_set_scale (pself, cc_display_mode_get_preferred_scale (mode));
+
+ g_signal_emit_by_name (self, "mode");
+}
+
+static void
+cc_display_monitor_dbus_set_compatible_clone_mode (CcDisplayMonitor *pself,
+ CcDisplayMode *clone_mode)
+{
+ CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself);
+ GList *l;
+ CcDisplayMode *best_mode = NULL;
+ int clone_width, clone_height;
+
+ g_return_if_fail (cc_display_mode_is_clone_mode (clone_mode));
+
+ cc_display_mode_get_resolution (clone_mode, &clone_width, &clone_height);
+
+ for (l = self->modes; l; l = l->next)
+ {
+ CcDisplayMode *mode = l->data;
+ int width, height;
+
+ cc_display_mode_get_resolution (mode, &width, &height);
+ if (width != clone_width || height != clone_height)
+ continue;
+
+ if (!best_mode)
+ {
+ best_mode = mode;
+ continue;
+ }
+
+ if (cc_display_mode_get_freq_f (mode) >
+ cc_display_mode_get_freq_f (best_mode))
+ best_mode = mode;
+ }
+
+ g_return_if_fail (best_mode);
+
+ cc_display_monitor_set_mode (CC_DISPLAY_MONITOR (self), best_mode);
+}
+
+static void
+cc_display_monitor_dbus_set_position (CcDisplayMonitor *pself,
+ int x, int y)
+{
+ CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself);
+
+ if (self->logical_monitor)
+ {
+ gboolean notify = FALSE;
+
+ if (self->logical_monitor->x != x || self->logical_monitor->y != y)
+ notify = TRUE;
+
+ self->logical_monitor->x = x;
+ self->logical_monitor->y = y;
+
+ if (notify)
+ g_signal_emit_by_name (self, "position-changed");
+ }
+
+}
+
+static double
+cc_display_monitor_dbus_get_scale (CcDisplayMonitor *pself)
+{
+ CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself);
+
+ if (self->logical_monitor)
+ return self->logical_monitor->scale;
+
+ return 1.0;
+}
+
+static void
+cc_display_monitor_dbus_set_scale (CcDisplayMonitor *pself,
+ double scale)
+{
+ CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself);
+
+ if (!self->current_mode)
+ return;
+
+ if (!cc_display_mode_dbus_is_supported_scale (self->current_mode, scale))
+ return;
+
+ if (!self->logical_monitor)
+ return;
+
+ if (!G_APPROX_VALUE (self->logical_monitor->scale, scale, DBL_EPSILON))
+ {
+ self->logical_monitor->scale = scale;
+
+ g_signal_emit_by_name (self, "scale");
+ }
+}
+
+static void
+cc_display_monitor_dbus_init (CcDisplayMonitorDBus *self)
+{
+ self->underscanning = UNDERSCANNING_UNSUPPORTED;
+ self->max_width = G_MAXINT;
+ self->max_height = G_MAXINT;
+}
+
+static void
+cc_display_monitor_dbus_finalize (GObject *object)
+{
+ CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (object);
+
+ g_free (self->connector_name);
+ g_free (self->vendor_name);
+ g_free (self->product_name);
+ g_free (self->product_serial);
+ g_free (self->display_name);
+
+ g_list_free_full (self->modes, g_object_unref);
+
+ if (self->logical_monitor)
+ {
+ g_hash_table_remove (self->logical_monitor->monitors, self);
+ g_object_unref (self->logical_monitor);
+ }
+
+ G_OBJECT_CLASS (cc_display_monitor_dbus_parent_class)->finalize (object);
+}
+
+static void
+cc_display_monitor_dbus_class_init (CcDisplayMonitorDBusClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ CcDisplayMonitorClass *parent_class = CC_DISPLAY_MONITOR_CLASS (klass);
+
+ gobject_class->finalize = cc_display_monitor_dbus_finalize;
+
+ parent_class->get_display_name = cc_display_monitor_dbus_get_display_name;
+ parent_class->get_connector_name = cc_display_monitor_dbus_get_connector_name;
+ parent_class->is_builtin = cc_display_monitor_dbus_is_builtin;
+ parent_class->is_primary = cc_display_monitor_dbus_is_primary;
+ parent_class->set_primary = cc_display_monitor_dbus_set_primary;
+ parent_class->is_active = cc_display_monitor_dbus_is_active;
+ parent_class->set_active = cc_display_monitor_dbus_set_active;
+ parent_class->get_rotation = cc_display_monitor_dbus_get_rotation;
+ parent_class->set_rotation = cc_display_monitor_dbus_set_rotation;
+ parent_class->supports_rotation = cc_display_monitor_dbus_supports_rotation;
+ parent_class->get_physical_size = cc_display_monitor_dbus_get_physical_size;
+ parent_class->get_geometry = cc_display_monitor_dbus_get_geometry;
+ parent_class->get_mode = cc_display_monitor_dbus_get_mode;
+ parent_class->get_preferred_mode = cc_display_monitor_dbus_get_preferred_mode;
+ parent_class->get_id = cc_display_monitor_dbus_get_id;
+ parent_class->get_modes = cc_display_monitor_dbus_get_modes;
+ parent_class->supports_underscanning = cc_display_monitor_dbus_supports_underscanning;
+ parent_class->get_underscanning = cc_display_monitor_dbus_get_underscanning;
+ parent_class->set_underscanning = cc_display_monitor_dbus_set_underscanning;
+ parent_class->get_privacy = cc_display_monitor_dbus_get_privacy;
+ parent_class->set_mode = cc_display_monitor_dbus_set_mode;
+ parent_class->set_compatible_clone_mode = cc_display_monitor_dbus_set_compatible_clone_mode;
+ parent_class->set_position = cc_display_monitor_dbus_set_position;
+ parent_class->get_scale = cc_display_monitor_dbus_get_scale;
+ parent_class->set_scale = cc_display_monitor_dbus_set_scale;
+}
+
+static void
+construct_modes (CcDisplayMonitorDBus *self,
+ GVariantIter *modes)
+{
+ CcDisplayModeDBus *mode;
+
+ while (TRUE)
+ {
+ g_autoptr(GVariant) variant = NULL;
+
+ if (!g_variant_iter_next (modes, "@"MODE_FORMAT, &variant))
+ break;
+
+ mode = cc_display_mode_dbus_new (self, variant);
+ self->modes = g_list_prepend (self->modes, mode);
+
+ if (mode->flags & MODE_PREFERRED)
+ self->preferred_mode = CC_DISPLAY_MODE (mode);
+ if (mode->flags & MODE_CURRENT)
+ self->current_mode = CC_DISPLAY_MODE (mode);
+ }
+
+ self->modes = g_list_reverse (self->modes);
+}
+
+static CcDisplayMonitorDBus *
+cc_display_monitor_dbus_new (GVariant *variant,
+ CcDisplayConfigDBus *config)
+{
+ CcDisplayMonitorDBus *self = g_object_new (CC_TYPE_DISPLAY_MONITOR_DBUS, NULL);
+ gchar *s1, *s2, *s3, *s4;
+ g_autoptr(GVariantIter) modes = NULL;
+ g_autoptr(GVariantIter) props = NULL;
+
+ self->config = config;
+
+ g_variant_get (variant, MONITOR_FORMAT,
+ &s1, &s2, &s3, &s4, &modes, &props);
+ self->connector_name = s1;
+ self->vendor_name = s2;
+ self->product_name = s3;
+ self->product_serial = s4;
+
+ construct_modes (self, modes);
+
+ while (TRUE)
+ {
+ const char *s;
+ g_autoptr(GVariant) v = NULL;
+
+ if (!g_variant_iter_next (props, "{&sv}", &s, &v))
+ break;
+
+ if (g_str_equal (s, "width-mm"))
+ {
+ g_variant_get (v, "i", &self->width_mm);
+ }
+ else if (g_str_equal (s, "height-mm"))
+ {
+ g_variant_get (v, "i", &self->height_mm);
+ }
+ else if (g_str_equal (s, "is-underscanning"))
+ {
+ gboolean underscanning = FALSE;
+ g_variant_get (v, "b", &underscanning);
+ if (underscanning)
+ self->underscanning = UNDERSCANNING_ENABLED;
+ else
+ self->underscanning = UNDERSCANNING_DISABLED;
+ }
+ else if (g_str_equal (s, "max-screen-size"))
+ {
+ g_variant_get (v, "ii", &self->max_width, &self->max_height);
+ }
+ else if (g_str_equal (s, "is-builtin"))
+ {
+ g_variant_get (v, "b", &self->builtin);
+ }
+ else if (g_str_equal (s, "display-name"))
+ {
+ g_variant_get (v, "s", &self->display_name);
+ }
+ else if (g_str_equal (s, "privacy-screen-state"))
+ {
+ gboolean enabled;
+ gboolean locked;
+ g_variant_get (v, "(bb)", &enabled, &locked);
+
+ if (enabled)
+ self->privacy_screen = CC_DISPLAY_MONITOR_PRIVACY_ENABLED;
+ else
+ self->privacy_screen = CC_DISPLAY_MONITOR_PRIVACY_DISABLED;
+
+ if (locked)
+ self->privacy_screen |= CC_DISPLAY_MONITOR_PRIVACY_LOCKED;
+ }
+ }
+
+ return self;
+}
+
+
+typedef enum _CcDisplayLayoutMode
+{
+ CC_DISPLAY_LAYOUT_MODE_LOGICAL = 1,
+ CC_DISPLAY_LAYOUT_MODE_PHYSICAL = 2
+} CcDisplayLayoutMode;
+
+typedef enum _CcDisplayConfigMethod
+{
+ CC_DISPLAY_CONFIG_METHOD_VERIFY = 0,
+ CC_DISPLAY_CONFIG_METHOD_TEMPORARY = 1,
+ CC_DISPLAY_CONFIG_METHOD_PERSISTENT = 2
+} CcDisplayConfigMethod;
+
+struct _CcDisplayConfigDBus
+{
+ CcDisplayConfig parent_instance;
+
+ GVariant *state;
+ GDBusConnection *connection;
+ GDBusProxy *proxy;
+
+ int min_width;
+ int min_height;
+
+ guint panel_orientation_managed;
+
+ guint32 serial;
+ gboolean supports_mirroring;
+ gboolean supports_changing_layout_mode;
+ gboolean global_scale_required;
+ CcDisplayLayoutMode layout_mode;
+
+ GList *monitors;
+ CcDisplayMonitorDBus *primary;
+
+ GHashTable *logical_monitors;
+};
+
+G_DEFINE_TYPE (CcDisplayConfigDBus,
+ cc_display_config_dbus,
+ CC_TYPE_DISPLAY_CONFIG)
+
+enum
+{
+ PROP_0,
+ PROP_STATE,
+ PROP_CONNECTION,
+};
+
+static GList *
+cc_display_config_dbus_get_monitors (CcDisplayConfig *pself)
+{
+ CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself);
+
+ return self->monitors;
+}
+
+static GVariant *
+build_monitors_variant (GHashTable *monitors)
+{
+ GVariantBuilder builder;
+ GHashTableIter iter;
+ CcDisplayMonitorDBus *monitor;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
+ g_hash_table_iter_init (&iter, monitors);
+
+ while (g_hash_table_iter_next (&iter, (void **) &monitor, NULL))
+ {
+ GVariantBuilder props_builder;
+ CcDisplayModeDBus *mode_dbus;
+
+ if (!monitor->current_mode)
+ continue;
+
+ g_variant_builder_init (&props_builder, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (&props_builder, "{sv}",
+ "underscanning",
+ g_variant_new_boolean (monitor->underscanning == UNDERSCANNING_ENABLED));
+
+ mode_dbus = CC_DISPLAY_MODE_DBUS (monitor->current_mode);
+ g_variant_builder_add (&builder, "(ss@*)",
+ monitor->connector_name,
+ mode_dbus->id,
+ g_variant_builder_end (&props_builder));
+ }
+
+ return g_variant_builder_end (&builder);
+}
+
+static GVariant *
+build_logical_monitors_parameter (CcDisplayConfigDBus *self)
+{
+ GVariantBuilder builder;
+ GHashTableIter iter;
+ CcDisplayLogicalMonitor *logical_monitor;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(iiduba(ssa{sv}))"));
+ g_hash_table_iter_init (&iter, self->logical_monitors);
+
+ while (g_hash_table_iter_next (&iter, (void **) &logical_monitor, NULL))
+ g_variant_builder_add (&builder, "(iidub@*)",
+ logical_monitor->x,
+ logical_monitor->y,
+ logical_monitor->scale,
+ logical_monitor->rotation,
+ logical_monitor->primary,
+ build_monitors_variant (logical_monitor->monitors));
+
+ return g_variant_builder_end (&builder);
+}
+
+static GVariant *
+build_apply_parameters (CcDisplayConfigDBus *self,
+ CcDisplayConfigMethod method)
+{
+ GVariantBuilder props_builder;
+ g_variant_builder_init (&props_builder, G_VARIANT_TYPE ("a{sv}"));
+
+ if (self->supports_changing_layout_mode)
+ g_variant_builder_add (&props_builder, "{sv}",
+ "layout-mode", g_variant_new_uint32 (self->layout_mode));
+
+ return g_variant_new ("(uu@*@*)",
+ self->serial,
+ method,
+ build_logical_monitors_parameter (self),
+ g_variant_builder_end (&props_builder));
+}
+
+static gboolean
+config_apply (CcDisplayConfigDBus *self,
+ CcDisplayConfigMethod method,
+ GError **error)
+{
+ g_autoptr(GVariant) retval = NULL;
+
+ cc_display_config_dbus_ensure_non_offset_coords (self);
+
+ retval = g_dbus_proxy_call_sync (self->proxy,
+ "ApplyMonitorsConfig",
+ build_apply_parameters (self, method),
+ G_DBUS_CALL_FLAGS_NO_AUTO_START,
+ -1,
+ NULL,
+ error);
+ return retval != NULL;
+}
+
+static gboolean
+cc_display_config_dbus_is_applicable (CcDisplayConfig *pself)
+{
+ CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself);
+ g_autoptr(GError) error = NULL;
+
+ if (!config_apply (self, CC_DISPLAY_CONFIG_METHOD_VERIFY, &error))
+ {
+ g_warning ("Config not applicable: %s", error->message);
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+static CcDisplayMonitorDBus *
+monitor_from_spec (CcDisplayConfigDBus *self,
+ const gchar *connector,
+ const gchar *vendor,
+ const gchar *product,
+ const gchar *serial)
+{
+ GList *l;
+ for (l = self->monitors; l != NULL; l = l->next)
+ {
+ CcDisplayMonitorDBus *m = l->data;
+ if (g_str_equal (m->connector_name, connector) &&
+ g_str_equal (m->vendor_name, vendor) &&
+ g_str_equal (m->product_name, product) &&
+ g_str_equal (m->product_serial, serial))
+ return m;
+ }
+ return NULL;
+}
+
+static gboolean
+cc_display_config_dbus_equal (CcDisplayConfig *pself,
+ CcDisplayConfig *pother)
+{
+ CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself);
+ CcDisplayConfigDBus *other = CC_DISPLAY_CONFIG_DBUS (pother);
+ GList *l;
+
+ g_return_val_if_fail (pself, FALSE);
+ g_return_val_if_fail (pother, FALSE);
+
+ cc_display_config_dbus_ensure_non_offset_coords (self);
+ cc_display_config_dbus_ensure_non_offset_coords (other);
+
+ for (l = self->monitors; l != NULL; l = l->next)
+ {
+ CcDisplayMonitorDBus *m1 = l->data;
+ CcDisplayMonitorDBus *m2 = monitor_from_spec (other,
+ m1->connector_name,
+ m1->vendor_name,
+ m1->product_name,
+ m1->product_serial);
+ if (!m2)
+ return FALSE;
+
+ if (m1->underscanning != m2->underscanning)
+ return FALSE;
+
+ if (!cc_display_logical_monitor_equal (m1->logical_monitor, m2->logical_monitor))
+ return FALSE;
+
+ /* Modes should not be compared if both monitors have no logical monitor. */
+ if (m1->logical_monitor == NULL && m2->logical_monitor == NULL)
+ continue;
+
+ if (!cc_display_mode_dbus_equal (CC_DISPLAY_MODE_DBUS (m1->current_mode),
+ CC_DISPLAY_MODE_DBUS (m2->current_mode)))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+cc_display_config_dbus_set_primary (CcDisplayConfigDBus *self,
+ CcDisplayMonitorDBus *new_primary)
+{
+ if (self->primary == new_primary)
+ return;
+
+ if (!new_primary->logical_monitor)
+ return;
+
+ if (self->primary && self->primary->logical_monitor)
+ {
+ self->primary->logical_monitor->primary = FALSE;
+ g_signal_emit_by_name (self->primary, "primary");
+ }
+
+ self->primary = new_primary;
+ self->primary->logical_monitor->primary = TRUE;
+
+ g_signal_emit_by_name (self->primary, "primary");
+ g_signal_emit_by_name (self, "primary");
+}
+
+static void
+cc_display_config_dbus_unset_primary (CcDisplayConfigDBus *self,
+ CcDisplayMonitorDBus *old_primary)
+{
+ GList *l;
+
+ if (self->primary != old_primary)
+ return;
+
+ for (l = self->monitors; l != NULL; l = l->next)
+ {
+ CcDisplayMonitorDBus *monitor = l->data;
+ if (monitor->logical_monitor &&
+ monitor != old_primary)
+ {
+ cc_display_config_dbus_set_primary (self, monitor);
+ break;
+ }
+ }
+
+ if (self->primary == old_primary)
+ self->primary = NULL;
+}
+
+static gboolean
+cc_display_config_dbus_is_cloning (CcDisplayConfig *pself)
+{
+ CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself);
+ guint n_active_monitors = 0;
+ GList *l;
+
+ for (l = self->monitors; l != NULL; l = l->next)
+ if (cc_display_monitor_is_active (CC_DISPLAY_MONITOR (l->data)))
+ n_active_monitors += 1;
+
+ return n_active_monitors > 1 && g_hash_table_size (self->logical_monitors) == 1;
+}
+
+static void
+cc_display_config_dbus_set_cloning (CcDisplayConfig *pself,
+ gboolean clone)
+{
+ CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself);
+ gboolean is_cloning = cc_display_config_is_cloning (pself);
+ CcDisplayLogicalMonitor *logical_monitor;
+ GList *l;
+
+ if (clone && !is_cloning)
+ {
+ logical_monitor = g_object_new (CC_TYPE_DISPLAY_LOGICAL_MONITOR, NULL);
+ for (l = self->monitors; l != NULL; l = l->next)
+ cc_display_monitor_dbus_set_logical_monitor (CC_DISPLAY_MONITOR_DBUS (l->data),
+ logical_monitor);
+ register_logical_monitor (self, logical_monitor);
+ }
+ else if (!clone && is_cloning)
+ {
+ for (l = self->monitors; l != NULL; l = l->next)
+ {
+ logical_monitor = g_object_new (CC_TYPE_DISPLAY_LOGICAL_MONITOR, NULL);
+ cc_display_monitor_dbus_set_logical_monitor (CC_DISPLAY_MONITOR_DBUS (l->data),
+ logical_monitor);
+ register_logical_monitor (self, logical_monitor);
+ }
+ cc_display_config_dbus_make_linear (self);
+ }
+}
+
+static gboolean
+mode_supports_scale (CcDisplayMode *mode,
+ double scale)
+{
+ g_autoptr(GArray) scales = NULL;
+ int i;
+
+ scales = cc_display_mode_get_supported_scales (mode);
+ for (i = 0; i < scales->len; i++)
+ {
+ if (G_APPROX_VALUE (scale, g_array_index (scales, double, i),
+ DBL_EPSILON))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+remove_unsupported_scales (CcDisplayMode *mode,
+ GArray *supported_scales)
+{
+ g_autoptr(GArray) mode_scales = NULL;
+ int i;
+
+ mode_scales = cc_display_mode_get_supported_scales (mode);
+ i = 0;
+ while (i < supported_scales->len)
+ {
+ double scale;
+
+ if (i == supported_scales->len)
+ break;
+
+ scale = g_array_index (supported_scales, double, i);
+
+ if (mode_supports_scale (mode, scale))
+ {
+ i++;
+ continue;
+ }
+
+ g_array_remove_range (supported_scales, i, 1);
+ }
+}
+
+static gboolean
+monitor_has_compatible_clone_mode (CcDisplayMonitorDBus *monitor,
+ CcDisplayModeDBus *mode,
+ GArray *supported_scales)
+{
+ GList *l;
+
+ for (l = monitor->modes; l; l = l->next)
+ {
+ CcDisplayModeDBus *other_mode = l->data;
+
+ if (other_mode->width != mode->width ||
+ other_mode->height != mode->height)
+ continue;
+
+ if ((other_mode->flags & MODE_INTERLACED) !=
+ (mode->flags & MODE_INTERLACED))
+ continue;
+
+ remove_unsupported_scales (CC_DISPLAY_MODE (other_mode), supported_scales);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+monitors_has_compatible_clone_mode (CcDisplayConfigDBus *self,
+ CcDisplayModeDBus *mode,
+ GArray *supported_scales)
+{
+ GList *l;
+
+ for (l = self->monitors; l; l = l->next)
+ {
+ CcDisplayMonitorDBus *monitor = l->data;
+
+ if (!monitor_has_compatible_clone_mode (monitor, mode, supported_scales))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+is_mode_better (CcDisplayModeDBus *mode,
+ CcDisplayModeDBus *other_mode)
+{
+ if (mode->width * mode->height > other_mode->width * other_mode->height)
+ return TRUE;
+ else if (mode->width * mode->height < other_mode->width * other_mode->height)
+ return FALSE;
+
+ if (!(mode->flags & MODE_INTERLACED) &&
+ (other_mode->flags & MODE_INTERLACED))
+ return TRUE;
+
+ return FALSE;
+}
+
+static GList *
+cc_display_config_dbus_generate_cloning_modes (CcDisplayConfig *pself)
+{
+ CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself);
+ CcDisplayMonitorDBus *base_monitor = NULL;
+ GList *l;
+ GList *clone_modes = NULL;
+ CcDisplayModeDBus *best_mode = NULL;
+
+ for (l = self->monitors; l; l = l->next)
+ {
+ CcDisplayMonitor *monitor = l->data;
+
+ if (cc_display_monitor_is_active (monitor))
+ {
+ base_monitor = CC_DISPLAY_MONITOR_DBUS (monitor);
+ break;
+ }
+ }
+
+ if (!base_monitor)
+ return NULL;
+
+ for (l = base_monitor->modes; l; l = l->next)
+ {
+ CcDisplayModeDBus *mode = l->data;
+ CcDisplayModeDBus *virtual_mode;
+ g_autoptr (GArray) supported_scales = NULL;
+
+ supported_scales =
+ cc_display_mode_get_supported_scales (CC_DISPLAY_MODE (mode));
+
+ if (!monitors_has_compatible_clone_mode (self, mode, supported_scales))
+ continue;
+
+ virtual_mode = cc_display_mode_dbus_new_virtual (mode->width,
+ mode->height,
+ mode->preferred_scale,
+ supported_scales);
+ clone_modes = g_list_append (clone_modes, virtual_mode);
+
+ if (!best_mode || is_mode_better (virtual_mode, best_mode))
+ best_mode = virtual_mode;
+ }
+
+ best_mode->flags |= MODE_PREFERRED;
+
+ return clone_modes;
+}
+
+static gboolean
+cc_display_config_dbus_apply (CcDisplayConfig *pself,
+ GError **error)
+{
+ CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself);
+
+ return config_apply (self, CC_DISPLAY_CONFIG_METHOD_PERSISTENT, error);
+}
+
+static gboolean
+cc_display_config_dbus_is_layout_logical (CcDisplayConfig *pself)
+{
+ CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself);
+
+ return self->layout_mode == CC_DISPLAY_LAYOUT_MODE_LOGICAL;
+}
+
+static gboolean
+is_scale_allowed_by_active_monitors (CcDisplayConfigDBus *self,
+ CcDisplayMode *mode,
+ double scale);
+
+static gboolean
+is_scaled_mode_allowed (CcDisplayConfigDBus *self,
+ CcDisplayModeDBus *mode,
+ double scale)
+{
+ gint width, height;
+
+ /* Do the math as if the monitor is always in landscape mode. */
+ width = round (mode->width / scale);
+ height = round (mode->height / scale);
+
+ if (MAX (width, height) < self->min_width ||
+ MIN (width, height) < self->min_height)
+ return FALSE;
+
+ if (!self->global_scale_required)
+ return TRUE;
+
+ return is_scale_allowed_by_active_monitors (self, CC_DISPLAY_MODE (mode), scale);
+}
+
+static gboolean
+is_scale_allowed_by_active_monitors (CcDisplayConfigDBus *self,
+ CcDisplayMode *mode,
+ double scale)
+{
+ GList *l;
+
+ for (l = self->monitors; l != NULL; l = l->next)
+ {
+ CcDisplayMonitorDBus *m = CC_DISPLAY_MONITOR_DBUS (l->data);
+
+ if (!cc_display_monitor_is_active (CC_DISPLAY_MONITOR (m)))
+ continue;
+
+ if (!cc_display_mode_dbus_is_supported_scale (mode, scale))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static GArray *
+cc_display_mode_dbus_get_supported_scales (CcDisplayMode *pself)
+{
+ CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (pself);
+ CcDisplayConfig *config = CC_DISPLAY_CONFIG (self->monitor->config);
+
+ if (cc_display_config_is_cloning (config))
+ {
+ GArray *scales = g_array_copy (self->supported_scales);
+ int i;
+
+ for (i = scales->len - 1; i >= 0; i--)
+ {
+ double scale = g_array_index (scales, double, i);
+
+ if (!is_scale_allowed_by_active_monitors (self->monitor->config,
+ pself, scale))
+ g_array_remove_index (scales, i);
+ }
+
+ return g_steal_pointer (&scales);
+ }
+
+ return g_array_ref (self->supported_scales);
+}
+
+static void
+filter_out_invalid_scaled_modes (CcDisplayConfigDBus *self)
+{
+ GList *l;
+
+ for (l = self->monitors; l; l = l->next)
+ {
+ CcDisplayMonitorDBus *monitor = l->data;
+ GList *ll = monitor->modes;
+
+ while (ll != NULL)
+ {
+ CcDisplayModeDBus *mode = ll->data;
+ GList *current = ll;
+ double current_scale = -1;
+ int i;
+
+ ll = ll->next;
+
+ if (monitor->current_mode != CC_DISPLAY_MODE (mode) &&
+ monitor->preferred_mode != CC_DISPLAY_MODE (mode) &&
+ !is_scaled_mode_allowed (self, mode, 1.0))
+ {
+ g_clear_object (&mode);
+ monitor->modes = g_list_delete_link (monitor->modes, current);
+ continue;
+ }
+
+ if (monitor->current_mode == CC_DISPLAY_MODE (mode))
+ current_scale = cc_display_monitor_dbus_get_scale (CC_DISPLAY_MONITOR (monitor));
+
+ for (i = mode->supported_scales->len - 1; i >= 0; i--)
+ {
+ float scale = g_array_index (mode->supported_scales, double, i);
+
+ if (!G_APPROX_VALUE (scale, current_scale, DBL_EPSILON) &&
+ !G_APPROX_VALUE (scale, mode->preferred_scale, DBL_EPSILON) &&
+ !is_scaled_mode_allowed (self, mode, scale))
+ {
+ g_array_remove_index (mode->supported_scales, i);
+ }
+ }
+ }
+ }
+}
+
+static void
+cc_display_config_dbus_set_minimum_size (CcDisplayConfig *pself,
+ int width,
+ int height)
+{
+ CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself);
+
+ g_assert (width >= 0 && height >= 0);
+ g_assert (((self->min_width == 0 && self->min_height == 0) ||
+ (self->min_width >= width && self->min_height >= height)) &&
+ "Minimum size can't be set again to higher values");
+
+ self->min_width = width;
+ self->min_height = height;
+
+ filter_out_invalid_scaled_modes (self);
+}
+
+static gboolean
+cc_display_config_dbus_is_scaled_mode_valid (CcDisplayConfig *pself,
+ CcDisplayMode *mode,
+ double scale)
+{
+ CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself);
+
+ if (cc_display_config_is_cloning (pself))
+ return is_scale_allowed_by_active_monitors (self, mode, scale);
+
+ return cc_display_mode_dbus_is_supported_scale (mode, scale);
+}
+
+static gboolean
+cc_display_config_dbus_get_panel_orientation_managed (CcDisplayConfig *pself)
+{
+ CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself);
+
+ return self->panel_orientation_managed;
+}
+
+static void
+cc_display_config_dbus_init (CcDisplayConfigDBus *self)
+{
+ self->serial = 0;
+ self->supports_mirroring = TRUE;
+ self->supports_changing_layout_mode = FALSE;
+ self->global_scale_required = FALSE;
+ self->layout_mode = CC_DISPLAY_LAYOUT_MODE_LOGICAL;
+ self->logical_monitors = g_hash_table_new (NULL, NULL);
+}
+
+static void
+remove_logical_monitor (gpointer data,
+ GObject *object)
+{
+ CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (data);
+
+ g_hash_table_remove (self->logical_monitors, object);
+}
+
+static void
+register_logical_monitor (CcDisplayConfigDBus *self,
+ CcDisplayLogicalMonitor *logical_monitor)
+{
+ g_hash_table_add (self->logical_monitors, logical_monitor);
+ g_object_weak_ref (G_OBJECT (logical_monitor), remove_logical_monitor, self);
+ g_object_unref (logical_monitor);
+}
+
+static void
+apply_global_scale_requirement (CcDisplayConfigDBus *self,
+ CcDisplayMonitor *monitor)
+{
+ GList *l;
+ double scale = cc_display_monitor_get_scale (monitor);
+
+ for (l = self->monitors; l != NULL; l = l->next)
+ {
+ CcDisplayMonitor *m = l->data;
+ if (m != monitor)
+ cc_display_monitor_set_scale (m, scale);
+ }
+}
+
+static void
+construct_monitors (CcDisplayConfigDBus *self,
+ GVariantIter *monitors,
+ GVariantIter *logical_monitors)
+{
+ while (TRUE)
+ {
+ CcDisplayMonitorDBus *monitor;
+ g_autoptr(GVariant) variant = NULL;
+
+ if (!g_variant_iter_next (monitors, "@"MONITOR_FORMAT, &variant))
+ break;
+
+ monitor = cc_display_monitor_dbus_new (variant, self);
+ self->monitors = g_list_prepend (self->monitors, monitor);
+
+ if (self->global_scale_required)
+ g_signal_connect_object (monitor, "scale",
+ G_CALLBACK (apply_global_scale_requirement),
+ self, G_CONNECT_SWAPPED);
+ }
+
+ self->monitors = g_list_reverse (self->monitors);
+
+ while (TRUE)
+ {
+ g_autoptr(GVariant) variant = NULL;
+ CcDisplayLogicalMonitor *logical_monitor;
+ g_autoptr(GVariantIter) monitor_specs = NULL;
+ const gchar *s1, *s2, *s3, *s4;
+ gboolean primary;
+
+ if (!g_variant_iter_next (logical_monitors, "@"LOGICAL_MONITOR_FORMAT, &variant))
+ break;
+
+ logical_monitor = g_object_new (CC_TYPE_DISPLAY_LOGICAL_MONITOR, NULL);
+ g_variant_get (variant, LOGICAL_MONITOR_FORMAT,
+ &logical_monitor->x,
+ &logical_monitor->y,
+ &logical_monitor->scale,
+ &logical_monitor->rotation,
+ &primary,
+ &monitor_specs,
+ NULL);
+
+ while (g_variant_iter_next (monitor_specs, "(&s&s&s&s)", &s1, &s2, &s3, &s4))
+ {
+ CcDisplayMonitorDBus *m = monitor_from_spec (self, s1, s2, s3, s4);
+ if (!m)
+ {
+ g_warning ("Couldn't find monitor given spec: %s, %s, %s, %s",
+ s1, s2, s3, s4);
+ continue;
+ }
+
+ cc_display_monitor_dbus_set_logical_monitor (m, logical_monitor);
+ }
+
+ if (g_hash_table_size (logical_monitor->monitors) > 0)
+ {
+ if (primary)
+ {
+ CcDisplayMonitorDBus *m = NULL;
+ GHashTableIter iter;
+ g_hash_table_iter_init (&iter, logical_monitor->monitors);
+ g_hash_table_iter_next (&iter, (void **) &m, NULL);
+
+ cc_display_config_dbus_set_primary (self, m);
+ }
+ }
+ else
+ {
+ g_warning ("Got an empty logical monitor, ignoring");
+ }
+
+ register_logical_monitor (self, logical_monitor);
+ }
+}
+
+static void
+update_panel_orientation_managed (CcDisplayConfigDBus *self)
+{
+ g_autoptr(GVariant) v = NULL;
+ gboolean panel_orientation_managed = FALSE;
+
+ if (self->proxy != NULL)
+ {
+ v = g_dbus_proxy_get_cached_property (self->proxy, "PanelOrientationManaged");
+ if (v)
+ {
+ panel_orientation_managed = g_variant_get_boolean (v);
+ }
+ }
+
+ if (panel_orientation_managed == self->panel_orientation_managed)
+ return;
+
+ self->panel_orientation_managed = panel_orientation_managed;
+ g_signal_emit_by_name (self, "panel-orientation-managed", self->panel_orientation_managed);
+}
+
+static void
+proxy_properties_changed_cb (GDBusProxy *proxy,
+ GVariant *changed_properties,
+ GStrv invalidated_properties,
+ CcDisplayConfigDBus *self)
+{
+ GVariantDict dict;
+
+ g_variant_dict_init (&dict, changed_properties);
+
+ if (g_variant_dict_contains (&dict, "PanelOrientationManaged"))
+ update_panel_orientation_managed (self);
+}
+
+static void
+cc_display_config_dbus_constructed (GObject *object)
+{
+ CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (object);
+ g_autoptr(GVariantIter) monitors = NULL;
+ g_autoptr(GVariantIter) logical_monitors = NULL;
+ g_autoptr(GVariantIter) props = NULL;
+ g_autoptr(GError) error = NULL;
+
+ g_variant_get (self->state,
+ CURRENT_STATE_FORMAT,
+ &self->serial,
+ &monitors,
+ &logical_monitors,
+ &props);
+
+ while (TRUE)
+ {
+ const char *s;
+ g_autoptr(GVariant) v = NULL;
+
+ if (!g_variant_iter_next (props, "{&sv}", &s, &v))
+ break;
+
+ if (g_str_equal (s, "supports-mirroring"))
+ {
+ g_variant_get (v, "b", &self->supports_mirroring);
+ }
+ else if (g_str_equal (s, "supports-changing-layout-mode"))
+ {
+ g_variant_get (v, "b", &self->supports_changing_layout_mode);
+ }
+ else if (g_str_equal (s, "global-scale-required"))
+ {
+ g_variant_get (v, "b", &self->global_scale_required);
+ }
+ else if (g_str_equal (s, "layout-mode"))
+ {
+ guint32 u = 0;
+ g_variant_get (v, "u", &u);
+ if (u >= CC_DISPLAY_LAYOUT_MODE_LOGICAL &&
+ u <= CC_DISPLAY_LAYOUT_MODE_PHYSICAL)
+ self->layout_mode = u;
+ }
+ }
+
+ construct_monitors (self, monitors, logical_monitors);
+ filter_out_invalid_scaled_modes (self);
+
+ self->proxy = g_dbus_proxy_new_sync (self->connection,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.gnome.Mutter.DisplayConfig",
+ "/org/gnome/Mutter/DisplayConfig",
+ "org.gnome.Mutter.DisplayConfig",
+ NULL,
+ &error);
+ if (error)
+ g_warning ("Could not create DisplayConfig proxy: %s", error->message);
+
+ g_signal_connect (self->proxy, "g-properties-changed",
+ G_CALLBACK (proxy_properties_changed_cb), self);
+ update_panel_orientation_managed (self);
+
+ G_OBJECT_CLASS (cc_display_config_dbus_parent_class)->constructed (object);
+}
+
+static void
+cc_display_config_dbus_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (object);
+
+ switch (prop_id)
+ {
+ case PROP_STATE:
+ self->state = g_value_dup_variant (value);
+ break;
+ case PROP_CONNECTION:
+ self->connection = g_value_dup_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_display_config_dbus_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (object);
+
+ switch (prop_id)
+ {
+ case PROP_STATE:
+ g_value_set_variant (value, self->state);
+ break;
+ case PROP_CONNECTION:
+ g_value_set_object (value, self->connection);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_display_config_dbus_dispose (GObject *object)
+{
+ CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (object);
+
+ if (self->logical_monitors)
+ {
+ GHashTableIter iter;
+ gpointer monitor;
+
+ g_hash_table_iter_init (&iter, self->logical_monitors);
+
+ while (g_hash_table_iter_next (&iter, &monitor, NULL))
+ g_object_weak_unref (G_OBJECT (monitor), remove_logical_monitor, self);
+ }
+
+ G_OBJECT_CLASS (cc_display_config_dbus_parent_class)->dispose (object);
+}
+
+static void
+cc_display_config_dbus_finalize (GObject *object)
+{
+ CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (object);
+
+ g_clear_pointer (&self->state, g_variant_unref);
+ g_clear_object (&self->connection);
+ g_clear_object (&self->proxy);
+
+ g_clear_list (&self->monitors, g_object_unref);
+ g_clear_pointer (&self->logical_monitors, g_hash_table_destroy);
+
+ G_OBJECT_CLASS (cc_display_config_dbus_parent_class)->finalize (object);
+}
+
+static void
+cc_display_config_dbus_class_init (CcDisplayConfigDBusClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ CcDisplayConfigClass *parent_class = CC_DISPLAY_CONFIG_CLASS (klass);
+ GParamSpec *pspec;
+
+ gobject_class->constructed = cc_display_config_dbus_constructed;
+ gobject_class->set_property = cc_display_config_dbus_set_property;
+ gobject_class->get_property = cc_display_config_dbus_get_property;
+ gobject_class->dispose = cc_display_config_dbus_dispose;
+ gobject_class->finalize = cc_display_config_dbus_finalize;
+
+ parent_class->get_monitors = cc_display_config_dbus_get_monitors;
+ parent_class->is_applicable = cc_display_config_dbus_is_applicable;
+ parent_class->equal = cc_display_config_dbus_equal;
+ parent_class->apply = cc_display_config_dbus_apply;
+ parent_class->is_cloning = cc_display_config_dbus_is_cloning;
+ parent_class->set_cloning = cc_display_config_dbus_set_cloning;
+ parent_class->generate_cloning_modes = cc_display_config_dbus_generate_cloning_modes;
+ parent_class->is_layout_logical = cc_display_config_dbus_is_layout_logical;
+ parent_class->is_scaled_mode_valid = cc_display_config_dbus_is_scaled_mode_valid;
+ parent_class->set_minimum_size = cc_display_config_dbus_set_minimum_size;
+ parent_class->get_panel_orientation_managed =
+ cc_display_config_dbus_get_panel_orientation_managed;
+
+ pspec = g_param_spec_variant ("state",
+ "GVariant",
+ "GVariant",
+ G_VARIANT_TYPE (CURRENT_STATE_FORMAT),
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS |
+ G_PARAM_CONSTRUCT_ONLY);
+ g_object_class_install_property (gobject_class, PROP_STATE, pspec);
+
+ pspec = g_param_spec_object ("connection",
+ "GDBusConnection",
+ "GDBusConnection",
+ G_TYPE_DBUS_CONNECTION,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS |
+ G_PARAM_CONSTRUCT_ONLY);
+ g_object_class_install_property (gobject_class, PROP_CONNECTION, pspec);
+}
+
+static gint
+sort_x_axis (gconstpointer a, gconstpointer b)
+{
+ const CcDisplayLogicalMonitor *ma = a;
+ const CcDisplayLogicalMonitor *mb = b;
+ return ma->x - mb->x;
+}
+
+static gint
+sort_y_axis (gconstpointer a, gconstpointer b)
+{
+ const CcDisplayLogicalMonitor *ma = a;
+ const CcDisplayLogicalMonitor *mb = b;
+ return ma->y - mb->y;
+}
+
+static void
+add_x_delta (gpointer d1, gpointer d2)
+{
+ CcDisplayLogicalMonitor *m = d1;
+ int delta = GPOINTER_TO_INT (d2);
+ m->x += delta;
+}
+
+static gboolean
+logical_monitor_is_rotated (CcDisplayLogicalMonitor *lm)
+{
+ switch (lm->rotation)
+ {
+ case CC_DISPLAY_ROTATION_90:
+ case CC_DISPLAY_ROTATION_270:
+ case CC_DISPLAY_ROTATION_90_FLIPPED:
+ case CC_DISPLAY_ROTATION_270_FLIPPED:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+static int
+logical_monitor_width (CcDisplayLogicalMonitor *lm)
+{
+ CcDisplayMonitorDBus *monitor;
+ CcDisplayModeDBus *mode;
+ GHashTableIter iter;
+ int width;
+
+ g_hash_table_iter_init (&iter, lm->monitors);
+ g_hash_table_iter_next (&iter, (void **) &monitor, NULL);
+ mode = CC_DISPLAY_MODE_DBUS (monitor->current_mode);
+ if (logical_monitor_is_rotated (lm))
+ width = mode ? mode->height : 0;
+ else
+ width = mode ? mode->width : 0;
+
+ if (monitor->config->layout_mode == CC_DISPLAY_LAYOUT_MODE_LOGICAL)
+ return round (width / lm->scale);
+ else
+ return width;
+}
+
+static void
+add_y_delta (gpointer d1, gpointer d2)
+{
+ CcDisplayLogicalMonitor *m = d1;
+ int delta = GPOINTER_TO_INT (d2);
+ m->y += delta;
+}
+
+static void
+cc_display_config_dbus_ensure_non_offset_coords (CcDisplayConfigDBus *self)
+{
+ GList *x_axis, *y_axis;
+ CcDisplayLogicalMonitor *m;
+
+ if (g_hash_table_size (self->logical_monitors) == 0)
+ return;
+
+ x_axis = g_hash_table_get_keys (self->logical_monitors);
+ x_axis = g_list_sort (x_axis, sort_x_axis);
+ y_axis = g_hash_table_get_keys (self->logical_monitors);
+ y_axis = g_list_sort (y_axis, sort_y_axis);
+
+ m = x_axis->data;
+ if (m->x != 0)
+ g_list_foreach (x_axis, add_x_delta, GINT_TO_POINTER (- m->x));
+
+ m = y_axis->data;
+ if (m->y != 0)
+ g_list_foreach (y_axis, add_y_delta, GINT_TO_POINTER (- m->y));
+
+ g_list_free (x_axis);
+ g_list_free (y_axis);
+}
+
+static void
+cc_display_config_dbus_append_right (CcDisplayConfigDBus *self,
+ CcDisplayLogicalMonitor *monitor)
+{
+ GList *x_axis;
+ CcDisplayLogicalMonitor *last;
+
+ if (g_hash_table_size (self->logical_monitors) == 0)
+ {
+ monitor->x = 0;
+ monitor->y = 0;
+ return;
+ }
+
+ x_axis = g_hash_table_get_keys (self->logical_monitors);
+ x_axis = g_list_sort (x_axis, sort_x_axis);
+ last = g_list_last (x_axis)->data;
+ monitor->x = last->x + logical_monitor_width (last);
+ monitor->y = last->y;
+
+ g_list_free (x_axis);
+}
+
+static void
+cc_display_config_dbus_make_linear (CcDisplayConfigDBus *self)
+{
+ CcDisplayLogicalMonitor *primary;
+ GList *logical_monitors, *l;
+ int x;
+
+ if (self->primary && self->primary->logical_monitor)
+ {
+ primary = self->primary->logical_monitor;
+ primary->x = primary->y = 0;
+ x = logical_monitor_width (primary);
+ }
+ else
+ {
+ primary = NULL;
+ x = 0;
+ }
+
+ logical_monitors = g_hash_table_get_keys (self->logical_monitors);
+ for (l = logical_monitors; l != NULL; l = l->next)
+ {
+ CcDisplayLogicalMonitor *m = l->data;
+
+ if (m == primary)
+ continue;
+
+ m->x = x;
+ m->y = 0;
+ x += logical_monitor_width (m);
+ }
+
+ g_list_free (logical_monitors);
+}
diff --git a/panels/display/cc-display-config-dbus.h b/panels/display/cc-display-config-dbus.h
new file mode 100644
index 0000000..8609087
--- /dev/null
+++ b/panels/display/cc-display-config-dbus.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#pragma once
+
+#include <glib-object.h>
+
+#include "cc-display-config.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_DISPLAY_MODE_DBUS (cc_display_mode_dbus_get_type ())
+G_DECLARE_FINAL_TYPE (CcDisplayModeDBus, cc_display_mode_dbus,
+ CC, DISPLAY_MODE_DBUS, CcDisplayMode)
+
+#define CC_TYPE_DISPLAY_MONITOR_DBUS (cc_display_monitor_dbus_get_type ())
+G_DECLARE_FINAL_TYPE (CcDisplayMonitorDBus, cc_display_monitor_dbus,
+ CC, DISPLAY_MONITOR_DBUS, CcDisplayMonitor)
+
+#define CC_TYPE_DISPLAY_CONFIG_DBUS (cc_display_config_dbus_get_type ())
+G_DECLARE_FINAL_TYPE (CcDisplayConfigDBus, cc_display_config_dbus,
+ CC, DISPLAY_CONFIG_DBUS, CcDisplayConfig)
+
+G_END_DECLS
diff --git a/panels/display/cc-display-config-manager-dbus.c b/panels/display/cc-display-config-manager-dbus.c
new file mode 100644
index 0000000..678b696
--- /dev/null
+++ b/panels/display/cc-display-config-manager-dbus.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include "cc-display-config-dbus.h"
+#include "cc-display-config-manager-dbus.h"
+
+#include <gio/gio.h>
+
+struct _CcDisplayConfigManagerDBus
+{
+ CcDisplayConfigManager parent_instance;
+
+ GCancellable *cancellable;
+ GDBusConnection *connection;
+ guint monitors_changed_id;
+
+ GVariant *current_state;
+
+ gboolean apply_allowed;
+ gboolean night_light_supported;
+};
+
+G_DEFINE_TYPE (CcDisplayConfigManagerDBus,
+ cc_display_config_manager_dbus,
+ CC_TYPE_DISPLAY_CONFIG_MANAGER)
+
+static CcDisplayConfig *
+cc_display_config_manager_dbus_get_current (CcDisplayConfigManager *pself)
+{
+ CcDisplayConfigManagerDBus *self = CC_DISPLAY_CONFIG_MANAGER_DBUS (pself);
+
+ if (!self->current_state)
+ return NULL;
+
+ return g_object_new (CC_TYPE_DISPLAY_CONFIG_DBUS,
+ "state", self->current_state,
+ "connection", self->connection, NULL);
+}
+
+static void
+got_current_state (GObject *object,
+ GAsyncResult *result,
+ gpointer data)
+{
+ CcDisplayConfigManagerDBus *self;
+ GVariant *variant;
+ g_autoptr(GError) error = NULL;
+
+ variant = g_dbus_connection_call_finish (G_DBUS_CONNECTION (object),
+ result, &error);
+ if (!variant)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ self = CC_DISPLAY_CONFIG_MANAGER_DBUS (data);
+ g_clear_pointer (&self->current_state, g_variant_unref);
+ _cc_display_config_manager_emit_changed (CC_DISPLAY_CONFIG_MANAGER (data));
+ g_warning ("Error calling GetCurrentState: %s", error->message);
+ }
+ return;
+ }
+
+ self = CC_DISPLAY_CONFIG_MANAGER_DBUS (data);
+ g_clear_pointer (&self->current_state, g_variant_unref);
+ self->current_state = variant;
+
+ _cc_display_config_manager_emit_changed (CC_DISPLAY_CONFIG_MANAGER (self));
+}
+
+static void
+get_current_state (CcDisplayConfigManagerDBus *self)
+{
+ g_dbus_connection_call (self->connection,
+ "org.gnome.Mutter.DisplayConfig",
+ "/org/gnome/Mutter/DisplayConfig",
+ "org.gnome.Mutter.DisplayConfig",
+ "GetCurrentState",
+ NULL,
+ NULL,
+ G_DBUS_CALL_FLAGS_NO_AUTO_START,
+ -1,
+ self->cancellable,
+ got_current_state,
+ self);
+}
+
+static void
+monitors_changed (GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer data)
+{
+ CcDisplayConfigManagerDBus *self = CC_DISPLAY_CONFIG_MANAGER_DBUS (data);
+ get_current_state (self);
+}
+
+static void
+bus_gotten (GObject *object,
+ GAsyncResult *result,
+ gpointer data)
+{
+ CcDisplayConfigManagerDBus *self;
+ GDBusConnection *connection;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GDBusProxy) proxy = NULL;
+ g_autoptr(GVariant) variant = NULL;
+
+ connection = g_bus_get_finish (result, &error);
+ if (!connection)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ _cc_display_config_manager_emit_changed (CC_DISPLAY_CONFIG_MANAGER (data));
+ g_warning ("Error obtaining DBus connection: %s", error->message);
+ }
+ return;
+ }
+
+ self = CC_DISPLAY_CONFIG_MANAGER_DBUS (data);
+ self->connection = connection;
+ self->monitors_changed_id =
+ g_dbus_connection_signal_subscribe (self->connection,
+ "org.gnome.Mutter.DisplayConfig",
+ "org.gnome.Mutter.DisplayConfig",
+ "MonitorsChanged",
+ "/org/gnome/Mutter/DisplayConfig",
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ monitors_changed,
+ self,
+ NULL);
+
+ proxy = g_dbus_proxy_new_sync (self->connection,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.gnome.Mutter.DisplayConfig",
+ "/org/gnome/Mutter/DisplayConfig",
+ "org.gnome.Mutter.DisplayConfig",
+ NULL,
+ &error);
+ if (!proxy)
+ {
+ g_warning ("Failed to create D-Bus proxy to \"org.gnome.Mutter.DisplayConfig\": %s",
+ error->message);
+ return;
+ }
+
+ variant = g_dbus_proxy_get_cached_property (proxy, "ApplyMonitorsConfigAllowed");
+ if (variant)
+ self->apply_allowed = g_variant_get_boolean (variant);
+ else
+ g_warning ("Missing property 'ApplyMonitorsConfigAllowed' on DisplayConfig API");
+
+ variant = g_dbus_proxy_get_cached_property (proxy, "NightLightSupported");
+ if (variant)
+ self->night_light_supported = g_variant_get_boolean (variant);
+ else
+ g_warning ("Missing property 'NightLightSupported' on DisplayConfig API");
+
+ get_current_state (self);
+}
+
+static void
+cc_display_config_manager_dbus_init (CcDisplayConfigManagerDBus *self)
+{
+ self->apply_allowed = TRUE;
+ self->night_light_supported = TRUE;
+ self->cancellable = g_cancellable_new ();
+ g_bus_get (G_BUS_TYPE_SESSION, self->cancellable, bus_gotten, self);
+}
+
+static void
+cc_display_config_manager_dbus_finalize (GObject *object)
+{
+ CcDisplayConfigManagerDBus *self = CC_DISPLAY_CONFIG_MANAGER_DBUS (object);
+
+ g_cancellable_cancel (self->cancellable);
+ g_clear_object (&self->cancellable);
+
+ if (self->monitors_changed_id && self->connection)
+ g_dbus_connection_signal_unsubscribe (self->connection,
+ self->monitors_changed_id);
+ g_clear_object (&self->connection);
+ g_clear_pointer (&self->current_state, g_variant_unref);
+
+ G_OBJECT_CLASS (cc_display_config_manager_dbus_parent_class)->finalize (object);
+}
+
+static gboolean
+cc_display_config_manager_dbus_get_apply_allowed (CcDisplayConfigManager *pself)
+{
+ CcDisplayConfigManagerDBus *self = CC_DISPLAY_CONFIG_MANAGER_DBUS (pself);
+
+ return self->apply_allowed;
+}
+
+static gboolean
+cc_display_config_manager_dbus_get_night_light_supported (CcDisplayConfigManager *pself)
+{
+ CcDisplayConfigManagerDBus *self = CC_DISPLAY_CONFIG_MANAGER_DBUS (pself);
+
+ return self->night_light_supported;
+}
+
+static void
+cc_display_config_manager_dbus_class_init (CcDisplayConfigManagerDBusClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ CcDisplayConfigManagerClass *parent_class = CC_DISPLAY_CONFIG_MANAGER_CLASS (klass);
+
+ gobject_class->finalize = cc_display_config_manager_dbus_finalize;
+
+ parent_class->get_current = cc_display_config_manager_dbus_get_current;
+ parent_class->get_apply_allowed = cc_display_config_manager_dbus_get_apply_allowed;
+ parent_class->get_night_light_supported = cc_display_config_manager_dbus_get_night_light_supported;
+}
+
+CcDisplayConfigManager *
+cc_display_config_manager_dbus_new (void)
+{
+ return g_object_new (CC_TYPE_DISPLAY_CONFIG_MANAGER_DBUS, NULL);
+}
diff --git a/panels/display/cc-display-config-manager-dbus.h b/panels/display/cc-display-config-manager-dbus.h
new file mode 100644
index 0000000..a099598
--- /dev/null
+++ b/panels/display/cc-display-config-manager-dbus.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#pragma once
+
+#include <glib-object.h>
+
+#include "cc-display-config-manager.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_DISPLAY_CONFIG_MANAGER_DBUS (cc_display_config_manager_dbus_get_type ())
+G_DECLARE_FINAL_TYPE (CcDisplayConfigManagerDBus, cc_display_config_manager_dbus,
+ CC, DISPLAY_CONFIG_MANAGER_DBUS, CcDisplayConfigManager)
+
+CcDisplayConfigManager * cc_display_config_manager_dbus_new (void);
+
+G_END_DECLS
diff --git a/panels/display/cc-display-config-manager.c b/panels/display/cc-display-config-manager.c
new file mode 100644
index 0000000..f231edd
--- /dev/null
+++ b/panels/display/cc-display-config-manager.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include "cc-display-config-manager.h"
+
+G_DEFINE_TYPE (CcDisplayConfigManager,
+ cc_display_config_manager,
+ G_TYPE_OBJECT)
+
+enum
+{
+ CONFIG_MANAGER_CHANGED,
+ N_CONFIG_MANAGER_SIGNALS,
+};
+
+static guint config_manager_signals[N_CONFIG_MANAGER_SIGNALS] = { 0 };
+
+static void
+cc_display_config_manager_init (CcDisplayConfigManager *self)
+{
+}
+
+static void
+cc_display_config_manager_class_init (CcDisplayConfigManagerClass *klass)
+{
+ config_manager_signals[CONFIG_MANAGER_CHANGED] =
+ g_signal_new ("changed",
+ CC_TYPE_DISPLAY_CONFIG_MANAGER,
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+void
+_cc_display_config_manager_emit_changed (CcDisplayConfigManager *self)
+{
+ g_signal_emit (self, config_manager_signals[CONFIG_MANAGER_CHANGED], 0);
+}
+
+CcDisplayConfig *
+cc_display_config_manager_get_current (CcDisplayConfigManager *self)
+{
+ return CC_DISPLAY_CONFIG_MANAGER_GET_CLASS (self)->get_current (self);
+}
+
+gboolean
+cc_display_config_manager_get_apply_allowed (CcDisplayConfigManager *self)
+{
+ return CC_DISPLAY_CONFIG_MANAGER_GET_CLASS (self)->get_apply_allowed (self);
+}
+
+gboolean
+cc_display_config_manager_get_night_light_supported (CcDisplayConfigManager *self)
+{
+ return CC_DISPLAY_CONFIG_MANAGER_GET_CLASS (self)->get_night_light_supported (self);
+}
diff --git a/panels/display/cc-display-config-manager.h b/panels/display/cc-display-config-manager.h
new file mode 100644
index 0000000..ab1e84f
--- /dev/null
+++ b/panels/display/cc-display-config-manager.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#pragma once
+
+#include <glib-object.h>
+
+#include "cc-display-config.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_DISPLAY_CONFIG_MANAGER (cc_display_config_manager_get_type ())
+G_DECLARE_DERIVABLE_TYPE (CcDisplayConfigManager, cc_display_config_manager,
+ CC, DISPLAY_CONFIG_MANAGER, GObject)
+
+struct _CcDisplayConfigManagerClass
+{
+ GObjectClass parent_class;
+
+ CcDisplayConfig * (*get_current) (CcDisplayConfigManager *self);
+ gboolean (* get_apply_allowed) (CcDisplayConfigManager *self);
+ gboolean (* get_night_light_supported) (CcDisplayConfigManager *self);
+};
+
+CcDisplayConfig * cc_display_config_manager_get_current (CcDisplayConfigManager *self);
+
+gboolean cc_display_config_manager_get_apply_allowed (CcDisplayConfigManager *self);
+
+gboolean cc_display_config_manager_get_night_light_supported (CcDisplayConfigManager *self);
+
+void _cc_display_config_manager_emit_changed (CcDisplayConfigManager *self);
+
+G_END_DECLS
diff --git a/panels/display/cc-display-config.c b/panels/display/cc-display-config.c
new file mode 100644
index 0000000..b7532f9
--- /dev/null
+++ b/panels/display/cc-display-config.c
@@ -0,0 +1,665 @@
+/*
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <gio/gio.h>
+#include <math.h>
+#include "cc-display-config.h"
+
+static const double known_diagonals[] = {
+ 12.1,
+ 13.3,
+ 15.6
+};
+
+static char *
+diagonal_to_str (double d)
+{
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (known_diagonals); i++)
+ {
+ double delta;
+
+ delta = fabs(known_diagonals[i] - d);
+ if (delta < 0.1)
+ return g_strdup_printf ("%0.1lf\"", known_diagonals[i]);
+ }
+
+ return g_strdup_printf ("%d\"", (int) (d + 0.5));
+}
+
+static char *
+make_display_size_string (int width_mm,
+ int height_mm)
+{
+ char *inches = NULL;
+
+ if (width_mm > 0 && height_mm > 0)
+ {
+ double d = sqrt (width_mm * width_mm + height_mm * height_mm);
+
+ inches = diagonal_to_str (d / 25.4);
+ }
+
+ return inches;
+}
+
+static char *
+make_output_ui_name (CcDisplayMonitor *output)
+{
+ int width_mm, height_mm;
+ g_autofree char *size = NULL;
+
+ cc_display_monitor_get_physical_size (output, &width_mm, &height_mm);
+ size = make_display_size_string (width_mm, height_mm);
+ if (size)
+ return g_strdup_printf ("%s (%s)", cc_display_monitor_get_display_name (output), size);
+ else
+ return g_strdup_printf ("%s", cc_display_monitor_get_display_name (output));
+}
+
+
+
+G_DEFINE_TYPE (CcDisplayMode,
+ cc_display_mode,
+ G_TYPE_OBJECT)
+
+static void
+cc_display_mode_init (CcDisplayMode *self)
+{
+}
+
+static void
+cc_display_mode_class_init (CcDisplayModeClass *klass)
+{
+}
+
+gboolean
+cc_display_mode_is_clone_mode (CcDisplayMode *self)
+{
+ return CC_DISPLAY_MODE_GET_CLASS (self)->is_clone_mode (self);
+}
+
+void
+cc_display_mode_get_resolution (CcDisplayMode *self, int *w, int *h)
+{
+ return CC_DISPLAY_MODE_GET_CLASS (self)->get_resolution (self, w, h);
+}
+
+GArray *
+cc_display_mode_get_supported_scales (CcDisplayMode *self)
+{
+ return CC_DISPLAY_MODE_GET_CLASS (self)->get_supported_scales (self);
+}
+
+double
+cc_display_mode_get_preferred_scale (CcDisplayMode *self)
+{
+ return CC_DISPLAY_MODE_GET_CLASS (self)->get_preferred_scale (self);
+}
+
+gboolean
+cc_display_mode_is_interlaced (CcDisplayMode *self)
+{
+ return CC_DISPLAY_MODE_GET_CLASS (self)->is_interlaced (self);
+}
+
+gboolean
+cc_display_mode_is_preferred (CcDisplayMode *self)
+{
+ return CC_DISPLAY_MODE_GET_CLASS (self)->is_preferred (self);
+}
+
+int
+cc_display_mode_get_freq (CcDisplayMode *self)
+{
+ return CC_DISPLAY_MODE_GET_CLASS (self)->get_freq (self);
+}
+
+double
+cc_display_mode_get_freq_f (CcDisplayMode *self)
+{
+ return CC_DISPLAY_MODE_GET_CLASS (self)->get_freq_f (self);
+}
+
+
+struct _CcDisplayMonitorPrivate {
+ int ui_number;
+ gchar *ui_name;
+ gchar *ui_number_name;
+ gboolean is_usable;
+};
+typedef struct _CcDisplayMonitorPrivate CcDisplayMonitorPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (CcDisplayMonitor,
+ cc_display_monitor,
+ G_TYPE_OBJECT)
+
+static void
+cc_display_monitor_init (CcDisplayMonitor *self)
+{
+ CcDisplayMonitorPrivate *priv = cc_display_monitor_get_instance_private (self);
+
+ priv->ui_number = 0;
+ priv->ui_name = NULL;
+ priv->ui_number_name = NULL;
+ priv->is_usable = TRUE;
+}
+
+static void
+cc_display_monitor_finalize (GObject *object)
+{
+ CcDisplayMonitor *self = CC_DISPLAY_MONITOR (object);
+ CcDisplayMonitorPrivate *priv = cc_display_monitor_get_instance_private (self);
+
+ g_clear_pointer (&priv->ui_name, g_free);
+ g_clear_pointer (&priv->ui_number_name, g_free);
+
+ G_OBJECT_CLASS (cc_display_monitor_parent_class)->finalize (object);
+}
+
+static void
+cc_display_monitor_class_init (CcDisplayMonitorClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = cc_display_monitor_finalize;
+
+ g_signal_new ("rotation",
+ CC_TYPE_DISPLAY_MONITOR,
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+ g_signal_new ("mode",
+ CC_TYPE_DISPLAY_MONITOR,
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+ g_signal_new ("primary",
+ CC_TYPE_DISPLAY_MONITOR,
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+ g_signal_new ("active",
+ CC_TYPE_DISPLAY_MONITOR,
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+ g_signal_new ("scale",
+ CC_TYPE_DISPLAY_MONITOR,
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+ g_signal_new ("position-changed",
+ CC_TYPE_DISPLAY_MONITOR,
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+ g_signal_new ("is-usable",
+ CC_TYPE_DISPLAY_MONITOR,
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+}
+
+const char *
+cc_display_monitor_get_display_name (CcDisplayMonitor *self)
+{
+ return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_display_name (self);
+}
+
+const char *
+cc_display_monitor_get_connector_name (CcDisplayMonitor *self)
+{
+ return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_connector_name (self);
+}
+
+gboolean
+cc_display_monitor_is_builtin (CcDisplayMonitor *self)
+{
+ return CC_DISPLAY_MONITOR_GET_CLASS (self)->is_builtin (self);
+}
+
+gboolean
+cc_display_monitor_is_primary (CcDisplayMonitor *self)
+{
+ return CC_DISPLAY_MONITOR_GET_CLASS (self)->is_primary (self);
+}
+
+void
+cc_display_monitor_set_primary (CcDisplayMonitor *self, gboolean primary)
+{
+ return CC_DISPLAY_MONITOR_GET_CLASS (self)->set_primary (self, primary);
+}
+
+gboolean
+cc_display_monitor_is_active (CcDisplayMonitor *self)
+{
+ return CC_DISPLAY_MONITOR_GET_CLASS (self)->is_active (self);
+}
+
+void
+cc_display_monitor_set_active (CcDisplayMonitor *self, gboolean active)
+{
+ return CC_DISPLAY_MONITOR_GET_CLASS (self)->set_active (self, active);
+}
+
+CcDisplayRotation
+cc_display_monitor_get_rotation (CcDisplayMonitor *self)
+{
+ return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_rotation (self);
+}
+
+void
+cc_display_monitor_set_rotation (CcDisplayMonitor *self,
+ CcDisplayRotation rotation)
+{
+ return CC_DISPLAY_MONITOR_GET_CLASS (self)->set_rotation (self, rotation);
+}
+
+gboolean
+cc_display_monitor_supports_rotation (CcDisplayMonitor *self, CcDisplayRotation r)
+{
+ return CC_DISPLAY_MONITOR_GET_CLASS (self)->supports_rotation (self, r);
+}
+
+void
+cc_display_monitor_get_physical_size (CcDisplayMonitor *self, int *w, int *h)
+{
+ return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_physical_size (self, w, h);
+}
+
+void
+cc_display_monitor_get_geometry (CcDisplayMonitor *self, int *x, int *y, int *w, int *h)
+{
+ return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_geometry (self, x, y, w, h);
+}
+
+CcDisplayMode *
+cc_display_monitor_get_mode (CcDisplayMonitor *self)
+{
+ return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_mode (self);
+}
+
+CcDisplayMode *
+cc_display_monitor_get_preferred_mode (CcDisplayMonitor *self)
+{
+ return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_preferred_mode (self);
+}
+
+guint32
+cc_display_monitor_get_id (CcDisplayMonitor *self)
+{
+ return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_id (self);
+}
+
+GList *
+cc_display_monitor_get_modes (CcDisplayMonitor *self)
+{
+ return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_modes (self);
+}
+
+gboolean
+cc_display_monitor_supports_underscanning (CcDisplayMonitor *self)
+{
+ return CC_DISPLAY_MONITOR_GET_CLASS (self)->supports_underscanning (self);
+}
+
+gboolean
+cc_display_monitor_get_underscanning (CcDisplayMonitor *self)
+{
+ return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_underscanning (self);
+}
+
+void
+cc_display_monitor_set_underscanning (CcDisplayMonitor *self,
+ gboolean underscanning)
+{
+ return CC_DISPLAY_MONITOR_GET_CLASS (self)->set_underscanning (self, underscanning);
+}
+
+CcDisplayMonitorPrivacy
+cc_display_monitor_get_privacy (CcDisplayMonitor *self)
+{
+ return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_privacy (self);
+}
+
+void
+cc_display_monitor_set_mode (CcDisplayMonitor *self, CcDisplayMode *m)
+{
+ return CC_DISPLAY_MONITOR_GET_CLASS (self)->set_mode (self, m);
+}
+
+void
+cc_display_monitor_set_compatible_clone_mode (CcDisplayMonitor *self, CcDisplayMode *m)
+{
+ return CC_DISPLAY_MONITOR_GET_CLASS (self)->set_mode (self, m);
+}
+
+void
+cc_display_monitor_set_position (CcDisplayMonitor *self, int x, int y)
+{
+ return CC_DISPLAY_MONITOR_GET_CLASS (self)->set_position (self, x, y);
+}
+
+double
+cc_display_monitor_get_scale (CcDisplayMonitor *self)
+{
+ return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_scale (self);
+}
+
+void
+cc_display_monitor_set_scale (CcDisplayMonitor *self, double s)
+{
+ return CC_DISPLAY_MONITOR_GET_CLASS (self)->set_scale (self, s);
+}
+
+gboolean
+cc_display_monitor_is_useful (CcDisplayMonitor *self)
+{
+ CcDisplayMonitorPrivate *priv = cc_display_monitor_get_instance_private (self);
+
+ return priv->is_usable &&
+ cc_display_monitor_is_active (self);
+}
+
+gboolean
+cc_display_monitor_is_usable (CcDisplayMonitor *self)
+{
+ CcDisplayMonitorPrivate *priv = cc_display_monitor_get_instance_private (self);
+
+ return priv->is_usable;
+}
+
+void
+cc_display_monitor_set_usable (CcDisplayMonitor *self, gboolean is_usable)
+{
+ CcDisplayMonitorPrivate *priv = cc_display_monitor_get_instance_private (self);
+
+ priv->is_usable = is_usable;
+
+ g_signal_emit_by_name (self, "is-usable");
+}
+
+gint
+cc_display_monitor_get_ui_number (CcDisplayMonitor *self)
+{
+ CcDisplayMonitorPrivate *priv = cc_display_monitor_get_instance_private (self);
+
+ return priv->ui_number;
+}
+
+const char *
+cc_display_monitor_get_ui_name (CcDisplayMonitor *self)
+{
+ CcDisplayMonitorPrivate *priv = cc_display_monitor_get_instance_private (self);
+
+ return priv->ui_name;
+}
+
+const char *
+cc_display_monitor_get_ui_number_name (CcDisplayMonitor *self)
+{
+ CcDisplayMonitorPrivate *priv = cc_display_monitor_get_instance_private (self);
+
+ return priv->ui_number_name;
+}
+
+char *
+cc_display_monitor_dup_ui_number_name (CcDisplayMonitor *self)
+{
+ CcDisplayMonitorPrivate *priv = cc_display_monitor_get_instance_private (self);
+
+ return g_strdup (priv->ui_number_name);
+}
+
+static void
+cc_display_monitor_set_ui_info (CcDisplayMonitor *self, gint ui_number, gchar *ui_name)
+{
+
+ CcDisplayMonitorPrivate *priv = cc_display_monitor_get_instance_private (self);
+
+ priv->ui_number = ui_number;
+ g_free (priv->ui_name);
+ priv->ui_name = ui_name;
+ priv->ui_number_name = g_strdup_printf ("%d\u2003%s", ui_number, ui_name);
+}
+
+struct _CcDisplayConfigPrivate {
+ GList *ui_sorted_monitors;
+};
+typedef struct _CcDisplayConfigPrivate CcDisplayConfigPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (CcDisplayConfig,
+ cc_display_config,
+ G_TYPE_OBJECT)
+
+static void
+cc_display_config_init (CcDisplayConfig *self)
+{
+ CcDisplayConfigPrivate *priv = cc_display_config_get_instance_private (self);
+
+ priv->ui_sorted_monitors = NULL;
+}
+
+static void
+cc_display_config_constructed (GObject *object)
+{
+ CcDisplayConfig *self = CC_DISPLAY_CONFIG (object);
+ CcDisplayConfigPrivate *priv = cc_display_config_get_instance_private (self);
+ GList *monitors = cc_display_config_get_monitors (self);
+ GList *item;
+ gint ui_number = 1;
+
+ for (item = monitors; item != NULL; item = item->next)
+ {
+ CcDisplayMonitor *monitor = item->data;
+
+ if (cc_display_monitor_is_builtin (monitor))
+ priv->ui_sorted_monitors = g_list_prepend (priv->ui_sorted_monitors, monitor);
+ else
+ priv->ui_sorted_monitors = g_list_append (priv->ui_sorted_monitors, monitor);
+ }
+
+ for (item = priv->ui_sorted_monitors; item != NULL; item = item->next)
+ {
+ CcDisplayMonitor *monitor = item->data;
+ char *ui_name;
+ ui_name = make_output_ui_name (monitor);
+
+ cc_display_monitor_set_ui_info (monitor, ui_number, ui_name);
+
+ ui_number += 1;
+ }
+}
+
+static void
+cc_display_config_finalize (GObject *object)
+{
+ CcDisplayConfig *self = CC_DISPLAY_CONFIG (object);
+ CcDisplayConfigPrivate *priv = cc_display_config_get_instance_private (self);
+
+ g_list_free (priv->ui_sorted_monitors);
+
+ G_OBJECT_CLASS (cc_display_config_parent_class)->finalize (object);
+}
+
+static void
+cc_display_config_class_init (CcDisplayConfigClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ g_signal_new ("primary",
+ CC_TYPE_DISPLAY_CONFIG,
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+ g_signal_new ("panel-orientation-managed",
+ CC_TYPE_DISPLAY_CONFIG,
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+
+ gobject_class->constructed = cc_display_config_constructed;
+ gobject_class->finalize = cc_display_config_finalize;
+}
+
+GList *
+cc_display_config_get_monitors (CcDisplayConfig *self)
+{
+ g_return_val_if_fail (CC_IS_DISPLAY_CONFIG (self), NULL);
+ return CC_DISPLAY_CONFIG_GET_CLASS (self)->get_monitors (self);
+}
+
+GList *
+cc_display_config_get_ui_sorted_monitors (CcDisplayConfig *self)
+{
+ CcDisplayConfigPrivate *priv = cc_display_config_get_instance_private (self);
+
+ g_return_val_if_fail (CC_IS_DISPLAY_CONFIG (self), NULL);
+ return priv->ui_sorted_monitors;
+}
+
+int
+cc_display_config_count_useful_monitors (CcDisplayConfig *self)
+{
+ CcDisplayConfigPrivate *priv = cc_display_config_get_instance_private (self);
+ GList *outputs, *l;
+ guint count = 0;
+
+ g_return_val_if_fail (CC_IS_DISPLAY_CONFIG (self), 0);
+
+ outputs = priv->ui_sorted_monitors;
+ for (l = outputs; l != NULL; l = l->next)
+ {
+ CcDisplayMonitor *output = l->data;
+ if (!cc_display_monitor_is_useful (output))
+ continue;
+ else
+ count++;
+ }
+ return count;
+
+}
+
+gboolean
+cc_display_config_is_applicable (CcDisplayConfig *self)
+{
+ g_return_val_if_fail (CC_IS_DISPLAY_CONFIG (self), FALSE);
+ return CC_DISPLAY_CONFIG_GET_CLASS (self)->is_applicable (self);
+}
+
+void
+cc_display_config_set_mode_on_all_outputs (CcDisplayConfig *config,
+ CcDisplayMode *clone_mode)
+{
+ GList *outputs, *l;
+
+ g_return_if_fail (CC_IS_DISPLAY_CONFIG (config));
+ g_return_if_fail (cc_display_mode_is_clone_mode (clone_mode));
+
+ outputs = cc_display_config_get_monitors (config);
+ for (l = outputs; l; l = l->next)
+ {
+ CcDisplayMonitor *output = l->data;
+ cc_display_monitor_set_compatible_clone_mode (output, clone_mode);
+ cc_display_monitor_set_position (output, 0, 0);
+ }
+}
+
+gboolean
+cc_display_config_equal (CcDisplayConfig *self,
+ CcDisplayConfig *other)
+{
+ g_return_val_if_fail (CC_IS_DISPLAY_CONFIG (self), FALSE);
+ g_return_val_if_fail (CC_IS_DISPLAY_CONFIG (other), FALSE);
+
+ return CC_DISPLAY_CONFIG_GET_CLASS (self)->equal (self, other);
+}
+
+gboolean
+cc_display_config_apply (CcDisplayConfig *self,
+ GError **error)
+{
+ if (!CC_IS_DISPLAY_CONFIG (self))
+ {
+ g_warning ("Cannot apply invalid configuration");
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Cannot apply invalid configuration");
+ return FALSE;
+ }
+
+ return CC_DISPLAY_CONFIG_GET_CLASS (self)->apply (self, error);
+}
+
+gboolean
+cc_display_config_is_cloning (CcDisplayConfig *self)
+{
+ g_return_val_if_fail (CC_IS_DISPLAY_CONFIG (self), FALSE);
+ return CC_DISPLAY_CONFIG_GET_CLASS (self)->is_cloning (self);
+}
+
+void
+cc_display_config_set_cloning (CcDisplayConfig *self,
+ gboolean clone)
+{
+ g_return_if_fail (CC_IS_DISPLAY_CONFIG (self));
+ return CC_DISPLAY_CONFIG_GET_CLASS (self)->set_cloning (self, clone);
+}
+
+GList *
+cc_display_config_generate_cloning_modes (CcDisplayConfig *self)
+{
+ g_return_val_if_fail (CC_IS_DISPLAY_CONFIG (self), NULL);
+ return CC_DISPLAY_CONFIG_GET_CLASS (self)->generate_cloning_modes (self);
+}
+
+gboolean
+cc_display_config_is_layout_logical (CcDisplayConfig *self)
+{
+ g_return_val_if_fail (CC_IS_DISPLAY_CONFIG (self), FALSE);
+ return CC_DISPLAY_CONFIG_GET_CLASS (self)->is_layout_logical (self);
+}
+
+void
+cc_display_config_set_minimum_size (CcDisplayConfig *self,
+ int width,
+ int height)
+{
+ g_return_if_fail (CC_IS_DISPLAY_CONFIG (self));
+ CC_DISPLAY_CONFIG_GET_CLASS (self)->set_minimum_size (self, width, height);
+}
+
+gboolean
+cc_display_config_is_scaled_mode_valid (CcDisplayConfig *self,
+ CcDisplayMode *mode,
+ double scale)
+{
+ g_return_val_if_fail (CC_IS_DISPLAY_CONFIG (self), FALSE);
+ g_return_val_if_fail (CC_IS_DISPLAY_MODE (mode), FALSE);
+ return CC_DISPLAY_CONFIG_GET_CLASS (self)->is_scaled_mode_valid (self, mode, scale);
+}
+
+gboolean
+cc_display_config_get_panel_orientation_managed (CcDisplayConfig *self)
+{
+ return CC_DISPLAY_CONFIG_GET_CLASS (self)->get_panel_orientation_managed (self);
+}
diff --git a/panels/display/cc-display-config.h b/panels/display/cc-display-config.h
new file mode 100644
index 0000000..1241adc
--- /dev/null
+++ b/panels/display/cc-display-config.h
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#pragma once
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/*
+ * GNOME Control Center display configuration system:
+ *
+ * The display configuration system consists of multiple concepts:
+ *
+ * CcDisplayConfig:
+ *
+ * Configuration instance, read from mutter using the
+ * org.gnome.Mutter.DisplayConfig D-Bus API. Contains information about the
+ * current configuration. Can be copied, to create a representation of a
+ * configuration at a given time, and applied, applying any changes that has
+ * been made to the objects associated with the configuration.
+ *
+ * CcDisplayConfig provides a list of all known "monitors" known to the
+ * compositor. It does not know about ports without any monitors connected,
+ * nor low level details about monitors, such as tiling etc.
+ *
+ * CcDisplayMonitor:
+ *
+ * A high level representation of a connected monitor. A monitor have details
+ * associated with it, some which can be altered. Each CcDisplayMonitor
+ * instance is associated with a single CcDisplayConfig instance. All
+ * alteration to a monitor is cached and not applied until
+ * cc_display_config_apply() is called on the corresponding CcDisplayConfig
+ * object.
+ *
+ * CcDisplayMode:
+ *
+ * A monitor mode, including resolution, refresh rate, and scale. Each monitor
+ * will have a list of possible modes.
+ *
+ */
+
+typedef enum _CcDisplayRotation
+{
+ CC_DISPLAY_ROTATION_NONE,
+ CC_DISPLAY_ROTATION_90,
+ CC_DISPLAY_ROTATION_180,
+ CC_DISPLAY_ROTATION_270,
+ CC_DISPLAY_ROTATION_FLIPPED,
+ CC_DISPLAY_ROTATION_90_FLIPPED,
+ CC_DISPLAY_ROTATION_180_FLIPPED,
+ CC_DISPLAY_ROTATION_270_FLIPPED,
+} CcDisplayRotation;
+
+typedef enum _CcDisplayMonitorPrivacy
+{
+ CC_DISPLAY_MONITOR_PRIVACY_UNSUPPORTED = 0,
+ CC_DISPLAY_MONITOR_PRIVACY_DISABLED = 1 << 0,
+ CC_DISPLAY_MONITOR_PRIVACY_ENABLED = 1 << 1,
+ CC_DISPLAY_MONITOR_PRIVACY_LOCKED = 1 << 2,
+} CcDisplayMonitorPrivacy;
+
+
+#define CC_TYPE_DISPLAY_MODE (cc_display_mode_get_type ())
+G_DECLARE_DERIVABLE_TYPE (CcDisplayMode, cc_display_mode,
+ CC, DISPLAY_MODE, GObject)
+
+struct _CcDisplayModeClass
+{
+ GObjectClass parent_class;
+
+ gboolean (*is_clone_mode) (CcDisplayMode *self);
+ void (*get_resolution) (CcDisplayMode *self, int *w, int *h);
+ GArray* (*get_supported_scales) (CcDisplayMode *self);
+ double (*get_preferred_scale) (CcDisplayMode *self);
+ gboolean (*is_interlaced) (CcDisplayMode *self);
+ gboolean (*is_preferred) (CcDisplayMode *self);
+ int (*get_freq) (CcDisplayMode *self);
+ double (*get_freq_f) (CcDisplayMode *self);
+};
+
+
+#define CC_TYPE_DISPLAY_MONITOR (cc_display_monitor_get_type ())
+G_DECLARE_DERIVABLE_TYPE (CcDisplayMonitor, cc_display_monitor,
+ CC, DISPLAY_MONITOR, GObject)
+
+struct _CcDisplayMonitorClass
+{
+ GObjectClass parent_class;
+
+ guint32 (*get_id) (CcDisplayMonitor *self);
+ const char* (*get_display_name) (CcDisplayMonitor *self);
+ const char* (*get_connector_name) (CcDisplayMonitor *self);
+ gboolean (*is_builtin) (CcDisplayMonitor *self);
+ gboolean (*is_primary) (CcDisplayMonitor *self);
+ void (*set_primary) (CcDisplayMonitor *self,
+ gboolean primary);
+ gboolean (*is_active) (CcDisplayMonitor *self);
+ void (*set_active) (CcDisplayMonitor *self,
+ gboolean a);
+ CcDisplayRotation (*get_rotation) (CcDisplayMonitor *self);
+ void (*set_rotation) (CcDisplayMonitor *self,
+ CcDisplayRotation r);
+ gboolean (*supports_rotation) (CcDisplayMonitor *self,
+ CcDisplayRotation r);
+ void (*get_physical_size) (CcDisplayMonitor *self,
+ int *w,
+ int *h);
+ void (*get_geometry) (CcDisplayMonitor *self,
+ int *x,
+ int *y,
+ int *w,
+ int *h);
+ gboolean (*supports_underscanning) (CcDisplayMonitor *self);
+ gboolean (*get_underscanning) (CcDisplayMonitor *self);
+ void (*set_underscanning) (CcDisplayMonitor *self,
+ gboolean u);
+ CcDisplayMonitorPrivacy (*get_privacy) (CcDisplayMonitor *self);
+ CcDisplayMode* (*get_mode) (CcDisplayMonitor *self);
+ CcDisplayMode* (*get_preferred_mode) (CcDisplayMonitor *self);
+ GList* (*get_modes) (CcDisplayMonitor *self);
+ void (*set_compatible_clone_mode) (CcDisplayMonitor *self,
+ CcDisplayMode *m);
+ void (*set_mode) (CcDisplayMonitor *self,
+ CcDisplayMode *m);
+ void (*set_position) (CcDisplayMonitor *self,
+ int x,
+ int y);
+ double (*get_scale) (CcDisplayMonitor *self);
+ void (*set_scale) (CcDisplayMonitor *self,
+ double s);
+};
+
+
+#define CC_TYPE_DISPLAY_CONFIG (cc_display_config_get_type ())
+G_DECLARE_DERIVABLE_TYPE (CcDisplayConfig, cc_display_config,
+ CC, DISPLAY_CONFIG, GObject)
+
+struct _CcDisplayConfigClass
+{
+ GObjectClass parent_class;
+
+ GList* (*get_monitors) (CcDisplayConfig *self);
+ gboolean (*is_applicable) (CcDisplayConfig *self);
+ gboolean (*equal) (CcDisplayConfig *self,
+ CcDisplayConfig *other);
+ gboolean (*apply) (CcDisplayConfig *self,
+ GError **error);
+ gboolean (*is_cloning) (CcDisplayConfig *self);
+ void (*set_cloning) (CcDisplayConfig *self,
+ gboolean clone);
+ GList* (*generate_cloning_modes) (CcDisplayConfig *self);
+ gboolean (*is_layout_logical) (CcDisplayConfig *self);
+ void (*set_minimum_size) (CcDisplayConfig *self,
+ int width,
+ int height);
+ gboolean (*is_scaled_mode_valid) (CcDisplayConfig *self,
+ CcDisplayMode *mode,
+ double scale);
+ gboolean (* get_panel_orientation_managed) (CcDisplayConfig *self);
+};
+
+
+GList* cc_display_config_get_monitors (CcDisplayConfig *config);
+GList* cc_display_config_get_ui_sorted_monitors (CcDisplayConfig *config);
+int cc_display_config_count_useful_monitors (CcDisplayConfig *config);
+gboolean cc_display_config_is_applicable (CcDisplayConfig *config);
+gboolean cc_display_config_equal (CcDisplayConfig *config,
+ CcDisplayConfig *other);
+gboolean cc_display_config_apply (CcDisplayConfig *config,
+ GError **error);
+gboolean cc_display_config_is_cloning (CcDisplayConfig *config);
+void cc_display_config_set_cloning (CcDisplayConfig *config,
+ gboolean clone);
+GList* cc_display_config_generate_cloning_modes (CcDisplayConfig *config);
+
+void cc_display_config_set_mode_on_all_outputs (CcDisplayConfig *config,
+ CcDisplayMode *mode);
+
+gboolean cc_display_config_is_layout_logical (CcDisplayConfig *self);
+void cc_display_config_set_minimum_size (CcDisplayConfig *self,
+ int width,
+ int height);
+gboolean cc_display_config_is_scaled_mode_valid (CcDisplayConfig *self,
+ CcDisplayMode *mode,
+ double scale);
+gboolean cc_display_config_get_panel_orientation_managed
+ (CcDisplayConfig *self);
+
+const char* cc_display_monitor_get_display_name (CcDisplayMonitor *monitor);
+gboolean cc_display_monitor_is_active (CcDisplayMonitor *monitor);
+void cc_display_monitor_set_active (CcDisplayMonitor *monitor,
+ gboolean active);
+const char* cc_display_monitor_get_connector_name (CcDisplayMonitor *monitor);
+CcDisplayRotation cc_display_monitor_get_rotation (CcDisplayMonitor *monitor);
+void cc_display_monitor_set_rotation (CcDisplayMonitor *monitor,
+ CcDisplayRotation r);
+gboolean cc_display_monitor_supports_rotation (CcDisplayMonitor *monitor,
+ CcDisplayRotation rotation);
+void cc_display_monitor_get_physical_size (CcDisplayMonitor *monitor,
+ int *w,
+ int *h);
+gboolean cc_display_monitor_is_builtin (CcDisplayMonitor *monitor);
+gboolean cc_display_monitor_is_primary (CcDisplayMonitor *monitor);
+void cc_display_monitor_set_primary (CcDisplayMonitor *monitor,
+ gboolean primary);
+guint32 cc_display_monitor_get_id (CcDisplayMonitor *monitor);
+
+gboolean cc_display_monitor_supports_underscanning (CcDisplayMonitor *monitor);
+gboolean cc_display_monitor_get_underscanning (CcDisplayMonitor *monitor);
+void cc_display_monitor_set_underscanning (CcDisplayMonitor *monitor,
+ gboolean underscanning);
+
+CcDisplayMonitorPrivacy cc_display_monitor_get_privacy (CcDisplayMonitor *self);
+
+CcDisplayMode* cc_display_monitor_get_mode (CcDisplayMonitor *monitor);
+void cc_display_monitor_get_geometry (CcDisplayMonitor *monitor,
+ int *x,
+ int *y,
+ int *width,
+ int *height);
+GList* cc_display_monitor_get_modes (CcDisplayMonitor *monitor);
+CcDisplayMode* cc_display_monitor_get_preferred_mode (CcDisplayMonitor *monitor);
+double cc_display_monitor_get_scale (CcDisplayMonitor *monitor);
+void cc_display_monitor_set_scale (CcDisplayMonitor *monitor,
+ double s);
+
+void cc_display_monitor_set_compatible_clone_mode (CcDisplayMonitor *monitor,
+ CcDisplayMode *mode);
+void cc_display_monitor_set_mode (CcDisplayMonitor *monitor,
+ CcDisplayMode *mode);
+void cc_display_monitor_set_position (CcDisplayMonitor *monitor,
+ int x,
+ int y);
+
+gboolean cc_display_monitor_is_useful (CcDisplayMonitor *monitor);
+gboolean cc_display_monitor_is_usable (CcDisplayMonitor *monitor);
+void cc_display_monitor_set_usable (CcDisplayMonitor *monitor,
+ gboolean is_usable);
+int cc_display_monitor_get_ui_number (CcDisplayMonitor *monitor);
+const char* cc_display_monitor_get_ui_name (CcDisplayMonitor *monitor);
+const char* cc_display_monitor_get_ui_number_name (CcDisplayMonitor *monitor);
+char* cc_display_monitor_dup_ui_number_name (CcDisplayMonitor *monitor);
+
+gboolean cc_display_mode_is_clone_mode (CcDisplayMode *mode);
+void cc_display_mode_get_resolution (CcDisplayMode *mode,
+ int *width,
+ int *height);
+GArray* cc_display_mode_get_supported_scales (CcDisplayMode *self);
+double cc_display_mode_get_preferred_scale (CcDisplayMode *self);
+gboolean cc_display_mode_is_interlaced (CcDisplayMode *mode);
+gboolean cc_display_mode_is_preferred (CcDisplayMode *mode);
+int cc_display_mode_get_freq (CcDisplayMode *mode);
+double cc_display_mode_get_freq_f (CcDisplayMode *mode);
+
+G_END_DECLS
diff --git a/panels/display/cc-display-panel.c b/panels/display/cc-display-panel.c
new file mode 100644
index 0000000..6958e19
--- /dev/null
+++ b/panels/display/cc-display-panel.c
@@ -0,0 +1,1140 @@
+/*
+ * Copyright (C) 2007, 2008 Red Hat, Inc.
+ * Copyright (C) 2013 Intel, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include "cc-display-panel.h"
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <stdlib.h>
+#include <gdesktop-enums.h>
+#include <math.h>
+
+#include "shell/cc-object-storage.h"
+#include <libupower-glib/upower.h>
+
+#include "cc-display-config-manager-dbus.h"
+#include "cc-display-config.h"
+#include "cc-display-arrangement.h"
+#include "cc-night-light-page.h"
+#include "cc-display-resources.h"
+#include "cc-display-settings.h"
+
+/* The minimum supported size for the panel
+ * Note that WIDTH is assumed to be the larger size and we accept portrait
+ * mode too effectively (in principle we should probably restrict the rotation
+ * setting in that case). */
+#define MINIMUM_WIDTH 720
+#define MINIMUM_HEIGHT 360
+
+#define PANEL_PADDING 32
+#define SECTION_PADDING 32
+#define HEADING_PADDING 12
+
+#define DISPLAY_SCHEMA "org.gnome.settings-daemon.plugins.color"
+
+typedef enum {
+ CC_DISPLAY_CONFIG_JOIN,
+ CC_DISPLAY_CONFIG_CLONE,
+
+ CC_DISPLAY_CONFIG_INVALID_NONE,
+} CcDisplayConfigType;
+
+#define CC_DISPLAY_CONFIG_LAST_VALID CC_DISPLAY_CONFIG_CLONE
+
+struct _CcDisplayPanel
+{
+ CcPanel parent_instance;
+
+ CcDisplayConfigManager *manager;
+ CcDisplayConfig *current_config;
+ CcDisplayMonitor *current_output;
+
+ gint rebuilding_counter;
+
+ CcDisplayArrangement *arrangement;
+ CcDisplaySettings *settings;
+
+ guint focus_id;
+
+ CcNightLightPage *night_light_page;
+ GtkLabel *night_light_state_label;
+
+ UpClient *up_client;
+ gboolean lid_is_closed;
+
+ GDBusProxy *shell_proxy;
+
+ GtkWidget *apply_titlebar;
+ GtkWidget *apply_button;
+ GtkWidget *cancel_button;
+ AdwWindowTitle *apply_titlebar_title_widget;
+
+ GListStore *primary_display_list;
+ GList *monitor_rows;
+
+ GtkWidget *display_settings_disabled_group;
+
+ GtkWidget *arrangement_row;
+ AdwBin *arrangement_bin;
+ GtkToggleButton *config_type_join;
+ GtkToggleButton *config_type_mirror;
+ GtkWidget *display_multiple_displays;
+ AdwBin *display_settings_bin;
+ GtkWidget *display_settings_group;
+ AdwWindowTitle *display_settings_title_widget;
+ AdwLeaflet *leaflet;
+ AdwComboRow *primary_display_row;
+ AdwPreferencesGroup *single_display_settings_group;
+
+ GtkShortcutController *toplevel_shortcuts;
+ GtkShortcut *escape_shortcut;
+
+ GSettings *display_settings;
+};
+
+CC_PANEL_REGISTER (CcDisplayPanel, cc_display_panel)
+
+static void
+update_apply_button (CcDisplayPanel *panel);
+static void
+apply_current_configuration (CcDisplayPanel *self);
+static void
+reset_current_config (CcDisplayPanel *panel);
+static void
+rebuild_ui (CcDisplayPanel *panel);
+static void
+set_current_output (CcDisplayPanel *panel,
+ CcDisplayMonitor *output,
+ gboolean force);
+static void
+on_screen_changed (CcDisplayPanel *panel);
+
+
+static CcDisplayConfigType
+config_get_current_type (CcDisplayPanel *panel)
+{
+ guint n_active_outputs;
+ GList *outputs, *l;
+
+ outputs = cc_display_config_get_ui_sorted_monitors (panel->current_config);
+ n_active_outputs = 0;
+ for (l = outputs; l; l = l->next)
+ {
+ CcDisplayMonitor *output = l->data;
+
+ if (cc_display_monitor_is_useful (output))
+ n_active_outputs += 1;
+ }
+
+ if (n_active_outputs == 0)
+ return CC_DISPLAY_CONFIG_INVALID_NONE;
+
+ if (cc_display_config_is_cloning (panel->current_config))
+ return CC_DISPLAY_CONFIG_CLONE;
+
+ return CC_DISPLAY_CONFIG_JOIN;
+}
+
+static CcDisplayConfigType
+cc_panel_get_selected_type (CcDisplayPanel *panel)
+{
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (panel->config_type_join)))
+ return CC_DISPLAY_CONFIG_JOIN;
+ else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (panel->config_type_mirror)))
+ return CC_DISPLAY_CONFIG_CLONE;
+ else
+ g_assert_not_reached ();
+}
+
+static CcDisplayMode *
+find_preferred_mode (GList *modes)
+{
+ GList *l;
+
+ for (l = modes; l; l = l->next)
+ {
+ CcDisplayMode *mode = l->data;
+
+ if (cc_display_mode_is_preferred (mode))
+ return mode;
+ }
+
+ return NULL;
+}
+
+static void
+config_ensure_of_type (CcDisplayPanel *panel, CcDisplayConfigType type)
+{
+ CcDisplayConfigType current_type = config_get_current_type (panel);
+ GList *outputs, *l;
+ CcDisplayMonitor *current_primary = NULL;
+ gdouble old_primary_scale = -1;
+
+ /* Do not do anything if the current detected configuration type is
+ * identitcal to what we expect. */
+ if (type == current_type)
+ return;
+
+ reset_current_config (panel);
+
+ outputs = cc_display_config_get_ui_sorted_monitors (panel->current_config);
+ for (l = outputs; l; l = l->next)
+ {
+ CcDisplayMonitor *output = l->data;
+
+ if (cc_display_monitor_is_primary (output))
+ {
+ current_primary = output;
+ old_primary_scale = cc_display_monitor_get_scale (current_primary);
+ break;
+ }
+ }
+
+ switch (type)
+ {
+ case CC_DISPLAY_CONFIG_JOIN:
+ g_debug ("Creating new join config");
+ /* Enable all usable outputs
+ * Note that this might result in invalid configurations as we
+ * we might not be able to drive all attached monitors. */
+ cc_display_config_set_cloning (panel->current_config, FALSE);
+ for (l = outputs; l; l = l->next)
+ {
+ CcDisplayMonitor *output = l->data;
+ gdouble scale;
+ CcDisplayMode *mode;
+
+ mode = cc_display_monitor_get_preferred_mode (output);
+ /* If the monitor was active, try using the current scale, otherwise
+ * try picking the preferred scale. */
+ if (cc_display_monitor_is_active (output))
+ scale = cc_display_monitor_get_scale (output);
+ else
+ scale = cc_display_mode_get_preferred_scale (mode);
+
+ /* If we cannot use the current/preferred scale, try to fall back to
+ * the previously scale of the primary monitor instead.
+ * This is not guaranteed to result in a valid configuration! */
+ if (!cc_display_config_is_scaled_mode_valid (panel->current_config,
+ mode,
+ scale))
+ {
+ if (current_primary &&
+ cc_display_config_is_scaled_mode_valid (panel->current_config,
+ mode,
+ old_primary_scale))
+ scale = old_primary_scale;
+ }
+
+ cc_display_monitor_set_active (output, cc_display_monitor_is_usable (output));
+ cc_display_monitor_set_mode (output, mode);
+ cc_display_monitor_set_scale (output, scale);
+ }
+ break;
+
+ case CC_DISPLAY_CONFIG_CLONE:
+ {
+ g_debug ("Creating new clone config");
+ gdouble scale;
+ g_autolist(CcDisplayMode) modes = NULL;
+ CcDisplayMode *clone_mode;
+
+ /* Turn on cloning and select the best mode we can find by default */
+ cc_display_config_set_cloning (panel->current_config, TRUE);
+
+ modes = cc_display_config_generate_cloning_modes (panel->current_config);
+ clone_mode = find_preferred_mode (modes);
+ g_return_if_fail (clone_mode);
+
+ /* Take the preferred scale by default, */
+ scale = cc_display_mode_get_preferred_scale (clone_mode);
+ /* but prefer the old primary scale if that is valid. */
+ if (current_primary &&
+ cc_display_config_is_scaled_mode_valid (panel->current_config,
+ clone_mode,
+ old_primary_scale))
+ scale = old_primary_scale;
+
+ for (l = outputs; l; l = l->next)
+ {
+ CcDisplayMonitor *output = l->data;
+
+ cc_display_monitor_set_compatible_clone_mode (output, clone_mode);
+ cc_display_monitor_set_scale (output, scale);
+ }
+ }
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ if (!panel->rebuilding_counter)
+ rebuild_ui (panel);
+}
+
+static void
+cc_panel_set_selected_type (CcDisplayPanel *panel, CcDisplayConfigType type)
+{
+ switch (type)
+ {
+ case CC_DISPLAY_CONFIG_JOIN:
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (panel->config_type_join), TRUE);
+ break;
+ case CC_DISPLAY_CONFIG_CLONE:
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (panel->config_type_mirror), TRUE);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ config_ensure_of_type (panel, type);
+}
+
+static void
+monitor_labeler_hide (CcDisplayPanel *self)
+{
+ if (!self->shell_proxy)
+ return;
+
+ g_dbus_proxy_call (self->shell_proxy,
+ "HideMonitorLabels",
+ NULL, G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, NULL, NULL);
+}
+
+static void
+monitor_labeler_show (CcDisplayPanel *self)
+{
+ GList *outputs, *l;
+ GVariantBuilder builder;
+ gint number = 0;
+
+ if (!self->shell_proxy || !self->current_config)
+ return;
+
+ outputs = cc_display_config_get_ui_sorted_monitors (self->current_config);
+ if (!outputs)
+ return;
+
+ if (cc_display_config_is_cloning (self->current_config))
+ return monitor_labeler_hide (self);
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
+ g_variant_builder_open (&builder, G_VARIANT_TYPE_ARRAY);
+
+ for (l = outputs; l != NULL; l = l->next)
+ {
+ CcDisplayMonitor *output = l->data;
+
+ number = cc_display_monitor_get_ui_number (output);
+ if (number == 0)
+ continue;
+
+ g_variant_builder_add (&builder, "{sv}",
+ cc_display_monitor_get_connector_name (output),
+ g_variant_new_int32 (number));
+ }
+
+ g_variant_builder_close (&builder);
+
+ if (number < 2)
+ {
+ g_variant_builder_clear (&builder);
+ return monitor_labeler_hide (self);
+ }
+
+ g_dbus_proxy_call (self->shell_proxy,
+ "ShowMonitorLabels",
+ g_variant_builder_end (&builder),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, NULL, NULL);
+}
+
+static void
+ensure_monitor_labels (CcDisplayPanel *self)
+{
+ g_autoptr(GList) windows = NULL;
+ GList *w;
+
+ windows = gtk_window_list_toplevels ();
+
+ for (w = windows; w; w = w->next)
+ {
+ if (gtk_window_is_active (GTK_WINDOW (w->data)))
+ {
+ monitor_labeler_show (self);
+ break;
+ }
+ }
+
+ if (!w)
+ monitor_labeler_hide (self);
+}
+
+static void
+dialog_toplevel_is_active_changed (CcDisplayPanel *self)
+{
+ ensure_monitor_labels (self);
+}
+
+static void
+reset_titlebar (CcDisplayPanel *self)
+{
+ gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (self->toplevel_shortcuts),
+ GTK_PHASE_NONE);
+ gtk_widget_hide (self->apply_titlebar);
+}
+
+static void
+active_panel_changed (CcPanel *self)
+{
+ CcShell *shell;
+ g_autoptr(CcPanel) panel = NULL;
+
+ shell = cc_panel_get_shell (CC_PANEL (self));
+ g_object_get (shell, "active-panel", &panel, NULL);
+ if (panel != self)
+ reset_titlebar (CC_DISPLAY_PANEL (self));
+}
+
+static void
+cc_display_panel_dispose (GObject *object)
+{
+ CcDisplayPanel *self = CC_DISPLAY_PANEL (object);
+ GtkWidget *toplevel = cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (self)));
+
+ reset_titlebar (CC_DISPLAY_PANEL (object));
+
+ if (self->focus_id)
+ {
+ self->focus_id = 0;
+ monitor_labeler_hide (CC_DISPLAY_PANEL (object));
+ }
+
+ g_clear_pointer (&self->monitor_rows, g_list_free);
+ g_clear_object (&self->manager);
+ g_clear_object (&self->current_config);
+ g_clear_object (&self->up_client);
+
+ g_clear_object (&self->shell_proxy);
+
+ g_signal_handlers_disconnect_by_data (toplevel, self);
+
+ G_OBJECT_CLASS (cc_display_panel_parent_class)->dispose (object);
+}
+
+static void
+on_arrangement_selected_ouptut_changed_cb (CcDisplayPanel *panel)
+{
+ set_current_output (panel, cc_display_arrangement_get_selected_output (panel->arrangement), FALSE);
+}
+
+static void
+on_monitor_settings_updated_cb (CcDisplayPanel *panel,
+ CcDisplayMonitor *monitor,
+ CcDisplaySettings *settings)
+{
+ if (monitor)
+ cc_display_config_snap_output (panel->current_config, monitor);
+ update_apply_button (panel);
+}
+
+static void
+on_back_button_clicked_cb (GtkButton *button,
+ CcDisplayPanel *self)
+{
+ adw_leaflet_set_visible_child_name (self->leaflet, "displays");
+}
+
+static void
+on_config_type_toggled_cb (CcDisplayPanel *panel,
+ GtkCheckButton *btn)
+{
+ CcDisplayConfigType type;
+
+ if (panel->rebuilding_counter > 0)
+ return;
+
+ if (!panel->current_config)
+ return;
+
+ if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (btn)))
+ return;
+
+ type = cc_panel_get_selected_type (panel);
+ config_ensure_of_type (panel, type);
+}
+
+static void
+on_night_light_enabled_changed_cb (GSettings *settings,
+ const gchar *key,
+ CcDisplayPanel *self)
+{
+ if (g_settings_get_boolean (self->display_settings, "night-light-enabled"))
+ gtk_label_set_label (self->night_light_state_label, _("On"));
+ else
+ gtk_label_set_label (self->night_light_state_label, _("Off"));
+}
+
+static void
+on_night_light_row_activated_cb (GtkListBoxRow *row,
+ CcDisplayPanel *self)
+{
+ adw_leaflet_set_visible_child_name (self->leaflet, "night-light");
+}
+
+static void
+on_primary_display_selected_item_changed_cb (CcDisplayPanel *panel)
+{
+ gint idx = adw_combo_row_get_selected (panel->primary_display_row);
+ g_autoptr(CcDisplayMonitor) output = NULL;
+
+ if (idx < 0 || panel->rebuilding_counter > 0)
+ return;
+
+ output = g_list_model_get_item (G_LIST_MODEL (panel->primary_display_list), idx);
+
+ if (cc_display_monitor_is_primary (output))
+ return;
+
+ cc_display_monitor_set_primary (output, TRUE);
+ update_apply_button (panel);
+}
+
+static void
+on_toplevel_folded (CcDisplayPanel *panel, GParamSpec *pspec, GtkWidget *toplevel)
+{
+ gboolean folded;
+
+ g_object_get (toplevel, "folded", &folded, NULL);
+ cc_display_settings_refresh_layout (panel->settings, folded);
+}
+
+static gboolean
+on_toplevel_escape_pressed_cb (GtkWidget *widget,
+ GVariant *args,
+ CcDisplayPanel *self)
+{
+ if (gtk_widget_get_visible (self->apply_titlebar))
+ {
+ gtk_widget_activate (self->cancel_button);
+ return GDK_EVENT_STOP;
+ }
+
+ return GDK_EVENT_PROPAGATE;
+}
+
+static void
+cc_display_panel_constructed (GObject *object)
+{
+ CcShell *shell = cc_panel_get_shell (CC_PANEL (object));
+ GtkWidget *toplevel = cc_shell_get_toplevel (shell);
+
+ g_signal_connect_object (cc_panel_get_shell (CC_PANEL (object)), "notify::active-panel",
+ G_CALLBACK (active_panel_changed), object, G_CONNECT_SWAPPED);
+
+ g_signal_connect_swapped (toplevel, "notify::folded", G_CALLBACK (on_toplevel_folded), object);
+ on_toplevel_folded (CC_DISPLAY_PANEL (object), NULL, toplevel);
+
+ G_OBJECT_CLASS (cc_display_panel_parent_class)->constructed (object);
+}
+
+static const char *
+cc_display_panel_get_help_uri (CcPanel *panel)
+{
+ return "help:gnome-help/prefs-display";
+}
+
+static void
+cc_display_panel_class_init (CcDisplayPanelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ g_type_ensure (CC_TYPE_NIGHT_LIGHT_PAGE);
+
+ panel_class->get_help_uri = cc_display_panel_get_help_uri;
+
+ object_class->constructed = cc_display_panel_constructed;
+ object_class->dispose = cc_display_panel_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/display/cc-display-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, apply_button);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, apply_titlebar);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, apply_titlebar_title_widget);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, display_settings_disabled_group);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, arrangement_bin);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, arrangement_row);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, cancel_button);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, display_multiple_displays);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, config_type_join);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, config_type_mirror);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, display_settings_bin);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, display_settings_group);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, display_settings_title_widget);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, escape_shortcut);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, leaflet);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, night_light_page);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, night_light_state_label);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, primary_display_row);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, single_display_settings_group);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, toplevel_shortcuts);
+
+ gtk_widget_class_bind_template_callback (widget_class, apply_current_configuration);
+ gtk_widget_class_bind_template_callback (widget_class, on_back_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_config_type_toggled_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_night_light_row_activated_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_primary_display_selected_item_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_screen_changed);
+ gtk_widget_class_bind_template_callback (widget_class, on_toplevel_escape_pressed_cb);
+}
+
+static void
+set_current_output (CcDisplayPanel *panel,
+ CcDisplayMonitor *output,
+ gboolean force)
+{
+ gboolean changed;
+
+ /* Note, this function is also called if the internal UI needs updating after a rebuild. */
+ changed = (output != panel->current_output);
+
+ if (!changed && !force)
+ return;
+
+ panel->rebuilding_counter++;
+
+ panel->current_output = output;
+
+ if (changed)
+ {
+ cc_display_settings_set_selected_output (panel->settings, panel->current_output);
+ cc_display_arrangement_set_selected_output (panel->arrangement, panel->current_output);
+
+ adw_window_title_set_title (panel->display_settings_title_widget,
+ output ? cc_display_monitor_get_ui_name (output) : "");
+ }
+
+ panel->rebuilding_counter--;
+}
+
+static void
+on_monitor_row_activated_cb (GtkListBoxRow *row,
+ CcDisplayPanel *self)
+{
+ CcDisplayMonitor *monitor;
+
+ monitor = g_object_get_data (G_OBJECT (row), "monitor");
+ set_current_output (self, monitor, FALSE);
+
+ adw_leaflet_set_visible_child_name (self->leaflet, "display-settings");
+}
+
+static void
+add_display_row (CcDisplayPanel *self,
+ CcDisplayMonitor *monitor)
+{
+ g_autofree gchar *number_string = NULL;
+ GtkWidget *number_label;
+ GtkWidget *icon;
+ GtkWidget *row;
+
+ row = adw_action_row_new ();
+ g_object_set_data (G_OBJECT (row), "monitor", monitor);
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row),
+ cc_display_monitor_get_ui_name (monitor));
+
+ number_string = g_strdup_printf ("%d", cc_display_monitor_get_ui_number (monitor));
+ number_label = gtk_label_new (number_string);
+ gtk_widget_set_valign (number_label, GTK_ALIGN_CENTER);
+ gtk_widget_set_halign (number_label, GTK_ALIGN_CENTER);
+ gtk_widget_add_css_class (number_label, "monitor-label");
+ adw_action_row_add_prefix (ADW_ACTION_ROW (row), number_label);
+
+ icon = gtk_image_new_from_icon_name ("go-next-symbolic");
+ adw_action_row_add_suffix (ADW_ACTION_ROW (row), icon);
+ adw_action_row_set_activatable_widget (ADW_ACTION_ROW (row), icon);
+
+ adw_preferences_group_add (ADW_PREFERENCES_GROUP (self->display_settings_group), row);
+
+ g_signal_connect (row, "activated", G_CALLBACK (on_monitor_row_activated_cb), self);
+
+ self->monitor_rows = g_list_prepend (self->monitor_rows, row);
+}
+
+static void
+move_display_settings_to_main_page (CcDisplayPanel *self)
+{
+ GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (self->settings));
+
+ if (parent != GTK_WIDGET (self->display_settings_bin))
+ return;
+
+ g_object_ref (self->settings);
+ adw_bin_set_child (self->display_settings_bin, NULL);
+ adw_preferences_group_add (self->single_display_settings_group,
+ GTK_WIDGET (self->settings));
+ g_object_unref (self->settings);
+
+ gtk_widget_show (GTK_WIDGET (self->single_display_settings_group));
+}
+
+static void
+move_display_settings_to_separate_page (CcDisplayPanel *self)
+{
+ GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (self->settings));
+
+ if (parent == GTK_WIDGET (self->display_settings_bin))
+ return;
+
+ g_object_ref (self->settings);
+ adw_preferences_group_remove (self->single_display_settings_group,
+ GTK_WIDGET (self->settings));
+ adw_bin_set_child (self->display_settings_bin,
+ GTK_WIDGET (self->settings));
+ g_object_unref (self->settings);
+
+ gtk_widget_hide (GTK_WIDGET (self->single_display_settings_group));
+}
+
+static void
+rebuild_ui (CcDisplayPanel *panel)
+{
+ guint n_outputs, n_active_outputs, n_usable_outputs;
+ GList *outputs, *l;
+ CcDisplayConfigType type;
+
+ if (!cc_display_config_manager_get_apply_allowed (panel->manager))
+ {
+ gtk_widget_set_visible (panel->display_settings_disabled_group, TRUE);
+ gtk_widget_set_visible (panel->display_settings_group, FALSE);
+ gtk_widget_set_visible (panel->arrangement_row, FALSE);
+ return;
+ }
+
+ panel->rebuilding_counter++;
+
+ g_list_store_remove_all (panel->primary_display_list);
+
+ /* Remove all monitor rows */
+ while (panel->monitor_rows)
+ {
+ adw_preferences_group_remove (ADW_PREFERENCES_GROUP (panel->display_settings_group),
+ panel->monitor_rows->data);
+ panel->monitor_rows = g_list_remove_link (panel->monitor_rows, panel->monitor_rows);
+ }
+
+ if (!panel->current_config)
+ {
+ panel->rebuilding_counter--;
+ return;
+ }
+
+ gtk_widget_set_visible (panel->display_settings_disabled_group, FALSE);
+
+ n_active_outputs = 0;
+ n_usable_outputs = 0;
+ outputs = cc_display_config_get_ui_sorted_monitors (panel->current_config);
+ for (l = outputs; l; l = l->next)
+ {
+ CcDisplayMonitor *output = l->data;
+
+ if (!cc_display_monitor_is_usable (output))
+ continue;
+
+ n_usable_outputs += 1;
+
+ if (cc_display_monitor_is_active (output))
+ {
+ n_active_outputs += 1;
+
+ g_list_store_append (panel->primary_display_list, output);
+ if (cc_display_monitor_is_primary (output))
+ adw_combo_row_set_selected (panel->primary_display_row,
+ g_list_model_get_n_items (G_LIST_MODEL (panel->primary_display_list)) - 1);
+
+ /* Ensure that an output is selected; note that this doesn't ensure
+ * the selected output is any useful (i.e. when switching types).
+ */
+ if (!panel->current_output)
+ set_current_output (panel, output, FALSE);
+ }
+
+ add_display_row (panel, l->data);
+ }
+
+ /* Sync the rebuild lists/buttons */
+ set_current_output (panel, panel->current_output, TRUE);
+
+ n_outputs = g_list_length (outputs);
+ type = config_get_current_type (panel);
+
+ if (n_outputs == 2 && n_usable_outputs == 2)
+ {
+ /* We only show the top chooser with two monitors that are
+ * both usable (i.e. two monitors incl. internal and lid not closed).
+ * In this case, the arrangement widget is shown if we are in JOIN mode.
+ */
+ if (type > CC_DISPLAY_CONFIG_LAST_VALID)
+ type = CC_DISPLAY_CONFIG_JOIN;
+
+ gtk_widget_set_visible (panel->display_settings_group, type == CC_DISPLAY_CONFIG_JOIN);
+ gtk_widget_set_visible (panel->display_multiple_displays, TRUE);
+ gtk_widget_set_visible (panel->arrangement_row, type == CC_DISPLAY_CONFIG_JOIN);
+
+ if (type == CC_DISPLAY_CONFIG_CLONE)
+ move_display_settings_to_main_page (panel);
+ else
+ move_display_settings_to_separate_page (panel);
+ }
+ else if (n_usable_outputs > 1)
+ {
+ /* We have more than one usable monitor. In this case there is no chooser,
+ * and we always show the arrangement widget.
+ */
+ gtk_widget_set_visible (panel->display_settings_group, TRUE);
+ gtk_widget_set_visible (panel->display_multiple_displays, FALSE);
+ gtk_widget_set_visible (panel->arrangement_row, TRUE);
+
+ /* Mirror is also invalid as it cannot be configured using this UI. */
+ if (type == CC_DISPLAY_CONFIG_CLONE || type > CC_DISPLAY_CONFIG_LAST_VALID)
+ type = CC_DISPLAY_CONFIG_JOIN;
+
+ move_display_settings_to_separate_page (panel);
+ }
+ else
+ {
+ type = CC_DISPLAY_CONFIG_JOIN;
+
+ gtk_widget_set_visible (panel->display_settings_group, FALSE);
+ gtk_widget_set_visible (panel->display_multiple_displays, FALSE);
+ gtk_widget_set_visible (panel->arrangement_row, FALSE);
+
+ move_display_settings_to_main_page (panel);
+ }
+
+ cc_display_settings_set_multimonitor (panel->settings,
+ n_outputs > 1 &&
+ type != CC_DISPLAY_CONFIG_CLONE);
+
+ cc_panel_set_selected_type (panel, type);
+
+ panel->rebuilding_counter--;
+ update_apply_button (panel);
+}
+
+static void
+update_panel_orientation_managed (CcDisplayPanel *panel,
+ gboolean managed)
+{
+ cc_display_settings_set_has_accelerometer (panel->settings, managed);
+}
+
+static void
+reset_current_config (CcDisplayPanel *panel)
+{
+ CcDisplayConfig *current;
+ CcDisplayConfig *old;
+ GList *outputs, *l;
+
+ g_debug ("Resetting current config!");
+
+ /* We need to hold on to the config until all display references are dropped. */
+ old = panel->current_config;
+ panel->current_output = NULL;
+
+ current = cc_display_config_manager_get_current (panel->manager);
+
+ if (!current)
+ return;
+
+ cc_display_config_set_minimum_size (current, MINIMUM_WIDTH, MINIMUM_HEIGHT);
+ panel->current_config = current;
+
+ g_signal_connect_object (current, "panel-orientation-managed",
+ G_CALLBACK (update_panel_orientation_managed), panel,
+ G_CONNECT_SWAPPED);
+ update_panel_orientation_managed (panel,
+ cc_display_config_get_panel_orientation_managed (current));
+
+ g_list_store_remove_all (panel->primary_display_list);
+
+ if (panel->current_config)
+ {
+ outputs = cc_display_config_get_ui_sorted_monitors (panel->current_config);
+ for (l = outputs; l; l = l->next)
+ {
+ CcDisplayMonitor *output = l->data;
+
+ /* Mark any builtin monitor as unusable if the lid is closed. */
+ if (cc_display_monitor_is_builtin (output) && panel->lid_is_closed)
+ cc_display_monitor_set_usable (output, FALSE);
+ }
+ }
+
+ cc_display_arrangement_set_config (panel->arrangement, panel->current_config);
+ cc_display_settings_set_config (panel->settings, panel->current_config);
+ set_current_output (panel, NULL, FALSE);
+
+ g_clear_object (&old);
+
+ update_apply_button (panel);
+}
+
+static void
+on_screen_changed (CcDisplayPanel *panel)
+{
+ if (!panel->manager)
+ return;
+
+ reset_titlebar (panel);
+
+ reset_current_config (panel);
+ rebuild_ui (panel);
+
+ if (!panel->current_config)
+ return;
+
+ ensure_monitor_labels (panel);
+}
+
+static void
+show_apply_titlebar (CcDisplayPanel *panel, gboolean is_applicable)
+{
+ gtk_widget_show (panel->apply_titlebar);
+ gtk_widget_set_sensitive (panel->apply_button, is_applicable);
+
+ if (is_applicable)
+ {
+ adw_window_title_set_title (panel->apply_titlebar_title_widget,
+ _("Apply Changes?"));
+ }
+ else
+ {
+ adw_window_title_set_title (panel->apply_titlebar_title_widget,
+ _("Changes Cannot be Applied"));
+ adw_window_title_set_subtitle (panel->apply_titlebar_title_widget,
+ _("This could be due to hardware limitations."));
+ }
+
+ gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (panel->toplevel_shortcuts),
+ GTK_PHASE_BUBBLE);
+}
+
+static void
+update_apply_button (CcDisplayPanel *panel)
+{
+ gboolean config_equal;
+ g_autoptr(CcDisplayConfig) applied_config = NULL;
+
+ if (!panel->current_config)
+ {
+ reset_titlebar (panel);
+ return;
+ }
+
+ applied_config = cc_display_config_manager_get_current (panel->manager);
+
+ config_equal = cc_display_config_equal (panel->current_config,
+ applied_config);
+
+ if (config_equal)
+ reset_titlebar (panel);
+ else
+ show_apply_titlebar (panel, cc_display_config_is_applicable (panel->current_config));
+}
+
+static void
+apply_current_configuration (CcDisplayPanel *self)
+{
+ g_autoptr(GError) error = NULL;
+
+ cc_display_config_apply (self->current_config, &error);
+
+ /* re-read the configuration */
+ on_screen_changed (self);
+
+ if (error)
+ g_warning ("Error applying configuration: %s", error->message);
+
+ adw_leaflet_set_visible_child_name (self->leaflet, "displays");
+}
+
+static void
+mapped_cb (CcDisplayPanel *panel)
+{
+ CcShell *shell;
+ GtkWidget *toplevel;
+
+ shell = cc_panel_get_shell (CC_PANEL (panel));
+ toplevel = cc_shell_get_toplevel (shell);
+ if (toplevel && !panel->focus_id)
+ panel->focus_id = g_signal_connect_object (toplevel, "notify::is-active",
+ G_CALLBACK (dialog_toplevel_is_active_changed), panel, G_CONNECT_SWAPPED);
+}
+
+static void
+cc_display_panel_up_client_changed (CcDisplayPanel *self)
+{
+ gboolean lid_is_closed;
+
+ lid_is_closed = up_client_get_lid_is_closed (self->up_client);
+
+ if (lid_is_closed != self->lid_is_closed)
+ {
+ self->lid_is_closed = lid_is_closed;
+
+ on_screen_changed (self);
+ }
+}
+
+static void
+shell_proxy_ready (GObject *source,
+ GAsyncResult *res,
+ CcDisplayPanel *self)
+{
+ GDBusProxy *proxy;
+ g_autoptr(GError) error = NULL;
+
+ proxy = cc_object_storage_create_dbus_proxy_finish (res, &error);
+ if (!proxy)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to contact gnome-shell: %s", error->message);
+ return;
+ }
+
+ self->shell_proxy = proxy;
+
+ ensure_monitor_labels (self);
+}
+
+static void
+session_bus_ready (GObject *source,
+ GAsyncResult *res,
+ CcDisplayPanel *self)
+{
+ GDBusConnection *bus;
+ g_autoptr(GError) error = NULL;
+
+ bus = g_bus_get_finish (res, &error);
+ if (!bus)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ g_warning ("Failed to get session bus: %s", error->message);
+ }
+ return;
+ }
+
+ self->manager = cc_display_config_manager_dbus_new ();
+ g_signal_connect_object (self->manager, "changed",
+ G_CALLBACK (on_screen_changed),
+ self,
+ G_CONNECT_SWAPPED);
+}
+
+static void
+cc_display_panel_init (CcDisplayPanel *self)
+{
+ g_autoptr(GtkCssProvider) provider = NULL;
+ GtkExpression *expression;
+
+ g_resources_register (cc_display_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->arrangement = cc_display_arrangement_new (NULL);
+ gtk_widget_set_size_request (GTK_WIDGET (self->arrangement), 375, 175);
+ adw_bin_set_child (self->arrangement_bin, GTK_WIDGET (self->arrangement));
+
+ g_signal_connect_object (self->arrangement, "updated",
+ G_CALLBACK (update_apply_button), self,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->arrangement, "notify::selected-output",
+ G_CALLBACK (on_arrangement_selected_ouptut_changed_cb), self,
+ G_CONNECT_SWAPPED);
+
+ self->settings = cc_display_settings_new ();
+ adw_bin_set_child (self->display_settings_bin, GTK_WIDGET (self->settings));
+ g_signal_connect_object (self->settings, "updated",
+ G_CALLBACK (on_monitor_settings_updated_cb), self,
+ G_CONNECT_SWAPPED);
+
+ self->primary_display_list = g_list_store_new (CC_TYPE_DISPLAY_MONITOR);
+
+ expression = gtk_cclosure_expression_new (G_TYPE_STRING,
+ NULL, 0, NULL,
+ G_CALLBACK (cc_display_monitor_dup_ui_number_name),
+ self, NULL);
+ adw_combo_row_set_expression (self->primary_display_row, expression);
+ adw_combo_row_set_model (self->primary_display_row,
+ G_LIST_MODEL (self->primary_display_list));
+
+ self->up_client = up_client_new ();
+ if (up_client_get_lid_is_present (self->up_client))
+ {
+ g_signal_connect_object (self->up_client, "notify::lid-is-closed",
+ G_CALLBACK (cc_display_panel_up_client_changed), self, G_CONNECT_SWAPPED);
+ cc_display_panel_up_client_changed (self);
+ }
+ else
+ g_clear_object (&self->up_client);
+
+ g_signal_connect (self, "map", G_CALLBACK (mapped_cb), NULL);
+
+ cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
+ G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS |
+ G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+ "org.gnome.Shell",
+ "/org/gnome/Shell",
+ "org.gnome.Shell",
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ (GAsyncReadyCallback) shell_proxy_ready,
+ self);
+
+ g_bus_get (G_BUS_TYPE_SESSION,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ (GAsyncReadyCallback) session_bus_ready,
+ self);
+
+ provider = gtk_css_provider_new ();
+ gtk_css_provider_load_from_resource (provider, "/org/gnome/control-center/display/display-arrangement.css");
+ gtk_style_context_add_provider_for_display (gdk_display_get_default (),
+ GTK_STYLE_PROVIDER (provider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+ gtk_shortcut_set_action (self->escape_shortcut,
+ gtk_callback_action_new ((GtkShortcutFunc) on_toplevel_escape_pressed_cb,
+ self,
+ NULL));
+
+ self->display_settings = g_settings_new (DISPLAY_SCHEMA);
+ g_signal_connect_object (self->display_settings,
+ "changed::night-light-enabled",
+ G_CALLBACK (on_night_light_enabled_changed_cb),
+ self,
+ 0);
+ on_night_light_enabled_changed_cb (NULL, NULL, self);
+}
diff --git a/panels/display/cc-display-panel.h b/panels/display/cc-display-panel.h
new file mode 100644
index 0000000..a7ade28
--- /dev/null
+++ b/panels/display/cc-display-panel.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2010 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ *
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_DISPLAY_PANEL (cc_display_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcDisplayPanel, cc_display_panel, CC, DISPLAY_PANEL, CcPanel)
+
+G_END_DECLS
diff --git a/panels/display/cc-display-panel.ui b/panels/display/cc-display-panel.ui
new file mode 100644
index 0000000..9337b18
--- /dev/null
+++ b/panels/display/cc-display-panel.ui
@@ -0,0 +1,316 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcDisplayPanel" parent="CcPanel">
+
+ <child>
+ <object class="GtkShortcutController" id="toplevel_shortcuts">
+ <property name="scope">global</property>
+ <property name="name">Display Panel Globals Shortcuts</property>
+ <child>
+ <object class="GtkShortcut" id="escape_shortcut">
+ <property name="trigger">Escape</property>
+ <property name="action">callback(on_toplevel_escape_pressed_cb)</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkOverlay">
+
+ <child type="overlay">
+ <object class="AdwHeaderBar" id="apply_titlebar">
+ <property name="visible">False</property>
+ <property name="valign">start</property>
+ <property name="show-start-title-buttons">False</property>
+ <property name="show-end-title-buttons">False</property>
+
+ <child type="start">
+ <object class="GtkButton" id="cancel_button">
+ <property name="use-underline">True</property>
+ <property name="label" translatable="yes">_Cancel</property>
+ <signal name="clicked" handler="on_screen_changed" object="CcDisplayPanel" swapped="yes" />
+ </object>
+ </child>
+
+ <property name="title-widget">
+ <object class="AdwWindowTitle" id="apply_titlebar_title_widget" />
+ </property>
+
+ <child type="end">
+ <object class="GtkButton" id="apply_button">
+ <property name="use-underline">True</property>
+ <property name="label" translatable="yes">_Apply</property>
+ <signal name="clicked" handler="apply_current_configuration" object="CcDisplayPanel" swapped="yes" />
+ <style>
+ <class name="suggested-action" />
+ </style>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwLeaflet" id="leaflet">
+ <property name="can-unfold">False</property>
+
+ <!-- Displays page -->
+ <child>
+ <object class="AdwLeafletPage">
+ <property name="name">displays</property>
+ <property name="child">
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+
+ <!-- Displays page titlebar -->
+ <child>
+ <object class="AdwHeaderBar" id="displays_titlebar">
+ <property name="show-end-title-buttons">True</property>
+ <property name="show-start-title-buttons" bind-source="CcDisplayPanel" bind-property="folded" bind-flags="default|sync-create" />
+ <child type="start">
+ <object class="GtkButton">
+ <property name="visible" bind-source="CcDisplayPanel" bind-property="folded" bind-flags="default|sync-create" />
+ <property name="icon-name">go-previous-symbolic</property>
+ <property name="action-name">window.navigate</property>
+ <property name="action-target">0</property> <!-- 0: ADW_NAVIGATION_DIRECTION_BACK -->
+ <accessibility>
+ <property name="label" translatable="yes">Back</property>
+ </accessibility>
+ </object>
+ </child>
+ <property name="title-widget">
+ <object class="AdwWindowTitle">
+ <property name="title" bind-source="CcDisplayPanel" bind-property="title" bind-flags="default|sync-create" />
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesPage">
+
+ <child>
+ <object class="AdwPreferencesGroup" id="display_settings_disabled_group">
+ <property name="visible">False</property>
+ <child>
+ <object class="AdwStatusPage">
+ <property name="vexpand">True</property>
+ <property name="icon-name">computer-symbolic</property>
+ <property name="title" translatable="yes">Display Settings Disabled</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup" id="display_multiple_displays">
+ <!-- Config Type -->
+ <child>
+ <object class="AdwActionRow" id="config_type_switcher_row">
+ <property name="title" translatable="yes">Multiple Displays</property>
+ <child type="suffix">
+ <object class="GtkBox">
+ <property name="valign">center</property>
+ <style>
+ <class name="linked" />
+ </style>
+ <child>
+ <object class="GtkToggleButton" id="config_type_join">
+ <property name="label" translatable="yes" comments="'Join' as in 'Join displays'">Join</property>
+ <property name="active">True</property>
+ <signal name="toggled" handler="on_config_type_toggled_cb" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="config_type_mirror">
+ <property name="label" translatable="yes">Mirror</property>
+ <property name="group">config_type_join</property>
+ <signal name="toggled" handler="on_config_type_toggled_cb" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup" id="display_settings_group">
+ <!-- Display Arrangement -->
+ <child>
+ <object class="AdwPreferencesRow" id="arrangement_row">
+ <property name="activatable">False</property>
+ <child>
+ <object class="AdwBin" id="arrangement_bin">
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- Primary Display -->
+ <child>
+ <object class="AdwComboRow" id="primary_display_row">
+ <property name="subtitle" translatable="yes">Contains top bar and Activities</property>
+ <property name="title" translatable="yes">Primary Display</property>
+ <signal name="notify::selected-item" handler="on_primary_display_selected_item_changed_cb" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+
+ </child>
+
+ <!-- Single Display Settings -->
+ <child>
+ <object class="AdwPreferencesGroup" id="single_display_settings_group">
+ <property name="visible">False</property>
+ </object>
+ </child>
+
+ <!-- Night Light -->
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="AdwActionRow">
+ <property name="activatable">True</property>
+ <property name="title" translatable="yes" comments="This is the redshift functionality where we suppress blue light when the sun has gone down">Night Light</property>
+ <signal name="activated" handler="on_night_light_row_activated_cb" object="CcDisplayPanel" swapped="no" />
+
+ <child type="suffix">
+ <object class="GtkLabel" id="night_light_state_label">
+ <property name="label">On</property>
+ </object>
+ </child>
+
+ <child type="suffix">
+ <object class="GtkImage">
+ <property name="icon-name">go-next-symbolic</property>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <!-- Night Light page -->
+ <child>
+ <object class="AdwLeafletPage">
+ <property name="name">night-light</property>
+ <property name="child">
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+
+ <!-- Night Light titlebar -->
+ <child>
+ <object class="AdwHeaderBar" id="night_light_titlebar">
+ <property name="show-start-title-buttons">True</property>
+ <property name="show-end-title-buttons">True</property>
+ <child type="start">
+ <object class="GtkButton">
+ <property name="icon-name">go-previous-symbolic</property>
+ <accessibility>
+ <property name="label" translatable="yes">Back</property>
+ </accessibility>
+ <signal name="clicked" handler="on_back_button_clicked_cb" object="CcDisplayPanel" swapped="no" />
+ </object>
+ </child>
+ <property name="title-widget">
+ <object class="AdwWindowTitle">
+ <property name="title" translatable="yes">Night Light</property>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <!-- Night Light -->
+ <child>
+ <object class="CcNightLightPage" id="night_light_page" />
+ </child>
+
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <!-- Display Settings page -->
+ <child>
+ <object class="AdwLeafletPage">
+ <property name="name">display-settings</property>
+ <property name="child"><object class="GtkBox">
+ <property name="orientation">vertical</property>
+
+ <!-- Display Settings titlebar -->
+ <child>
+ <object class="AdwHeaderBar" id="display_settings_titlebar">
+ <property name="show-start-title-buttons">True</property>
+ <property name="show-end-title-buttons">True</property>
+ <child type="start">
+ <object class="GtkButton">
+ <property name="icon-name">go-previous-symbolic</property>
+ <accessibility>
+ <property name="label" translatable="yes">Back</property>
+ </accessibility>
+ <signal name="clicked" handler="on_back_button_clicked_cb" object="CcDisplayPanel" swapped="no" />
+ </object>
+ </child>
+ <property name="title-widget">
+ <object class="AdwWindowTitle" id="display_settings_title_widget" />
+ </property>
+ </object>
+ </child>
+
+ <!-- Display Settings -->
+ <child>
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="AdwBin" id="display_settings_bin" />
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </property>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </template>
+
+ <object class="GtkSizeGroup">
+ <property name="mode">horizontal</property>
+ <widgets>
+ <widget name="apply_button" />
+ <widget name="cancel_button" />
+ </widgets>
+ </object>
+
+ <object class="GtkSizeGroup">
+ <property name="mode">vertical</property>
+ <widgets>
+ <widget name="apply_titlebar" />
+ <widget name="displays_titlebar" />
+ <widget name="display_settings_titlebar" />
+ <widget name="night_light_titlebar" />
+ </widgets>
+ </object>
+
+</interface>
+
diff --git a/panels/display/cc-display-settings.c b/panels/display/cc-display-settings.c
new file mode 100644
index 0000000..8fec65b
--- /dev/null
+++ b/panels/display/cc-display-settings.c
@@ -0,0 +1,919 @@
+/* cc-display-settings.c
+ *
+ * Copyright (C) 2007, 2008, 2018, 2019 Red Hat, Inc.
+ * Copyright (C) 2013 Intel, Inc.
+ *
+ * Written by: Benjamin Berg <bberg@redhat.com>
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <float.h>
+#include <glib/gi18n.h>
+#include <float.h>
+#include <math.h>
+#include "cc-display-settings.h"
+#include "cc-display-config.h"
+
+#define MAX_SCALE_BUTTONS 5
+
+struct _CcDisplaySettings
+{
+ GtkBox object;
+
+ gboolean updating;
+ gboolean num_scales;
+ gboolean folded;
+ guint idle_udpate_id;
+
+ gboolean has_accelerometer;
+ CcDisplayConfig *config;
+ CcDisplayMonitor *selected_output;
+
+ GListModel *orientation_list;
+ GListStore *refresh_rate_list;
+ GListStore *resolution_list;
+ GListModel *scale_list;
+
+ GtkWidget *enabled_listbox;
+ AdwActionRow *enabled_row;
+ GtkSwitch *enabled_switch;
+ GtkWidget *orientation_row;
+ GtkWidget *refresh_rate_row;
+ GtkWidget *resolution_row;
+ GtkWidget *scale_bbox;
+ GtkWidget *scale_buttons_row;
+ GtkWidget *scale_combo_row;
+ GtkWidget *underscanning_row;
+ GtkWidget *underscanning_switch;
+};
+
+typedef struct _CcDisplaySettings CcDisplaySettings;
+
+enum {
+ PROP_0,
+ PROP_HAS_ACCELEROMETER,
+ PROP_CONFIG,
+ PROP_SELECTED_OUTPUT,
+ PROP_LAST
+};
+
+G_DEFINE_TYPE (CcDisplaySettings, cc_display_settings, GTK_TYPE_BOX)
+
+static GParamSpec *props[PROP_LAST];
+
+static void on_scale_btn_active_changed_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ CcDisplaySettings *self);
+
+
+static gboolean
+should_show_rotation (CcDisplaySettings *self)
+{
+ gboolean supports_rotation;
+
+ supports_rotation = cc_display_monitor_supports_rotation (self->selected_output,
+ CC_DISPLAY_ROTATION_90 |
+ CC_DISPLAY_ROTATION_180 |
+ CC_DISPLAY_ROTATION_270);
+
+ /* Doesn't support rotation at all */
+ if (!supports_rotation)
+ return FALSE;
+
+ /* We can always rotate displays that aren't builtin */
+ if (!cc_display_monitor_is_builtin (self->selected_output))
+ return TRUE;
+
+ /* Only offer rotation if there's no accelerometer */
+ return !self->has_accelerometer;
+}
+
+static const gchar *
+string_for_rotation (CcDisplayRotation rotation)
+{
+ switch (rotation)
+ {
+ case CC_DISPLAY_ROTATION_NONE:
+ case CC_DISPLAY_ROTATION_180_FLIPPED:
+ return C_("Display rotation", "Landscape");
+ case CC_DISPLAY_ROTATION_90:
+ case CC_DISPLAY_ROTATION_270_FLIPPED:
+ return C_("Display rotation", "Portrait Right");
+ case CC_DISPLAY_ROTATION_270:
+ case CC_DISPLAY_ROTATION_90_FLIPPED:
+ return C_("Display rotation", "Portrait Left");
+ case CC_DISPLAY_ROTATION_180:
+ case CC_DISPLAY_ROTATION_FLIPPED:
+ return C_("Display rotation", "Landscape (flipped)");
+ }
+ return "";
+}
+
+static const gchar *
+make_aspect_string (gint width,
+ gint height)
+{
+ int ratio;
+ const gchar *aspect = NULL;
+
+ /* We use a number of Unicode characters below:
+ * ∶ is U+2236 RATIO
+ *   is U+2009 THIN SPACE,
+ * × is U+00D7 MULTIPLICATION SIGN
+ */
+ if (width && height) {
+ if (width > height)
+ ratio = width * 10 / height;
+ else
+ ratio = height * 10 / width;
+
+ switch (ratio) {
+ case 13:
+ aspect = "4∶3";
+ break;
+ case 16:
+ aspect = "16∶10";
+ break;
+ case 17:
+ aspect = "16∶9";
+ break;
+ case 23:
+ aspect = "21∶9";
+ break;
+ case 35:
+ aspect = "32∶9";
+ break;
+ case 12:
+ aspect = "5∶4";
+ break;
+ /* This catches 1.5625 as well (1600x1024) when maybe it shouldn't. */
+ case 15:
+ aspect = "3∶2";
+ break;
+ case 18:
+ aspect = "9∶5";
+ break;
+ case 10:
+ aspect = "1∶1";
+ break;
+ }
+ }
+
+ return aspect;
+}
+
+static gchar *
+make_refresh_rate_string (CcDisplayMode *mode)
+{
+ return g_strdup_printf (_("%.2lf Hz"), cc_display_mode_get_freq_f (mode));
+}
+
+static gchar *
+make_resolution_string (CcDisplayMode *mode)
+{
+ const char *interlaced;
+ const char *aspect;
+ int width, height;
+
+ cc_display_mode_get_resolution (mode, &width, &height);
+ aspect = make_aspect_string (width, height);
+ interlaced = cc_display_mode_is_interlaced (mode) ? "i" : "";
+
+ if (aspect != NULL)
+ return g_strdup_printf ("%d × %d%s (%s)", width, height, interlaced, aspect);
+ else
+ return g_strdup_printf ("%d × %d%s", width, height, interlaced);
+}
+
+static double
+round_scale_for_ui (double scale)
+{
+ /* Keep in sync with mutter */
+ return round (scale*4)/4;
+}
+
+static gchar *
+make_scale_string (gdouble scale)
+{
+ return g_strdup_printf ("%d %%", (int) (round_scale_for_ui (scale)*100));
+}
+
+static gint
+sort_modes_by_area_desc (CcDisplayMode *a, CcDisplayMode *b)
+{
+ gint wa, ha, wb, hb;
+ gint res;
+
+ cc_display_mode_get_resolution (a, &wa, &ha);
+ cc_display_mode_get_resolution (b, &wb, &hb);
+
+ /* Sort first by width, then height.
+ * We used to sort by area, but that can be confusing. */
+ res = wb - wa;
+ if (res)
+ return res;
+ return hb - ha;
+}
+
+static gint
+sort_modes_by_freq_desc (CcDisplayMode *a, CcDisplayMode *b)
+{
+ double delta = (cc_display_mode_get_freq_f (b) - cc_display_mode_get_freq_f (a))*1000.;
+ return delta;
+}
+
+static gboolean
+cc_display_settings_rebuild_ui (CcDisplaySettings *self)
+{
+ GtkWidget *child;
+ g_autolist(CcDisplayMode) clone_modes = NULL;
+ GList *modes;
+ GList *item;
+ gint width, height;
+ CcDisplayMode *current_mode;
+ GtkToggleButton *group = NULL;
+ g_autoptr(GArray) scales = NULL;
+ gint i;
+
+ self->idle_udpate_id = 0;
+
+ if (!self->config || !self->selected_output)
+ {
+ gtk_widget_set_visible (self->enabled_listbox, FALSE);
+ gtk_widget_set_visible (self->orientation_row, FALSE);
+ gtk_widget_set_visible (self->refresh_rate_row, FALSE);
+ gtk_widget_set_visible (self->resolution_row, FALSE);
+ gtk_widget_set_visible (self->scale_combo_row, FALSE);
+ gtk_widget_set_visible (self->scale_buttons_row, FALSE);
+ gtk_widget_set_visible (self->underscanning_row, FALSE);
+
+ return G_SOURCE_REMOVE;
+ }
+
+ g_object_freeze_notify ((GObject*) self->enabled_switch);
+ g_object_freeze_notify ((GObject*) self->orientation_row);
+ g_object_freeze_notify ((GObject*) self->refresh_rate_row);
+ g_object_freeze_notify ((GObject*) self->resolution_row);
+ g_object_freeze_notify ((GObject*) self->scale_combo_row);
+ g_object_freeze_notify ((GObject*) self->underscanning_switch);
+
+ cc_display_monitor_get_geometry (self->selected_output, NULL, NULL, &width, &height);
+
+ /* Selecte the first mode we can find if the monitor is disabled. */
+ current_mode = cc_display_monitor_get_mode (self->selected_output);
+ if (current_mode == NULL)
+ current_mode = cc_display_monitor_get_preferred_mode (self->selected_output);
+ if (current_mode == NULL) {
+ modes = cc_display_monitor_get_modes (self->selected_output);
+ /* Lets assume that a monitor always has at least one mode. */
+ g_assert (modes);
+ current_mode = CC_DISPLAY_MODE (modes->data);
+ }
+
+ /* Enabled Switch */
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self->enabled_row),
+ cc_display_monitor_get_ui_name (self->selected_output));
+ gtk_switch_set_active (GTK_SWITCH (self->enabled_switch),
+ cc_display_monitor_is_active (self->selected_output));
+
+ if (should_show_rotation (self))
+ {
+ guint i;
+ CcDisplayRotation rotations[] = { CC_DISPLAY_ROTATION_NONE,
+ CC_DISPLAY_ROTATION_90,
+ CC_DISPLAY_ROTATION_270,
+ CC_DISPLAY_ROTATION_180 };
+
+ gtk_widget_set_visible (self->orientation_row, TRUE);
+
+ gtk_string_list_splice (GTK_STRING_LIST (self->orientation_list),
+ 0,
+ g_list_model_get_n_items (self->orientation_list),
+ NULL);
+ for (i = 0; i < G_N_ELEMENTS (rotations); i++)
+ {
+ g_autoptr(GObject) obj = NULL;
+
+ if (!cc_display_monitor_supports_rotation (self->selected_output, rotations[i]))
+ continue;
+
+ gtk_string_list_append (GTK_STRING_LIST (self->orientation_list),
+ string_for_rotation (rotations[i]));
+ obj = g_list_model_get_item (self->orientation_list, i);
+ g_object_set_data (G_OBJECT (obj), "rotation-value", GINT_TO_POINTER (rotations[i]));
+
+ if (cc_display_monitor_get_rotation (self->selected_output) == rotations[i])
+ adw_combo_row_set_selected (ADW_COMBO_ROW (self->orientation_row),
+ g_list_model_get_n_items (G_LIST_MODEL (self->orientation_list)) - 1);
+ }
+ }
+ else
+ {
+ gtk_widget_set_visible (self->orientation_row, FALSE);
+ }
+
+ /* Only show refresh rate if we are not in cloning mode. */
+ if (!cc_display_config_is_cloning (self->config))
+ {
+ GList *item;
+ gdouble freq;
+
+ freq = cc_display_mode_get_freq_f (current_mode);
+
+ modes = cc_display_monitor_get_modes (self->selected_output);
+
+ g_list_store_remove_all (self->refresh_rate_list);
+
+ for (item = modes; item != NULL; item = item->next)
+ {
+ gint w, h;
+ guint new;
+ CcDisplayMode *mode = CC_DISPLAY_MODE (item->data);
+
+ cc_display_mode_get_resolution (mode, &w, &h);
+ if (w != width || h != height)
+ continue;
+
+ /* At some point we used to filter very close resolutions,
+ * but we don't anymore these days.
+ */
+ new = g_list_store_insert_sorted (self->refresh_rate_list,
+ mode,
+ (GCompareDataFunc) sort_modes_by_freq_desc,
+ NULL);
+ if (freq == cc_display_mode_get_freq_f (mode))
+ adw_combo_row_set_selected (ADW_COMBO_ROW (self->refresh_rate_row), new);
+ }
+
+ gtk_widget_set_visible (self->refresh_rate_row, TRUE);
+ }
+ else
+ {
+ gtk_widget_set_visible (self->refresh_rate_row, FALSE);
+ }
+
+
+ /* Resolutions are always shown. */
+ gtk_widget_set_visible (self->resolution_row, TRUE);
+ if (cc_display_config_is_cloning (self->config))
+ {
+ clone_modes = cc_display_config_generate_cloning_modes (self->config);
+ modes = clone_modes;
+ }
+ else
+ {
+ modes = cc_display_monitor_get_modes (self->selected_output);
+ }
+
+ g_list_store_remove_all (self->resolution_list);
+ g_list_store_append (self->resolution_list, current_mode);
+ adw_combo_row_set_selected (ADW_COMBO_ROW (self->resolution_row), 0);
+ for (item = modes; item != NULL; item = item->next)
+ {
+ gint ins;
+ gint w, h;
+ CcDisplayMode *mode = CC_DISPLAY_MODE (item->data);
+
+ cc_display_mode_get_resolution (mode, &w, &h);
+
+ /* Find the appropriate insertion point. */
+ for (ins = 0; ins < g_list_model_get_n_items (G_LIST_MODEL (self->resolution_list)); ins++)
+ {
+ g_autoptr(CcDisplayMode) m = NULL;
+ gint cmp;
+
+ m = g_list_model_get_item (G_LIST_MODEL (self->resolution_list), ins);
+
+ cmp = sort_modes_by_area_desc (mode, m);
+ /* Next item is smaller, insert at this point. */
+ if (cmp < 0)
+ break;
+
+ /* Don't insert if it is already in the list */
+ if (cmp == 0)
+ {
+ ins = -1;
+ break;
+ }
+ }
+
+ if (ins >= 0)
+ g_list_store_insert (self->resolution_list, ins, mode);
+ }
+
+
+ /* Scale row is usually shown. */
+ while ((child = gtk_widget_get_first_child (self->scale_bbox)) != NULL)
+ gtk_box_remove (GTK_BOX (self->scale_bbox), child);
+
+ gtk_string_list_splice (GTK_STRING_LIST (self->scale_list),
+ 0,
+ g_list_model_get_n_items (self->scale_list),
+ NULL);
+ scales = cc_display_mode_get_supported_scales (current_mode);
+ self->num_scales = scales->len;
+ for (i = 0; i < scales->len; i++)
+ {
+ g_autofree gchar *scale_str = NULL;
+ g_autoptr(GObject) value_object = NULL;
+ double scale = g_array_index (scales, double, i);
+ GtkWidget *scale_btn;
+ gboolean is_selected;
+
+ /* ComboRow */
+ scale_str = make_scale_string (scale);
+ is_selected = G_APPROX_VALUE (cc_display_monitor_get_scale (self->selected_output),
+ scale, DBL_EPSILON);
+
+ gtk_string_list_append (GTK_STRING_LIST (self->scale_list), scale_str);
+ value_object = g_list_model_get_item (self->scale_list, i);
+ g_object_set_data_full (G_OBJECT (value_object), "scale",
+ g_memdup2 (&scale, sizeof (double)), g_free);
+ if (is_selected)
+ adw_combo_row_set_selected (ADW_COMBO_ROW (self->scale_combo_row),
+ g_list_model_get_n_items (G_LIST_MODEL (self->scale_list)) - 1);
+
+ /* ButtonBox */
+ scale_btn = gtk_toggle_button_new_with_label (scale_str);
+ gtk_toggle_button_set_group (GTK_TOGGLE_BUTTON (scale_btn), group);
+ g_object_set_data_full (G_OBJECT (scale_btn), "scale",
+ g_memdup2 (&scale, sizeof (double)), g_free);
+
+ if (!group)
+ group = GTK_TOGGLE_BUTTON (scale_btn);
+ gtk_box_append (GTK_BOX (self->scale_bbox), scale_btn);
+ /* Set active before connecting the signal */
+ if (is_selected)
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (scale_btn), TRUE);
+
+ g_signal_connect_object (scale_btn,
+ "notify::active",
+ G_CALLBACK (on_scale_btn_active_changed_cb),
+ self, 0);
+ }
+ cc_display_settings_refresh_layout (self, self->folded);
+
+ gtk_widget_set_visible (self->underscanning_row,
+ cc_display_monitor_supports_underscanning (self->selected_output) &&
+ !cc_display_config_is_cloning (self->config));
+ gtk_switch_set_active (GTK_SWITCH (self->underscanning_switch),
+ cc_display_monitor_get_underscanning (self->selected_output));
+
+ self->updating = TRUE;
+ g_object_thaw_notify ((GObject*) self->enabled_switch);
+ g_object_thaw_notify ((GObject*) self->orientation_row);
+ g_object_thaw_notify ((GObject*) self->refresh_rate_row);
+ g_object_thaw_notify ((GObject*) self->resolution_row);
+ g_object_thaw_notify ((GObject*) self->scale_combo_row);
+ g_object_thaw_notify ((GObject*) self->underscanning_switch);
+ self->updating = FALSE;
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+on_output_changed_cb (CcDisplaySettings *self,
+ GParamSpec *pspec,
+ CcDisplayMonitor *output)
+{
+ /* Do this frmo an idle handler, because otherwise we may create an
+ * infinite loop triggering the notify::selected-index from the
+ * combo rows. */
+ if (self->idle_udpate_id)
+ return;
+
+ self->idle_udpate_id = g_idle_add ((GSourceFunc) cc_display_settings_rebuild_ui, self);
+}
+
+static void
+on_enabled_switch_active_changed_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ CcDisplaySettings *self)
+{
+ if (self->updating)
+ return;
+
+ cc_display_monitor_set_active (self->selected_output,
+ gtk_switch_get_active (self->enabled_switch));
+
+ g_signal_emit_by_name (G_OBJECT (self), "updated", self->selected_output);
+}
+
+static void
+on_orientation_selection_changed_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ CcDisplaySettings *self)
+{
+ gint idx;
+ g_autoptr(GObject) obj = NULL;
+
+ if (self->updating)
+ return;
+
+ idx = adw_combo_row_get_selected (ADW_COMBO_ROW (self->orientation_row));
+ obj = g_list_model_get_item (G_LIST_MODEL (self->orientation_list), idx);
+
+ if (!obj)
+ return;
+
+ cc_display_monitor_set_rotation (self->selected_output,
+ GPOINTER_TO_INT (g_object_get_data (G_OBJECT (obj), "rotation-value")));
+
+ g_signal_emit_by_name (G_OBJECT (self), "updated", self->selected_output);
+}
+
+static void
+on_refresh_rate_selection_changed_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ CcDisplaySettings *self)
+{
+ gint idx;
+ g_autoptr(CcDisplayMode) mode = NULL;
+
+ if (self->updating)
+ return;
+
+ idx = adw_combo_row_get_selected (ADW_COMBO_ROW (self->refresh_rate_row));
+ mode = g_list_model_get_item (G_LIST_MODEL (self->refresh_rate_list), idx);
+
+ if (!mode)
+ return;
+
+ cc_display_monitor_set_mode (self->selected_output, mode);
+
+ g_signal_emit_by_name (G_OBJECT (self), "updated", self->selected_output);
+}
+
+static void
+on_resolution_selection_changed_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ CcDisplaySettings *self)
+{
+ gint idx;
+ g_autoptr(CcDisplayMode) mode = NULL;
+
+ if (self->updating)
+ return;
+
+ idx = adw_combo_row_get_selected (ADW_COMBO_ROW (self->resolution_row));
+ mode = g_list_model_get_item (G_LIST_MODEL (self->resolution_list), idx);
+
+ if (!mode)
+ return;
+
+ /* This is the only row that can be changed when in cloning mode. */
+ if (!cc_display_config_is_cloning (self->config))
+ cc_display_monitor_set_mode (self->selected_output, mode);
+ else
+ cc_display_config_set_mode_on_all_outputs (self->config, mode);
+
+ g_signal_emit_by_name (G_OBJECT (self), "updated", self->selected_output);
+}
+
+static void
+on_scale_btn_active_changed_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ CcDisplaySettings *self)
+{
+ gdouble scale;
+ if (self->updating)
+ return;
+
+ if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
+ return;
+
+ scale = *(gdouble*) g_object_get_data (G_OBJECT (widget), "scale");
+ cc_display_monitor_set_scale (self->selected_output,
+ scale);
+
+ g_signal_emit_by_name (G_OBJECT (self), "updated", self->selected_output);
+}
+
+static void
+on_scale_selection_changed_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ CcDisplaySettings *self)
+{
+ int idx;
+ double scale;
+ g_autoptr(GObject) obj = NULL;
+
+ if (self->updating)
+ return;
+
+ idx = adw_combo_row_get_selected (ADW_COMBO_ROW (self->scale_combo_row));
+ obj = g_list_model_get_item (G_LIST_MODEL (self->scale_list), idx);
+ if (!obj)
+ return;
+ scale = *(gdouble*) g_object_get_data (G_OBJECT (obj), "scale");
+
+ cc_display_monitor_set_scale (self->selected_output, scale);
+
+ g_signal_emit_by_name (G_OBJECT (self), "updated", self->selected_output);
+}
+
+static void
+on_underscanning_switch_active_changed_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ CcDisplaySettings *self)
+{
+ if (self->updating)
+ return;
+
+ cc_display_monitor_set_underscanning (self->selected_output,
+ gtk_switch_get_active (GTK_SWITCH (self->underscanning_switch)));
+
+ g_signal_emit_by_name (G_OBJECT (self), "updated", self->selected_output);
+}
+
+static void
+cc_display_settings_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcDisplaySettings *self = CC_DISPLAY_SETTINGS (object);
+
+ switch (prop_id)
+ {
+ case PROP_HAS_ACCELEROMETER:
+ g_value_set_boolean (value, cc_display_settings_get_has_accelerometer (self));
+ break;
+
+ case PROP_CONFIG:
+ g_value_set_object (value, self->config);
+ break;
+
+ case PROP_SELECTED_OUTPUT:
+ g_value_set_object (value, self->selected_output);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_display_settings_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcDisplaySettings *self = CC_DISPLAY_SETTINGS (object);
+
+ switch (prop_id)
+ {
+ case PROP_HAS_ACCELEROMETER:
+ cc_display_settings_set_has_accelerometer (self, g_value_get_boolean (value));
+ break;
+
+ case PROP_CONFIG:
+ cc_display_settings_set_config (self, g_value_get_object (value));
+ break;
+
+ case PROP_SELECTED_OUTPUT:
+ cc_display_settings_set_selected_output (self, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_display_settings_finalize (GObject *object)
+{
+ CcDisplaySettings *self = CC_DISPLAY_SETTINGS (object);
+
+ g_clear_object (&self->config);
+
+ g_clear_object (&self->orientation_list);
+ g_clear_object (&self->refresh_rate_list);
+ g_clear_object (&self->resolution_list);
+ g_clear_object (&self->scale_list);
+
+ if (self->idle_udpate_id)
+ g_source_remove (self->idle_udpate_id);
+ self->idle_udpate_id = 0;
+
+ G_OBJECT_CLASS (cc_display_settings_parent_class)->finalize (object);
+}
+
+static void
+cc_display_settings_class_init (CcDisplaySettingsClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gobject_class->finalize = cc_display_settings_finalize;
+ gobject_class->get_property = cc_display_settings_get_property;
+ gobject_class->set_property = cc_display_settings_set_property;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/display/cc-display-settings.ui");
+
+ props[PROP_HAS_ACCELEROMETER] =
+ g_param_spec_boolean ("has-accelerometer", "Has Accelerometer",
+ "If an accelerometre is available for the builtin display",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+ props[PROP_CONFIG] =
+ g_param_spec_object ("config", "Display Config",
+ "The display configuration to work with",
+ CC_TYPE_DISPLAY_CONFIG,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+ props[PROP_SELECTED_OUTPUT] =
+ g_param_spec_object ("selected-output", "Selected Output",
+ "The output that is currently selected on the configuration",
+ CC_TYPE_DISPLAY_MONITOR,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (gobject_class,
+ PROP_LAST,
+ props);
+
+ g_signal_new ("updated",
+ CC_TYPE_DISPLAY_SETTINGS,
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE, 1, CC_TYPE_DISPLAY_MONITOR);
+
+ gtk_widget_class_bind_template_child (widget_class, CcDisplaySettings, enabled_listbox);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplaySettings, enabled_row);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplaySettings, enabled_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplaySettings, orientation_row);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplaySettings, refresh_rate_row);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplaySettings, resolution_row);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplaySettings, scale_bbox);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplaySettings, scale_buttons_row);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplaySettings, scale_combo_row);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplaySettings, underscanning_row);
+ gtk_widget_class_bind_template_child (widget_class, CcDisplaySettings, underscanning_switch);
+
+ gtk_widget_class_bind_template_callback (widget_class, on_enabled_switch_active_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_orientation_selection_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_refresh_rate_selection_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_resolution_selection_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_scale_selection_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_underscanning_switch_active_changed_cb);
+}
+
+static void
+cc_display_settings_init (CcDisplaySettings *self)
+{
+ GtkExpression *expression;
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->orientation_list = G_LIST_MODEL (gtk_string_list_new (NULL));
+ self->refresh_rate_list = g_list_store_new (CC_TYPE_DISPLAY_MODE);
+ self->resolution_list = g_list_store_new (CC_TYPE_DISPLAY_MODE);
+ self->scale_list = G_LIST_MODEL (gtk_string_list_new (NULL));
+
+ self->updating = TRUE;
+
+ adw_combo_row_set_model (ADW_COMBO_ROW (self->orientation_row),
+ G_LIST_MODEL (self->orientation_list));
+ adw_combo_row_set_model (ADW_COMBO_ROW (self->scale_combo_row),
+ G_LIST_MODEL (self->scale_list));
+
+ expression = gtk_cclosure_expression_new (G_TYPE_STRING,
+ NULL, 0, NULL,
+ G_CALLBACK (make_refresh_rate_string),
+ self, NULL);
+ adw_combo_row_set_expression (ADW_COMBO_ROW (self->refresh_rate_row), expression);
+ adw_combo_row_set_model (ADW_COMBO_ROW (self->refresh_rate_row),
+ G_LIST_MODEL (self->refresh_rate_list));
+
+ expression = gtk_cclosure_expression_new (G_TYPE_STRING,
+ NULL, 0, NULL,
+ G_CALLBACK (make_resolution_string),
+ self, NULL);
+ adw_combo_row_set_expression (ADW_COMBO_ROW (self->resolution_row), expression);
+ adw_combo_row_set_model (ADW_COMBO_ROW (self->resolution_row),
+ G_LIST_MODEL (self->resolution_list));
+
+ self->updating = FALSE;
+}
+
+CcDisplaySettings*
+cc_display_settings_new (void)
+{
+ return g_object_new (CC_TYPE_DISPLAY_SETTINGS,
+ NULL);
+}
+
+gboolean
+cc_display_settings_get_has_accelerometer (CcDisplaySettings *settings)
+{
+ return settings->has_accelerometer;
+}
+
+void
+cc_display_settings_set_has_accelerometer (CcDisplaySettings *self,
+ gboolean has_accelerometer)
+{
+ self->has_accelerometer = has_accelerometer;
+
+ cc_display_settings_rebuild_ui (self);
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CONFIG]);
+}
+
+CcDisplayConfig*
+cc_display_settings_get_config (CcDisplaySettings *self)
+{
+ return self->config;
+}
+
+void
+cc_display_settings_set_config (CcDisplaySettings *self,
+ CcDisplayConfig *config)
+{
+ const gchar *signals[] = { "rotation", "mode", "scale", "is-usable", "active" };
+ GList *outputs, *l;
+ guint i;
+
+ if (self->config)
+ {
+ outputs = cc_display_config_get_monitors (self->config);
+ for (l = outputs; l; l = l->next)
+ {
+ CcDisplayMonitor *output = l->data;
+
+ g_signal_handlers_disconnect_by_data (output, self);
+ }
+ }
+ g_clear_object (&self->config);
+
+ self->config = g_object_ref (config);
+
+ /* Listen to all the signals */
+ if (self->config)
+ {
+ outputs = cc_display_config_get_monitors (self->config);
+ for (l = outputs; l; l = l->next)
+ {
+ CcDisplayMonitor *output = l->data;
+
+ for (i = 0; i < G_N_ELEMENTS (signals); ++i)
+ g_signal_connect_object (output, signals[i], G_CALLBACK (on_output_changed_cb), self, G_CONNECT_SWAPPED);
+ }
+ }
+
+ cc_display_settings_set_selected_output (self, NULL);
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CONFIG]);
+}
+
+CcDisplayMonitor*
+cc_display_settings_get_selected_output (CcDisplaySettings *self)
+{
+ return self->selected_output;
+}
+
+void
+cc_display_settings_set_selected_output (CcDisplaySettings *self,
+ CcDisplayMonitor *output)
+{
+ self->selected_output = output;
+
+ cc_display_settings_rebuild_ui (self);
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SELECTED_OUTPUT]);
+}
+
+void
+cc_display_settings_refresh_layout (CcDisplaySettings *self,
+ gboolean folded)
+{
+ gboolean use_combo;
+
+ self->folded = folded;
+ use_combo = self->num_scales > MAX_SCALE_BUTTONS || (self->num_scales > 2 && folded);
+
+ gtk_widget_set_visible (self->scale_combo_row, use_combo);
+ gtk_widget_set_visible (self->scale_buttons_row, self->num_scales > 1 && !use_combo);
+}
+
+void
+cc_display_settings_set_multimonitor (CcDisplaySettings *self,
+ gboolean multimonitor)
+{
+ gtk_widget_set_visible (self->enabled_listbox, multimonitor);
+
+ if (!multimonitor)
+ gtk_switch_set_active (GTK_SWITCH (self->enabled_switch), TRUE);
+}
diff --git a/panels/display/cc-display-settings.h b/panels/display/cc-display-settings.h
new file mode 100644
index 0000000..4794414
--- /dev/null
+++ b/panels/display/cc-display-settings.h
@@ -0,0 +1,48 @@
+/* -*- mode: c; style: linux -*-
+ *
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * Written by: Benjamin Berg <bberg@redhat.com>
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <adwaita.h>
+#include "cc-display-config.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_DISPLAY_SETTINGS cc_display_settings_get_type ()
+G_DECLARE_FINAL_TYPE (CcDisplaySettings, cc_display_settings, CC, DISPLAY_SETTINGS, GtkBox);
+
+CcDisplaySettings* cc_display_settings_new (void);
+
+gboolean cc_display_settings_get_has_accelerometer (CcDisplaySettings *settings);
+void cc_display_settings_set_has_accelerometer (CcDisplaySettings *settings,
+ gboolean has_accelerometer);
+CcDisplayConfig* cc_display_settings_get_config (CcDisplaySettings *settings);
+void cc_display_settings_set_config (CcDisplaySettings *settings,
+ CcDisplayConfig *config);
+CcDisplayMonitor* cc_display_settings_get_selected_output (CcDisplaySettings *settings);
+void cc_display_settings_set_selected_output (CcDisplaySettings *settings,
+ CcDisplayMonitor *output);
+void cc_display_settings_refresh_layout (CcDisplaySettings *settings,
+ gboolean folded);
+void cc_display_settings_set_multimonitor (CcDisplaySettings *self,
+ gboolean multimonitor);
+
+G_END_DECLS
+
diff --git a/panels/display/cc-display-settings.ui b/panels/display/cc-display-settings.ui
new file mode 100644
index 0000000..64c44d1
--- /dev/null
+++ b/panels/display/cc-display-settings.ui
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.0 -->
+<interface>
+ <template class="CcDisplaySettings" parent="GtkBox">
+ <property name="spacing">18</property>
+ <property name="orientation">vertical</property>
+
+ <child>
+ <object class="GtkListBox" id="enabled_listbox">
+ <property name="hexpand">True</property>
+ <property name="selection_mode">none</property>
+ <style>
+ <class name="boxed-list" />
+ </style>
+ <child>
+ <object class="AdwActionRow" id="enabled_row">
+ <property name="activatable-widget">enabled_switch</property>
+ <child>
+ <object class="GtkSwitch" id="enabled_switch">
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Enabled</property>
+ </accessibility>
+ <signal name="notify::active" handler="on_enabled_switch_active_changed_cb" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkListBox" id="listbox">
+ <property name="hexpand">True</property>
+ <property name="selection_mode">none</property>
+ <style>
+ <class name="boxed-list" />
+ </style>
+ <child>
+ <object class="AdwComboRow" id="orientation_row">
+ <property name="width_request">100</property>
+ <property name="title" translatable="yes" context="display setting">Orientation</property>
+ <signal name="notify::selected-item" handler="on_orientation_selection_changed_cb" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="AdwComboRow" id="resolution_row">
+ <property name="width_request">100</property>
+ <property name="title" translatable="yes" context="display setting">Resolution</property>
+ <signal name="notify::selected-item" handler="on_resolution_selection_changed_cb" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="AdwComboRow" id="refresh_rate_row">
+ <property name="width_request">100</property>
+ <property name="title" translatable="yes">Refresh Rate</property>
+ <signal name="notify::selected-item" handler="on_refresh_rate_selection_changed_cb" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="underscanning_row">
+ <property name="width_request">100</property>
+ <property name="title" translatable="yes">Adjust for TV</property>
+ <property name="activatable-widget">underscanning_switch</property>
+ <child>
+ <object class="GtkSwitch" id="underscanning_switch">
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <signal name="notify::active" handler="on_underscanning_switch_active_changed_cb" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="scale_buttons_row">
+ <property name="width_request">100</property>
+ <property name="title" translatable="yes" context="display setting">Scale</property>
+ <child>
+ <object class="GtkBox" id="scale_bbox">
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <style>
+ <class name="linked" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwComboRow" id="scale_combo_row">
+ <property name="width_request">100</property>
+ <property name="title" translatable="yes" context="display setting">Scale</property>
+ <signal name="notify::selected-item" handler="on_scale_selection_changed_cb" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/display/cc-night-light-page.c b/panels/display/cc-night-light-page.c
new file mode 100644
index 0000000..4b7b112
--- /dev/null
+++ b/panels/display/cc-night-light-page.c
@@ -0,0 +1,746 @@
+/*
+ * Copyright (C) 2017 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <gdesktop-enums.h>
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <math.h>
+
+#include "cc-night-light-page.h"
+
+#include "shell/cc-object-storage.h"
+#include "cc-display-config-manager-dbus.h"
+
+struct _CcNightLightPage {
+ AdwBin parent;
+
+ GtkWidget *night_light_settings;
+ GtkWidget *box_manual;
+ GtkButton *button_from_am;
+ GtkButton *button_from_pm;
+ GtkButton *button_to_am;
+ GtkButton *button_to_pm;
+ GtkWidget *infobar_unsupported;
+ GtkWidget *infobar_disabled;
+ GtkListBox *listbox;
+ GtkWidget *scale_color_temperature;
+ GtkWidget *night_light_toggle_switch;
+ GtkComboBox *schedule_type_combo;
+ GtkWidget *from_spinbuttons_box;
+ GtkWidget *spinbutton_from_hours;
+ GtkWidget *spinbutton_from_minutes;
+ GtkWidget *to_spinbuttons_box;
+ GtkWidget *spinbutton_to_hours;
+ GtkWidget *spinbutton_to_minutes;
+ GtkStack *stack_from;
+ GtkStack *stack_to;
+
+ GtkAdjustment *adjustment_from_hours;
+ GtkAdjustment *adjustment_from_minutes;
+ GtkAdjustment *adjustment_to_hours;
+ GtkAdjustment *adjustment_to_minutes;
+ GtkAdjustment *adjustment_color_temperature;
+
+ GSettings *settings_display;
+ GSettings *settings_clock;
+ GDBusProxy *proxy_color;
+ GDBusProxy *proxy_color_props;
+ GCancellable *cancellable;
+ gboolean ignore_value_changed;
+ guint timer_id;
+ GDesktopClockFormat clock_format;
+
+ CcDisplayConfigManager *config_manager;
+};
+
+G_DEFINE_TYPE (CcNightLightPage, cc_night_light_page, ADW_TYPE_BIN);
+
+#define CLOCK_SCHEMA "org.gnome.desktop.interface"
+#define DISPLAY_SCHEMA "org.gnome.settings-daemon.plugins.color"
+#define CLOCK_FORMAT_KEY "clock-format"
+#define NIGHT_LIGHT_PREVIEW_TIMEOUT_SECONDS 5
+
+static void
+dialog_adjustments_set_frac_hours (CcNightLightPage *self,
+ gdouble value,
+ GtkAdjustment *adj_hours,
+ GtkAdjustment *adj_mins,
+ GtkStack *stack,
+ GtkButton *button_am,
+ GtkButton *button_pm)
+{
+ gdouble hours;
+ gdouble mins = 0.f;
+ gboolean is_pm = FALSE;
+ gboolean is_24h;
+
+ /* display the right thing for AM/PM */
+ is_24h = self->clock_format == G_DESKTOP_CLOCK_FORMAT_24H;
+ mins = modf (value, &hours) * 60.f;
+ if (!is_24h)
+ {
+ if (hours > 12)
+ {
+ hours -= 12;
+ is_pm = TRUE;
+ }
+ else if (hours < 1.0)
+ {
+ hours += 12;
+ is_pm = FALSE;
+ }
+ else if (hours == 12.f)
+ {
+ is_pm = TRUE;
+ }
+ }
+
+ g_debug ("setting adjustment %.3f to %.0f:%02.0f", value, hours, mins);
+
+ self->ignore_value_changed = TRUE;
+ gtk_adjustment_set_value (GTK_ADJUSTMENT (adj_hours), hours);
+ gtk_adjustment_set_value (GTK_ADJUSTMENT (adj_mins), mins);
+ self->ignore_value_changed = FALSE;
+
+ gtk_widget_set_visible (GTK_WIDGET (stack), !is_24h);
+ gtk_stack_set_visible_child (stack, is_pm ? GTK_WIDGET (button_pm) : GTK_WIDGET (button_am));
+}
+
+static void
+dialog_update_state (CcNightLightPage *self)
+{
+ if (cc_display_config_manager_get_night_light_supported (self->config_manager))
+ {
+ gboolean automatic;
+ gboolean disabled_until_tomorrow = FALSE;
+ gboolean enabled;
+ gdouble value = 0.f;
+
+ /* only show the infobar if we are disabled */
+ if (self->proxy_color != NULL)
+ {
+ g_autoptr(GVariant) disabled = NULL;
+ disabled = g_dbus_proxy_get_cached_property (self->proxy_color,
+ "DisabledUntilTomorrow");
+ if (disabled != NULL)
+ disabled_until_tomorrow = g_variant_get_boolean (disabled);
+ }
+ gtk_widget_set_visible (self->infobar_disabled, disabled_until_tomorrow);
+
+ /* make things insensitive if the switch is disabled */
+ enabled = g_settings_get_boolean (self->settings_display, "night-light-enabled");
+ automatic = g_settings_get_boolean (self->settings_display, "night-light-schedule-automatic");
+
+ gtk_widget_set_sensitive (self->box_manual, enabled && !automatic);
+
+ gtk_combo_box_set_active_id (self->schedule_type_combo, automatic ? "automatic" : "manual");
+
+ /* set from */
+ if (automatic && self->proxy_color != NULL)
+ {
+ g_autoptr(GVariant) sunset = NULL;
+ sunset = g_dbus_proxy_get_cached_property (self->proxy_color, "Sunset");
+ if (sunset != NULL)
+ {
+ value = g_variant_get_double (sunset);
+ }
+ else
+ {
+ value = 16.0f;
+ g_warning ("no sunset data, using %02.2f", value);
+ }
+ }
+ else
+ {
+ value = g_settings_get_double (self->settings_display, "night-light-schedule-from");
+ value = fmod (value, 24.f);
+ }
+ dialog_adjustments_set_frac_hours (self, value,
+ self->adjustment_from_hours,
+ self->adjustment_from_minutes,
+ self->stack_from,
+ self->button_from_am,
+ self->button_from_pm);
+
+ /* set to */
+ if (automatic && self->proxy_color != NULL)
+ {
+ g_autoptr(GVariant) sunset = NULL;
+ sunset = g_dbus_proxy_get_cached_property (self->proxy_color, "Sunrise");
+ if (sunset != NULL)
+ {
+ value = g_variant_get_double (sunset);
+ }
+ else
+ {
+ value = 8.0f;
+ g_warning ("no sunrise data, using %02.2f", value);
+ }
+ }
+ else
+ {
+ value = g_settings_get_double (self->settings_display, "night-light-schedule-to");
+ value = fmod (value, 24.f);
+ }
+ dialog_adjustments_set_frac_hours (self, value,
+ self->adjustment_to_hours,
+ self->adjustment_to_minutes,
+ self->stack_to,
+ self->button_to_am,
+ self->button_to_pm);
+
+ self->ignore_value_changed = TRUE;
+ value = (gdouble) g_settings_get_uint (self->settings_display, "night-light-temperature");
+ gtk_adjustment_set_value (self->adjustment_color_temperature, value);
+ self->ignore_value_changed = FALSE;
+ }
+ else
+ {
+ gtk_widget_set_visible (self->infobar_unsupported, TRUE);
+ gtk_widget_set_visible (self->infobar_disabled, FALSE);
+ gtk_widget_set_sensitive (self->night_light_settings, FALSE);
+ }
+}
+
+static void
+build_schedule_combo_row (CcNightLightPage *self)
+{
+ gboolean automatic;
+ gboolean enabled;
+
+ self->ignore_value_changed = TRUE;
+
+
+ enabled = g_settings_get_boolean (self->settings_display, "night-light-enabled");
+ automatic = g_settings_get_boolean (self->settings_display, "night-light-schedule-automatic");
+
+ gtk_widget_set_sensitive (self->box_manual, enabled && !automatic);
+
+ gtk_combo_box_set_active_id (self->schedule_type_combo, automatic ? "automatic" : "manual");
+
+ self->ignore_value_changed = FALSE;
+}
+
+static void
+on_schedule_type_combo_active_changed_cb (GtkComboBox *combo_box,
+ GParamSpec *pspec,
+ CcNightLightPage *self)
+{
+ const gchar *active_id;
+ gboolean automatic;
+
+ if (self->ignore_value_changed)
+ return;
+
+ active_id = gtk_combo_box_get_active_id (combo_box);
+ automatic = g_str_equal (active_id, "automatic");
+
+ g_settings_set_boolean (self->settings_display, "night-light-schedule-automatic", automatic);
+}
+
+static gboolean
+dialog_tick_cb (gpointer user_data)
+{
+ CcNightLightPage *self = (CcNightLightPage *) user_data;
+ dialog_update_state (self);
+ return G_SOURCE_CONTINUE;
+}
+
+static void
+dialog_enabled_notify_cb (GtkSwitch *sw,
+ GParamSpec *pspec,
+ CcNightLightPage *self)
+{
+ g_settings_set_boolean (self->settings_display, "night-light-enabled",
+ gtk_switch_get_active (sw));
+}
+
+static void
+dialog_undisable_call_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GVariant) val = NULL;
+ g_autoptr(GError) error = NULL;
+
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
+ res, &error);
+ if (val == NULL)
+ {
+ g_warning ("failed to undisable: %s", error->message);
+ return;
+ }
+}
+
+static void
+dialog_undisable_clicked_cb (GtkButton *button,
+ CcNightLightPage *self)
+{
+ g_dbus_proxy_call (self->proxy_color_props,
+ "Set",
+ g_variant_new ("(ssv)",
+ "org.gnome.SettingsDaemon.Color",
+ "DisabledUntilTomorrow",
+ g_variant_new_boolean (FALSE)),
+ G_DBUS_CALL_FLAGS_NONE,
+ 5000,
+ self->cancellable,
+ dialog_undisable_call_cb,
+ self);
+}
+
+static gdouble
+dialog_adjustments_get_frac_hours (CcNightLightPage *self,
+ GtkAdjustment *adj_hours,
+ GtkAdjustment *adj_mins,
+ GtkStack *stack)
+{
+ gdouble value;
+
+ value = gtk_adjustment_get_value (adj_hours);
+ value += gtk_adjustment_get_value (adj_mins) / 60.0f;
+
+ if (g_strcmp0 (gtk_stack_get_visible_child_name (stack), "pm") == 0)
+ value += 12.f;
+
+ return value;
+}
+
+static void
+dialog_time_from_value_changed_cb (GtkAdjustment *adjustment,
+ CcNightLightPage *self)
+{
+ gdouble value;
+
+ if (self->ignore_value_changed)
+ return;
+
+ value = dialog_adjustments_get_frac_hours (self,
+ self->adjustment_from_hours,
+ self->adjustment_from_minutes,
+ self->stack_from);
+
+ if (value >= 24.f)
+ value = fmod (value, 24);
+
+ g_debug ("new value = %.3f", value);
+
+ g_settings_set_double (self->settings_display, "night-light-schedule-from", value);
+}
+
+static void
+dialog_time_to_value_changed_cb (GtkAdjustment *adjustment,
+ CcNightLightPage *self)
+{
+ gdouble value;
+
+ if (self->ignore_value_changed)
+ return;
+
+ value = dialog_adjustments_get_frac_hours (self,
+ self->adjustment_to_hours,
+ self->adjustment_to_minutes,
+ self->stack_to);
+ if (value >= 24.f)
+ value = fmod (value, 24);
+
+ g_debug ("new value = %.3f", value);
+
+ g_settings_set_double (self->settings_display, "night-light-schedule-to", value);
+}
+
+static void
+dialog_color_temperature_value_changed_cb (GtkAdjustment *adjustment,
+ CcNightLightPage *self)
+{
+ gdouble value;
+
+ if (self->ignore_value_changed)
+ return;
+
+ value = gtk_adjustment_get_value (adjustment);
+
+ g_debug ("new value = %.0f", value);
+
+ if (self->proxy_color != NULL)
+ g_dbus_proxy_call (self->proxy_color,
+ "NightLightPreview",
+ g_variant_new ("(u)", NIGHT_LIGHT_PREVIEW_TIMEOUT_SECONDS),
+ G_DBUS_CALL_FLAGS_NONE,
+ 5000,
+ NULL,
+ NULL,
+ NULL);
+
+ g_settings_set_uint (self->settings_display, "night-light-temperature", (guint) value);
+}
+
+static void
+dialog_color_properties_changed_cb (CcNightLightPage *self)
+{
+ dialog_update_state (self);
+}
+
+static void
+dialog_got_proxy_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcNightLightPage *self = (CcNightLightPage *) user_data;
+ GDBusProxy *proxy;
+ g_autoptr(GError) error = NULL;
+
+ proxy = cc_object_storage_create_dbus_proxy_finish (res, &error);
+ if (proxy == NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("failed to connect to g-s-d: %s", error->message);
+ return;
+ }
+
+ self->proxy_color = proxy;
+
+ g_signal_connect_object (self->proxy_color, "g-properties-changed",
+ G_CALLBACK (dialog_color_properties_changed_cb), self, G_CONNECT_SWAPPED);
+ dialog_update_state (self);
+ self->timer_id = g_timeout_add_seconds (10, dialog_tick_cb, self);
+}
+
+static void
+dialog_got_proxy_props_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcNightLightPage *self = (CcNightLightPage *) user_data;
+ GDBusProxy *proxy;
+ g_autoptr(GError) error = NULL;
+
+ proxy = cc_object_storage_create_dbus_proxy_finish (res, &error);
+ if (proxy == NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("failed to connect to g-s-d: %s", error->message);
+ return;
+ }
+
+ self->proxy_color_props = proxy;
+}
+
+static gboolean
+dialog_format_minutes_combobox (GtkSpinButton *spin,
+ CcNightLightPage *self)
+{
+ GtkAdjustment *adjustment;
+ g_autofree gchar *text = NULL;
+ adjustment = gtk_spin_button_get_adjustment (spin);
+ text = g_strdup_printf ("%02.0f", gtk_adjustment_get_value (adjustment));
+ gtk_editable_set_text (GTK_EDITABLE (spin), text);
+ return TRUE;
+}
+
+static gboolean
+dialog_format_hours_combobox (GtkSpinButton *spin,
+ CcNightLightPage *self)
+{
+ GtkAdjustment *adjustment;
+ g_autofree gchar *text = NULL;
+ adjustment = gtk_spin_button_get_adjustment (spin);
+ if (self->clock_format == G_DESKTOP_CLOCK_FORMAT_12H)
+ text = g_strdup_printf ("%.0f", gtk_adjustment_get_value (adjustment));
+ else
+ text = g_strdup_printf ("%02.0f", gtk_adjustment_get_value (adjustment));
+ gtk_editable_set_text (GTK_EDITABLE (spin), text);
+ return TRUE;
+}
+
+static void
+dialog_update_adjustments (CcNightLightPage *self)
+{
+ /* from */
+ if (self->clock_format == G_DESKTOP_CLOCK_FORMAT_24H)
+ {
+ gtk_adjustment_set_lower (self->adjustment_from_hours, 0);
+ gtk_adjustment_set_upper (self->adjustment_from_hours, 23);
+ }
+ else
+ {
+ if (gtk_adjustment_get_value (self->adjustment_from_hours) > 12)
+ gtk_stack_set_visible_child (self->stack_from, GTK_WIDGET (self->button_from_pm));
+
+ gtk_adjustment_set_lower (self->adjustment_from_hours, 1);
+ gtk_adjustment_set_upper (self->adjustment_from_hours, 12);
+ }
+
+ /* to */
+ if (self->clock_format == G_DESKTOP_CLOCK_FORMAT_24H)
+ {
+ gtk_adjustment_set_lower (self->adjustment_to_hours, 0);
+ gtk_adjustment_set_upper (self->adjustment_to_hours, 23);
+ }
+ else
+ {
+ if (gtk_adjustment_get_value (self->adjustment_to_hours) > 12)
+ gtk_stack_set_visible_child (self->stack_to, GTK_WIDGET (self->button_to_pm));
+
+ gtk_adjustment_set_lower (self->adjustment_to_hours, 1);
+ gtk_adjustment_set_upper (self->adjustment_to_hours, 12);
+ }
+}
+
+static void
+dialog_settings_changed_cb (CcNightLightPage *self)
+{
+ dialog_update_state (self);
+}
+
+static void
+dialog_clock_settings_changed_cb (CcNightLightPage *self)
+{
+ self->clock_format = g_settings_get_enum (self->settings_clock, CLOCK_FORMAT_KEY);
+
+ /* uncontionally widen this to avoid truncation */
+ gtk_adjustment_set_lower (self->adjustment_from_hours, 0);
+ gtk_adjustment_set_upper (self->adjustment_from_hours, 23);
+ gtk_adjustment_set_lower (self->adjustment_to_hours, 0);
+ gtk_adjustment_set_upper (self->adjustment_to_hours, 23);
+
+ /* update spinbuttons */
+ gtk_spin_button_update (GTK_SPIN_BUTTON (self->spinbutton_from_hours));
+ gtk_spin_button_update (GTK_SPIN_BUTTON (self->spinbutton_to_hours));
+
+ /* update UI */
+ dialog_update_state (self);
+ dialog_update_adjustments (self);
+}
+
+static void
+dialog_am_pm_from_button_clicked_cb (GtkButton *button,
+ CcNightLightPage *self)
+{
+ gdouble value;
+ value = g_settings_get_double (self->settings_display, "night-light-schedule-from");
+ if (value > 12.f)
+ value -= 12.f;
+ else
+ value += 12.f;
+ if (value >= 24.f)
+ value = fmod (value, 24);
+ g_settings_set_double (self->settings_display, "night-light-schedule-from", value);
+ g_debug ("new value = %.3f", value);
+}
+
+static void
+dialog_am_pm_to_button_clicked_cb (GtkButton *button,
+ CcNightLightPage *self)
+{
+ gdouble value;
+ value = g_settings_get_double (self->settings_display, "night-light-schedule-to");
+ if (value > 12.f)
+ value -= 12.f;
+ else
+ value += 12.f;
+ if (value >= 24.f)
+ value = fmod (value, 24);
+ g_settings_set_double (self->settings_display, "night-light-schedule-to", value);
+ g_debug ("new value = %.3f", value);
+}
+
+static void
+config_manager_changed_cb (CcDisplayConfigManager *config_manager,
+ CcNightLightPage *self)
+{
+ dialog_update_state (self);
+}
+
+/* GObject overrides */
+static void
+cc_night_light_page_finalize (GObject *object)
+{
+ CcNightLightPage *self = CC_NIGHT_LIGHT_PAGE (object);
+
+ g_cancellable_cancel (self->cancellable);
+
+ g_clear_object (&self->cancellable);
+ g_clear_object (&self->proxy_color);
+ g_clear_object (&self->proxy_color_props);
+ g_clear_object (&self->settings_display);
+ g_clear_object (&self->settings_clock);
+ if (self->timer_id > 0)
+ g_source_remove (self->timer_id);
+
+ G_OBJECT_CLASS (cc_night_light_page_parent_class)->finalize (object);
+}
+
+static void
+cc_night_light_page_class_init (CcNightLightPageClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = cc_night_light_page_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/display/cc-night-light-page.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcNightLightPage, adjustment_from_hours);
+ gtk_widget_class_bind_template_child (widget_class, CcNightLightPage, adjustment_from_minutes);
+ gtk_widget_class_bind_template_child (widget_class, CcNightLightPage, adjustment_to_hours);
+ gtk_widget_class_bind_template_child (widget_class, CcNightLightPage, adjustment_to_minutes);
+ gtk_widget_class_bind_template_child (widget_class, CcNightLightPage, adjustment_color_temperature);
+ gtk_widget_class_bind_template_child (widget_class, CcNightLightPage, night_light_settings);
+ gtk_widget_class_bind_template_child (widget_class, CcNightLightPage, box_manual);
+ gtk_widget_class_bind_template_child (widget_class, CcNightLightPage, button_from_am);
+ gtk_widget_class_bind_template_child (widget_class, CcNightLightPage, button_from_pm);
+ gtk_widget_class_bind_template_child (widget_class, CcNightLightPage, button_to_am);
+ gtk_widget_class_bind_template_child (widget_class, CcNightLightPage, button_to_pm);
+ gtk_widget_class_bind_template_child (widget_class, CcNightLightPage, infobar_unsupported);
+ gtk_widget_class_bind_template_child (widget_class, CcNightLightPage, infobar_disabled);
+ gtk_widget_class_bind_template_child (widget_class, CcNightLightPage, listbox);
+ gtk_widget_class_bind_template_child (widget_class, CcNightLightPage, night_light_toggle_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcNightLightPage, schedule_type_combo);
+ gtk_widget_class_bind_template_child (widget_class, CcNightLightPage, scale_color_temperature);
+ gtk_widget_class_bind_template_child (widget_class, CcNightLightPage, from_spinbuttons_box);
+ gtk_widget_class_bind_template_child (widget_class, CcNightLightPage, spinbutton_from_hours);
+ gtk_widget_class_bind_template_child (widget_class, CcNightLightPage, spinbutton_from_minutes);
+ gtk_widget_class_bind_template_child (widget_class, CcNightLightPage, to_spinbuttons_box);
+ gtk_widget_class_bind_template_child (widget_class, CcNightLightPage, spinbutton_to_hours);
+ gtk_widget_class_bind_template_child (widget_class, CcNightLightPage, spinbutton_to_minutes);
+ gtk_widget_class_bind_template_child (widget_class, CcNightLightPage, stack_from);
+ gtk_widget_class_bind_template_child (widget_class, CcNightLightPage, stack_to);
+
+ gtk_widget_class_bind_template_callback (widget_class, dialog_am_pm_from_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, dialog_am_pm_to_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, dialog_enabled_notify_cb);
+ gtk_widget_class_bind_template_callback (widget_class, dialog_format_hours_combobox);
+ gtk_widget_class_bind_template_callback (widget_class, dialog_format_minutes_combobox);
+ gtk_widget_class_bind_template_callback (widget_class, dialog_time_from_value_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, dialog_time_to_value_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, dialog_color_temperature_value_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, dialog_undisable_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_schedule_type_combo_active_changed_cb);
+
+}
+
+static void
+cc_night_light_page_init (CcNightLightPage *self)
+{
+ g_autoptr(GtkCssProvider) provider = NULL;
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ gtk_scale_add_mark (GTK_SCALE (self->scale_color_temperature),
+ 1700, GTK_POS_BOTTOM,
+ NULL);
+
+ gtk_scale_add_mark (GTK_SCALE (self->scale_color_temperature),
+ 2700, GTK_POS_BOTTOM,
+ NULL);
+
+ gtk_scale_add_mark (GTK_SCALE (self->scale_color_temperature),
+ 3700, GTK_POS_BOTTOM,
+ NULL);
+
+ gtk_scale_add_mark (GTK_SCALE (self->scale_color_temperature),
+ 4700, GTK_POS_BOTTOM,
+ NULL);
+
+ self->cancellable = g_cancellable_new ();
+ self->settings_display = g_settings_new (DISPLAY_SCHEMA);
+
+ g_signal_connect_object (self->settings_display, "changed", G_CALLBACK (dialog_settings_changed_cb), self, G_CONNECT_SWAPPED);
+
+ build_schedule_combo_row (self);
+
+ g_settings_bind (self->settings_display, "night-light-enabled",
+ self->night_light_toggle_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind_writable (self->settings_display, "night-light-enabled",
+ self->night_light_toggle_switch, "sensitive",
+ FALSE);
+
+ g_settings_bind_writable (self->settings_display, "night-light-schedule-from",
+ self->spinbutton_from_hours, "sensitive",
+ FALSE);
+ g_settings_bind_writable (self->settings_display, "night-light-schedule-from",
+ self->spinbutton_from_minutes, "sensitive",
+ FALSE);
+ g_settings_bind_writable (self->settings_display, "night-light-schedule-to",
+ self->spinbutton_to_minutes, "sensitive",
+ FALSE);
+ g_settings_bind_writable (self->settings_display, "night-light-schedule-to",
+ self->spinbutton_to_minutes, "sensitive",
+ FALSE);
+
+ /* use custom CSS */
+ provider = gtk_css_provider_new ();
+ gtk_css_provider_load_from_resource (provider, "/org/gnome/control-center/display/night-light.css");
+ gtk_style_context_add_provider_for_display (gdk_display_get_default (),
+ GTK_STYLE_PROVIDER (provider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+ cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "org.gnome.SettingsDaemon.Color",
+ "/org/gnome/SettingsDaemon/Color",
+ "org.gnome.SettingsDaemon.Color",
+ self->cancellable,
+ dialog_got_proxy_cb,
+ self);
+
+ cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "org.gnome.SettingsDaemon.Color",
+ "/org/gnome/SettingsDaemon/Color",
+ "org.freedesktop.DBus.Properties",
+ self->cancellable,
+ dialog_got_proxy_props_cb,
+ self);
+
+ /* clock settings_display */
+ self->settings_clock = g_settings_new (CLOCK_SCHEMA);
+ self->clock_format = g_settings_get_enum (self->settings_clock, CLOCK_FORMAT_KEY);
+ dialog_update_adjustments (self);
+ g_signal_connect_object (self->settings_clock,
+ "changed::" CLOCK_FORMAT_KEY,
+ G_CALLBACK (dialog_clock_settings_changed_cb),
+ self, G_CONNECT_SWAPPED);
+
+ if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL)
+ {
+ gtk_widget_set_direction (self->to_spinbuttons_box, GTK_TEXT_DIR_LTR);
+ gtk_widget_set_direction (self->from_spinbuttons_box, GTK_TEXT_DIR_LTR);
+ }
+
+ self->config_manager = cc_display_config_manager_dbus_new ();
+ g_signal_connect (self->config_manager, "changed",
+ G_CALLBACK (config_manager_changed_cb), self);
+
+ dialog_update_state (self);
+}
+
+CcNightLightPage *
+cc_night_light_page_new (void)
+{
+ return g_object_new (CC_TYPE_NIGHT_LIGHT_PAGE,
+ NULL);
+}
+
diff --git a/panels/display/cc-night-light-page.h b/panels/display/cc-night-light-page.h
new file mode 100644
index 0000000..7e7be4b
--- /dev/null
+++ b/panels/display/cc-night-light-page.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2017 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <adwaita.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_NIGHT_LIGHT_PAGE (cc_night_light_page_get_type ())
+G_DECLARE_FINAL_TYPE (CcNightLightPage, cc_night_light_page, CC, NIGHT_LIGHT_PAGE, AdwBin)
+
+CcNightLightPage* cc_night_light_page_new (void);
+
+G_END_DECLS
diff --git a/panels/display/cc-night-light-page.ui b/panels/display/cc-night-light-page.ui
new file mode 100644
index 0000000..6e5b12b
--- /dev/null
+++ b/panels/display/cc-night-light-page.ui
@@ -0,0 +1,438 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcNightLightPage" parent="AdwBin">
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkInfoBar" id="infobar_unsupported">
+ <property name="visible">False</property>
+ <property name="name">infobar_unsupported</property>
+ <property name="message-type">warning</property>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">16</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="halign">start</property>
+ <property name="margin-start">6</property>
+ <property name="hexpand">False</property>
+ <property name="label" translatable="yes">Night Light unavailable</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="margin-start">6</property>
+ <property name="label" translatable="yes">This could be the result of the graphics driver being used, or the desktop being used remotely</property>
+ <property name="wrap">True</property>
+ <property name="xalign">0.0</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="night_light_settings">
+ <property name="halign">center</property>
+ <property name="valign">start</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkInfoBar" id="infobar_disabled">
+ <property name="name">infobar_disabled</property>
+ <child>
+ <object class="GtkBox">
+ <property name="hexpand">True</property>
+ <property name="spacing">16</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="halign">start</property>
+ <property name="margin-start">12</property>
+ <property name="hexpand">False</property>
+ <property name="wrap">True</property>
+ <property name="label" translatable="yes" comments="Inhibit the redshift functionality until the next day starts">Temporarily Disabled Until Tomorrow</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="button_undisable">
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="label" translatable="yes" comments="This cancels the redshift inhibit.">Restart Filter</property>
+ <property name="name">button_undisable</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="valign">GTK_ALIGN_CENTER</property>
+ <signal name="clicked" handler="dialog_undisable_clicked_cb" object="CcNightLightPage" swapped="no" />
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkBox">
+ <property name="margin_top">30</property>
+ <property name="margin_end">12</property>
+ <property name="margin_start">12</property>
+ <property name="margin_bottom">36</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">26</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="halign">start</property>
+ <property name="valign">start</property>
+ <property name="label" translatable="yes">Night light makes the screen color warmer. This can help to prevent eye strain and sleeplessness.</property>
+ <property name="wrap">True</property>
+ <property name="max_width_chars">60</property>
+ <property name="xalign">0</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkListBox" id="listbox">
+ <property name="selection-mode">none</property>
+
+ <style>
+ <class name="boxed-list" />
+ </style>
+
+ <!-- Night Light -->
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Night Light</property>
+ <property name="activatable-widget">night_light_toggle_switch</property>
+
+ <child>
+ <object class="GtkSwitch" id="night_light_toggle_switch">
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Enable</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- Schedule -->
+ <child>
+ <object class="AdwActionRow" id="schedule_row">
+ <property name="title" translatable="yes">Schedule</property>
+ <property name="sensitive" bind-source="night_light_toggle_switch" bind-property="active" bind-flags="default|sync-create" />
+
+ <child>
+ <object class="GtkComboBoxText" id="schedule_type_combo">
+ <property name="valign">center</property>
+ <signal name="notify::active" handler="on_schedule_type_combo_active_changed_cb" object="CcNightLightPage" swapped="no" />
+ <items>
+ <item translatable="yes" id="automatic">Sunset to Sunrise</item>
+ <item translatable="yes" id="manual">Manual Schedule</item>
+ </items>
+ <accessibility>
+ <relation name="labelled-by">schedule_row</relation>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- Time -->
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Times</property>
+ <property name="sensitive" bind-source="night_light_toggle_switch" bind-property="active" bind-flags="default|sync-create" />
+
+ <child>
+ <object class="GtkBox" id="box_manual">
+ <property name="spacing">6</property>
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <style>
+ <class name="time-widget" />
+ </style>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">From</property>
+ <property name="mnemonic_widget">spinbutton_from_hours</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="from_spinbuttons_box">
+ <property name="spacing">4</property>
+ <child>
+ <object class="GtkSpinButton" id="spinbutton_from_hours">
+ <property name="can_focus">True</property>
+ <property name="max_width_chars">2</property>
+ <property name="text">4</property>
+ <property name="orientation">vertical</property>
+ <property name="adjustment">adjustment_from_hours</property>
+ <property name="numeric">True</property>
+ <property name="wrap">True</property>
+ <property name="value">4</property>
+ <signal name="output" handler="dialog_format_hours_combobox" object="CcNightLightPage" swapped="no" />
+ <style>
+ <class name="padded-spinbutton"/>
+ </style>
+ <accessibility>
+ <property name="description" translatable="yes">Hour</property>
+ </accessibility>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">:</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="spinbutton_from_minutes">
+ <property name="can_focus">True</property>
+ <property name="max_width_chars">2</property>
+ <property name="text">0</property>
+ <property name="orientation">vertical</property>
+ <property name="adjustment">adjustment_from_minutes</property>
+ <property name="numeric">True</property>
+ <property name="wrap">True</property>
+ <signal name="output" handler="dialog_format_minutes_combobox" object="CcNightLightPage" swapped="no" />
+ <style>
+ <class name="padded-spinbutton"/>
+ </style>
+ <accessibility>
+ <property name="description" translatable="yes">Minute</property>
+ </accessibility>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStack" id="stack_from">
+ <property name="hhomogeneous">False</property>
+ <property name="vhomogeneous">False</property>
+ <child>
+ <object class="GtkButton" id="button_from_am">
+ <property name="label" translatable="yes" comments="This is the short form for the time period in the morning">AM</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="valign">center</property>
+ <signal name="clicked" handler="dialog_am_pm_from_button_clicked_cb" object="CcNightLightPage" swapped="no" />
+ <style>
+ <class name="unpadded-button"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="button_from_pm">
+ <property name="label" translatable="yes" comments="This is the short form for the time period in the afternoon">PM</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="valign">center</property>
+ <signal name="clicked" handler="dialog_am_pm_from_button_clicked_cb" object="CcNightLightPage" swapped="no" />
+ <style>
+ <class name="unpadded-button"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="margin-start">6</property>
+ <property name="label" translatable="yes">To</property>
+ <property name="mnemonic_widget">spinbutton_to_hours</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="to_spinbuttons_box">
+ <property name="spacing">4</property>
+ <child>
+ <object class="GtkSpinButton" id="spinbutton_to_hours">
+ <property name="can_focus">True</property>
+ <property name="max_width_chars">2</property>
+ <property name="text">4</property>
+ <property name="orientation">vertical</property>
+ <property name="adjustment">adjustment_to_hours</property>
+ <property name="numeric">True</property>
+ <property name="wrap">True</property>
+ <property name="value">4</property>
+ <signal name="output" handler="dialog_format_hours_combobox" object="CcNightLightPage" swapped="no" />
+ <style>
+ <class name="padded-spinbutton"/>
+ </style>
+ <accessibility>
+ <property name="description" translatable="yes">Hour</property>
+ </accessibility>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">:</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="spinbutton_to_minutes">
+ <property name="can_focus">True</property>
+ <property name="max_width_chars">2</property>
+ <property name="text">0</property>
+ <property name="orientation">vertical</property>
+ <property name="adjustment">adjustment_to_minutes</property>
+ <property name="numeric">True</property>
+ <property name="wrap">True</property>
+ <signal name="output" handler="dialog_format_minutes_combobox" object="CcNightLightPage" swapped="no" />
+ <style>
+ <class name="padded-spinbutton"/>
+ </style>
+ <accessibility>
+ <property name="description" translatable="yes">Minute</property>
+ </accessibility>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStack" id="stack_to">
+ <property name="hhomogeneous">False</property>
+ <property name="vhomogeneous">False</property>
+ <child>
+ <object class="GtkButton" id="button_to_am">
+ <property name="label" translatable="yes">AM</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="valign">center</property>
+ <signal name="clicked" handler="dialog_am_pm_to_button_clicked_cb" object="CcNightLightPage" swapped="no" />
+ <style>
+ <class name="unpadded-button"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="button_to_pm">
+ <property name="label" translatable="yes">PM</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="valign">center</property>
+ <signal name="clicked" handler="dialog_am_pm_to_button_clicked_cb" object="CcNightLightPage" swapped="no" />
+ <style>
+ <class name="unpadded-button"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- Color Temperature -->
+ <child>
+ <object class="AdwPreferencesRow">
+ <property name="activatable">False</property>
+ <property name="sensitive" bind-source="night_light_toggle_switch" bind-property="active" bind-flags="default|sync-create" />
+
+ <child>
+ <object class="GtkBox">
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="spacing">6</property>
+ <property name="orientation">vertical</property>
+
+ <child>
+ <object class="GtkLabel" id="title">
+ <property name="label" translatable="yes">Color Temperature</property>
+ <property name="ellipsize">none</property>
+ <property name="lines">0</property>
+ <property name="xalign">0.0</property>
+ <property name="mnemonic_widget">scale_color_temperature</property>
+ <style>
+ <class name="title"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkScale" id="scale_color_temperature">
+ <property name="hexpand">True</property>
+ <property name="width-request">280</property>
+ <property name="adjustment">adjustment_color_temperature</property>
+ <property name="inverted">True</property>
+ <property name="restrict_to_fill_level">False</property>
+ <property name="fill_level">1</property>
+ <property name="digits">0</property>
+ <property name="draw_value">False</property>
+ <property name="has_origin">False</property>
+ <property name="value_pos">bottom</property>
+ <style>
+ <class name="night-light-temperature"/>
+ </style>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+
+ <object class="GtkAdjustment" id="adjustment_from_hours">
+ <property name="upper">23</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ <signal name="value-changed" handler="dialog_time_from_value_changed_cb" object="CcNightLightPage" swapped="no" />
+ </object>
+ <object class="GtkAdjustment" id="adjustment_from_minutes">
+ <property name="upper">59</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ <signal name="value-changed" handler="dialog_time_from_value_changed_cb" object="CcNightLightPage" swapped="no" />
+ </object>
+ <object class="GtkAdjustment" id="adjustment_to_hours">
+ <property name="upper">23</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ <signal name="value-changed" handler="dialog_time_to_value_changed_cb" object="CcNightLightPage" swapped="no" />
+ </object>
+ <object class="GtkAdjustment" id="adjustment_to_minutes">
+ <property name="upper">59</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ <signal name="value-changed" handler="dialog_time_to_value_changed_cb" object="CcNightLightPage" swapped="no" />
+ </object>
+ <object class="GtkAdjustment" id="adjustment_color_temperature">
+ <property name="lower">1700</property>
+ <property name="upper">4700</property>
+ <property name="step_increment">100</property>
+ <property name="page_increment">500</property>
+ <signal name="value-changed" handler="dialog_color_temperature_value_changed_cb" object="CcNightLightPage" swapped="no" />
+ </object>
+</interface>
diff --git a/panels/display/display-arrangement.css b/panels/display/display-arrangement.css
new file mode 100644
index 0000000..a3bc80b
--- /dev/null
+++ b/panels/display/display-arrangement.css
@@ -0,0 +1,33 @@
+display-arrangement {
+ font-weight: bold;
+ font-size: larger;
+}
+
+display-arrangement.monitor {
+ border: solid 1px @borders;
+ margin: 0px 0px 1px 1px;
+ background: @theme_bg_color;
+ padding: 0.4em;
+ border-radius: 5px;
+}
+
+display-arrangement.monitor.primary {
+ border-top: 0.4em solid #000000;
+}
+
+display-arrangement.monitor-label {
+ border-radius: 50%;
+ min-width: 1.5em;
+ min-height: 1.5em;
+ color: #000;
+ background: #ddd;
+}
+
+label.monitor-label {
+ border-radius: 50%;
+ font-weight: bold;
+ min-width: 1.5em;
+ min-height: 1.5em;
+ color: #000;
+ background: #ddd;
+}
diff --git a/panels/display/display.gresource.xml b/panels/display/display.gresource.xml
new file mode 100644
index 0000000..fcac1a2
--- /dev/null
+++ b/panels/display/display.gresource.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/display">
+ <file preprocess="xml-stripblanks">cc-display-panel.ui</file>
+ <file preprocess="xml-stripblanks">cc-display-settings.ui</file>
+ <file preprocess="xml-stripblanks">cc-night-light-page.ui</file>
+ <file>display-arrangement.css</file>
+ <file>night-light.css</file>
+ </gresource>
+</gresources>
diff --git a/panels/display/gnome-display-panel.desktop.in.in b/panels/display/gnome-display-panel.desktop.in.in
new file mode 100644
index 0000000..61f5ee7
--- /dev/null
+++ b/panels/display/gnome-display-panel.desktop.in.in
@@ -0,0 +1,18 @@
+[Desktop Entry]
+Name=Displays
+Comment=Choose how to use connected monitors and projectors
+Exec=gnome-control-center display
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-display-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;HardwareSettings;X-GNOME-Settings-Panel;X-GNOME-DevicesSettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=Screen resolution
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: Search terms to find the Displays panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=Panel;Projector;xrandr;Screen;Resolution;Refresh;Monitor;Night;Light;Blue;redshift;color;sunset;sunrise;
diff --git a/panels/display/icons/meson.build b/panels/display/icons/meson.build
new file mode 100644
index 0000000..91a313d
--- /dev/null
+++ b/panels/display/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-display-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/display/icons/scalable/org.gnome.Settings-display-symbolic.svg b/panels/display/icons/scalable/org.gnome.Settings-display-symbolic.svg
new file mode 100644
index 0000000..04f7a3b
--- /dev/null
+++ b/panels/display/icons/scalable/org.gnome.Settings-display-symbolic.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <path d="m 12 1 c 1.660156 0 3 1.339844 3 3 v 6 c 0 1.660156 -1.339844 3 -3 3 h -8 c -1.660156 0 -3 -1.339844 -3 -3 v -6 c 0 -1.660156 1.339844 -3 3 -3 z m 0 2 h -8 c -0.554688 0 -1 0.445312 -1 1 v 6 c 0 0.554688 0.445312 1 1 1 h 8 c 0.554688 0 1 -0.445312 1 -1 v -6 c 0 -0.554688 -0.445312 -1 -1 -1 z m -4 11 c -5 0 -5 1 -5 1 c 0 1 1 1 1 1 h 8 c 1 0 1 -1 1 -1 s 0 -1 -5 -1 z m 0 0" fill="#2e3436"/>
+</svg>
diff --git a/panels/display/meson.build b/panels/display/meson.build
new file mode 100644
index 0000000..726a898
--- /dev/null
+++ b/panels/display/meson.build
@@ -0,0 +1,64 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+sources = files(
+ 'cc-display-panel.c',
+ 'cc-display-arrangement.c',
+ 'cc-display-config.c',
+ 'cc-display-config-dbus.c',
+ 'cc-display-config-manager-dbus.c',
+ 'cc-display-config-manager.c',
+ 'cc-display-settings.c',
+ 'cc-night-light-page.c',
+)
+
+resource_data = files(
+ 'cc-display-panel.ui',
+ 'cc-display-settings.ui',
+ 'cc-night-light-page.ui',
+)
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ source_dir: ['.', 'icons'],
+ c_name: 'cc_' + cappletname,
+ dependencies: resource_data,
+ export: true
+)
+
+deps = common_deps + [
+ colord_dep,
+ gnome_rr_dep,
+ m_dep,
+ upower_glib_dep
+]
+
+cflags += [
+ '-DDATADIR="@0@"'.format(control_center_datadir)
+]
+
+panels_libs += static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [ top_inc, common_inc ],
+ dependencies: deps,
+ c_args: cflags
+)
+
+subdir('icons')
diff --git a/panels/display/night-light.css b/panels/display/night-light.css
new file mode 100644
index 0000000..02c0a09
--- /dev/null
+++ b/panels/display/night-light.css
@@ -0,0 +1,28 @@
+/* color selection by Daniel Foré and elementary OS */
+@define-color ORANGE_100 #ffc27d;
+@define-color ORANGE_500 #f37329;
+@define-color base_color white;
+@define-color bg_color shade(@base_color, 0.96);
+
+/* Hide the marks at the beginning and the end */
+.night-light-temperature mark indicator:nth-child(even) {
+ color:transparent;
+}
+
+.night-light-temperature trough {
+ padding-top: 2px;
+ padding-bottom: 2px;
+ background-image: linear-gradient(to right, mix(@bg_color, @ORANGE_100, 0.5), @ORANGE_500);
+}
+
+.night-light-temperature:dir(rtl) trough {
+ background-image: linear-gradient(to left, mix(@bg_color, @ORANGE_100, 0.5), @ORANGE_500);
+}
+
+.padded-spinbutton {
+ min-width: 40px;
+}
+
+.unpadded-button {
+ padding: 6px;
+}
diff --git a/panels/firmware-security/cc-firmware-security-boot-dialog.c b/panels/firmware-security/cc-firmware-security-boot-dialog.c
new file mode 100644
index 0000000..bf8a0e7
--- /dev/null
+++ b/panels/firmware-security/cc-firmware-security-boot-dialog.c
@@ -0,0 +1,113 @@
+/* cc-firmware-security-boot-dialog.c
+ *
+ * Copyright (C) 2021 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Kate Hsuan <hpa@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+
+#include "cc-firmware-security-boot-dialog.h"
+
+struct _CcFirmwareSecurityBootDialog
+{
+ GtkDialog parent;
+
+ GtkWidget *secure_boot_icon;
+ GtkWidget *secure_boot_title;
+ GtkWidget *secure_boot_description;
+};
+
+G_DEFINE_TYPE (CcFirmwareSecurityBootDialog, cc_firmware_security_boot_dialog, GTK_TYPE_DIALOG)
+
+static void
+cc_firmware_security_boot_dialog_class_init (CcFirmwareSecurityBootDialogClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/firmware-security/cc-firmware-security-boot-dialog.ui");
+ gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityBootDialog, secure_boot_title);
+ gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityBootDialog, secure_boot_icon);
+ gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityBootDialog, secure_boot_description);
+}
+
+static void
+cc_firmware_security_boot_dialog_init (CcFirmwareSecurityBootDialog *dialog)
+{
+ gtk_widget_init_template (GTK_WIDGET (dialog));
+ load_custom_css ("/org/gnome/control-center/firmware-security/security-level.css");
+}
+
+GtkWidget *
+cc_firmware_security_boot_dialog_new (SecureBootState secure_boot_state)
+{
+ CcFirmwareSecurityBootDialog *dialog;
+ g_autofree gchar *status_description = NULL;
+
+ dialog = g_object_new (CC_TYPE_FIRMWARE_SECURITY_BOOT_DIALOG,
+ "use-header-bar", TRUE,
+ NULL);
+
+ switch (secure_boot_state)
+ {
+ case SECURE_BOOT_STATE_ACTIVE:
+ /* TRANSLATORS: secure boot refers to the system firmware security mode */
+ gtk_label_set_text (GTK_LABEL(dialog->secure_boot_title), _("Secure Boot is Active"));
+ gtk_image_set_from_icon_name (GTK_IMAGE (dialog->secure_boot_icon), "channel-secure-symbolic");
+ gtk_widget_add_css_class (dialog->secure_boot_icon, "good");
+ status_description = g_strdup_printf ("%s",
+ /* TRANSLATORS: this is the first section of the decription */
+ _("Secure boot prevents malicious software from being loaded when the device starts. "
+ "It is currently turned on and is functioning correctly."));
+ break;
+
+ case SECURE_BOOT_STATE_PROBLEMS:
+ /* TRANSLATORS: secure boot refers to the system firmware security mode */
+ gtk_label_set_text (GTK_LABEL (dialog->secure_boot_title), _("Secure Boot Has Problems"));
+ gtk_widget_add_css_class (dialog->secure_boot_icon, "error");
+ status_description = g_strdup_printf ("%s\n\n%s\n\n%s",
+ /* TRANSLATORS: this is the first section of the decription. */
+ _("Secure boot prevents malicious software from being loaded when the device "
+ "starts. It is currently turned on, but will not work due to having an invalid key."),
+ /* TRANSLATORS: this is the second section of description. */
+ _("Secure boot problems can often be resolved from your computer's UEFI firmware settings "
+ "(BIOS) and your hardware manufacturer may provide information on how to do this."),
+ /* TRANSLATORS: this is the third section of description. */
+ _("For help, contact your hardware manufacturer or IT support provider."));
+ break;
+
+ case SECURE_BOOT_STATE_INACTIVE:
+ case SECURE_BOOT_STATE_UNKNOWN:
+ /* TRANSLATORS: secure boot refers to the system firmware security mode */
+ gtk_label_set_text (GTK_LABEL (dialog->secure_boot_title), _("Secure Boot is Turned Off"));
+ gtk_widget_add_css_class (dialog->secure_boot_icon, "error");
+ status_description = g_strdup_printf ("%s\n\n%s",
+ /* TRANSLATORS: this is the first section of the description. */
+ _("Secure boot prevents malicious software from being loaded when the device starts. It is "
+ "currently turned off."),
+ /* TRANSLATORS: this is the second section of the description. */
+ _("Secure boot can often be turned on from your computer's UEFI firmware settings (BIOS). "
+ "For help, contact your hardware manufacturer or IT support provider."));
+ break;
+ }
+ gtk_label_set_text (GTK_LABEL(dialog->secure_boot_description), status_description);
+
+ return GTK_WIDGET (dialog);
+}
diff --git a/panels/firmware-security/cc-firmware-security-boot-dialog.h b/panels/firmware-security/cc-firmware-security-boot-dialog.h
new file mode 100644
index 0000000..78b7d3a
--- /dev/null
+++ b/panels/firmware-security/cc-firmware-security-boot-dialog.h
@@ -0,0 +1,37 @@
+/* cc-firmware-security-boot-dialog.h
+ *
+ * Copyright (C) 2021 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Kate Hsuan <hpa@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "cc-firmware-security-utils.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_FIRMWARE_SECURITY_BOOT_DIALOG (cc_firmware_security_boot_dialog_get_type ())
+G_DECLARE_FINAL_TYPE (CcFirmwareSecurityBootDialog, cc_firmware_security_boot_dialog,
+ CC, FIRMWARE_SECURITY_BOOT_DIALOG, GtkDialog)
+
+GtkWidget *cc_firmware_security_boot_dialog_new (SecureBootState secure_boot_state);
+
+G_END_DECLS
diff --git a/panels/firmware-security/cc-firmware-security-boot-dialog.ui b/panels/firmware-security/cc-firmware-security-boot-dialog.ui
new file mode 100644
index 0000000..8b8957e
--- /dev/null
+++ b/panels/firmware-security/cc-firmware-security-boot-dialog.ui
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcFirmwareSecurityBootDialog" parent="GtkDialog">
+ <property name="use-header-bar">True</property>
+ <property name="default-width">400</property>
+ <property name="modal">True</property>
+ <child internal-child="headerbar">
+ <object class="GtkHeaderBar">
+ <property name="show_title_buttons">True</property>
+ <child type="title">
+ <object class="AdwBin" />
+ </child>
+ <style>
+ <class name="flat" />
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="margin-start">32</property>
+ <property name="margin-end">32</property>
+ <property name="margin-bottom">32</property>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">16</property>
+ <child>
+ <object class="GtkImage" id="secure_boot_icon">
+ <property name="pixel-size">32</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="icon-name">channel-insecure</property>
+ <style>
+ <class name="security-level-icon"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="secure_boot_title">
+ <property name="wrap">True</property>
+ <style>
+ <class name="title-2" />
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="secure_boot_description">
+ <property name="wrap">True</property>
+ <property name="width-chars">40</property>
+ <property name="max-width-chars">40</property>
+ <property name="justify">left</property>
+ <property name="label" translatable="yes">Secure boot prevents malicious software from being loaded when the device starts.
+
+For more information, contact the hardware manufacturer or IT support.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/firmware-security/cc-firmware-security-dialog.c b/panels/firmware-security/cc-firmware-security-dialog.c
new file mode 100644
index 0000000..2109aa5
--- /dev/null
+++ b/panels/firmware-security/cc-firmware-security-dialog.c
@@ -0,0 +1,442 @@
+/* cc-firmware-security-dialog.c
+ *
+ * Copyright (C) 2021 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Kate Hsuan <hpa@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+
+#include "cc-firmware-security-panel.h"
+#include "cc-firmware-security-dialog.h"
+#include "cc-firmware-security-utils.h"
+
+struct _CcFirmwareSecurityDialog
+{
+ AdwWindow parent;
+
+ GtkWidget *dialog_hsi_circle_box;
+ GtkWidget *dialog_hsi_circle_number;
+
+ GtkWidget *hsi1_icon;
+ GtkWidget *hsi2_icon;
+ GtkWidget *hsi3_icon;
+ GtkWidget *hsi1_title;
+ GtkWidget *hsi2_title;
+ GtkWidget *hsi3_title;
+
+ GtkWidget *firmware_security_dialog_title_label;
+ GtkWidget *firmware_security_dialog_body_label;
+ GtkWidget *firmware_security_dialog_min_row;
+ GtkWidget *firmware_security_dialog_basic_row;
+ GtkWidget *firmware_security_dialog_extend_row;
+ GtkWidget *firmware_security_dialog_hsi1_pg;
+ GtkWidget *firmware_security_dialog_hsi2_pg;
+ GtkWidget *firmware_security_dialog_hsi3_pg;
+ GtkWidget *firmware_security_dialog_hsi_label;
+ AdwLeaflet *leaflet;
+ AdwWindowTitle *second_page_title;
+
+ gboolean is_created;
+
+ GHashTable *hsi1_dict;
+ GHashTable *hsi2_dict;
+ GHashTable *hsi3_dict;
+ GHashTable *hsi4_dict;
+
+ guint hsi_number;
+};
+
+G_DEFINE_TYPE (CcFirmwareSecurityDialog, cc_firmware_security_dialog, ADW_TYPE_WINDOW)
+
+static void
+set_dialog_item_layer1 (CcFirmwareSecurityDialog *self,
+ const gchar *circle_str,
+ const gchar *title,
+ const gchar *body)
+{
+ g_autofree gchar *str = NULL;
+
+ gtk_label_set_label (GTK_LABEL (self->dialog_hsi_circle_number), circle_str);
+ gtk_label_set_text (GTK_LABEL (self->firmware_security_dialog_title_label), title);
+ gtk_label_set_text (GTK_LABEL (self->firmware_security_dialog_body_label), body);
+
+ if (self->hsi_number == G_MAXUINT)
+ {
+ gtk_widget_add_css_class (self->dialog_hsi_circle_box, "level1");
+ gtk_widget_add_css_class (self->dialog_hsi_circle_number, "hsi1");
+ gtk_widget_hide (self->hsi1_icon);
+ gtk_widget_hide (self->hsi2_icon);
+ gtk_widget_hide (self->hsi3_icon);
+ gtk_widget_hide (self->hsi1_title);
+ gtk_widget_hide (self->hsi2_title);
+ gtk_widget_hide (self->hsi3_title);
+ gtk_widget_hide (self->firmware_security_dialog_hsi_label);
+ return;
+ }
+
+ gtk_image_set_from_icon_name (GTK_IMAGE (self->hsi1_icon), self->hsi_number >= 1 ? "emblem-ok" : "process-stop");
+ gtk_label_set_text (GTK_LABEL (self->hsi1_title), self->hsi_number >= 1 ? _("Passed") : _("Failed"));
+ gtk_image_set_from_icon_name (GTK_IMAGE (self->hsi2_icon), self->hsi_number >= 2 ? "emblem-ok" : "process-stop");
+ gtk_label_set_text (GTK_LABEL (self->hsi2_title), self->hsi_number >= 2 ? _("Passed") : _("Failed"));
+ gtk_image_set_from_icon_name (GTK_IMAGE (self->hsi3_icon), self->hsi_number >= 3 ? "emblem-ok" : "process-stop");
+ gtk_label_set_text (GTK_LABEL (self->hsi3_title), self->hsi_number >= 3 ? _("Passed") : _("Failed"));
+
+ gtk_widget_add_css_class (self->firmware_security_dialog_min_row,
+ self->hsi_number >= 1 ? "success-hsi-icon" : "error-hsi-icon");
+ gtk_widget_add_css_class (self->firmware_security_dialog_min_row,
+ self->hsi_number >= 1 ? "success-title" : "error-title");
+ gtk_widget_add_css_class (self->firmware_security_dialog_basic_row,
+ self->hsi_number >= 2 ? "success-hsi-icon" : "error-hsi-icon");
+ gtk_widget_add_css_class (self->firmware_security_dialog_basic_row,
+ self->hsi_number >= 2 ? "success-title" : "error-title");
+ gtk_widget_add_css_class (self->firmware_security_dialog_extend_row,
+ self->hsi_number >= 3 ? "success-hsi-icon" : "error-hsi-icon");
+ gtk_widget_add_css_class (self->firmware_security_dialog_extend_row,
+ self->hsi_number >= 3 ? "success-title" : "error-title");
+
+ switch (self->hsi_number)
+ {
+ case 0:
+ gtk_widget_add_css_class (self->dialog_hsi_circle_box, "level0");
+ gtk_widget_add_css_class (self->dialog_hsi_circle_number, "hsi0");
+ break;
+ case 1:
+ gtk_widget_add_css_class (self->dialog_hsi_circle_box, "level1");
+ gtk_widget_add_css_class (self->dialog_hsi_circle_number, "hsi1");
+ break;
+ case 2:
+ gtk_widget_add_css_class (self->dialog_hsi_circle_box, "level2");
+ gtk_widget_add_css_class (self->dialog_hsi_circle_number, "hsi2");
+ break;
+ case 3:
+ case 4:
+ gtk_widget_add_css_class (self->dialog_hsi_circle_box, "level3");
+ gtk_widget_add_css_class (self->dialog_hsi_circle_number, "hsi3");
+ break;
+ }
+
+ /* TRANSLATORS: HSI stands for Host Security ID and device refers to the computer as a whole */
+ str = g_strdup_printf (_("Device conforms to HSI level %d"), self->hsi_number);
+ gtk_label_set_text (GTK_LABEL (self->firmware_security_dialog_hsi_label), str);
+}
+
+static void
+update_dialog (CcFirmwareSecurityDialog *self)
+{
+ switch (self->hsi_number)
+ {
+ case 0:
+ set_dialog_item_layer1 (self,
+ "0",
+ _("Security Level 0"),
+ _("This device has no protection against hardware security issues. This could "
+ "be because of a hardware or firmware configuration issue. It is "
+ "recommended to contact your IT support provider."));
+ break;
+
+ case 1:
+ set_dialog_item_layer1 (self,
+ "1",
+ _("Security Level 1"),
+ _("This device has minimal protection against hardware security issues. This "
+ "is the lowest device security level and only provides protection against "
+ "simple security threats."));
+ break;
+
+ case 2:
+ set_dialog_item_layer1 (self,
+ "2",
+ _("Security Level 2"),
+ _("This device has basic protection against hardware security issues. This "
+ "provides protection against some common security threats."));
+ break;
+
+ case 3:
+ case 4:
+ set_dialog_item_layer1 (self,
+ "3",
+ _("Security Level 3"),
+ _("This device has extended protection against hardware security issues. This "
+ "is the highest device security level and provides protection against "
+ "advanced security threats."));
+ break;
+
+ default:
+ set_dialog_item_layer1 (self,
+ "?",
+ _("Security Level"),
+ _("Security levels are not available for this device."));
+ }
+}
+
+static gchar *
+fu_security_attr_get_description_for_dialog (FwupdSecurityAttr *attr)
+{
+ GString *str = g_string_new (attr->description);
+
+ if (attr->flags & FWUPD_SECURITY_ATTR_FLAG_ACTION_CONTACT_OEM &&
+ attr->flags & FWUPD_SECURITY_ATTR_FLAG_ACTION_CONFIG_FW &&
+ attr->flags & FWUPD_SECURITY_ATTR_FLAG_ACTION_CONFIG_FW)
+ {
+ g_string_append_printf (str, "\n\n%s %s",
+ /* TRANSLATORS: hardware manufacturer as in OEM */
+ _("Contact your hardware manufacturer for help with security updates."),
+ /* TRANSLATORS: support technician as in someone with root */
+ _("It might be possible to resolve this issue in the device’s UEFI "
+ "firmware settings, or by a support technician."));
+ }
+ else if (attr->flags & FWUPD_SECURITY_ATTR_FLAG_ACTION_CONTACT_OEM &&
+ attr->flags & FWUPD_SECURITY_ATTR_FLAG_ACTION_CONFIG_FW)
+ {
+ g_string_append_printf (str, "\n\n%s %s",
+ /* TRANSLATORS: hardware manufacturer as in OEM */
+ _("Contact your hardware manufacturer for help with security updates."),
+ _("It might be possible to resolve this issue in the device’s UEFI firmware settings."));
+ }
+ else if (attr->flags & FWUPD_SECURITY_ATTR_FLAG_ACTION_CONTACT_OEM)
+ {
+ g_string_append_printf (str, "\n\n%s",
+ /* TRANSLATORS: hardware manufacturer as in OEM */
+ _("Contact your hardware manufacturer for help with security updates."));
+ }
+ else if (attr->flags & FWUPD_SECURITY_ATTR_FLAG_ACTION_CONFIG_FW)
+ {
+ g_string_append_printf (str, "\n\n%s",
+ _("It might be possible to resolve this issue in the device’s UEFI firmware settings."));
+ }
+ else if (attr->flags & FWUPD_SECURITY_ATTR_FLAG_ACTION_CONFIG_OS)
+ {
+ g_string_append_printf (str, "\n\n%s",
+ /* TRANSLATORS: support technician as in someone with root */
+ _("It might be possible for a support technician to resolve this issue."));
+ }
+
+ return g_string_free (str, FALSE);
+}
+
+static GtkWidget *
+hsi_create_pg_row (const gchar *icon_name,
+ const gchar *style,
+ FwupdSecurityAttr *attr)
+{
+ GtkWidget *row;
+ GtkWidget *status_icon;
+ GtkWidget *status_label;
+ GtkWidget *actions_parent;
+ const gchar *result_str = NULL;
+
+ row = adw_expander_row_new ();
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row), attr->title);
+
+ result_str = fwupd_security_attr_result_to_string(attr->result);
+ if (result_str)
+ {
+ status_label = gtk_label_new (result_str);
+ if (firmware_security_attr_has_flag (attr, FWUPD_SECURITY_ATTR_FLAG_SUCCESS))
+ status_icon = gtk_image_new_from_icon_name ("emblem-ok");
+ else
+ status_icon = gtk_image_new_from_icon_name ("process-stop");
+
+ adw_expander_row_add_action (ADW_EXPANDER_ROW (row), status_label);
+ adw_expander_row_add_action (ADW_EXPANDER_ROW (row), status_icon);
+
+ gtk_widget_add_css_class (status_icon, "icon");
+ gtk_widget_add_css_class (status_label, "hsi_label");
+
+ actions_parent = gtk_widget_get_parent (status_icon);
+ gtk_box_set_spacing (GTK_BOX (actions_parent), 6);
+ gtk_widget_set_margin_end (actions_parent, 12);
+ }
+
+ if (attr->description != NULL)
+ {
+ GtkWidget *subrow = adw_action_row_new ();
+ g_autofree gchar *str = fu_security_attr_get_description_for_dialog (attr);
+ adw_action_row_set_subtitle (ADW_ACTION_ROW (subrow), str);
+ adw_expander_row_add_row (ADW_EXPANDER_ROW (row), subrow);
+ gtk_widget_add_css_class (subrow, "security-description-row");
+ }
+ else
+ {
+ adw_expander_row_set_enable_expansion (ADW_EXPANDER_ROW (row), FALSE);
+ gtk_widget_add_css_class (row, "hide-arrow");
+ }
+
+ return row;
+}
+
+static void
+update_hsi_listbox (CcFirmwareSecurityDialog *self,
+ const gint hsi_level)
+{
+ g_autoptr (GList) hash_keys = NULL;
+ GHashTable *hsi_dict = NULL;
+ GtkWidget *pg_row;
+ GtkWidget *hsi_pg;
+
+ switch (hsi_level)
+ {
+ case 1:
+ hsi_dict = self->hsi1_dict;
+ hsi_pg = self->firmware_security_dialog_hsi1_pg;
+ break;
+ case 2:
+ hsi_dict = self->hsi2_dict;
+ hsi_pg = self->firmware_security_dialog_hsi2_pg;
+ break;
+ case 3:
+ hsi_dict = self->hsi3_dict;
+ hsi_pg = self->firmware_security_dialog_hsi3_pg;
+ break;
+ case 4:
+ hsi_dict = self->hsi4_dict;
+ hsi_pg = self->firmware_security_dialog_hsi3_pg;
+ break;
+ }
+
+ hash_keys = g_hash_table_get_keys (hsi_dict);
+ for (GList *item = g_list_first (hash_keys); item != NULL; item = g_list_next (item))
+ {
+ FwupdSecurityAttr *attr = g_hash_table_lookup (hsi_dict, item->data);
+ if (g_strcmp0 (attr->appstream_id, FWUPD_SECURITY_ATTR_ID_SUPPORTED_CPU) == 0)
+ continue;
+ if (attr->title == NULL)
+ continue;
+ if (firmware_security_attr_has_flag (attr, FWUPD_SECURITY_ATTR_FLAG_SUCCESS))
+ {
+ pg_row = hsi_create_pg_row ("emblem-ok", "color_green", attr);
+ gtk_widget_add_css_class (pg_row, "success-icon");
+ gtk_widget_add_css_class (pg_row, "success-title");
+ }
+ else
+ {
+ pg_row = hsi_create_pg_row ("process-stop", "color_dim", attr);
+ gtk_widget_add_css_class (pg_row, "error-icon");
+ gtk_widget_add_css_class (pg_row, "error-title");
+ }
+ adw_preferences_group_add (ADW_PREFERENCES_GROUP (hsi_pg), GTK_WIDGET (pg_row));
+ }
+ self->is_created = TRUE;
+}
+
+static void
+on_hsi_clicked_cb (GtkWidget *widget,
+ CcFirmwareSecurityDialog *self)
+{
+ adw_leaflet_navigate (self->leaflet, ADW_NAVIGATION_DIRECTION_FORWARD);
+
+ if (!self->is_created)
+ {
+ update_hsi_listbox (self, 1);
+ update_hsi_listbox (self, 2);
+ update_hsi_listbox (self, 3);
+ update_hsi_listbox (self, 4);
+ self->is_created = TRUE;
+ }
+
+ if (widget == self->firmware_security_dialog_min_row)
+ {
+ adw_window_title_set_title (self->second_page_title, _("Security Level 1"));
+ gtk_widget_set_visible (self->firmware_security_dialog_hsi1_pg, TRUE);
+ }
+ else if (widget == self->firmware_security_dialog_basic_row)
+ {
+ adw_window_title_set_title (self->second_page_title, _("Security Level 2"));
+ gtk_widget_set_visible (self->firmware_security_dialog_hsi2_pg, TRUE);
+ }
+ else if (widget == self->firmware_security_dialog_extend_row)
+ {
+ adw_window_title_set_title (self->second_page_title, _("Security Level 3"));
+ gtk_widget_set_visible (self->firmware_security_dialog_hsi3_pg, TRUE);
+ }
+}
+
+static void
+on_fw_back_button_clicked_cb (GtkWidget *widget,
+ gpointer data)
+{
+ CcFirmwareSecurityDialog *self = CC_FIRMWARE_SECURITY_DIALOG (data);
+
+ adw_leaflet_navigate (self->leaflet, ADW_NAVIGATION_DIRECTION_BACK);
+
+ gtk_widget_set_visible (self->firmware_security_dialog_hsi1_pg, FALSE);
+ gtk_widget_set_visible (self->firmware_security_dialog_hsi2_pg, FALSE);
+ gtk_widget_set_visible (self->firmware_security_dialog_hsi3_pg, FALSE);
+}
+
+static void
+cc_firmware_security_dialog_class_init (CcFirmwareSecurityDialogClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/firmware-security/cc-firmware-security-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, dialog_hsi_circle_box);
+ gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, dialog_hsi_circle_number);
+ gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, hsi1_icon);
+ gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, hsi2_icon);
+ gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, hsi3_icon);
+ gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, hsi1_title);
+ gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, hsi2_title);
+ gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, hsi3_title);
+ gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_title_label);
+ gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_body_label);
+ gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_hsi_label);
+ gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_min_row);
+ gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_basic_row);
+ gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_extend_row);
+ gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_hsi1_pg);
+ gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_hsi2_pg);
+ gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_hsi3_pg);
+ gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, leaflet);
+ gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, second_page_title);
+
+ gtk_widget_class_bind_template_callback (widget_class, on_hsi_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_fw_back_button_clicked_cb);
+}
+
+static void
+cc_firmware_security_dialog_init (CcFirmwareSecurityDialog *dialog)
+{
+ gtk_widget_init_template (GTK_WIDGET (dialog));
+ load_custom_css ("/org/gnome/control-center/firmware-security/security-level.css");
+}
+
+GtkWidget *
+cc_firmware_security_dialog_new (guint hsi_number,
+ GHashTable *hsi1_dict,
+ GHashTable *hsi2_dict,
+ GHashTable *hsi3_dict,
+ GHashTable *hsi4_dict)
+{
+ CcFirmwareSecurityDialog *dialog;
+
+ dialog = g_object_new (CC_TYPE_FIRMWARE_SECURITY_DIALOG, NULL);
+ dialog->hsi_number = hsi_number;
+ dialog->is_created = FALSE;
+ dialog->hsi1_dict = hsi1_dict;
+ dialog->hsi2_dict = hsi2_dict;
+ dialog->hsi3_dict = hsi3_dict;
+ dialog->hsi4_dict = hsi4_dict;
+ update_dialog (dialog);
+
+ return GTK_WIDGET (dialog);
+}
diff --git a/panels/firmware-security/cc-firmware-security-dialog.h b/panels/firmware-security/cc-firmware-security-dialog.h
new file mode 100644
index 0000000..3857fb2
--- /dev/null
+++ b/panels/firmware-security/cc-firmware-security-dialog.h
@@ -0,0 +1,38 @@
+/* cc-firmware-security-dialog.h
+ *
+ * Copyright (C) 2021 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Kate Hsuan <hpa@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#pragma once
+
+#include <adwaita.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_FIRMWARE_SECURITY_DIALOG (cc_firmware_security_dialog_get_type ())
+G_DECLARE_FINAL_TYPE (CcFirmwareSecurityDialog, cc_firmware_security_dialog, CC, FIRMWARE_SECURITY_DIALOG, AdwWindow)
+
+GtkWidget * cc_firmware_security_dialog_new (guint hsi_number,
+ GHashTable *hsi1_dict,
+ GHashTable *hsi2_dict,
+ GHashTable *hsi3_dict,
+ GHashTable *hsi4_dict);
+
+G_END_DECLS
diff --git a/panels/firmware-security/cc-firmware-security-dialog.ui b/panels/firmware-security/cc-firmware-security-dialog.ui
new file mode 100644
index 0000000..c1a3a67
--- /dev/null
+++ b/panels/firmware-security/cc-firmware-security-dialog.ui
@@ -0,0 +1,271 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcFirmwareSecurityDialog" parent="AdwWindow">
+ <property name="default-width">500</property>
+ <property name="default-height">550</property>
+ <property name="modal">True</property>
+ <child>
+ <object class="AdwLeaflet" id="leaflet">
+ <property name="can-unfold">False</property>
+ <child>
+ <object class="AdwLeafletPage">
+ <property name="child">
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+
+ <child>
+ <object class="GtkHeaderBar">
+ <property name="valign">start</property>
+ <property name="show-title-buttons">True</property>
+ <property name="title-widget">
+ <object class="AdwWindowTitle">
+ <property name="title" translatable="yes">Security Level</property>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesPage">
+ <property name="vexpand-set">True</property>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="GtkBox" id="dialog_hsi_circle_box">
+ <property name="orientation">vertical</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <child>
+ <object class="GtkLabel" id="dialog_hsi_circle_number">
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="vexpand">True</property>
+ <property name="justify">center</property>
+ <property name="label">9</property>
+ <style>
+ <class name="hsi-level-font" />
+ </style>
+ </object>
+ </child>
+ <style>
+ <class name="hsi-level-box" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="GtkLabel" id="firmware_security_dialog_title_label">
+ <style>
+ <class name="title-2" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="GtkLabel" id="firmware_security_dialog_body_label">
+ <property name="wrap">True</property>
+ <property name="justify">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="AdwActionRow" id="firmware_security_dialog_min_row">
+ <property name="use-underline">True</property>
+ <property name="activatable">True</property>
+ <property name="title" translatable="yes">Level 1</property>
+ <signal name="activated" handler="on_hsi_clicked_cb" swapped="no" />
+ <child>
+ <object class="GtkImage" id="hsi1_icon">
+ <property name="icon-name">process-stop</property>
+ <style>
+ <class name="hsi_icon" />
+ <class name="error-hsi-icon" />
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="hsi1_title">
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <property name="vexpand">True</property>
+ <property name="justify">left</property>
+ <property name="label">Failed</property>
+ <property name="margin-end">6</property>
+ <style>
+ <class name="hsi_label" />
+ <class name="error-title" />
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="firmware_security_dialog_basic_row">
+ <property name="use-underline">True</property>
+ <property name="activatable">True</property>
+ <property name="title" translatable="yes">Level 2</property>
+ <signal name="activated" handler="on_hsi_clicked_cb" swapped="no" />
+ <child>
+ <object class="GtkImage" id="hsi2_icon">
+ <property name="icon-name">process-stop</property>
+ <style>
+ <class name="hsi_icon" />
+ <class name="error-hsi-icon" />
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="hsi2_title">
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <property name="vexpand">True</property>
+ <property name="justify">left</property>
+ <property name="label">Failed</property>
+ <property name="margin-end">6</property>
+ <style>
+ <class name="hsi_label" />
+ <class name="error-title" />
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="firmware_security_dialog_extend_row">
+ <property name="use-underline">True</property>
+ <property name="activatable">True</property>
+ <property name="title" translatable="yes">Level 3</property>
+ <signal name="activated" handler="on_hsi_clicked_cb" swapped="no" />
+ <child>
+ <object class="GtkImage" id="hsi3_icon">
+ <property name="icon-name">process-stop</property>
+ <style>
+ <class name="hsi_icon" />
+ <class name="error-hsi-icon" />
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="hsi3_title">
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <property name="vexpand">True</property>
+ <property name="justify">left</property>
+ <property name="label">Failed</property>
+ <property name="margin-end">6</property>
+ <style>
+ <class name="hsi_label" />
+ <class name="error-title" />
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="GtkLabel" id="firmware_security_dialog_hsi_label">
+ <property name="label">Device conform text</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwLeafletPage">
+ <property name="child">
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+
+ <child>
+ <object class="GtkHeaderBar">
+ <property name="valign">start</property>
+ <property name="show-title-buttons">True</property>
+ <property name="title-widget">
+ <object class="AdwWindowTitle" id="second_page_title" />
+ </property>
+ <child>
+ <object class="GtkButton">
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="icon-name">go-previous-symbolic</property>
+ <signal name="clicked" handler="on_fw_back_button_clicked_cb" swapped="no" />
+ <style>
+ <class name="image-button" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup" id="firmware_security_dialog_hsi1_pg">
+ <property name="visible">False</property>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup" id="firmware_security_dialog_hsi2_pg">
+ <property name="visible">False</property>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup" id="firmware_security_dialog_hsi3_pg">
+ <property name="visible">False</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </property>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/firmware-security/cc-firmware-security-panel.c b/panels/firmware-security/cc-firmware-security-panel.c
new file mode 100644
index 0000000..d48e7ab
--- /dev/null
+++ b/panels/firmware-security/cc-firmware-security-panel.c
@@ -0,0 +1,717 @@
+/* cc-firmware-security-panel.c
+ *
+ * Copyright (C) 2021 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Kate Hsuan <hpa@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "shell/cc-application.h"
+
+#include "cc-firmware-security-panel.h"
+#include "cc-firmware-security-resources.h"
+#include "cc-firmware-security-dialog.h"
+#include "cc-firmware-security-boot-dialog.h"
+#include "cc-firmware-security-utils.h"
+#include "cc-util.h"
+
+#include <gio/gdesktopappinfo.h>
+#include <glib/gi18n.h>
+
+struct _CcfirmwareSecurityPanel
+{
+ CcPanel parent_instance;
+
+ GtkButton *hsi_button;
+ GtkButton *secure_boot_button;
+
+ /* HSI button */
+ GtkWidget *hsi_grid;
+
+ GtkWidget *hsi_circle_box;
+ GtkWidget *hsi_circle_number;
+
+ GtkWidget *hsi_label;
+ GtkWidget *hsi_description;
+
+ /* secure boot button */
+ GtkWidget *secure_boot_button_grid;
+ GtkWidget *secure_boot_icon;
+ GtkWidget *secure_boot_label;
+ GtkWidget *secure_boot_description;
+
+ /* event listbox */
+ GtkWidget *firmware_security_log_listbox;
+ GtkWidget *firmware_security_log_stack;
+ GtkWidget *firmware_security_log_pgroup;
+
+ GDBusProxy *bus_proxy;
+ GDBusProxy *properties_bus_proxy;
+
+ GHashTable *hsi1_dict;
+ GHashTable *hsi2_dict;
+ GHashTable *hsi3_dict;
+ GHashTable *hsi4_dict;
+
+ guint hsi_number;
+ SecureBootState secure_boot_state;
+};
+
+CC_PANEL_REGISTER (CcfirmwareSecurityPanel, cc_firmware_security_panel)
+
+static void
+set_hsi_button_view (CcfirmwareSecurityPanel *self);
+
+static void
+set_secure_boot_button_view (CcfirmwareSecurityPanel *self)
+{
+ FwupdSecurityAttr *attr;
+ guint64 sb_flags = 0;
+ guint64 pk_flags = 0;
+
+ /* get HSI-1 flags if set */
+ attr = g_hash_table_lookup (self->hsi1_dict, FWUPD_SECURITY_ATTR_ID_UEFI_SECUREBOOT);
+ if (attr != NULL)
+ sb_flags = attr->flags;
+ attr = g_hash_table_lookup (self->hsi1_dict, FWUPD_SECURITY_ATTR_ID_UEFI_PK);
+ if (attr != NULL)
+ pk_flags = attr->flags;
+
+ /* enabled and valid */
+ if ((sb_flags & FWUPD_SECURITY_ATTR_FLAG_SUCCESS) > 0 &&
+ (pk_flags & FWUPD_SECURITY_ATTR_FLAG_SUCCESS) > 0)
+ {
+ self->secure_boot_state = SECURE_BOOT_STATE_ACTIVE;
+ }
+ else if ((sb_flags & FWUPD_SECURITY_ATTR_RESULT_ENABLED) > 0)
+ {
+ self->secure_boot_state = SECURE_BOOT_STATE_PROBLEMS;
+ }
+ else
+ {
+ self->secure_boot_state = SECURE_BOOT_STATE_INACTIVE;
+ }
+
+ /* update UI */
+ if (self->secure_boot_state == SECURE_BOOT_STATE_ACTIVE)
+ {
+ gtk_label_set_text (GTK_LABEL (self->secure_boot_label), _("Secure Boot is Active"));
+ gtk_label_set_text (GTK_LABEL (self->secure_boot_description), _("Protected against malicious software when the device starts."));
+ gtk_image_set_from_icon_name (GTK_IMAGE (self->secure_boot_icon), "channel-secure-symbolic");
+ gtk_widget_add_css_class (self->secure_boot_icon, "good");
+ }
+ else if (self->secure_boot_state == SECURE_BOOT_STATE_PROBLEMS)
+ {
+ gtk_label_set_text (GTK_LABEL (self->secure_boot_label), _("Secure Boot has Problems"));
+ gtk_label_set_text (GTK_LABEL (self->secure_boot_description), _("Some protection when the device is started."));
+ gtk_widget_add_css_class (self->secure_boot_icon, "error");
+ }
+ else
+ {
+ gtk_label_set_text (GTK_LABEL (self->secure_boot_label), _("Secure Boot is Off"));
+ gtk_label_set_text (GTK_LABEL (self->secure_boot_description), _("No protection when the device is started."));
+ gtk_widget_add_css_class (self->secure_boot_icon, "error");
+ }
+}
+
+static gchar *
+fu_security_attr_get_description_for_eventlog (FwupdSecurityAttr *attr)
+{
+ GString *str = g_string_new (attr->description);
+
+ /* nothing to do */
+ if (attr->flags & FWUPD_SECURITY_ATTR_FLAG_SUCCESS)
+ return g_string_free (str, FALSE);
+
+ if (attr->flags & FWUPD_SECURITY_ATTR_FLAG_ACTION_CONTACT_OEM &&
+ attr->flags & FWUPD_SECURITY_ATTR_FLAG_ACTION_CONFIG_FW)
+ {
+ g_string_append_printf (str, "\n\n%s",
+ /* TRANSLATORS: this is to explain an event that has already happened */
+ _("This issue could have been caused by a change in UEFI firmware "
+ "settings, an operating system configuration change, or because of "
+ "malicious software on this system."));
+ }
+ else if (attr->flags & FWUPD_SECURITY_ATTR_FLAG_ACTION_CONFIG_FW)
+ {
+ g_string_append_printf (str, "\n\n%s",
+ /* TRANSLATORS: this is to explain an event that has already happened */
+ _("This issue could have been caused by a change in the UEFI firmware "
+ "settings, or because of malicious software on this system."));
+ }
+ else if (attr->flags & FWUPD_SECURITY_ATTR_FLAG_ACTION_CONFIG_OS)
+ {
+ g_string_append_printf (str, "\n\n%s",
+ /* TRANSLATORS: this is to explain an event that has already happened */
+ _("This issue could have been caused by an operating system configuration "
+ "change, or because of malicious software on this system."));
+ }
+
+ return g_string_free (str, FALSE);
+}
+
+static void
+parse_event_variant_iter (CcfirmwareSecurityPanel *self,
+ GVariantIter *iter)
+{
+ g_autofree gchar *date_string = NULL;
+ g_autoptr (GDateTime) date = NULL;
+ g_autoptr (FwupdSecurityAttr) attr = fu_security_attr_new_from_variant(iter);
+ GtkWidget *row;
+
+ /* unknown to us */
+ if (attr->appstream_id == NULL || attr->title == NULL)
+ return;
+
+ /* skip events that have either been added or removed with no prior value */
+ if (attr->result == FWUPD_SECURITY_ATTR_RESULT_UNKNOWN ||
+ attr->result_fallback == FWUPD_SECURITY_ATTR_RESULT_UNKNOWN)
+ return;
+
+ /* build new row */
+ date = g_date_time_new_from_unix_local (attr->timestamp);
+ date_string = g_date_time_format (date, "\%F \%H:\%m:\%S");
+
+ row = adw_expander_row_new ();
+ if (attr->flags & FWUPD_SECURITY_ATTR_FLAG_SUCCESS)
+ {
+ adw_expander_row_set_icon_name (ADW_EXPANDER_ROW (row), "emblem-ok");
+ gtk_widget_add_css_class (row, "success-icon");
+ }
+ else
+ {
+ adw_expander_row_set_icon_name (ADW_EXPANDER_ROW (row), "process-stop");
+ gtk_widget_add_css_class (row, "error-icon");
+ }
+
+ if (attr->description != NULL)
+ {
+ GtkWidget *subrow = adw_action_row_new ();
+ g_autofree gchar *str = fu_security_attr_get_description_for_eventlog (attr);
+ adw_action_row_set_subtitle (ADW_ACTION_ROW (subrow), str);
+ adw_expander_row_add_row (ADW_EXPANDER_ROW (row), subrow);
+ }
+ else
+ {
+ adw_expander_row_set_enable_expansion (ADW_EXPANDER_ROW (row), FALSE);
+ gtk_widget_add_css_class (row, "hide-arrow");
+ }
+
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row), attr->title);
+ adw_expander_row_set_subtitle (ADW_EXPANDER_ROW (row), date_string);
+ adw_preferences_group_add (ADW_PREFERENCES_GROUP (self->firmware_security_log_pgroup), GTK_WIDGET (row));
+
+ adw_view_stack_set_visible_child_name (ADW_VIEW_STACK (self->firmware_security_log_stack), "page2");
+}
+
+static void
+parse_variant_iter (CcfirmwareSecurityPanel *self,
+ GVariantIter *iter)
+{
+ g_autoptr (FwupdSecurityAttr) attr = fu_security_attr_new_from_variant(iter);
+ const gchar *appstream_id = attr->appstream_id;
+
+ /* invalid */
+ if (appstream_id == NULL)
+ return;
+
+ /* in fwupd <= 1.8.3 org.fwupd.hsi.Uefi.SecureBoot was incorrectly marked as HSI-0,
+ * so lower the HSI number forcefully if this attribute failed -- the correct thing
+ * to do of course is to update fwupd to a newer build */
+ if (g_strcmp0 (attr->appstream_id, FWUPD_SECURITY_ATTR_ID_UEFI_SECUREBOOT) == 0 &&
+ (attr->flags & FWUPD_SECURITY_ATTR_FLAG_SUCCESS) == 0)
+ {
+ self->hsi_number = 0;
+ set_hsi_button_view (self);
+ }
+
+ /* insert into correct hash table */
+ switch (attr->hsi_level)
+ {
+ case 1:
+ g_hash_table_insert (self->hsi1_dict,
+ g_strdup (appstream_id),
+ g_steal_pointer (&attr));
+ break;
+ case 2:
+ g_hash_table_insert (self->hsi2_dict,
+ g_strdup (appstream_id),
+ g_steal_pointer (&attr));
+ break;
+ case 3:
+ g_hash_table_insert (self->hsi3_dict,
+ g_strdup (appstream_id),
+ g_steal_pointer (&attr));
+ break;
+ case 4:
+ g_hash_table_insert (self->hsi4_dict,
+ g_strdup (appstream_id),
+ g_steal_pointer (&attr));
+ break;
+ }
+}
+
+static void
+parse_data_from_variant (CcfirmwareSecurityPanel *self,
+ GVariant *value,
+ const gboolean is_event)
+{
+ const gchar *type_string;
+ g_autoptr (GVariantIter) iter = NULL;
+
+ type_string = g_variant_get_type_string (value);
+ if (g_strcmp0 (type_string, "(a{sv})") == 0)
+ {
+ g_variant_get (value, "(a{sv})", &iter);
+ if (is_event)
+ parse_event_variant_iter (self, iter);
+ else
+ parse_variant_iter (self, iter);
+ }
+ else if (g_strcmp0 (type_string, "a{sv}") == 0)
+ {
+ g_variant_get (value, "a{sv}", &iter);
+ if (is_event)
+ parse_event_variant_iter (self, iter);
+ else
+ parse_variant_iter (self, iter);
+ }
+ else
+ {
+ g_warning ("type %s not known", type_string);
+ }
+}
+
+static void
+parse_array_from_variant (CcfirmwareSecurityPanel *self,
+ GVariant *value,
+ const gboolean is_event)
+{
+ gsize sz;
+ g_autoptr (GVariant) untuple = NULL;
+
+ untuple = g_variant_get_child_value (value, 0);
+ sz = g_variant_n_children (untuple);
+ for (guint i = 0; i < sz; i++)
+ {
+ g_autoptr (GVariant) data = NULL;
+ data = g_variant_get_child_value (untuple, i);
+ if (is_event)
+ parse_data_from_variant (self, data, TRUE);
+ else
+ parse_data_from_variant (self, data, FALSE);
+ }
+}
+
+static void
+on_bus_event_done_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr (GError) error = NULL;
+ g_autoptr (GVariant) val = NULL;
+ CcfirmwareSecurityPanel *self = CC_FIRMWARE_SECURITY_PANEL (user_data);
+
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
+ if (val == NULL)
+ {
+ g_warning ("failed to get Security Attribute Event: %s", error->message);
+ return;
+ }
+
+ parse_array_from_variant (self, val, TRUE);
+}
+
+static void
+on_bus_done (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcfirmwareSecurityPanel *self = CC_FIRMWARE_SECURITY_PANEL (user_data);
+ g_autoptr (GError) error = NULL;
+ g_autoptr (GVariant) val = NULL;
+
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
+ if (val == NULL)
+ {
+ CcApplication *application = CC_APPLICATION (g_application_get_default ());
+ g_warning ("failed to get Security Attribute: %s", error->message);
+ cc_shell_model_set_panel_visibility (cc_application_get_model (application),
+ "firmware-security",
+ CC_PANEL_HIDDEN);
+ set_secure_boot_button_view (self);
+ return;
+ }
+
+ parse_array_from_variant (self, val, FALSE);
+ set_secure_boot_button_view (self);
+}
+
+static void
+on_bus_ready_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr (GError) error = NULL;
+ CcfirmwareSecurityPanel *self = CC_FIRMWARE_SECURITY_PANEL (user_data);
+
+ self->bus_proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+ if (self->bus_proxy == NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("failed to connect fwupd: %s", error->message);
+
+ return;
+ }
+
+ g_dbus_proxy_call (self->bus_proxy,
+ "GetHostSecurityAttrs",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ on_bus_done,
+ self);
+ g_dbus_proxy_call (self->bus_proxy,
+ "GetHostSecurityEvents",
+ g_variant_new ("(u)",
+ 100),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ on_bus_event_done_cb,
+ self);
+}
+
+static void
+on_hsi_button_clicked_cb (GtkWidget *widget,
+ gpointer data)
+{
+ GtkWidget *toplevel;
+ CcShell *shell;
+ GtkWidget *dialog;
+ CcfirmwareSecurityPanel *self = CC_FIRMWARE_SECURITY_PANEL (data);
+
+ dialog = cc_firmware_security_dialog_new (self->hsi_number,
+ self->hsi1_dict,
+ self->hsi2_dict,
+ self->hsi3_dict,
+ self->hsi4_dict);
+ shell = cc_panel_get_shell (CC_PANEL (self));
+ toplevel = cc_shell_get_toplevel (shell);
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel));
+ gtk_widget_show (GTK_WIDGET (dialog));
+}
+
+static void
+on_secure_boot_button_clicked_cb (GtkWidget *widget,
+ gpointer data)
+{
+ GtkWidget *toplevel;
+ CcShell *shell;
+ GtkWidget *boot_dialog;
+ CcfirmwareSecurityPanel *self = CC_FIRMWARE_SECURITY_PANEL (data);
+
+ boot_dialog = cc_firmware_security_boot_dialog_new (self->secure_boot_state);
+ shell = cc_panel_get_shell (CC_PANEL (self));
+ toplevel = cc_shell_get_toplevel (shell);
+ gtk_window_set_transient_for (GTK_WINDOW (boot_dialog), GTK_WINDOW (toplevel));
+ gtk_widget_show (boot_dialog);
+}
+
+static void
+set_hsi_button_view_contain (CcfirmwareSecurityPanel *self,
+ guint hsi_number,
+ gchar *title,
+ const gchar *description)
+{
+ switch (hsi_number)
+ {
+ case 0:
+ gtk_label_set_label (GTK_LABEL (self->hsi_circle_number), "0");
+ gtk_widget_add_css_class (self->hsi_circle_box, "level0");
+ gtk_widget_add_css_class (self->hsi_circle_number, "hsi0");
+ break;
+ case 1:
+ gtk_label_set_label (GTK_LABEL (self->hsi_circle_number), "1");
+ gtk_widget_add_css_class (self->hsi_circle_box, "level1");
+ gtk_widget_add_css_class (self->hsi_circle_number, "hsi1");
+ break;
+ case 2:
+ gtk_label_set_label (GTK_LABEL (self->hsi_circle_number), "2");
+ gtk_widget_add_css_class (self->hsi_circle_box, "level2");
+ gtk_widget_add_css_class (self->hsi_circle_number, "hsi2");
+ break;
+ case 3:
+ case 4:
+ gtk_label_set_label (GTK_LABEL (self->hsi_circle_number), "3");
+ gtk_widget_add_css_class (self->hsi_circle_box, "level3");
+ gtk_widget_add_css_class (self->hsi_circle_number, "hsi3");
+ break;
+ default:
+ gtk_label_set_label (GTK_LABEL (self->hsi_circle_number), "?");
+ gtk_widget_add_css_class (self->hsi_circle_box, "level1");
+ gtk_widget_add_css_class (self->hsi_circle_number, "hsi1");
+ break;
+ }
+
+ gtk_label_set_text (GTK_LABEL (self->hsi_label), title);
+ gtk_label_set_text (GTK_LABEL (self->hsi_description), description);
+}
+
+static void
+set_hsi_button_view (CcfirmwareSecurityPanel *self)
+{
+ switch (self->hsi_number)
+ {
+ case 0:
+ set_hsi_button_view_contain (self,
+ self->hsi_number,
+ /* TRANSLATORS: in reference to firmware protection: 0/4 stars */
+ _("Security Level 0"),
+ _("Exposed to serious security threats."));
+ break;
+ case 1:
+ set_hsi_button_view_contain (self,
+ self->hsi_number,
+ /* TRANSLATORS: in reference to firmware protection: 1/4 stars */
+ _("Security Level 1"),
+ _("Limited protection against simple security threats."));
+ break;
+ case 2:
+ set_hsi_button_view_contain (self,
+ self->hsi_number,
+ /* TRANSLATORS: in reference to firmware protection: 2/4 stars */
+ _("Security Level 2"),
+ _("Protected against common security threats."));
+ break;
+ case 3:
+ set_hsi_button_view_contain (self,
+ self->hsi_number,
+ /* TRANSLATORS: in reference to firmware protection: 3/4 stars */
+ _("Security Level 3"),
+ _("Protected against a wide range of security threats."));
+ break;
+ case 4:
+ set_hsi_button_view_contain (self,
+ /* Based on current HSI definition, the max HSI value would be 3. */
+ 3,
+ /* TRANSLATORS: in reference to firmware protection: 4/4 stars */
+ _("Comprehensive Protection"),
+ _("Protected against a wide range of security threats."));
+ break;
+ case G_MAXUINT:
+ set_hsi_button_view_contain (self,
+ self->hsi_number,
+ /* TRANSLATORS: in reference to firmware protection: ??? stars */
+ _("Security Level"),
+ _("Security levels are not available for this device."));
+ break;
+ default:
+ g_warning ("incorrect HSI number %u", self->hsi_number);
+ }
+}
+
+static void
+on_properties_bus_done_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr (GError) error = NULL;
+ g_autoptr (GVariant) val = NULL;
+ const gchar *hsi_str = NULL;
+ CcfirmwareSecurityPanel *self = CC_FIRMWARE_SECURITY_PANEL (user_data);
+
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
+ if (val == NULL)
+ {
+ g_warning ("failed to get HSI number");
+ return;
+ }
+
+ /* parse value */
+ hsi_str = g_variant_get_data (val);
+ if (hsi_str != NULL && g_str_has_prefix (hsi_str, "HSI:INVALID"))
+ {
+ self->hsi_number = G_MAXUINT;
+ }
+ else if (hsi_str != NULL && g_str_has_prefix (hsi_str, "HSI:"))
+ {
+ self->hsi_number = g_ascii_strtoll (hsi_str + 4, NULL, 10);
+ }
+ set_hsi_button_view (self);
+}
+
+static void
+on_properties_bus_ready_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcfirmwareSecurityPanel *self = CC_FIRMWARE_SECURITY_PANEL (user_data);
+ g_autoptr (GError) error = NULL;
+
+ self->properties_bus_proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+ if (self->properties_bus_proxy == NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("failed to connect fwupd: %s", error->message);
+
+ return;
+ }
+
+ g_dbus_proxy_call (self->properties_bus_proxy,
+ "Get",
+ g_variant_new ("(ss)",
+ "org.freedesktop.fwupd",
+ "HostSecurityId"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ on_properties_bus_done_cb,
+ self);
+}
+
+static void
+update_panel_visibility (const gchar *chassis_type)
+{
+ CcApplication *application;
+ gboolean visible = TRUE;
+
+ /* there's no point showing this */
+ if (g_strcmp0 (chassis_type, "vm") == 0 || g_strcmp0 (chassis_type, "") == 0)
+ visible = FALSE;
+ application = CC_APPLICATION (g_application_get_default ());
+ cc_shell_model_set_panel_visibility (cc_application_get_model (application),
+ "firmware-security",
+ visible ? CC_PANEL_VISIBLE : CC_PANEL_HIDDEN);
+ g_debug ("Firmware Security panel visible: %s as chassis was %s",
+ visible ? "yes" : "no",
+ chassis_type);
+}
+
+void
+cc_firmware_security_panel_static_init_func (void)
+{
+ g_autoptr(GDBusConnection) connection = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) inner = NULL;
+ g_autoptr(GVariant) variant = NULL;
+
+ connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!connection)
+ {
+ g_warning ("system bus not available: %s", error->message);
+ return;
+ }
+ variant = g_dbus_connection_call_sync (connection,
+ "org.freedesktop.hostname1",
+ "/org/freedesktop/hostname1",
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ g_variant_new ("(ss)",
+ "org.freedesktop.hostname1",
+ "Chassis"),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+ if (!variant)
+ {
+ g_warning ("Cannot get org.freedesktop.hostname1.Chassis: %s", error->message);
+ return;
+ }
+ g_variant_get (variant, "(v)", &inner);
+ update_panel_visibility (g_variant_get_string (inner, NULL));
+}
+
+static void
+cc_firmware_security_panel_finalize (GObject *object)
+{
+ CcfirmwareSecurityPanel *self = CC_FIRMWARE_SECURITY_PANEL (object);
+
+ g_clear_pointer (&self->hsi1_dict, g_hash_table_unref);
+ g_clear_pointer (&self->hsi2_dict, g_hash_table_unref);
+ g_clear_pointer (&self->hsi3_dict, g_hash_table_unref);
+ g_clear_pointer (&self->hsi4_dict, g_hash_table_unref);
+
+ g_clear_object (&self->bus_proxy);
+ g_clear_object (&self->properties_bus_proxy);
+
+ G_OBJECT_CLASS (cc_firmware_security_panel_parent_class)->finalize (object);
+}
+
+
+static void
+cc_firmware_security_panel_class_init (CcfirmwareSecurityPanelClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = cc_firmware_security_panel_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/firmware-security/cc-firmware-security-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcfirmwareSecurityPanel, firmware_security_log_pgroup);
+ gtk_widget_class_bind_template_child (widget_class, CcfirmwareSecurityPanel, firmware_security_log_stack);
+ gtk_widget_class_bind_template_child (widget_class, CcfirmwareSecurityPanel, hsi_button);
+ gtk_widget_class_bind_template_child (widget_class, CcfirmwareSecurityPanel, hsi_description);
+ gtk_widget_class_bind_template_child (widget_class, CcfirmwareSecurityPanel, hsi_circle_box);
+ gtk_widget_class_bind_template_child (widget_class, CcfirmwareSecurityPanel, hsi_circle_number);
+ gtk_widget_class_bind_template_child (widget_class, CcfirmwareSecurityPanel, hsi_label);
+ gtk_widget_class_bind_template_child (widget_class, CcfirmwareSecurityPanel, secure_boot_button);
+ gtk_widget_class_bind_template_child (widget_class, CcfirmwareSecurityPanel, secure_boot_description);
+ gtk_widget_class_bind_template_child (widget_class, CcfirmwareSecurityPanel, secure_boot_icon);
+ gtk_widget_class_bind_template_child (widget_class, CcfirmwareSecurityPanel, secure_boot_label);
+
+ gtk_widget_class_bind_template_callback (widget_class, on_hsi_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_secure_boot_button_clicked_cb);
+}
+
+static void
+cc_firmware_security_panel_init (CcfirmwareSecurityPanel *self)
+{
+ g_resources_register (cc_firmware_security_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->hsi1_dict = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) fu_security_attr_free);
+ self->hsi2_dict = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) fu_security_attr_free);
+ self->hsi3_dict = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) fu_security_attr_free);
+ self->hsi4_dict = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) fu_security_attr_free);
+
+ load_custom_css ("/org/gnome/control-center/firmware-security/security-level.css");
+
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.freedesktop.fwupd",
+ "/",
+ "org.freedesktop.DBus.Properties",
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ on_properties_bus_ready_cb,
+ self);
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.freedesktop.fwupd",
+ "/",
+ "org.freedesktop.fwupd",
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ on_bus_ready_cb,
+ self);
+}
diff --git a/panels/firmware-security/cc-firmware-security-panel.h b/panels/firmware-security/cc-firmware-security-panel.h
new file mode 100644
index 0000000..1c7a024
--- /dev/null
+++ b/panels/firmware-security/cc-firmware-security-panel.h
@@ -0,0 +1,34 @@
+/* cc-firmware-security-panel.h
+ *
+ * Copyright (C) 2021 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Kate Hsuan <hpa@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_FIRMWARE_SECURITY_PANEL (cc_firmware_security_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcfirmwareSecurityPanel, cc_firmware_security_panel, CC, FIRMWARE_SECURITY_PANEL, CcPanel)
+
+void cc_firmware_security_panel_static_init_func (void);
+
+G_END_DECLS
diff --git a/panels/firmware-security/cc-firmware-security-panel.ui b/panels/firmware-security/cc-firmware-security-panel.ui
new file mode 100644
index 0000000..f975ee7
--- /dev/null
+++ b/panels/firmware-security/cc-firmware-security-panel.ui
@@ -0,0 +1,176 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcfirmwareSecurityPanel" parent="CcPanel">
+ <child type="content">
+ <object class="AdwPreferencesPage">
+
+ <child>
+ <object class="AdwPreferencesGroup">
+
+ <child>
+ <object class="GtkBox" id="firmware_security_hbox">
+ <property name="spacing">24</property>
+ <property name="homogeneous">True</property>
+ <child>
+ <object class="GtkButton" id="hsi_button">
+ <property name="receives-default">True</property>
+ <property name="sensitive">True</property>
+ <property name="vexpand-set">True</property>
+ <signal name="clicked" handler="on_hsi_button_clicked_cb" swapped="no" />
+ <style>
+ <class name="card" />
+ </style>
+ <child>
+ <object class="GtkBox" id="hsi_box">
+ <property name="orientation">vertical</property>
+ <property name="halign">fill</property>
+ <property name="valign">start</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="margin-top">24</property>
+ <property name="margin-bottom">24</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkBox" id="hsi_circle_box">
+ <property name="orientation">vertical</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="margin-bottom">6</property>
+ <child>
+ <object class="GtkLabel" id="hsi_circle_number">
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="vexpand">True</property>
+ <property name="justify">center</property>
+ <property name="label">9</property>
+ <style>
+ <class name="hsi-level-font" />
+ </style>
+ </object>
+ </child>
+ <style>
+ <class name="hsi-level-box" />
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="hsi_label">
+ <property name="justify">center</property>
+ <property name="wrap">True</property>
+ <style>
+ <class name="heading" />
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="hsi_description">
+ <property name="wrap">True</property>
+ <property name="justify">center</property>
+ <property name="ellipsize">none</property>
+ <property name="lines">2</property>
+ <style>
+ <class name="caption" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="secure_boot_button">
+ <property name="receives-default">True</property>
+ <signal name="clicked" handler="on_secure_boot_button_clicked_cb" swapped="no" />
+ <style>
+ <class name="card" />
+ </style>
+ <child>
+ <object class="GtkBox" id="secure_boot_box">
+ <property name="orientation">vertical</property>
+ <property name="halign">fill</property>
+ <property name="valign">start</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="margin-top">24</property>
+ <property name="margin-bottom">24</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkImage" id="secure_boot_icon">
+ <property name="pixel-size">32</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="icon-name">channel-insecure</property>
+ <property name="margin-bottom">6</property>
+ <style>
+ <class name="security-level-icon" />
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="secure_boot_label">
+ <property name="justify">center</property>
+ <property name="wrap">True</property>
+ <style>
+ <class name="heading" />
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="secure_boot_description">
+ <property name="wrap">True</property>
+ <property name="justify">center</property>
+ <property name="ellipsize">none</property>
+ <property name="lines">2</property>
+ <style>
+ <class name="caption" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title">Security Events</property>
+ <child>
+ <object class="AdwViewStack" id="firmware_security_log_stack">
+ <child>
+ <object class="AdwViewStackPage">
+ <property name="name">no_event</property>
+ <property name="child">
+ <object class="AdwStatusPage">
+ <property name="vexpand">True</property>
+ <property name="opacity">0.5</property>
+ <property name="title" translatable="yes">No Events</property>
+ <property name="icon-name">document-open-recent-symbolic</property>
+ <style>
+ <class name="card" />
+ <class name="compact" />
+ </style>
+ </object>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="AdwViewStackPage">
+ <property name="name">page2</property>
+ <property name="child">
+ <object class="AdwPreferencesGroup" id="firmware_security_log_pgroup" />
+ </property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/firmware-security/cc-firmware-security-utils.c b/panels/firmware-security/cc-firmware-security-utils.c
new file mode 100644
index 0000000..f6df3ae
--- /dev/null
+++ b/panels/firmware-security/cc-firmware-security-utils.c
@@ -0,0 +1,373 @@
+/* cc-firmware-security-utils.c
+ *
+ * Copyright (C) 2021 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Kate Hsuan <hpa@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+
+#include "cc-firmware-security-utils.h"
+
+/* we don't need to keep this up to date, as any new attrs added by fwupd >= 1.8.3 will also
+ * come with translated titles *and* descriptions */
+static const gchar *
+fu_security_attr_get_title_fallback (const gchar *appstream_id)
+{
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_SPI_BIOSWE) == 0)
+ {
+ /* TRANSLATORS: Title: firmware refers to the flash chip in the computer */
+ return _("Firmware Write Protection");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_SPI_BLE) == 0)
+ {
+ /* TRANSLATORS: Title: firmware refers to the flash chip in the computer */
+ return _("Firmware Write Protection Lock");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_SPI_SMM_BWP) == 0)
+ {
+ /* TRANSLATORS: Title: SPI refers to the flash chip in the computer */
+ return _("Firmware BIOS Region");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_SPI_DESCRIPTOR) == 0)
+ {
+ /* TRANSLATORS: Title: firmware refers to the flash chip in the computer */
+ return _("Firmware BIOS Descriptor");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_PREBOOT_DMA_PROTECTION) == 0)
+ {
+ /* TRANSLATORS: Title: DMA as in https://en.wikipedia.org/wiki/DMA_attack */
+ return _("Pre-boot DMA Protection");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_INTEL_BOOTGUARD_ENABLED) == 0)
+ {
+ /* TRANSLATORS: Title: BootGuard is a trademark from Intel */
+ return _("Intel BootGuard");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_INTEL_BOOTGUARD_VERIFIED) == 0)
+ {
+ /* TRANSLATORS: Title: BootGuard is a trademark from Intel,
+ * verified boot refers to the way the boot process is verified */
+ return _("Intel BootGuard Verified Boot");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_INTEL_BOOTGUARD_ACM) == 0)
+ {
+ /* TRANSLATORS: Title: BootGuard is a trademark from Intel,
+ * ACM means to verify the integrity of Initial Boot Block */
+ return _("Intel BootGuard ACM Protected");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_INTEL_BOOTGUARD_POLICY) == 0)
+ {
+ /* TRANSLATORS: Title: BootGuard is a trademark from Intel,
+ * error policy is what to do on failure */
+ return _("Intel BootGuard Error Policy");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_INTEL_BOOTGUARD_OTP) == 0)
+ {
+ /* TRANSLATORS: Title: BootGuard is a trademark from Intel */
+ return _("Intel BootGuard Fuse");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_INTEL_CET_ENABLED) == 0)
+ {
+ /* TRANSLATORS: Title: CET = Control-flow Enforcement Technology,
+ * enabled means supported by the processor */
+ return _("Intel CET Enabled");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_INTEL_CET_ACTIVE) == 0)
+ {
+ /* TRANSLATORS: Title: CET = Control-flow Enforcement Technology,
+ * active means being used by the OS */
+ return _("Intel CET Active");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_INTEL_SMAP) == 0)
+ {
+ /* TRANSLATORS: Title: SMAP = Supervisor Mode Access Prevention */
+ return _("Intel SMAP");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_ENCRYPTED_RAM) == 0)
+ {
+ /* TRANSLATORS: Title: Memory contents are encrypted, e.g. Intel TME */
+ return _("Encrypted RAM");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_IOMMU) == 0)
+ {
+ /* TRANSLATORS: Title:
+ * https://en.wikipedia.org/wiki/Input%E2%80%93output_memory_management_unit */
+ return _("IOMMU Protection");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_KERNEL_LOCKDOWN) == 0)
+ {
+ /* TRANSLATORS: Title: lockdown is a security mode of the kernel */
+ return _("Linux Kernel Lockdown");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_KERNEL_TAINTED) == 0)
+ {
+ /* TRANSLATORS: Title: if it's tainted or not */
+ return _("Linux Kernel Verification");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_KERNEL_SWAP) == 0)
+ {
+ /* TRANSLATORS: Title: swap space or swap partition */
+ return _("Linux Swap");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_SUSPEND_TO_RAM) == 0)
+ {
+ /* TRANSLATORS: Title: sleep state */
+ return _("Suspend To RAM");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_SUSPEND_TO_IDLE) == 0)
+ {
+ /* TRANSLATORS: Title: a better sleep state */
+ return _("Suspend To Idle");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_UEFI_PK) == 0)
+ {
+ /* TRANSLATORS: Title: PK is the 'platform key' for the machine */
+ return _("UEFI Platform Key");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_UEFI_SECUREBOOT) == 0)
+ {
+ /* TRANSLATORS: Title: SB is a way of locking down UEFI */
+ return _("UEFI Secure Boot");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_TPM_EMPTY_PCR) == 0)
+ {
+ /* TRANSLATORS: Title: PCRs (Platform Configuration Registers) shouldn't be empty */
+ return _("TPM Platform Configuration");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_TPM_RECONSTRUCTION_PCR0) == 0)
+ {
+ /* TRANSLATORS: Title: the PCR is rebuilt from the TPM event log */
+ return _("TPM Reconstruction");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_TPM_VERSION_20) == 0)
+ {
+ /* TRANSLATORS: Title: TPM = Trusted Platform Module */
+ return _("TPM v2.0");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_MEI_MANUFACTURING_MODE) == 0)
+ {
+ /* TRANSLATORS: Title: MEI = Intel Management Engine */
+ return _("Intel Management Engine Manufacturing Mode");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_MEI_OVERRIDE_STRAP) == 0)
+ {
+ /* TRANSLATORS: Title: MEI = Intel Management Engine, and the "override" is enabled
+ * with a jumper -- luckily it is probably not accessible to end users on consumer
+ * boards */
+ return _("Intel Management Engine Override");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_MEI_VERSION) == 0)
+ {
+ /* TRANSLATORS: Title: MEI = Intel Management Engine */
+ return _("Intel Management Engine Version");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_FWUPD_UPDATES) == 0)
+ {
+ /* TRANSLATORS: Title: if firmware updates are available */
+ return _("Firmware Updates");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_FWUPD_ATTESTATION) == 0)
+ {
+ /* TRANSLATORS: Title: if we can verify the firmware checksums */
+ return _("Firmware Attestation");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_FWUPD_PLUGINS) == 0)
+ {
+ /* TRANSLATORS: Title: if the fwupd plugins are all present and correct */
+ return _("Firmware Updater Verification");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_PLATFORM_DEBUG_ENABLED) == 0 ||
+ g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_PLATFORM_DEBUG_LOCKED) == 0)
+ {
+ /* TRANSLATORS: Title: Allows debugging of parts using proprietary hardware */
+ return _("Platform Debugging");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_SUPPORTED_CPU) == 0)
+ {
+ /* TRANSLATORS: Title: if fwupd supports HSI on this chip */
+ return _("Processor Security Checks");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_AMD_ROLLBACK_PROTECTION) == 0)
+ {
+ /* TRANSLATORS: Title: if firmware enforces rollback protection */
+ return _("AMD Rollback Protection");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_AMD_SPI_REPLAY_PROTECTION) == 0)
+ {
+ /* TRANSLATORS: Title: if hardware enforces control of SPI replays */
+ return _("AMD Firmware Replay Protection");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_AMD_SPI_WRITE_PROTECTION) == 0)
+ {
+ /* TRANSLATORS: Title: if hardware enforces control of SPI writes */
+ return _("AMD Firmware Write Protection");
+ }
+ if (g_strcmp0 (appstream_id, FWUPD_SECURITY_ATTR_ID_PLATFORM_FUSED) == 0)
+ {
+ /* TRANSLATORS: Title: if the part has been fused */
+ return _("Fused Platform");
+ }
+ return NULL;
+}
+
+const gchar *
+fwupd_security_attr_result_to_string (FwupdSecurityAttrResult result)
+{
+ if (result == FWUPD_SECURITY_ATTR_RESULT_VALID)
+ {
+ /* TRANSLATORS: if the stauts is valid. For example security check is valid and key is valid. */
+ return _("Valid");
+ }
+ if (result == FWUPD_SECURITY_ATTR_RESULT_NOT_VALID)
+ {
+ /* TRANSLATORS: if the status or key is not valid. */
+ return _("Not Valid");
+ }
+ if (result == FWUPD_SECURITY_ATTR_RESULT_ENABLED)
+ {
+ /* TRANSLATORS: if the function is enabled through BIOS or OS settings. */
+ return _("Enabled");
+ }
+ if (result == FWUPD_SECURITY_ATTR_RESULT_NOT_ENABLED)
+ {
+ /* TRANSLATORS: if the function is not enabled through BIOS or OS settings. */
+ return _("Not Enabled");
+ }
+ if (result == FWUPD_SECURITY_ATTR_RESULT_LOCKED)
+ {
+ /* TRANSLATORS: the memory space or system mode is locked to prevent from malicious modification. */
+ return _("Locked");
+ }
+ if (result == FWUPD_SECURITY_ATTR_RESULT_NOT_LOCKED)
+ {
+ /* TRANSLATORS: the memory space or system mode is not locked. */
+ return _("Not Locked");
+ }
+ if (result == FWUPD_SECURITY_ATTR_RESULT_ENCRYPTED)
+ {
+ /* TRANSLATORS: The data is encrypted to prevent from malicious reading. */
+ return _("Encrypted");
+ }
+ if (result == FWUPD_SECURITY_ATTR_RESULT_NOT_ENCRYPTED)
+ {
+ /* TRANSLATORS: the data in memory is plane text. */
+ return _("Not Encrypted");
+ }
+ if (result == FWUPD_SECURITY_ATTR_RESULT_TAINTED)
+ {
+ /* TRANSLATORS: Linux kernel is tainted by third party kernel module. */
+ return _("Tainted");
+ }
+ if (result == FWUPD_SECURITY_ATTR_RESULT_NOT_TAINTED)
+ {
+ /* TRANSLATORS: All the loaded kernel module are licensed. */
+ return _("Not Tainted");
+ }
+ if (result == FWUPD_SECURITY_ATTR_RESULT_FOUND)
+ {
+ /* TRANSLATORS: the feature can be detected. */
+ return _("Found");
+ }
+ if (result == FWUPD_SECURITY_ATTR_RESULT_NOT_FOUND)
+ {
+ /* TRANSLATORS: the feature can't be detected. */
+ return _("Not Found");
+ }
+ if (result == FWUPD_SECURITY_ATTR_RESULT_SUPPORTED)
+ {
+ /* TRANSLATORS: the function is supported by hardware. */
+ return _("Supported");
+ }
+ if (result == FWUPD_SECURITY_ATTR_RESULT_NOT_SUPPORTED)
+ {
+ /* TRANSLATORS: the function isn't supported by hardware. */
+ return _("Not Supported");
+ }
+ return NULL;
+}
+
+
+/* ->summary and ->description are translated */
+FwupdSecurityAttr *
+fu_security_attr_new_from_variant (GVariantIter *iter)
+{
+ FwupdSecurityAttr *attr = g_new0 (FwupdSecurityAttr, 1);
+ const gchar *key;
+ GVariant *value;
+
+ while (g_variant_iter_next (iter, "{&sv}", &key, &value))
+ {
+ if (g_strcmp0 (key, "AppstreamId") == 0)
+ attr->appstream_id = g_variant_dup_string (value, NULL);
+ else if (g_strcmp0 (key, "Flags") == 0)
+ attr->flags = g_variant_get_uint64(value);
+ else if (g_strcmp0 (key, "HsiLevel") == 0)
+ attr->hsi_level = g_variant_get_uint32 (value);
+ else if (g_strcmp0 (key, "HsiResult") == 0)
+ attr->result = g_variant_get_uint32 (value);
+ else if (g_strcmp0 (key, "HsiResultFallback") == 0)
+ attr->result_fallback = g_variant_get_uint32 (value);
+ else if (g_strcmp0 (key, "Created") == 0)
+ attr->timestamp = g_variant_get_uint64 (value);
+ else if (g_strcmp0 (key, "Description") == 0)
+ attr->description = g_strdup (dgettext ("fwupd", g_variant_get_string (value, NULL)));
+ else if (g_strcmp0 (key, "Summary") == 0)
+ attr->title = g_strdup (dgettext ("fwupd", g_variant_get_string (value, NULL)));
+ g_variant_unref (value);
+ }
+
+ /* in fwupd <= 1.8.3 org.fwupd.hsi.Uefi.SecureBoot was incorrectly marked as HSI-0 */
+ if (g_strcmp0 (attr->appstream_id, FWUPD_SECURITY_ATTR_ID_UEFI_SECUREBOOT) == 0)
+ attr->hsi_level = 1;
+
+ /* fallback for older fwupd versions */
+ if (attr->appstream_id != NULL && attr->title == NULL)
+ attr->title = g_strdup (fu_security_attr_get_title_fallback (attr->appstream_id));
+
+ /* success */
+ return attr;
+}
+
+void
+fu_security_attr_free (FwupdSecurityAttr *attr)
+{
+ g_free (attr->appstream_id);
+ g_free (attr->title);
+ g_free (attr->description);
+ g_free (attr);
+}
+
+gboolean
+firmware_security_attr_has_flag (FwupdSecurityAttr *attr,
+ FwupdSecurityAttrFlags flag)
+{
+ return (attr->flags & flag) > 0;
+}
+
+void
+load_custom_css (const char *path)
+{
+ g_autoptr (GtkCssProvider) provider = gtk_css_provider_new ();
+ gtk_css_provider_load_from_resource (provider, path);
+ gtk_style_context_add_provider_for_display (gdk_display_get_default (),
+ GTK_STYLE_PROVIDER (provider),
+ GTK_STYLE_PROVIDER_PRIORITY_USER);
+}
diff --git a/panels/firmware-security/cc-firmware-security-utils.h b/panels/firmware-security/cc-firmware-security-utils.h
new file mode 100644
index 0000000..08343f5
--- /dev/null
+++ b/panels/firmware-security/cc-firmware-security-utils.h
@@ -0,0 +1,133 @@
+/* cc-firmware-security-utils.h
+ *
+ * Copyright (C) 2021 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Kate Hsuan <hpa@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+/* we don't need to keep this up to date and from fwupd >= 1.8.3 we only need the defines
+ * for the things we actually query, e.g. FWUPD_SECURITY_ATTR_ID_UEFI_SECUREBOOT */
+#define FWUPD_SECURITY_ATTR_ID_ACPI_DMAR "org.fwupd.hsi.AcpiDmar"
+#define FWUPD_SECURITY_ATTR_ID_ENCRYPTED_RAM "org.fwupd.hsi.EncryptedRam"
+#define FWUPD_SECURITY_ATTR_ID_FWUPD_ATTESTATION "org.fwupd.hsi.Fwupd.Attestation"
+#define FWUPD_SECURITY_ATTR_ID_FWUPD_PLUGINS "org.fwupd.hsi.Fwupd.Plugins"
+#define FWUPD_SECURITY_ATTR_ID_FWUPD_UPDATES "org.fwupd.hsi.Fwupd.Updates"
+#define FWUPD_SECURITY_ATTR_ID_INTEL_BOOTGUARD_ENABLED "org.fwupd.hsi.IntelBootguard.Enabled"
+#define FWUPD_SECURITY_ATTR_ID_INTEL_BOOTGUARD_VERIFIED "org.fwupd.hsi.IntelBootguard.Verified"
+#define FWUPD_SECURITY_ATTR_ID_INTEL_BOOTGUARD_ACM "org.fwupd.hsi.IntelBootguard.Acm"
+#define FWUPD_SECURITY_ATTR_ID_INTEL_BOOTGUARD_POLICY "org.fwupd.hsi.IntelBootguard.Policy"
+#define FWUPD_SECURITY_ATTR_ID_INTEL_BOOTGUARD_OTP "org.fwupd.hsi.IntelBootguard.Otp"
+#define FWUPD_SECURITY_ATTR_ID_INTEL_CET_ENABLED "org.fwupd.hsi.IntelCet.Enabled"
+#define FWUPD_SECURITY_ATTR_ID_INTEL_CET_ACTIVE "org.fwupd.hsi.IntelCet.Active"
+#define FWUPD_SECURITY_ATTR_ID_INTEL_SMAP "org.fwupd.hsi.IntelSmap"
+#define FWUPD_SECURITY_ATTR_ID_IOMMU "org.fwupd.hsi.Iommu"
+#define FWUPD_SECURITY_ATTR_ID_KERNEL_LOCKDOWN "org.fwupd.hsi.Kernel.Lockdown"
+#define FWUPD_SECURITY_ATTR_ID_KERNEL_SWAP "org.fwupd.hsi.Kernel.Swap"
+#define FWUPD_SECURITY_ATTR_ID_KERNEL_TAINTED "org.fwupd.hsi.Kernel.Tainted"
+#define FWUPD_SECURITY_ATTR_ID_MEI_MANUFACTURING_MODE "org.fwupd.hsi.Mei.ManufacturingMode"
+#define FWUPD_SECURITY_ATTR_ID_MEI_OVERRIDE_STRAP "org.fwupd.hsi.Mei.OverrideStrap"
+#define FWUPD_SECURITY_ATTR_ID_MEI_VERSION "org.fwupd.hsi.Mei.Version"
+#define FWUPD_SECURITY_ATTR_ID_SPI_BIOSWE "org.fwupd.hsi.Spi.Bioswe"
+#define FWUPD_SECURITY_ATTR_ID_SPI_BLE "org.fwupd.hsi.Spi.Ble"
+#define FWUPD_SECURITY_ATTR_ID_SPI_SMM_BWP "org.fwupd.hsi.Spi.SmmBwp"
+#define FWUPD_SECURITY_ATTR_ID_SPI_DESCRIPTOR "org.fwupd.hsi.Spi.Descriptor"
+#define FWUPD_SECURITY_ATTR_ID_SUSPEND_TO_IDLE "org.fwupd.hsi.SuspendToIdle"
+#define FWUPD_SECURITY_ATTR_ID_SUSPEND_TO_RAM "org.fwupd.hsi.SuspendToRam"
+#define FWUPD_SECURITY_ATTR_ID_TPM_EMPTY_PCR "org.fwupd.hsi.Tpm.EmptyPcr"
+#define FWUPD_SECURITY_ATTR_ID_TPM_RECONSTRUCTION_PCR0 "org.fwupd.hsi.Tpm.ReconstructionPcr0"
+#define FWUPD_SECURITY_ATTR_ID_TPM_VERSION_20 "org.fwupd.hsi.Tpm.Version20"
+#define FWUPD_SECURITY_ATTR_ID_UEFI_SECUREBOOT "org.fwupd.hsi.Uefi.SecureBoot"
+#define FWUPD_SECURITY_ATTR_ID_INTEL_DCI_ENABLED "org.fwupd.hsi.IntelDci.Enabled"
+#define FWUPD_SECURITY_ATTR_ID_INTEL_DCI_LOCKED "org.fwupd.hsi.IntelDci.Locked"
+#define FWUPD_SECURITY_ATTR_ID_UEFI_PK "org.fwupd.hsi.Uefi.Pk"
+#define FWUPD_SECURITY_ATTR_ID_PREBOOT_DMA_PROTECTION "org.fwupd.hsi.PrebootDma"
+#define FWUPD_SECURITY_ATTR_ID_SUPPORTED_CPU "org.fwupd.hsi.SupportedCpu"
+#define FWUPD_SECURITY_ATTR_ID_PLATFORM_DEBUG_LOCKED "org.fwupd.hsi.PlatformDebugLocked"
+#define FWUPD_SECURITY_ATTR_ID_AMD_ROLLBACK_PROTECTION "org.fwupd.hsi.Amd.RollbackProtection"
+#define FWUPD_SECURITY_ATTR_ID_AMD_SPI_WRITE_PROTECTION "org.fwupd.hsi.Amd.SpiWriteProtection"
+#define FWUPD_SECURITY_ATTR_ID_AMD_SPI_REPLAY_PROTECTION "org.fwupd.hsi.Amd.SpiReplayProtection"
+#define FWUPD_SECURITY_ATTR_ID_PLATFORM_DEBUG_ENABLED "org.fwupd.hsi.PlatformDebugEnabled"
+#define FWUPD_SECURITY_ATTR_ID_PLATFORM_FUSED "org.fwupd.hsi.PlatformFused"
+
+typedef enum {
+ SECURE_BOOT_STATE_UNKNOWN,
+ SECURE_BOOT_STATE_ACTIVE,
+ SECURE_BOOT_STATE_INACTIVE,
+ SECURE_BOOT_STATE_PROBLEMS,
+} SecureBootState;
+
+typedef enum {
+ FWUPD_SECURITY_ATTR_FLAG_NONE = 0,
+ FWUPD_SECURITY_ATTR_FLAG_SUCCESS = 1 << 0,
+ FWUPD_SECURITY_ATTR_FLAG_OBSOLETED = 1 << 1,
+ FWUPD_SECURITY_ATTR_FLAG_RUNTIME_UPDATES = 1 << 8,
+ FWUPD_SECURITY_ATTR_FLAG_RUNTIME_ATTESTATION = 1 << 9,
+ FWUPD_SECURITY_ATTR_FLAG_RUNTIME_ISSUE = 1 << 10,
+ FWUPD_SECURITY_ATTR_FLAG_ACTION_CONTACT_OEM = 1 << 11,
+ FWUPD_SECURITY_ATTR_FLAG_ACTION_CONFIG_FW = 1 << 12,
+ FWUPD_SECURITY_ATTR_FLAG_ACTION_CONFIG_OS = 1 << 13,
+} FwupdSecurityAttrFlags;
+
+typedef enum {
+ FWUPD_SECURITY_ATTR_RESULT_UNKNOWN,
+ FWUPD_SECURITY_ATTR_RESULT_ENABLED,
+ FWUPD_SECURITY_ATTR_RESULT_NOT_ENABLED,
+ FWUPD_SECURITY_ATTR_RESULT_VALID,
+ FWUPD_SECURITY_ATTR_RESULT_NOT_VALID,
+ FWUPD_SECURITY_ATTR_RESULT_LOCKED,
+ FWUPD_SECURITY_ATTR_RESULT_NOT_LOCKED,
+ FWUPD_SECURITY_ATTR_RESULT_ENCRYPTED,
+ FWUPD_SECURITY_ATTR_RESULT_NOT_ENCRYPTED,
+ FWUPD_SECURITY_ATTR_RESULT_TAINTED,
+ FWUPD_SECURITY_ATTR_RESULT_NOT_TAINTED,
+ FWUPD_SECURITY_ATTR_RESULT_FOUND,
+ FWUPD_SECURITY_ATTR_RESULT_NOT_FOUND,
+ FWUPD_SECURITY_ATTR_RESULT_SUPPORTED,
+ FWUPD_SECURITY_ATTR_RESULT_NOT_SUPPORTED,
+ FWUPD_SECURITY_ATTR_RESULT_LAST
+} FwupdSecurityAttrResult;
+
+typedef struct {
+ FwupdSecurityAttrResult result;
+ FwupdSecurityAttrResult result_fallback;
+ FwupdSecurityAttrFlags flags;
+ guint32 hsi_level;
+ guint64 timestamp;
+ gchar *appstream_id;
+ gchar *title;
+ gchar *description;
+} FwupdSecurityAttr;
+
+FwupdSecurityAttr *fu_security_attr_new_from_variant (GVariantIter *iter);
+void fu_security_attr_free (FwupdSecurityAttr *attr);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (FwupdSecurityAttr, fu_security_attr_free)
+
+gboolean firmware_security_attr_has_flag (FwupdSecurityAttr *attr,
+ FwupdSecurityAttrFlags flag);
+void load_custom_css (const char *path);
+const gchar *fwupd_security_attr_result_to_string (FwupdSecurityAttrResult result);
+gboolean fwupd_get_result_status (FwupdSecurityAttrResult result);
+
+G_END_DECLS
diff --git a/panels/firmware-security/firmware-security.gresource.xml b/panels/firmware-security/firmware-security.gresource.xml
new file mode 100644
index 0000000..f44f6fb
--- /dev/null
+++ b/panels/firmware-security/firmware-security.gresource.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/firmware-security">
+ <file preprocess="xml-stripblanks">cc-firmware-security-panel.ui</file>
+ <file preprocess="xml-stripblanks">cc-firmware-security-dialog.ui</file>
+ <file preprocess="xml-stripblanks">cc-firmware-security-boot-dialog.ui</file>
+ <file>security-level.css</file>
+ </gresource>
+</gresources>
diff --git a/panels/firmware-security/gnome-firmware-security-panel.desktop.in.in b/panels/firmware-security/gnome-firmware-security-panel.desktop.in.in
new file mode 100644
index 0000000..184ee22
--- /dev/null
+++ b/panels/firmware-security/gnome-firmware-security-panel.desktop.in.in
@@ -0,0 +1,19 @@
+[Desktop Entry]
+Name=Device Security
+Comment=Host firmware security status
+Exec=gnome-control-center firmware-security
+# FIXME
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=security-high-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-PrivacySettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=privacy
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: Search terms to find the Privacy panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=screen;lock;diagnostics;crash;private;recent;temporary;tmp;index;name;network;identity;privacy;
diff --git a/panels/firmware-security/meson.build b/panels/firmware-security/meson.build
new file mode 100644
index 0000000..0325568
--- /dev/null
+++ b/panels/firmware-security/meson.build
@@ -0,0 +1,44 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+sources = files('cc-firmware-security-utils.c',
+ 'cc-firmware-security-panel.c',
+ 'cc-firmware-security-dialog.c',
+ 'cc-firmware-security-boot-dialog.c')
+
+resource_data = files('cc-firmware-security-panel.ui',
+ 'cc-firmware-security-dialog.ui',
+ 'cc-firmware-security-boot-dialog.ui')
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname.underscorify (),
+ dependencies: resource_data,
+ export: true
+)
+
+cflags += '-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir)
+
+panels_libs += static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [top_inc, common_inc],
+ dependencies: common_deps,
+ c_args: cflags
+)
diff --git a/panels/firmware-security/security-level.css b/panels/firmware-security/security-level.css
new file mode 100644
index 0000000..64d724f
--- /dev/null
+++ b/panels/firmware-security/security-level.css
@@ -0,0 +1,119 @@
+.hsi-level-box {
+ border-radius: 9999px;
+ min-width: 64px;
+ min-height: 64px;
+
+}
+
+.hsi-level-box.level0 {
+ background-color: alpha(@error_color, .25);
+}
+
+.hsi-level-box.level1 {
+ background-color: alpha(@light_4, .25);
+}
+
+.hsi-level-box.level2 {
+ background-color: alpha(@warning_color, .25);
+}
+
+.hsi-level-box.level3 {
+ background-color: alpha(@success_color, .25);
+}
+
+.hsi-level-font {
+ font-size: 32px;
+ font-weight: 800;
+}
+
+.hsi-level-font.hsi0 {
+ color: @error_color;
+}
+
+.hsi-level-font.hsi1 {
+ color: @light_4;
+}
+
+.hsi-level-font.hsi2 {
+ color: @warning_color;
+}
+
+.hsi-level-font.hsi3 {
+ color: @success_color;
+}
+
+.security-level-icon {
+ border-radius: 9999px;
+ min-width: 64px;
+ min-height: 64px;
+}
+
+.security-level-icon.good {
+ color: @success_color;
+ background-color: alpha(@success_color, .25);
+}
+
+.security-level-icon.error {
+ color: @error_color;
+ background-color: alpha(@error_color, .25);
+}
+
+.security-level-icon.warning {
+ color: @warning_color;
+ background-color: alpha(@warning_color, .25);
+}
+
+.security-level-icon.neutral {
+ color: @light_4;
+ background-color: alpha(@light_4, .25);
+}
+
+#color_green {
+ color: @success_color;
+}
+
+#color_dim {
+ color: @light_4f;
+}
+
+row.success-icon image.icon {
+ color: @success_color;
+}
+
+row.warning-icon image.icon {
+ color: @warning_color;
+}
+
+row.error-icon image.icon {
+ color: @error_color;
+}
+
+row.gray-icon image {
+ color: @light_4;
+}
+
+row.success-hsi-icon image.hsi_icon {
+ color: @success_color;
+}
+
+row.error-hsi-icon image.hsi_icon {
+ color: @error_color;
+}
+
+row.success-title label.hsi_label {
+ font-weight: bold;
+ color: @success_color;
+}
+
+row.error-title label.hsi_label {
+ font-weight: bold;
+ color: @error_color;
+}
+
+row.security-description-row label.subtitle {
+ padding: 12px 0;
+}
+
+row.hide-arrow image.expander-row-arrow {
+ opacity: 0;
+}
diff --git a/panels/info-overview/cc-info-overview-panel.c b/panels/info-overview/cc-info-overview-panel.c
new file mode 100644
index 0000000..1ae5c7a
--- /dev/null
+++ b/panels/info-overview/cc-info-overview-panel.c
@@ -0,0 +1,993 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2019 Purism SPC
+ * Copyright (C) 2017 Mohammed Sadiq <sadiq@sadiqpk.org>
+ * Copyright (C) 2010 Red Hat, Inc
+ * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+
+#include "cc-hostname-entry.h"
+#include "shell/cc-object-storage.h"
+
+#include "cc-info-overview-resources.h"
+#include "info-cleanup.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gio/gunixmounts.h>
+#include <gio/gdesktopappinfo.h>
+
+#include <glibtop/fsusage.h>
+#include <glibtop/mountlist.h>
+#include <glibtop/mem.h>
+#include <glibtop/sysinfo.h>
+#include <udisks/udisks.h>
+#include <gudev/gudev.h>
+
+#include <gdk/gdk.h>
+
+#ifdef GDK_WINDOWING_WAYLAND
+#include <gdk/wayland/gdkwayland.h>
+#endif
+#ifdef GDK_WINDOWING_X11
+#include <gdk/x11/gdkx.h>
+#endif
+
+#include "cc-list-row.h"
+#include "cc-info-overview-panel.h"
+
+struct _CcInfoOverviewPanel
+{
+ CcPanel parent_instance;
+
+ GtkEntry *device_name_entry;
+ GtkWidget *rename_button;
+ CcListRow *disk_row;
+ CcListRow *gnome_version_row;
+ CcListRow *graphics_row;
+ CcListRow *hardware_model_row;
+ GtkDialog *hostname_editor;
+ CcHostnameEntry *hostname_entry;
+ CcListRow *hostname_row;
+ CcListRow *memory_row;
+ GtkPicture *os_logo;
+ CcListRow *os_name_row;
+ CcListRow *os_build_row;
+ CcListRow *os_type_row;
+ CcListRow *processor_row;
+ AdwActionRow *software_updates_row;
+ CcListRow *virtualization_row;
+ CcListRow *windowing_system_row;
+};
+
+G_DEFINE_TYPE (CcInfoOverviewPanel, cc_info_overview_panel, CC_TYPE_PANEL)
+
+static char *
+get_renderer_from_session (void)
+{
+ g_autoptr(GDBusProxy) session_proxy = NULL;
+ g_autoptr(GVariant) renderer_variant = NULL;
+ char *renderer;
+ g_autoptr(GError) error = NULL;
+
+ session_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.gnome.SessionManager",
+ "/org/gnome/SessionManager",
+ "org.gnome.SessionManager",
+ NULL, &error);
+ if (error != NULL)
+ {
+ g_warning ("Unable to connect to create a proxy for org.gnome.SessionManager: %s",
+ error->message);
+ return NULL;
+ }
+
+ renderer_variant = g_dbus_proxy_get_cached_property (session_proxy, "Renderer");
+
+ if (!renderer_variant)
+ {
+ g_warning ("Unable to retrieve org.gnome.SessionManager.Renderer property");
+ return NULL;
+ }
+
+ renderer = info_cleanup (g_variant_get_string (renderer_variant, NULL));
+
+ return renderer;
+}
+
+/* @env is an array of strings with each pair of strings being the
+ * key followed by the value */
+static char *
+get_renderer_from_helper (const char **env)
+{
+ int status;
+ char *argv[] = { LIBEXECDIR "/gnome-control-center-print-renderer", NULL };
+ g_auto(GStrv) envp = NULL;
+ g_autofree char *renderer = NULL;
+ g_autoptr(GError) error = NULL;
+
+ g_debug ("About to launch '%s'", argv[0]);
+
+ if (env != NULL)
+ {
+ guint i;
+ g_debug ("With environment:");
+ envp = g_get_environ ();
+ for (i = 0; env != NULL && env[i] != NULL; i = i + 2)
+ {
+ g_debug (" %s = %s", env[i], env[i+1]);
+ envp = g_environ_setenv (envp, env[i], env[i+1], TRUE);
+ }
+ }
+ else
+ {
+ g_debug ("No additional environment variables");
+ }
+
+ if (!g_spawn_sync (NULL, (char **) argv, envp, 0, NULL, NULL, &renderer, NULL, &status, &error))
+ {
+ g_debug ("Failed to get GPU: %s", error->message);
+ return NULL;
+ }
+
+ if (!g_spawn_check_wait_status (status, NULL))
+ return NULL;
+
+ if (renderer == NULL || *renderer == '\0')
+ return NULL;
+
+ return info_cleanup (renderer);
+}
+
+typedef struct {
+ char *name;
+ gboolean is_default;
+} GpuData;
+
+static int
+gpu_data_sort (gconstpointer a, gconstpointer b)
+{
+ GpuData *gpu_a = (GpuData *) a;
+ GpuData *gpu_b = (GpuData *) b;
+
+ if (gpu_a->is_default)
+ return 1;
+ if (gpu_b->is_default)
+ return -1;
+ return 0;
+}
+
+static void
+gpu_data_free (GpuData *data)
+{
+ g_free (data->name);
+ g_free (data);
+}
+
+static char *
+get_renderer_from_switcheroo (void)
+{
+ g_autoptr(GDBusProxy) switcheroo_proxy = NULL;
+ g_autoptr(GVariant) variant = NULL;
+ g_autoptr(GError) error = NULL;
+ GString *renderers_string;
+ guint i, num_children;
+ GSList *renderers, *l;
+
+ switcheroo_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "net.hadess.SwitcherooControl",
+ "/net/hadess/SwitcherooControl",
+ "net.hadess.SwitcherooControl",
+ NULL, &error);
+ if (switcheroo_proxy == NULL)
+ {
+ g_debug ("Unable to connect to create a proxy for net.hadess.SwitcherooControl: %s",
+ error->message);
+ return NULL;
+ }
+
+ variant = g_dbus_proxy_get_cached_property (switcheroo_proxy, "GPUs");
+
+ if (!variant)
+ {
+ g_debug ("Unable to retrieve net.hadess.SwitcherooControl.GPUs property, the daemon is likely not running");
+ return NULL;
+ }
+
+ renderers_string = g_string_new (NULL);
+ num_children = g_variant_n_children (variant);
+ renderers = NULL;
+ for (i = 0; i < num_children; i++)
+ {
+ g_autoptr(GVariant) gpu;
+ g_autoptr(GVariant) name = NULL;
+ g_autoptr(GVariant) env = NULL;
+ g_autoptr(GVariant) default_variant = NULL;
+ const char *name_s;
+ g_autofree const char **env_s = NULL;
+ gsize env_len;
+ g_autofree char *renderer = NULL;
+ GpuData *gpu_data;
+
+ gpu = g_variant_get_child_value (variant, i);
+ if (!gpu ||
+ !g_variant_is_of_type (gpu, G_VARIANT_TYPE ("a{s*}")))
+ continue;
+
+ name = g_variant_lookup_value (gpu, "Name", NULL);
+ env = g_variant_lookup_value (gpu, "Environment", NULL);
+ if (!name || !env)
+ continue;
+ name_s = g_variant_get_string (name, NULL);
+ g_debug ("Getting renderer from helper for GPU '%s'", name_s);
+ env_s = g_variant_get_strv (env, &env_len);
+ if (env_s != NULL && env_len % 2 != 0)
+ {
+ g_autofree char *debug = NULL;
+ debug = g_strjoinv ("\n", (char **) env_s);
+ g_warning ("Invalid environment returned from switcheroo:\n%s", debug);
+ g_clear_pointer (&env_s, g_free);
+ }
+
+ renderer = get_renderer_from_helper (env_s);
+ default_variant = g_variant_lookup_value (gpu, "Default", NULL);
+
+ /* We could give up if we don't have a renderer, but that
+ * might just mean gnome-session isn't installed. We fall back
+ * to the device name in udev instead, which is better than nothing */
+
+ gpu_data = g_new0 (GpuData, 1);
+ gpu_data->name = g_strdup (renderer ? renderer : name_s);
+ gpu_data->is_default = default_variant ? g_variant_get_boolean (default_variant) : FALSE;
+ renderers = g_slist_prepend (renderers, gpu_data);
+ }
+
+ renderers = g_slist_sort (renderers, gpu_data_sort);
+ for (l = renderers; l != NULL; l = l->next)
+ {
+ GpuData *data = l->data;
+ if (renderers_string->len > 0)
+ g_string_append (renderers_string, " / ");
+ g_string_append (renderers_string, data->name);
+ }
+ g_slist_free_full (renderers, (GDestroyNotify) gpu_data_free);
+
+ if (renderers_string->len == 0)
+ {
+ g_string_free (renderers_string, TRUE);
+ return NULL;
+ }
+
+ return g_string_free (renderers_string, FALSE);
+}
+
+static gchar *
+get_graphics_hardware_string (void)
+{
+ g_autofree char *discrete_renderer = NULL;
+ g_autofree char *renderer = NULL;
+
+ renderer = get_renderer_from_switcheroo ();
+ if (!renderer)
+ renderer = get_renderer_from_session ();
+ if (!renderer)
+ renderer = get_renderer_from_helper (NULL);
+ if (!renderer)
+ return g_strdup (_("Unknown"));
+ return g_strdup (renderer);
+}
+
+static char *
+get_os_name (void)
+{
+ g_autofree gchar *name = NULL;
+ g_autofree gchar *version_id = NULL;
+ g_autofree gchar *pretty_name = NULL;
+
+ name = g_get_os_info (G_OS_INFO_KEY_NAME);
+ version_id = g_get_os_info (G_OS_INFO_KEY_VERSION_ID);
+ pretty_name = g_get_os_info (G_OS_INFO_KEY_PRETTY_NAME);
+
+ if (pretty_name)
+ return g_steal_pointer (&pretty_name);
+ else if (name && version_id)
+ return g_strdup_printf ("%s %s", name, version_id);
+ else
+ return g_strdup (_("Unknown"));
+}
+
+static char *
+get_os_build_id (void)
+{
+ char *build_id = NULL;
+
+ build_id = g_get_os_info ("BUILD_ID");
+
+ return build_id;
+}
+
+static char *
+get_os_type (void)
+{
+ if (GLIB_SIZEOF_VOID_P == 8)
+ /* translators: This is the type of architecture for the OS */
+ return g_strdup_printf (_("64-bit"));
+ else
+ /* translators: This is the type of architecture for the OS */
+ return g_strdup_printf (_("32-bit"));
+}
+
+static void
+get_primary_disc_info (CcInfoOverviewPanel *self)
+{
+ g_autoptr(UDisksClient) client = NULL;
+ GDBusObjectManager *manager;
+ g_autolist(GDBusObject) objects = NULL;
+ GList *l;
+ guint64 total_size;
+ g_autoptr(GError) error = NULL;
+
+ total_size = 0;
+
+ client = udisks_client_new_sync (NULL, &error);
+ if (client == NULL)
+ {
+ g_warning ("Unable to get UDisks client: %s. Disk information will not be available.",
+ error->message);
+ cc_list_row_set_secondary_label (self->disk_row, _("Unknown"));
+ return;
+ }
+
+ manager = udisks_client_get_object_manager (client);
+ objects = g_dbus_object_manager_get_objects (manager);
+
+ for (l = objects; l != NULL; l = l->next)
+ {
+ UDisksDrive *drive;
+ drive = udisks_object_peek_drive (UDISKS_OBJECT (l->data));
+
+ /* Skip removable devices */
+ if (drive == NULL ||
+ udisks_drive_get_removable (drive) ||
+ udisks_drive_get_ejectable (drive))
+ {
+ continue;
+ }
+
+ total_size += udisks_drive_get_size (drive);
+ }
+
+ if (total_size > 0)
+ {
+ g_autofree gchar *size = g_format_size (total_size);
+ cc_list_row_set_secondary_label (self->disk_row, size);
+ }
+ else
+ {
+ cc_list_row_set_secondary_label (self->disk_row, _("Unknown"));
+ }
+}
+
+static void
+get_hardware_model (CcInfoOverviewPanel *self)
+{
+ g_autoptr(GDBusProxy) hostnamed_proxy = NULL;
+ g_autoptr(GVariant) vendor_variant = NULL;
+ g_autoptr(GVariant) model_variant = NULL;
+ const char *vendor_string, *model_string;
+ g_autoptr(GError) error = NULL;
+
+ hostnamed_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.freedesktop.hostname1",
+ "/org/freedesktop/hostname1",
+ "org.freedesktop.hostname1",
+ NULL,
+ &error);
+ if (hostnamed_proxy == NULL)
+ {
+ g_debug ("Couldn't get hostnamed to start, bailing: %s", error->message);
+ return;
+ }
+
+ vendor_variant = g_dbus_proxy_get_cached_property (hostnamed_proxy, "HardwareVendor");
+ if (!vendor_variant)
+ {
+ g_debug ("Unable to retrieve org.freedesktop.hostname1.HardwareVendor property");
+ return;
+ }
+
+ model_variant = g_dbus_proxy_get_cached_property (hostnamed_proxy, "HardwareModel");
+ if (!model_variant)
+ {
+ g_debug ("Unable to retrieve org.freedesktop.hostname1.HardwareModel property");
+ return;
+ }
+
+ vendor_string = g_variant_get_string (vendor_variant, NULL),
+ model_string = g_variant_get_string (model_variant, NULL);
+
+ if (vendor_string && g_strcmp0 (vendor_string, "") != 0)
+ {
+ g_autofree gchar *vendor_model = NULL;
+
+ vendor_model = g_strdup_printf ("%s %s", vendor_string, model_string);
+
+ cc_list_row_set_secondary_label (self->hardware_model_row, vendor_model);
+ gtk_widget_set_visible (GTK_WIDGET (self->hardware_model_row), TRUE);
+ }
+}
+
+static char *
+get_cpu_info (const glibtop_sysinfo *info)
+{
+ g_autoptr(GHashTable) counts = NULL;
+ g_autoptr(GString) cpu = NULL;
+ GHashTableIter iter;
+ gpointer key, value;
+ int i;
+ int j;
+
+ counts = g_hash_table_new (g_str_hash, g_str_equal);
+
+ /* count duplicates */
+ for (i = 0; i != info->ncpu; ++i)
+ {
+ const char * const keys[] = { "model name", "cpu", "Processor" };
+ char *model;
+ int *count;
+
+ model = NULL;
+
+ for (j = 0; model == NULL && j != G_N_ELEMENTS (keys); ++j)
+ {
+ model = g_hash_table_lookup (info->cpuinfo[i].values,
+ keys[j]);
+ }
+
+ if (model == NULL)
+ continue;
+
+ count = g_hash_table_lookup (counts, model);
+ if (count == NULL)
+ g_hash_table_insert (counts, model, GINT_TO_POINTER (1));
+ else
+ g_hash_table_replace (counts, model, GINT_TO_POINTER (GPOINTER_TO_INT (count) + 1));
+ }
+
+ cpu = g_string_new (NULL);
+ g_hash_table_iter_init (&iter, counts);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ g_autofree char *cleanedup = NULL;
+ int count;
+
+ count = GPOINTER_TO_INT (value);
+ cleanedup = info_cleanup ((const char *) key);
+ if (cpu->len != 0)
+ g_string_append_printf (cpu, " ");
+ if (count > 1)
+ g_string_append_printf (cpu, "%s \303\227 %d", cleanedup, count);
+ else
+ g_string_append_printf (cpu, "%s", cleanedup);
+ }
+
+ return g_strdup (cpu->str);
+}
+
+static struct {
+ const char *id;
+ const char *display;
+} const virt_tech[] = {
+ { "kvm", "KVM" },
+ { "qemu", "QEmu" },
+ { "vmware", "VMware" },
+ { "microsoft", "Microsoft" },
+ { "oracle", "Oracle" },
+ { "xen", "Xen" },
+ { "bochs", "Bochs" },
+ { "chroot", "chroot" },
+ { "openvz", "OpenVZ" },
+ { "lxc", "LXC" },
+ { "lxc-libvirt", "LXC (libvirt)" },
+ { "systemd-nspawn", "systemd (nspawn)" }
+};
+
+static void
+set_virtualization_label (CcInfoOverviewPanel *self,
+ const char *virt)
+{
+ const char *display_name;
+ guint i;
+
+ if (virt == NULL || *virt == '\0')
+ {
+ gtk_widget_hide (GTK_WIDGET (self->virtualization_row));
+ return;
+ }
+
+ gtk_widget_show (GTK_WIDGET (self->virtualization_row));
+
+ display_name = NULL;
+ for (i = 0; i < G_N_ELEMENTS (virt_tech); i++)
+ {
+ if (g_str_equal (virt_tech[i].id, virt))
+ {
+ display_name = _(virt_tech[i].display);
+ break;
+ }
+ }
+
+ cc_list_row_set_secondary_label (self->virtualization_row, display_name ? display_name : virt);
+}
+
+static void
+info_overview_panel_setup_virt (CcInfoOverviewPanel *self)
+{
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GDBusProxy) systemd_proxy = NULL;
+ g_autoptr(GVariant) variant = NULL;
+ GVariant *inner;
+
+ systemd_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1",
+ NULL,
+ &error);
+
+ if (systemd_proxy == NULL)
+ {
+ g_debug ("systemd not available, bailing: %s", error->message);
+ set_virtualization_label (self, NULL);
+ return;
+ }
+
+ variant = g_dbus_proxy_call_sync (systemd_proxy,
+ "org.freedesktop.DBus.Properties.Get",
+ g_variant_new ("(ss)", "org.freedesktop.systemd1.Manager", "Virtualization"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+ if (variant == NULL)
+ {
+ g_debug ("Failed to get property '%s': %s", "Virtualization", error->message);
+ set_virtualization_label (self, NULL);
+ return;
+ }
+
+ g_variant_get (variant, "(v)", &inner);
+ set_virtualization_label (self, g_variant_get_string (inner, NULL));
+}
+
+static const char *
+get_windowing_system (void)
+{
+ GdkDisplay *display;
+
+ display = gdk_display_get_default ();
+
+#if defined(GDK_WINDOWING_X11)
+ if (GDK_IS_X11_DISPLAY (display))
+ return _("X11");
+#endif /* GDK_WINDOWING_X11 */
+#if defined(GDK_WINDOWING_WAYLAND)
+ if (GDK_IS_WAYLAND_DISPLAY (display))
+ return _("Wayland");
+#endif /* GDK_WINDOWING_WAYLAND */
+ return C_("Windowing system (Wayland, X11, or Unknown)", "Unknown");
+}
+
+static guint64
+get_ram_size_libgtop (void)
+{
+ glibtop_mem mem;
+
+ glibtop_get_mem (&mem);
+ return mem.total;
+}
+
+static guint64
+get_ram_size_dmi (void)
+{
+ g_autoptr(GUdevClient) client = NULL;
+ g_autoptr(GUdevDevice) dmi = NULL;
+ const gchar * const subsystems[] = {"dmi", NULL };
+ guint64 ram_total = 0;
+ guint64 num_ram;
+ guint i;
+
+ client = g_udev_client_new (subsystems);
+ dmi = g_udev_client_query_by_sysfs_path (client, "/sys/devices/virtual/dmi/id");
+ if (!dmi)
+ return 0;
+ num_ram = g_udev_device_get_property_as_uint64 (dmi, "MEMORY_ARRAY_NUM_DEVICES");
+ for (i = 0; i < num_ram ; i++) {
+ g_autofree char *prop = NULL;
+
+ prop = g_strdup_printf ("MEMORY_DEVICE_%d_SIZE", i);
+ ram_total += g_udev_device_get_property_as_uint64 (dmi, prop);
+ }
+ return ram_total;
+}
+
+static char *
+get_gnome_version (GDBusProxy *proxy)
+{
+ g_autoptr(GVariant) variant = NULL;
+ const char *gnome_version = NULL;
+ if (!proxy)
+ return NULL;
+
+ variant = g_dbus_proxy_get_cached_property (proxy, "ShellVersion");
+ if (!variant)
+ return NULL;
+
+ gnome_version = g_variant_get_string (variant, NULL);
+ if (!gnome_version || *gnome_version == '\0')
+ return NULL;
+ return g_strdup (gnome_version);
+}
+
+static void
+shell_proxy_ready (GObject *source,
+ GAsyncResult *res,
+ CcInfoOverviewPanel *self)
+{
+ g_autoptr(GDBusProxy) proxy = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) variant = NULL;
+ g_autofree char *gnome_version = NULL;
+
+ proxy = cc_object_storage_create_dbus_proxy_finish (res, &error);
+ if (!proxy)
+ {
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+ g_warning ("Failed to contact gnome-shell: %s", error->message);
+ }
+
+ gnome_version = get_gnome_version (proxy);
+
+ if (!gnome_version)
+ {
+ /* translators: this is the placeholder string when the GNOME Shell
+ * version couldn't be loaded, eg. “GNOME Version: Not Available” */
+ cc_list_row_set_secondary_label (self->gnome_version_row, _("Not Available"));
+ }
+ else
+ {
+ cc_list_row_set_secondary_label (self->gnome_version_row, gnome_version);
+ }
+}
+
+static void
+info_overview_panel_setup_overview (CcInfoOverviewPanel *self)
+{
+ g_autofree gchar *gnome_version = NULL;
+ guint64 ram_size;
+ const glibtop_sysinfo *info;
+ g_autofree char *memory_text = NULL;
+ g_autofree char *cpu_text = NULL;
+ g_autofree char *os_type_text = NULL;
+ g_autofree char *os_name_text = NULL;
+ g_autofree char *os_build_text = NULL;
+ g_autofree gchar *graphics_hardware_string = NULL;
+
+ cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS |
+ G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+ "org.gnome.Shell",
+ "/org/gnome/Shell",
+ "org.gnome.Shell",
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ (GAsyncReadyCallback) shell_proxy_ready,
+ self);
+
+ get_hardware_model (self);
+
+ ram_size = get_ram_size_dmi ();
+ if (ram_size == 0)
+ ram_size = get_ram_size_libgtop ();
+ memory_text = g_format_size_full (ram_size, G_FORMAT_SIZE_IEC_UNITS);
+ cc_list_row_set_secondary_label (self->memory_row, memory_text);
+
+ info = glibtop_get_sysinfo ();
+
+ cpu_text = get_cpu_info (info);
+ cc_list_row_set_secondary_markup (self->processor_row, cpu_text);
+
+ graphics_hardware_string = get_graphics_hardware_string ();
+ cc_list_row_set_secondary_markup (self->graphics_row, graphics_hardware_string);
+
+ get_primary_disc_info (self);
+
+ os_name_text = get_os_name ();
+ cc_list_row_set_secondary_label (self->os_name_row, os_name_text);
+
+ os_build_text = get_os_build_id ();
+ cc_list_row_set_secondary_label (self->os_build_row, os_build_text);
+ gtk_widget_set_visible (GTK_WIDGET (self->os_build_row), os_build_text != NULL);
+
+ os_type_text = get_os_type ();
+ cc_list_row_set_secondary_label (self->os_type_row, os_type_text);
+
+ cc_list_row_set_secondary_label (self->windowing_system_row, get_windowing_system ());
+}
+
+static gboolean
+does_gnome_software_allow_updates (void)
+{
+ const gchar *schema_id = "org.gnome.software";
+ GSettingsSchemaSource *source;
+ g_autoptr(GSettingsSchema) schema = NULL;
+ g_autoptr(GSettings) settings = NULL;
+
+ source = g_settings_schema_source_get_default ();
+
+ if (source == NULL)
+ return FALSE;
+
+ schema = g_settings_schema_source_lookup (source, schema_id, FALSE);
+
+ if (schema == NULL)
+ return FALSE;
+
+ settings = g_settings_new (schema_id);
+ return g_settings_get_boolean (settings, "allow-updates");
+}
+
+static gboolean
+does_gnome_software_exist (void)
+{
+ g_autofree gchar *path = g_find_program_in_path ("gnome-software");
+ return path != NULL;
+}
+
+static gboolean
+does_gpk_update_viewer_exist (void)
+{
+ g_autofree gchar *path = g_find_program_in_path ("gpk-update-viewer");
+ return path != NULL;
+}
+
+static void
+open_software_update (CcInfoOverviewPanel *self)
+{
+ g_autoptr(GError) error = NULL;
+ gboolean ret;
+ char *argv[3];
+
+ if (does_gnome_software_exist ())
+ {
+ argv[0] = "gnome-software";
+ argv[1] = "--mode=updates";
+ argv[2] = NULL;
+ }
+ else
+ {
+ argv[0] = "gpk-update-viewer";
+ argv[1] = NULL;
+ }
+ ret = g_spawn_async (NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error);
+ if (!ret)
+ g_warning ("Failed to spawn %s: %s", argv[0], error->message);
+}
+
+static void
+on_device_name_entry_changed (CcInfoOverviewPanel *self)
+{
+ const gchar *current_hostname, *new_hostname;
+
+ current_hostname = gtk_editable_get_text (GTK_EDITABLE (self->hostname_entry));
+ new_hostname = gtk_editable_get_text (GTK_EDITABLE (self->device_name_entry));
+ gtk_widget_set_sensitive (self->rename_button,
+ g_strcmp0 (current_hostname, new_hostname) != 0);
+}
+
+static void
+update_device_name (CcInfoOverviewPanel *self)
+{
+ const gchar *hostname;
+
+ /* We simply change the CcHostnameEntry text. CcHostnameEntry
+ * listens to changes and updates hostname on change.
+ */
+ hostname = gtk_editable_get_text (GTK_EDITABLE (self->device_name_entry));
+ gtk_editable_set_text (GTK_EDITABLE (self->hostname_entry), hostname);
+}
+
+static void
+on_hostname_editor_dialog_response_cb (GtkDialog *dialog,
+ gint response,
+ CcInfoOverviewPanel *self)
+{
+ if (response == GTK_RESPONSE_APPLY)
+ {
+ update_device_name (self);
+ }
+
+ gtk_window_close (GTK_WINDOW (dialog));
+}
+
+static void
+on_device_name_entry_activated_cb (CcInfoOverviewPanel *self)
+{
+ update_device_name (self);
+ gtk_window_close (GTK_WINDOW (self->hostname_editor));
+}
+
+static void
+open_hostname_edit_dialog (CcInfoOverviewPanel *self)
+{
+ GtkWindow *toplevel;
+ CcShell *shell;
+ const gchar *hostname;
+
+ g_assert (CC_IS_INFO_OVERVIEW_PANEL (self));
+
+ shell = cc_panel_get_shell (CC_PANEL (self));
+ toplevel = GTK_WINDOW (cc_shell_get_toplevel (shell));
+ gtk_window_set_transient_for (GTK_WINDOW (self->hostname_editor), toplevel);
+
+ hostname = gtk_editable_get_text (GTK_EDITABLE (self->hostname_entry));
+ gtk_editable_set_text (GTK_EDITABLE (self->device_name_entry), hostname);
+ gtk_widget_grab_focus (GTK_WIDGET (self->device_name_entry));
+
+ gtk_window_present (GTK_WINDOW (self->hostname_editor));
+
+}
+
+static void
+cc_info_panel_row_activated_cb (CcInfoOverviewPanel *self,
+ AdwActionRow *row)
+{
+ g_assert (CC_IS_INFO_OVERVIEW_PANEL (self));
+ g_assert (ADW_IS_ACTION_ROW (row));
+
+ if (row == ADW_ACTION_ROW (self->hostname_row))
+ open_hostname_edit_dialog (self);
+ else if (row == self->software_updates_row)
+ open_software_update (self);
+}
+
+#if !defined(DISTRIBUTOR_LOGO) || defined(DARK_MODE_DISTRIBUTOR_LOGO)
+static gboolean
+use_dark_theme (CcInfoOverviewPanel *panel)
+{
+ AdwStyleManager *style_manager = adw_style_manager_get_default ();
+
+ return adw_style_manager_get_dark (style_manager);
+}
+#endif
+
+static void
+setup_os_logo (CcInfoOverviewPanel *panel)
+{
+#ifdef DISTRIBUTOR_LOGO
+#ifdef DARK_MODE_DISTRIBUTOR_LOGO
+ if (use_dark_theme (panel))
+ {
+ gtk_picture_set_filename (panel->os_logo, DARK_MODE_DISTRIBUTOR_LOGO);
+ return;
+ }
+#endif
+ gtk_picture_set_filename (panel->os_logo, DISTRIBUTOR_LOGO);
+ return;
+#else
+ GtkIconTheme *icon_theme;
+ g_autofree char *logo_name = g_get_os_info ("LOGO");
+ g_autoptr(GtkIconPaintable) icon_paintable = NULL;
+ g_autoptr(GPtrArray) array = NULL;
+ g_autoptr(GIcon) icon = NULL;
+ gboolean dark;
+
+ dark = use_dark_theme (panel);
+ if (logo_name == NULL)
+ logo_name = g_strdup ("gnome-logo");
+
+ array = g_ptr_array_new_with_free_func (g_free);
+ if (dark)
+ g_ptr_array_add (array, (gpointer) g_strdup_printf ("%s-text-dark", logo_name));
+ g_ptr_array_add (array, (gpointer) g_strdup_printf ("%s-text", logo_name));
+ if (dark)
+ g_ptr_array_add (array, (gpointer) g_strdup_printf ("%s-dark", logo_name));
+ g_ptr_array_add (array, (gpointer) g_strdup_printf ("%s", logo_name));
+
+ icon = g_themed_icon_new_from_names ((char **) array->pdata, array->len);
+ icon_theme = gtk_icon_theme_get_for_display (gdk_display_get_default ());
+ icon_paintable = gtk_icon_theme_lookup_by_gicon (icon_theme, icon,
+ 192,
+ gtk_widget_get_scale_factor (GTK_WIDGET (panel)),
+ gtk_widget_get_direction (GTK_WIDGET (panel)),
+ 0);
+ gtk_picture_set_paintable (panel->os_logo, GDK_PAINTABLE (icon_paintable));
+#endif
+}
+
+static void
+cc_info_overview_panel_class_init (CcInfoOverviewPanelClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/info-overview/cc-info-overview-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, device_name_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, disk_row);
+ gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, gnome_version_row);
+ gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, graphics_row);
+ gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, hardware_model_row);
+ gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, hostname_editor);
+ gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, hostname_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, hostname_row);
+ gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, memory_row);
+ gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, os_logo);
+ gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, os_name_row);
+ gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, os_build_row);
+ gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, os_type_row);
+ gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, processor_row);
+ gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, rename_button);
+ gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, software_updates_row);
+ gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, virtualization_row);
+ gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, windowing_system_row);
+
+ gtk_widget_class_bind_template_callback (widget_class, cc_info_panel_row_activated_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_device_name_entry_changed);
+ gtk_widget_class_bind_template_callback (widget_class, on_device_name_entry_activated_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_hostname_editor_dialog_response_cb);
+
+ g_type_ensure (CC_TYPE_LIST_ROW);
+ g_type_ensure (CC_TYPE_HOSTNAME_ENTRY);
+}
+
+static void
+cc_info_overview_panel_init (CcInfoOverviewPanel *self)
+{
+ AdwStyleManager *style_manager;
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ g_resources_register (cc_info_overview_get_resource ());
+
+ if ((!does_gnome_software_exist () || !does_gnome_software_allow_updates ()) && !does_gpk_update_viewer_exist ())
+ gtk_widget_hide (GTK_WIDGET (self->software_updates_row));
+
+ info_overview_panel_setup_overview (self);
+ info_overview_panel_setup_virt (self);
+
+ style_manager = adw_style_manager_get_default ();
+ g_signal_connect_swapped (style_manager, "notify::dark", G_CALLBACK (setup_os_logo), self);
+ setup_os_logo (self);
+}
+
+GtkWidget *
+cc_info_overview_panel_new (void)
+{
+ return g_object_new (CC_TYPE_INFO_OVERVIEW_PANEL,
+ NULL);
+}
diff --git a/panels/info-overview/cc-info-overview-panel.h b/panels/info-overview/cc-info-overview-panel.h
new file mode 100644
index 0000000..78a6785
--- /dev/null
+++ b/panels/info-overview/cc-info-overview-panel.h
@@ -0,0 +1,31 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2017 Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_INFO_OVERVIEW_PANEL (cc_info_overview_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcInfoOverviewPanel, cc_info_overview_panel, CC, INFO_OVERVIEW_PANEL, CcPanel)
+
+GtkWidget *cc_info_overview_panel_new (void);
+
+G_END_DECLS
diff --git a/panels/info-overview/cc-info-overview-panel.ui b/panels/info-overview/cc-info-overview-panel.ui
new file mode 100644
index 0000000..ec2ed27
--- /dev/null
+++ b/panels/info-overview/cc-info-overview-panel.ui
@@ -0,0 +1,232 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcInfoOverviewPanel" parent="CcPanel">
+ <child type="content">
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup">
+
+ <child>
+ <object class="AdwClamp">
+ <property name="orientation">vertical</property>
+ <property name="maximum-size">192</property>
+ <property name="tightening-threshold">192</property>
+ <property name="child">
+ <object class="GtkPicture" id="os_logo">
+ <property name="can-shrink">False</property>
+ <property name="alternative-text" translatable="yes">System Logo</property>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+
+ <!-- Device name -->
+ <child>
+ <object class="CcListRow" id="hostname_row">
+ <property name="title" translatable="yes">Device Name</property>
+ <property name="secondary-label" bind-source="hostname_entry" bind-property="text" bind-flags="sync-create" />
+ <property name="show-arrow">True</property>
+ <signal name="activated" handler="cc_info_panel_row_activated_cb" swapped="yes"/>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+
+ <!-- Hardware Model -->
+ <child>
+ <object class="CcListRow" id="hardware_model_row">
+ <property name="visible">False</property>
+ <property name="activatable">False</property>
+ <property name="title" translatable="yes">Hardware Model</property>
+ </object>
+ </child>
+
+ <!-- Memory -->
+ <child>
+ <object class="CcListRow" id="memory_row">
+ <property name="activatable">False</property>
+ <property name="title" translatable="yes">Memory</property>
+ </object>
+ </child>
+
+ <!-- Processor -->
+ <child>
+ <object class="CcListRow" id="processor_row">
+ <property name="activatable">False</property>
+ <property name="title" translatable="yes">Processor</property>
+ </object>
+ </child>
+
+ <!-- Graphics -->
+ <child>
+ <object class="CcListRow" id="graphics_row">
+ <property name="activatable">False</property>
+ <property name="title" translatable="yes">Graphics</property>
+ </object>
+ </child>
+
+ <!-- Disk Capacity -->
+ <child>
+ <object class="CcListRow" id="disk_row">
+ <property name="activatable">False</property>
+ <property name="title" translatable="yes">Disk Capacity</property>
+ <property name="secondary-label" translatable="yes">Calculating…</property>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+
+ <!-- OS Name -->
+ <child>
+ <object class="CcListRow" id="os_name_row">
+ <property name="activatable">False</property>
+ <property name="title" translatable="yes"
+ comments="translators: this field contains the distro name and version">OS Name</property>
+ </object>
+ </child>
+
+ <!-- OS Build -->
+ <child>
+ <object class="CcListRow" id="os_build_row">
+ <property name="activatable">False</property>
+ <property name="title" translatable="yes"
+ comments="translators: this field contains the distro build ID">OS Build ID</property>
+ </object>
+ </child>
+
+ <!-- OS Type -->
+ <child>
+ <object class="CcListRow" id="os_type_row">
+ <property name="activatable">False</property>
+ <property name="title" translatable="yes">OS Type</property>
+ </object>
+ </child>
+
+ <!-- GNOME Version -->
+ <child>
+ <object class="CcListRow" id="gnome_version_row">
+ <property name="activatable">False</property>
+ <property name="title" translatable="yes">GNOME Version</property>
+ <property name="secondary-label" translatable="yes"
+ comments="translators: this is a placeholder while the GNOME version is being fetched">Loading…</property>
+ </object>
+ </child>
+
+ <!-- Windowing System -->
+ <child>
+ <object class="CcListRow" id="windowing_system_row">
+ <property name="activatable">False</property>
+ <property name="title" translatable="yes">Windowing System</property>
+ </object>
+ </child>
+
+ <!-- Virtualization -->
+ <child>
+ <object class="CcListRow" id="virtualization_row">
+ <property name="visible">False</property>
+ <property name="title" translatable="yes">Virtualization</property>
+ <property name="activatable">False</property>
+ </object>
+ </child>
+
+ <!-- Software Updates -->
+ <child>
+ <object class="AdwActionRow" id="software_updates_row">
+ <property name="activatable">True</property>
+ <property name="title" translatable="yes">Software Updates</property>
+ <signal name="activated" handler="cc_info_panel_row_activated_cb" swapped="yes"/>
+ <child type="suffix">
+ <object class="GtkImage">
+ <property name="valign">center</property>
+ <property name="icon-name">adw-external-link-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </template>
+
+ <object class="GtkDialog" id="hostname_editor">
+ <property name="visible">False</property>
+ <property name="modal">True</property>
+ <property name="use-header-bar">1</property>
+ <property name="default-height">24</property>
+ <property name="hide-on-close">True</property>
+ <property name="title" translatable="yes">Rename Device</property>
+ <signal name="response" handler="on_hostname_editor_dialog_response_cb" object="CcInfoOverviewPanel" swapped="no" />
+
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">18</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="margin-bottom">18</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="device_name_description">
+ <property name="margin-bottom">18</property>
+ <property name="wrap">True</property>
+ <property name="max-width-chars">35</property>
+ <property name="xalign">0.0</property>
+ <property name="label" translatable="yes">The device name is used to identify this device when it is viewed over the network, or when pairing Bluetooth devices.</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="device_name_entry">
+ <accessibility>
+ <property name="label" translatable="yes">Device name</property>
+ <relation name="described-by">device_name_description</relation>
+ </accessibility>
+ <signal name="changed" handler="on_device_name_entry_changed" swapped="yes"/>
+ <signal name="activate" handler="on_device_name_entry_activated_cb" swapped="yes" />
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- Rename button -->
+ <child type="action">
+ <object class="GtkButton" id="rename_button">
+ <property name="use-underline">True</property>
+ <property name="label" translatable="yes">_Rename</property>
+ </object>
+ </child>
+
+ <!-- Cancel button -->
+ <child type="action">
+ <object class="GtkButton" id="cancel_button">
+ <property name="use-underline">True</property>
+ <property name="label" translatable="yes">_Cancel</property>
+ </object>
+ </child>
+
+ <action-widgets>
+ <action-widget response="apply" default="true">rename_button</action-widget>
+ <action-widget response="cancel">cancel_button</action-widget>
+ </action-widgets>
+ </object>
+
+ <object class="CcHostnameEntry" id="hostname_entry">
+ <property name="visible">0</property>
+ </object>
+
+</interface>
diff --git a/panels/info-overview/gnome-control-center-print-renderer.c b/panels/info-overview/gnome-control-center-print-renderer.c
new file mode 100644
index 0000000..e84a11a
--- /dev/null
+++ b/panels/info-overview/gnome-control-center-print-renderer.c
@@ -0,0 +1,65 @@
+/* -*- mode:c; c-basic-offset: 8; indent-tabs-mode: nil; -*- */
+/* Tool to set the property _GNOME_SESSION_ACCELERATED on the root window */
+/*
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author:
+ * Bastien Nocera <hadess@hadess.net>
+ * Matthias Clasen <mclasen@redhat.com>
+ */
+
+#include <gtk/gtk.h>
+#include <epoxy/gl.h>
+
+static char *
+get_gtk_gles_renderer (void)
+{
+ GdkSurface *surface;
+ GtkNative *native;
+ GtkWidget *win;
+ GdkGLContext *context;
+ char *renderer = NULL;
+
+ win = gtk_window_new ();
+ gtk_widget_realize (win);
+ native = gtk_widget_get_native (win);
+ surface = gtk_native_get_surface (native);
+ context = gdk_surface_create_gl_context (surface, NULL);
+ if (!context)
+ return NULL;
+ gdk_gl_context_make_current (context);
+ renderer = g_strdup ((char *) glGetString (GL_RENDERER));
+ gdk_gl_context_clear_current ();
+ g_object_unref (context);
+
+ return renderer;
+}
+
+int
+main (int argc, char **argv)
+{
+ g_autofree char *renderer_string = NULL;
+
+ gtk_init ();
+
+ renderer_string = get_gtk_gles_renderer ();
+ if (renderer_string) {
+ g_print ("%s", renderer_string);
+ return 0;
+ }
+ return 1;
+}
diff --git a/panels/info-overview/gnome-info-overview-panel.desktop.in.in b/panels/info-overview/gnome-info-overview-panel.desktop.in.in
new file mode 100644
index 0000000..e3cf377
--- /dev/null
+++ b/panels/info-overview/gnome-info-overview-panel.desktop.in.in
@@ -0,0 +1,22 @@
+[Desktop Entry]
+Name=About
+Comment=View information about your system
+Exec=gnome-control-center info-overview
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-about-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;X-GNOME-Settings-Panel;X-GNOME-DetailsSettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=info
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: Search terms to find the About panel.
+# Do NOT translate or localize the semicolons!
+# The list MUST also end with a semicolon!
+# "Preferred Applications" is the old name for the preference, so make
+# sure that you use the same "translation" for those keywords
+Keywords=device;system;information;hostname;memory;processor;version;default;application;preferred;cd;dvd;usb;audio;video;disc;removable;media;autorun;
diff --git a/panels/info-overview/gnome-logo-text-dark.svg b/panels/info-overview/gnome-logo-text-dark.svg
new file mode 100644
index 0000000..26e17b8
--- /dev/null
+++ b/panels/info-overview/gnome-logo-text-dark.svg
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.0"
+ width="97.966095"
+ height="138.95122"
+ id="svg1903"
+ inkscape:version="1.0.2 (e86c870879, 2021-01-15)"
+ sodipodi:docname="gnome-logo-text-dark.svg">
+ <metadata
+ id="metadata24">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="1011"
+ id="namedview22"
+ showgrid="false"
+ inkscape:zoom="2.0645911"
+ inkscape:cx="6.1022513"
+ inkscape:cy="68.392751"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg1903"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:document-rotation="0" />
+ <defs
+ id="defs1905">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 244.11613 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="401.74014 : 244.11613 : 1"
+ inkscape:persp3d-origin="200.87007 : 162.74409 : 1"
+ id="perspective26" />
+ </defs>
+ <g
+ transform="matrix(0.30686102,0,0,0.30686102,-57.94673,-76.524295)"
+ id="layer1"
+ style="fill:#ffffff">
+ <g
+ transform="translate(925.8326,120.8762)"
+ id="g3963"
+ style="fill:#ffffff">
+ <g
+ transform="matrix(2.914897,0,0,2.914897,-717.5904,128.5015)"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="g3771">
+ <g
+ style="fill:#ffffff;fill-opacity:1"
+ id="g3773">
+ <path
+ d="M 86.068,0 C 61.466,0 56.851,35.041 70.691,35.041 84.529,35.041 110.671,0 86.068,0 Z"
+ style="fill:#ffffff;fill-opacity:1"
+ id="path3775"
+ inkscape:connector-curvature="0" />
+ <path
+ d="M 45.217,30.699 C 52.586,31.149 60.671,2.577 46.821,4.374 32.976,6.171 37.845,30.249 45.217,30.699 Z"
+ style="fill:#ffffff;fill-opacity:1"
+ id="path3777"
+ inkscape:connector-curvature="0" />
+ <path
+ d="M 11.445,48.453 C 16.686,46.146 12.12,23.581 3.208,29.735 -5.7,35.89 6.204,50.759 11.445,48.453 Z"
+ style="fill:#ffffff;fill-opacity:1"
+ id="path3779"
+ inkscape:connector-curvature="0" />
+ <path
+ d="M 26.212,36.642 C 32.451,35.37 32.793,9.778 21.667,14.369 10.539,18.961 19.978,37.916 26.212,36.642 Z"
+ style="fill:#ffffff;fill-opacity:1"
+ id="path3781"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 58.791,93.913 c 1.107,8.454 -6.202,12.629 -13.36,7.179 C 22.644,83.743 83.16,75.088 79.171,51.386 75.86,31.712 15.495,37.769 8.621,68.553 3.968,89.374 27.774,118.26 52.614,118.26 c 12.22,0 26.315,-11.034 28.952,-25.012 C 83.58,82.589 57.867,86.86 58.791,93.913 Z"
+ style="fill:#ffffff;fill-opacity:1"
+ id="path3783"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="matrix(1.098291,0,0,1.098291,41.06056,-50.07504)"
+ id="g3956"
+ style="fill:#ffffff">
+ <path
+ d="m -565.99523,509.46063 c -8.08731,0.21792 -14.47394,3.12448 -19.17071,8.69866 -4.86385,5.80101 -7.31024,13.81651 -7.31024,24.03862 0,10.19394 2.44651,18.18745 7.31024,23.98846 4.88761,5.801 11.59815,8.69866 20.15764,8.69866 8.5831,0 15.3105,-2.89766 20.17436,-8.69866 4.86373,-5.80101 7.29358,-13.79452 7.29353,-23.98846 -5e-5,-10.22211 -2.4298,-18.23761 -7.29353,-24.03862 -4.86386,-5.80075 -11.59131,-8.69866 -20.17436,-8.69866 -0.33434,0 -0.6582,-0.009 -0.98693,0 z m 0.60221,11.77669 c 0.12927,-0.003 0.25357,0 0.38472,0 4.21998,0 7.48996,1.8261 9.8028,5.48697 2.31266,3.66086 3.47944,8.82788 3.47949,15.47362 0,6.61757 -1.16692,11.74604 -3.47949,15.40691 -2.31274,3.66086 -5.58286,5.50352 -9.8028,5.50352 -4.19632,0 -7.43983,-1.84266 -9.75257,-5.50352 -2.31274,-3.66087 -3.47944,-8.78934 -3.47949,-15.40691 0,-6.64574 1.16684,-11.81276 3.47949,-15.47362 2.24035,-3.54647 5.35963,-5.37604 9.36785,-5.48697 z"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:148.7px;line-height:125%;font-family:'Bitstream Vera Sans';text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none"
+ id="path3787"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m -657.35432,568.97161 c -7.12362,5.98235 -17.72219,5.91366 -22.13752,5.91366 -8.8932,0 -15.93855,-2.92879 -21.13613,-8.78612 -5.19765,-5.88525 -7.7964,-13.85456 -7.7964,-23.90791 0,-10.16578 2.64646,-18.16325 7.93945,-23.99241 5.293,-5.82892 12.54098,-8.74363 21.74413,-8.74363 3.55245,0 6.94991,0.39433 10.19254,1.18273 3.26638,0.78841 6.34203,1.95706 9.22697,3.50595 l -3.70487,10.9527 c -1.62185,-0.88773 -3.4788,-1.76286 -5.20022,-2.37807 -2.93262,-0.98557 -5.87712,-1.47823 -8.83351,-1.47823 -5.48379,0 -9.71581,1.81623 -12.69601,5.44892 -2.95649,3.60454 -4.4347,8.7718 -4.4347,15.50204 0,6.67415 1.4305,11.82733 4.29167,15.46003 2.86099,3.6327 7.16068,5.44892 12.19522,5.44892 5.11476,0 8.28269,-1.28922 9.97226,-2.64762 v -10.91144 h -11.08087 v -10.89809 h 21.45799"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:148.7px;line-height:125%;font-family:'Bitstream Vera Sans';text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none"
+ id="path3789"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m -528.50252,510.59568 h 17.5241 l 12.15952,39.37066 12.23105,-39.37066 h 14.81181 l 6.69132,63.06461 h -13.01787 l -4.0148,-39.4349 -12.30257,39.62391 h -8.72628 l -12.30263,-40.9623 -4.01479,40.77329 h -13.05365 l 6.69132,-63.06461"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:148.7px;line-height:125%;font-family:'Bitstream Vera Sans';text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none"
+ id="path3793"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m -455.68828,510.59568 h 37.15811 v 12.29183 h -23.38928 v 13.08097 h 17.97969 v 10.95369 h -17.97969 v 14.44629 h 24.17608 v 12.29183 h -37.94491 v -63.06461"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:148.7px;line-height:125%;font-family:'Bitstream Vera Sans';text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none"
+ id="path3795"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m -647.94283,510.59568 h 8.6869 l 27.44915,37.90083 v -37.90083 h 11.71533 v 63.06461 h -8.6869 l -27.4491,-37.90083 v 37.90083 h -11.71538 v -63.06461"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:148.7px;line-height:125%;font-family:'Bitstream Vera Sans';text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none"
+ id="path3791"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/panels/info-overview/gnome-logo-text.svg b/panels/info-overview/gnome-logo-text.svg
new file mode 100644
index 0000000..b697f06
--- /dev/null
+++ b/panels/info-overview/gnome-logo-text.svg
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.0"
+ width="97.966095"
+ height="138.95122"
+ id="svg1903"
+ inkscape:version="0.48.1 r9760"
+ sodipodi:docname="GnomeLogoVerticalMedium.svg">
+ <metadata
+ id="metadata24">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="818"
+ inkscape:window-height="738"
+ id="namedview22"
+ showgrid="false"
+ inkscape:zoom="2.0645911"
+ inkscape:cx="6.1022513"
+ inkscape:cy="68.392751"
+ inkscape:window-x="460"
+ inkscape:window-y="26"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg1903"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" />
+ <defs
+ id="defs1905">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 244.11613 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="401.74014 : 244.11613 : 1"
+ inkscape:persp3d-origin="200.87007 : 162.74409 : 1"
+ id="perspective26" />
+ </defs>
+ <g
+ transform="matrix(0.30686102,0,0,0.30686102,-57.94673,-76.524295)"
+ id="layer1">
+ <g
+ transform="translate(925.8326,120.8762)"
+ id="g3963">
+ <g
+ transform="matrix(2.914897,0,0,2.914897,-717.5904,128.5015)"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="g3771">
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g3773">
+ <path
+ d="M 86.068,0 C 61.466,0 56.851,35.041 70.691,35.041 84.529,35.041 110.671,0 86.068,0 z"
+ style="fill:#000000;fill-opacity:1"
+ id="path3775"
+ inkscape:connector-curvature="0" />
+ <path
+ d="M 45.217,30.699 C 52.586,31.149 60.671,2.577 46.821,4.374 32.976,6.171 37.845,30.249 45.217,30.699 z"
+ style="fill:#000000;fill-opacity:1"
+ id="path3777"
+ inkscape:connector-curvature="0" />
+ <path
+ d="M 11.445,48.453 C 16.686,46.146 12.12,23.581 3.208,29.735 -5.7,35.89 6.204,50.759 11.445,48.453 z"
+ style="fill:#000000;fill-opacity:1"
+ id="path3779"
+ inkscape:connector-curvature="0" />
+ <path
+ d="M 26.212,36.642 C 32.451,35.37 32.793,9.778 21.667,14.369 10.539,18.961 19.978,37.916 26.212,36.642 l 0,0 z"
+ style="fill:#000000;fill-opacity:1"
+ id="path3781"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 58.791,93.913 c 1.107,8.454 -6.202,12.629 -13.36,7.179 C 22.644,83.743 83.16,75.088 79.171,51.386 75.86,31.712 15.495,37.769 8.621,68.553 3.968,89.374 27.774,118.26 52.614,118.26 c 12.22,0 26.315,-11.034 28.952,-25.012 C 83.58,82.589 57.867,86.86 58.791,93.913 l 0,0 z"
+ style="fill:#000000;fill-opacity:1"
+ id="path3783"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="matrix(1.098291,0,0,1.098291,41.06056,-50.07504)"
+ id="g3956">
+ <path
+ d="m -565.99523,509.46063 c -8.08731,0.21792 -14.47394,3.12448 -19.17071,8.69866 -4.86385,5.80101 -7.31024,13.81651 -7.31024,24.03862 0,10.19394 2.44651,18.18745 7.31024,23.98846 4.88761,5.801 11.59815,8.69866 20.15764,8.69866 8.5831,0 15.3105,-2.89766 20.17436,-8.69866 4.86373,-5.80101 7.29358,-13.79452 7.29353,-23.98846 -5e-5,-10.22211 -2.4298,-18.23761 -7.29353,-24.03862 -4.86386,-5.80075 -11.59131,-8.69866 -20.17436,-8.69866 -0.33434,0 -0.6582,-0.009 -0.98693,0 z m 0.60221,11.77669 c 0.12927,-0.003 0.25357,0 0.38472,0 4.21998,0 7.48996,1.8261 9.8028,5.48697 2.31266,3.66086 3.47944,8.82788 3.47949,15.47362 0,6.61757 -1.16692,11.74604 -3.47949,15.40691 -2.31274,3.66086 -5.58286,5.50352 -9.8028,5.50352 -4.19632,0 -7.43983,-1.84266 -9.75257,-5.50352 -2.31274,-3.66087 -3.47944,-8.78934 -3.47949,-15.40691 0,-6.64574 1.16684,-11.81276 3.47949,-15.47362 2.24035,-3.54647 5.35963,-5.37604 9.36785,-5.48697 z"
+ style="font-size:148.699646px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ id="path3787"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m -657.35432,568.97161 c -7.12362,5.98235 -17.72219,5.91366 -22.13752,5.91366 -8.8932,0 -15.93855,-2.92879 -21.13613,-8.78612 -5.19765,-5.88525 -7.7964,-13.85456 -7.7964,-23.90791 0,-10.16578 2.64646,-18.16325 7.93945,-23.99241 5.293,-5.82892 12.54098,-8.74363 21.74413,-8.74363 3.55245,0 6.94991,0.39433 10.19254,1.18273 3.26638,0.78841 6.34203,1.95706 9.22697,3.50595 l -3.70487,10.9527 c -1.62185,-0.88773 -3.4788,-1.76286 -5.20022,-2.37807 -2.93262,-0.98557 -5.87712,-1.47823 -8.83351,-1.47823 -5.48379,0 -9.71581,1.81623 -12.69601,5.44892 -2.95649,3.60454 -4.4347,8.7718 -4.4347,15.50204 0,6.67415 1.4305,11.82733 4.29167,15.46003 2.86099,3.6327 7.16068,5.44892 12.19522,5.44892 5.11476,0 8.28269,-1.28922 9.97226,-2.64762 l 0,-10.91144 -11.08087,0 0,-10.89809 21.45799,0"
+ style="font-size:148.699646px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ id="path3789"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m -528.50252,510.59568 17.5241,0 12.15952,39.37066 12.23105,-39.37066 14.81181,0 6.69132,63.06461 -13.01787,0 -4.0148,-39.4349 -12.30257,39.62391 -8.72628,0 -12.30263,-40.9623 -4.01479,40.77329 -13.05365,0 6.69132,-63.06461"
+ style="font-size:148.699646px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ id="path3793"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m -455.68828,510.59568 37.15811,0 0,12.29183 -23.38928,0 0,13.08097 17.97969,0 0,10.95369 -17.97969,0 0,14.44629 24.17608,0 0,12.29183 -37.94491,0 0,-63.06461"
+ style="font-size:148.699646px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ id="path3795"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m -647.94283,510.59568 8.6869,0 27.44915,37.90083 0,-37.90083 11.71533,0 0,63.06461 -8.6869,0 -27.4491,-37.90083 0,37.90083 -11.71538,0 0,-63.06461"
+ style="font-size:148.699646px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ id="path3791"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/panels/info-overview/icons/meson.build b/panels/info-overview/icons/meson.build
new file mode 100644
index 0000000..53aac33
--- /dev/null
+++ b/panels/info-overview/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-about-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/info-overview/icons/scalable/org.gnome.Settings-about-symbolic.svg b/panels/info-overview/icons/scalable/org.gnome.Settings-about-symbolic.svg
new file mode 100644
index 0000000..bc627c9
--- /dev/null
+++ b/panels/info-overview/icons/scalable/org.gnome.Settings-about-symbolic.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <path d="m 8 0 c -4.421875 0 -8 3.578125 -8 8 s 3.578125 8 8 8 s 8 -3.578125 8 -8 s -3.578125 -8 -8 -8 z m 0 3.875 c 0.621094 0 1.125 0.503906 1.125 1.125 s -0.503906 1.125 -1.125 1.125 s -1.125 -0.503906 -1.125 -1.125 s 0.503906 -1.125 1.125 -1.125 z m -1.523438 3.125 h 2.523438 v 4 h 0.5 c 0.277344 0 0.5 0.222656 0.5 0.5 s -0.222656 0.5 -0.5 0.5 h -2.5 v -4 h -0.5 c -0.277344 0 -0.5 -0.222656 -0.5 -0.5 c 0 -0.269531 0.210938 -0.488281 0.476562 -0.5 z m 0 0" fill="#2e3436"/>
+</svg>
diff --git a/panels/info-overview/info-cleanup.c b/panels/info-overview/info-cleanup.c
new file mode 100644
index 0000000..5c3480c
--- /dev/null
+++ b/panels/info-overview/info-cleanup.c
@@ -0,0 +1,130 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2010 Red Hat, Inc
+ * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include "info-cleanup.h"
+
+typedef struct
+{
+ char *regex;
+ char *replacement;
+} ReplaceStrings;
+
+static char *
+prettify_info (const char *info)
+{
+ g_autofree char *escaped = NULL;
+ g_autofree gchar *pretty = NULL;
+ int i;
+ static const ReplaceStrings rs[] = {
+ { "Mesa DRI ", ""},
+ { "[(]R[)]", "\302\256"},
+ { "[(](tm|TM)[)]", "\342\204\242"},
+ { "(ATI|EPYC|AMD FX|Radeon|Ryzen|Threadripper|GeForce RTX) ", "\\1\342\204\242 "},
+ { "Gallium \\d+\\.\\d+ on (.*)", "\\1"},
+ { " CPU| Processor| \\S+-Core| @ \\d+\\.\\d+GHz", ""},
+ { " x86|/MMX|/SSE2|/PCIe", ""},
+ { " [(][^)]*(DRM|MESA|LLVM)[^)]*[)]?", ""},
+ { "Graphics Controller", "Graphics"},
+ { ".*llvmpipe.*", "Software Rendering"},
+ };
+
+ if (*info == '\0')
+ return NULL;
+
+ escaped = g_markup_escape_text (info, -1);
+ pretty = g_strdup (g_strstrip (escaped));
+
+ for (i = 0; i < G_N_ELEMENTS (rs); i++)
+ {
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GRegex) re = NULL;
+ g_autofree gchar *new = NULL;
+
+ re = g_regex_new (rs[i].regex, 0, 0, &error);
+ if (re == NULL)
+ {
+ g_warning ("Error building regex: %s", error->message);
+ continue;
+ }
+
+ new = g_regex_replace (re,
+ pretty,
+ -1,
+ 0,
+ rs[i].replacement,
+ 0,
+ &error);
+
+ if (error != NULL)
+ {
+ g_warning ("Error replacing %s: %s", rs[i].regex, error->message);
+ continue;
+ }
+
+ g_free (pretty);
+ pretty = g_steal_pointer (&new);
+ }
+
+ return g_steal_pointer (&pretty);
+}
+
+static char *
+remove_duplicate_whitespace (const char *old)
+{
+ g_autofree gchar *new = NULL;
+ g_autoptr(GRegex) re = NULL;
+ g_autoptr(GError) error = NULL;
+
+ if (old == NULL)
+ return NULL;
+
+ re = g_regex_new ("[ \t\n\r]+", G_REGEX_MULTILINE, 0, &error);
+ if (re == NULL)
+ {
+ g_warning ("Error building regex: %s", error->message);
+ return g_strdup (old);
+ }
+ new = g_regex_replace (re,
+ old,
+ -1,
+ 0,
+ " ",
+ 0,
+ &error);
+ if (new == NULL)
+ {
+ g_warning ("Error replacing string: %s", error->message);
+ return g_strdup (old);
+ }
+
+ return g_steal_pointer (&new);
+}
+
+char *
+info_cleanup (const char *input)
+{
+ g_autofree char *pretty = NULL;
+
+ pretty = prettify_info (input);
+ return remove_duplicate_whitespace (pretty);
+}
diff --git a/panels/info-overview/info-cleanup.h b/panels/info-overview/info-cleanup.h
new file mode 100644
index 0000000..cbc8d54
--- /dev/null
+++ b/panels/info-overview/info-cleanup.h
@@ -0,0 +1,23 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2010 Red Hat, Inc
+ * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <glib.h>
+
+char *info_cleanup (const char *input);
diff --git a/panels/info-overview/info-overview.gresource.xml b/panels/info-overview/info-overview.gresource.xml
new file mode 100644
index 0000000..6a63f75
--- /dev/null
+++ b/panels/info-overview/info-overview.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/info-overview">
+ <file preprocess="xml-stripblanks">cc-info-overview-panel.ui</file>
+ </gresource>
+</gresources>
diff --git a/panels/info-overview/meson.build b/panels/info-overview/meson.build
new file mode 100644
index 0000000..45251ab
--- /dev/null
+++ b/panels/info-overview/meson.build
@@ -0,0 +1,76 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+cflags += [
+ '-DDATADIR="@0@"'.format(control_center_datadir),
+ '-DLIBEXECDIR="@0@"'.format(control_center_libexecdir),
+]
+
+sources = files(
+ 'cc-info-overview-panel.c',
+ 'info-cleanup.c'
+)
+
+resource_data = files(
+ 'cc-info-overview-panel.ui'
+)
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname.underscorify (),
+ dependencies: resource_data,
+ export: true
+)
+
+deps = common_deps + [
+ dependency('udisks2', version: '>= 2.8.2'),
+ dependency('libgtop-2.0'),
+ gudev_dep,
+]
+
+info_panel_lib = static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [ top_inc, common_inc ],
+ dependencies: deps,
+ c_args: cflags
+)
+panels_libs += info_panel_lib
+
+print_renderer_deps = [
+ dependency('gtk4'),
+ epoxy_dep
+]
+
+executable(
+ 'gnome-control-center-print-renderer',
+ 'gnome-control-center-print-renderer.c',
+ include_directories: [ top_inc ],
+ dependencies: [ print_renderer_deps ],
+ c_args: cflags,
+ install: true,
+ install_dir: control_center_libexecdir,
+)
+
+install_data(
+ [ 'gnome-logo-text.svg', 'gnome-logo-text-dark.svg' ],
+ install_dir: join_paths(control_center_datadir, 'icons')
+)
+
+subdir('icons')
diff --git a/panels/keyboard/00-multimedia.xml.in b/panels/keyboard/00-multimedia.xml.in
new file mode 100644
index 0000000..bb1532d
--- /dev/null
+++ b/panels/keyboard/00-multimedia.xml.in
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<KeyListEntries group="system" schema="org.gnome.settings-daemon.plugins.media-keys" name="Sound and Media">
+
+ <KeyListEntry name="volume-mute" description="Volume mute/unmute"/>
+
+ <KeyListEntry name="volume-down" description="Volume down"/>
+
+ <KeyListEntry name="volume-up" description="Volume up"/>
+
+ <KeyListEntry name="mic-mute" description="Microphone mute/unmute"/>
+
+ <KeyListEntry name="media" description="Launch media player"/>
+
+ <KeyListEntry name="play" description="Play (or play/pause)"/>
+
+ <KeyListEntry name="pause" description="Pause playback"/>
+
+ <KeyListEntry name="stop" description="Stop playback"/>
+
+ <KeyListEntry name="previous" description="Previous track"/>
+
+ <KeyListEntry name="next" description="Next track"/>
+
+ <KeyListEntry name="eject" description="Eject"/>
+
+</KeyListEntries>
+
diff --git a/panels/keyboard/01-input-sources.xml.in b/panels/keyboard/01-input-sources.xml.in
new file mode 100644
index 0000000..355bba4
--- /dev/null
+++ b/panels/keyboard/01-input-sources.xml.in
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<KeyListEntries group="system"
+ schema="org.gnome.desktop.wm.keybindings"
+ name="Typing">
+
+ <KeyListEntry name="switch-input-source"
+ reverse-entry="switch-input-source-backward"
+ description="Switch to next input source"/>
+
+ <KeyListEntry name="switch-input-source-backward"
+ reverse-entry="switch-input-source"
+ is-reversed="true"
+ description="Switch to previous input source"/>
+
+</KeyListEntries>
diff --git a/panels/keyboard/01-launchers.xml.in b/panels/keyboard/01-launchers.xml.in
new file mode 100644
index 0000000..67c8325
--- /dev/null
+++ b/panels/keyboard/01-launchers.xml.in
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<KeyListEntries group="system" schema="org.gnome.settings-daemon.plugins.media-keys" name="Launchers">
+
+ <KeyListEntry name="help" description="Launch help browser"/>
+
+ <KeyListEntry name="control-center" description="Settings"/>
+
+ <KeyListEntry name="calculator" description="Launch calculator"/>
+
+ <KeyListEntry name="email" description="Launch email client"/>
+
+ <KeyListEntry name="www" description="Launch web browser"/>
+
+ <KeyListEntry name="home" description="Home folder"/>
+
+ <KeyListEntry name="search" description="Search" msgctxt="keybinding">Search</KeyListEntry>
+
+</KeyListEntries>
+
diff --git a/panels/keyboard/01-system.xml.in b/panels/keyboard/01-system.xml.in
new file mode 100644
index 0000000..1fcf78b
--- /dev/null
+++ b/panels/keyboard/01-system.xml.in
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<KeyListEntries group="system" schema="org.gnome.settings-daemon.plugins.media-keys" name="System">
+
+ <KeyListEntry name="logout" description="Log out"/>
+
+ <KeyListEntry name="screensaver" description="Lock screen"/>
+
+</KeyListEntries>
+
diff --git a/panels/keyboard/50-accessibility.xml.in b/panels/keyboard/50-accessibility.xml.in
new file mode 100644
index 0000000..34bcb04
--- /dev/null
+++ b/panels/keyboard/50-accessibility.xml.in
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<KeyListEntries group="system" name="Accessibility" schema="org.gnome.settings-daemon.plugins.media-keys">
+
+ <KeyListEntry name="magnifier" description="Turn zoom on or off"/>
+
+ <KeyListEntry name="magnifier-zoom-in" description="Zoom in"/>
+
+ <KeyListEntry name="magnifier-zoom-out" description="Zoom out"/>
+
+ <KeyListEntry name="screenreader" description="Turn screen reader on or off"/>
+
+ <KeyListEntry name="on-screen-keyboard" description="Turn on-screen keyboard on or off"/>
+
+ <KeyListEntry name="increase-text-size" description="Increase text size"/>
+
+ <KeyListEntry name="decrease-text-size" description="Decrease text size"/>
+
+ <KeyListEntry name="toggle-contrast" description="High contrast on or off"/>
+
+</KeyListEntries>
diff --git a/panels/keyboard/cc-ibus-utils.c b/panels/keyboard/cc-ibus-utils.c
new file mode 100644
index 0000000..424c69e
--- /dev/null
+++ b/panels/keyboard/cc-ibus-utils.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#ifdef HAVE_IBUS
+#include "cc-ibus-utils.h"
+
+gchar *
+engine_get_display_name (IBusEngineDesc *engine_desc)
+{
+ const gchar *name;
+ const gchar *language_code;
+ const gchar *language;
+ const gchar *textdomain;
+ gchar *display_name;
+
+ name = ibus_engine_desc_get_longname (engine_desc);
+ language_code = ibus_engine_desc_get_language (engine_desc);
+ language = ibus_get_language_name (language_code);
+ textdomain = ibus_engine_desc_get_textdomain (engine_desc);
+ if (*textdomain != '\0' && *name != '\0')
+ name = g_dgettext (textdomain, name);
+ display_name = g_strdup_printf ("%s (%s)", language, name);
+
+ return display_name;
+}
+
+#endif /* HAVE_IBUS */
diff --git a/panels/keyboard/cc-ibus-utils.h b/panels/keyboard/cc-ibus-utils.h
new file mode 100644
index 0000000..20a0516
--- /dev/null
+++ b/panels/keyboard/cc-ibus-utils.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <ibus.h>
+
+G_BEGIN_DECLS
+
+gchar *engine_get_display_name (IBusEngineDesc *engine_desc);
+
+G_END_DECLS
diff --git a/panels/keyboard/cc-input-chooser.c b/panels/keyboard/cc-input-chooser.c
new file mode 100644
index 0000000..728eb6d
--- /dev/null
+++ b/panels/keyboard/cc-input-chooser.c
@@ -0,0 +1,1087 @@
+/*
+ * Copyright © 2013 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <locale.h>
+#include <glib/gi18n.h>
+
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnome-desktop/gnome-languages.h>
+
+#include "cc-common-language.h"
+#include "cc-util.h"
+#include "cc-input-chooser.h"
+#include "cc-input-source-ibus.h"
+#include "cc-input-source-xkb.h"
+
+#ifdef HAVE_IBUS
+#include <ibus.h>
+#include "cc-ibus-utils.h"
+#endif /* HAVE_IBUS */
+
+#define INPUT_SOURCE_TYPE_XKB "xkb"
+#define INPUT_SOURCE_TYPE_IBUS "ibus"
+
+#define FILTER_TIMEOUT 150 /* ms */
+
+typedef enum
+{
+ ROW_TRAVEL_DIRECTION_NONE,
+ ROW_TRAVEL_DIRECTION_FORWARD,
+ ROW_TRAVEL_DIRECTION_BACKWARD
+} RowTravelDirection;
+
+typedef enum
+{
+ ROW_LABEL_POSITION_START,
+ ROW_LABEL_POSITION_CENTER,
+ ROW_LABEL_POSITION_END
+} RowLabelPosition;
+
+struct _CcInputChooser
+{
+ GtkDialog parent_instance;
+
+ GtkButton *add_button;
+ GtkSearchEntry *filter_entry;
+ GtkListBox *input_sources_listbox;
+ GtkLabel *login_label;
+ GtkListBoxRow *more_row;
+ GtkWidget *no_results;
+ GtkAdjustment *scroll_adjustment;
+
+ GnomeXkbInfo *xkb_info;
+ GHashTable *ibus_engines;
+ GHashTable *locales;
+ GHashTable *locales_by_language;
+ gboolean showing_extra;
+ guint filter_timeout_id;
+ gchar **filter_words;
+
+ gboolean is_login;
+};
+
+G_DEFINE_TYPE (CcInputChooser, cc_input_chooser, GTK_TYPE_DIALOG)
+
+typedef struct
+{
+ gchar *id;
+ gchar *name;
+ gchar *unaccented_name;
+ gchar *untranslated_name;
+ GtkListBoxRow *default_input_source_row;
+ GtkListBoxRow *locale_row;
+ GtkListBoxRow *back_row;
+ GHashTable *layout_rows_by_id;
+ GHashTable *engine_rows_by_id;
+} LocaleInfo;
+
+static void
+locale_info_free (gpointer data)
+{
+ LocaleInfo *info = data;
+
+ g_free (info->id);
+ g_free (info->name);
+ g_free (info->unaccented_name);
+ g_free (info->untranslated_name);
+ g_clear_object (&info->default_input_source_row);
+ g_clear_object (&info->locale_row);
+ g_clear_object (&info->back_row);
+ g_hash_table_destroy (info->layout_rows_by_id);
+ g_hash_table_destroy (info->engine_rows_by_id);
+ g_free (info);
+}
+
+static void
+set_row_widget_margins (GtkWidget *widget)
+{
+ gtk_widget_set_margin_start (widget, 20);
+ gtk_widget_set_margin_end (widget, 20);
+ gtk_widget_set_margin_top (widget, 6);
+ gtk_widget_set_margin_bottom (widget, 6);
+}
+
+static GtkWidget *
+padded_label_new (const gchar *text,
+ RowLabelPosition position,
+ RowTravelDirection direction,
+ gboolean dim_label)
+{
+ GtkWidget *widget;
+ GtkWidget *label;
+ GtkWidget *arrow;
+ GtkAlign alignment;
+
+ if (position == ROW_LABEL_POSITION_START)
+ alignment = GTK_ALIGN_START;
+ else if (position == ROW_LABEL_POSITION_CENTER)
+ alignment = GTK_ALIGN_CENTER;
+ else
+ alignment = GTK_ALIGN_END;
+
+ widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+ if (direction == ROW_TRAVEL_DIRECTION_BACKWARD)
+ {
+ arrow = gtk_image_new_from_icon_name ("go-previous-symbolic");
+ gtk_box_append (GTK_BOX (widget), arrow);
+ }
+
+ label = gtk_label_new (text);
+ gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_MIDDLE);
+ gtk_widget_set_hexpand (label, TRUE);
+ gtk_widget_set_halign (label, alignment);
+ set_row_widget_margins (label);
+ gtk_box_append (GTK_BOX (widget), label);
+ if (dim_label)
+ gtk_style_context_add_class (gtk_widget_get_style_context (label), "dim-label");
+
+ if (direction == ROW_TRAVEL_DIRECTION_FORWARD)
+ {
+ arrow = gtk_image_new_from_icon_name ("go-next-symbolic");
+ gtk_box_append (GTK_BOX (widget), arrow);
+ }
+
+ return widget;
+}
+
+static GtkListBoxRow *
+more_row_new (void)
+{
+ GtkWidget *row;
+ GtkWidget *box;
+ GtkWidget *arrow;
+
+ row = gtk_list_box_row_new ();
+ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), box);
+ gtk_widget_set_tooltip_text (row, _("More…"));
+
+ arrow = gtk_image_new_from_icon_name ("view-more-symbolic");
+ gtk_widget_set_hexpand (arrow, TRUE);
+ set_row_widget_margins (arrow);
+ gtk_box_append (GTK_BOX (box), arrow);
+
+ return GTK_LIST_BOX_ROW (row);
+}
+
+static GtkWidget *
+no_results_widget_new (void)
+{
+ return padded_label_new (_("No input sources found"), ROW_LABEL_POSITION_CENTER, ROW_TRAVEL_DIRECTION_NONE, TRUE);
+}
+
+static GtkListBoxRow *
+back_row_new (const gchar *text)
+{
+ GtkWidget *row;
+ GtkWidget *widget;
+
+ row = gtk_list_box_row_new ();
+ widget = padded_label_new (text, ROW_LABEL_POSITION_CENTER, ROW_TRAVEL_DIRECTION_BACKWARD, TRUE);
+ gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), widget);
+
+ return GTK_LIST_BOX_ROW (row);
+}
+
+static GtkListBoxRow *
+locale_row_new (const gchar *text)
+{
+ GtkWidget *row;
+ GtkWidget *widget;
+
+ row = gtk_list_box_row_new ();
+ widget = padded_label_new (text, ROW_LABEL_POSITION_CENTER, ROW_TRAVEL_DIRECTION_NONE, FALSE);
+ gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), widget);
+
+ return GTK_LIST_BOX_ROW (row);
+}
+
+static GtkListBoxRow *
+input_source_row_new (CcInputChooser *self,
+ const gchar *type,
+ const gchar *id)
+{
+ GtkWidget *row = NULL;
+ GtkWidget *widget;
+
+ if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB))
+ {
+ const gchar *display_name;
+
+ gnome_xkb_info_get_layout_info (self->xkb_info, id, &display_name, NULL, NULL, NULL);
+
+ row = gtk_list_box_row_new ();
+ widget = padded_label_new (display_name,
+ ROW_LABEL_POSITION_START,
+ ROW_TRAVEL_DIRECTION_NONE,
+ FALSE);
+ gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), widget);
+ g_object_set_data (G_OBJECT (row), "name", (gpointer) display_name);
+ g_object_set_data_full (G_OBJECT (row), "unaccented-name",
+ cc_util_normalize_casefold_and_unaccent (display_name), g_free);
+ }
+ else if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS))
+ {
+#ifdef HAVE_IBUS
+ gchar *display_name;
+ GtkWidget *image;
+
+ display_name = engine_get_display_name (g_hash_table_lookup (self->ibus_engines, id));
+
+ row = gtk_list_box_row_new ();
+ widget = padded_label_new (display_name,
+ ROW_LABEL_POSITION_START,
+ ROW_TRAVEL_DIRECTION_NONE,
+ FALSE);
+ gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), widget);
+
+ image = gtk_image_new_from_icon_name ("system-run-symbolic");
+ set_row_widget_margins (image);
+ gtk_box_append (GTK_BOX (widget), image);
+
+ g_object_set_data_full (G_OBJECT (row), "name", display_name, g_free);
+ g_object_set_data_full (G_OBJECT (row), "unaccented-name",
+ cc_util_normalize_casefold_and_unaccent (display_name), g_free);
+#else
+ widget = NULL;
+#endif /* HAVE_IBUS */
+ }
+
+ if (row)
+ {
+ g_object_set_data (G_OBJECT (row), "type", (gpointer) type);
+ g_object_set_data (G_OBJECT (row), "id", (gpointer) id);
+
+ return GTK_LIST_BOX_ROW (row);
+ }
+
+ return NULL;
+}
+
+static void
+remove_all_rows (GtkListBox *listbox)
+{
+ GtkWidget *child;
+
+ while ((child = gtk_widget_get_first_child (GTK_WIDGET (listbox))) != NULL)
+ gtk_list_box_remove (listbox, child);
+}
+
+static void
+add_input_source_rows_for_locale (CcInputChooser *self,
+ LocaleInfo *info)
+{
+ GtkWidget *row;
+ GHashTableIter iter;
+ const gchar *id;
+
+ if (info->default_input_source_row)
+ gtk_list_box_append (self->input_sources_listbox, GTK_WIDGET (info->default_input_source_row));
+
+ g_hash_table_iter_init (&iter, info->layout_rows_by_id);
+ while (g_hash_table_iter_next (&iter, (gpointer *) &id, (gpointer *) &row))
+ gtk_list_box_append (self->input_sources_listbox, row);
+
+ g_hash_table_iter_init (&iter, info->engine_rows_by_id);
+ while (g_hash_table_iter_next (&iter, (gpointer *) &id, (gpointer *) &row))
+ gtk_list_box_append (self->input_sources_listbox, row);
+}
+
+static void
+show_input_sources_for_locale (CcInputChooser *self,
+ LocaleInfo *info)
+{
+ remove_all_rows (self->input_sources_listbox);
+
+ if (!info->back_row)
+ {
+ info->back_row = g_object_ref_sink (back_row_new (info->name));
+ gtk_widget_show (GTK_WIDGET (info->back_row));
+ g_object_set_data (G_OBJECT (info->back_row), "back", GINT_TO_POINTER (TRUE));
+ g_object_set_data (G_OBJECT (info->back_row), "locale-info", info);
+ }
+ gtk_list_box_append (self->input_sources_listbox, GTK_WIDGET (info->back_row));
+
+ add_input_source_rows_for_locale (self, info);
+
+ gtk_adjustment_set_value (self->scroll_adjustment,
+ gtk_adjustment_get_lower (self->scroll_adjustment));
+ gtk_list_box_invalidate_filter (self->input_sources_listbox);
+ gtk_list_box_set_selection_mode (self->input_sources_listbox, GTK_SELECTION_SINGLE);
+ gtk_list_box_set_activate_on_single_click (self->input_sources_listbox, FALSE);
+ gtk_list_box_unselect_all (self->input_sources_listbox);
+
+ if (gtk_widget_is_visible (GTK_WIDGET (self->filter_entry)) &&
+ !gtk_widget_is_focus (GTK_WIDGET (self->filter_entry)))
+ gtk_widget_grab_focus (GTK_WIDGET (self->filter_entry));
+}
+
+static gboolean
+is_current_locale (const gchar *locale)
+{
+ return g_strcmp0 (setlocale (LC_CTYPE, NULL), locale) == 0;
+}
+
+static void
+show_locale_rows (CcInputChooser *self)
+{
+ g_autoptr(GHashTable) initial = NULL;
+ LocaleInfo *info;
+ GHashTableIter iter;
+
+ remove_all_rows (self->input_sources_listbox);
+
+ if (!self->showing_extra)
+ initial = cc_common_language_get_initial_languages ();
+
+ g_hash_table_iter_init (&iter, self->locales);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &info))
+ {
+ if (!info->default_input_source_row &&
+ !g_hash_table_size (info->layout_rows_by_id) &&
+ !g_hash_table_size (info->engine_rows_by_id))
+ continue;
+
+ if (!info->locale_row)
+ {
+ info->locale_row = g_object_ref_sink (locale_row_new (info->name));
+ gtk_widget_show (GTK_WIDGET (info->locale_row));
+ g_object_set_data (G_OBJECT (info->locale_row), "locale-info", info);
+
+ if (!self->showing_extra &&
+ !g_hash_table_contains (initial, info->id) &&
+ !is_current_locale (info->id))
+ g_object_set_data (G_OBJECT (info->locale_row), "is-extra", GINT_TO_POINTER (TRUE));
+ }
+ gtk_list_box_append (self->input_sources_listbox, GTK_WIDGET (info->locale_row));
+ }
+
+ gtk_list_box_append (self->input_sources_listbox, GTK_WIDGET (self->more_row));
+
+ gtk_adjustment_set_value (self->scroll_adjustment,
+ gtk_adjustment_get_lower (self->scroll_adjustment));
+ gtk_list_box_invalidate_filter (self->input_sources_listbox);
+ gtk_list_box_set_selection_mode (self->input_sources_listbox, GTK_SELECTION_NONE);
+ gtk_list_box_set_activate_on_single_click (self->input_sources_listbox, TRUE);
+
+ if (gtk_widget_is_visible (GTK_WIDGET (self->filter_entry)) &&
+ !gtk_widget_is_focus (GTK_WIDGET (self->filter_entry)))
+ gtk_widget_grab_focus (GTK_WIDGET (self->filter_entry));
+}
+
+static gint
+list_sort (GtkListBoxRow *a,
+ GtkListBoxRow *b,
+ gpointer data)
+{
+ CcInputChooser *self = data;
+ LocaleInfo *ia;
+ LocaleInfo *ib;
+ const gchar *la;
+ const gchar *lb;
+ gint retval;
+
+ /* Always goes at the end */
+ if (a == self->more_row)
+ return 1;
+ if (b == self->more_row)
+ return -1;
+
+ ia = g_object_get_data (G_OBJECT (a), "locale-info");
+ ib = g_object_get_data (G_OBJECT (b), "locale-info");
+
+ /* The "Other" locale always goes at the end */
+ if (!ia->id[0] && ib->id[0])
+ return 1;
+ else if (ia->id[0] && !ib->id[0])
+ return -1;
+
+ retval = g_strcmp0 (ia->name, ib->name);
+ if (retval)
+ return retval;
+
+ la = g_object_get_data (G_OBJECT (a), "name");
+ lb = g_object_get_data (G_OBJECT (b), "name");
+
+ /* Only input sources have a "name" property and they should always
+ go after their respective heading */
+ if (la && !lb)
+ return 1;
+ else if (!la && lb)
+ return -1;
+ else if (!la && !lb)
+ return 0; /* Shouldn't happen */
+
+ /* The default input source always goes first in its group */
+ if (g_object_get_data (G_OBJECT (a), "default"))
+ return -1;
+ if (g_object_get_data (G_OBJECT (b), "default"))
+ return 1;
+
+ return g_strcmp0 (la, lb);
+}
+
+static gboolean
+match_all (gchar **words,
+ const gchar *str)
+{
+ gchar **w;
+
+ for (w = words; *w; ++w)
+ if (!strstr (str, *w))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+match_default_source_in_table (gchar **words,
+ GtkListBoxRow *row)
+{
+ const gchar *source_name;
+ source_name = g_object_get_data (G_OBJECT (row), "unaccented-name");
+ if (source_name && match_all (words, source_name))
+ return TRUE;
+ return FALSE;
+}
+
+static gboolean
+match_source_in_table (gchar **words,
+ GHashTable *table)
+{
+ GHashTableIter iter;
+ gpointer row;
+ const gchar *source_name;
+
+ g_hash_table_iter_init (&iter, table);
+ while (g_hash_table_iter_next (&iter, NULL, &row))
+ {
+ source_name = g_object_get_data (G_OBJECT (row), "unaccented-name");
+ if (source_name && match_all (words, source_name))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+list_filter (GtkListBoxRow *row,
+ gpointer user_data)
+{
+ CcInputChooser *self = user_data;
+ LocaleInfo *info;
+ gboolean is_extra;
+ const gchar *source_name;
+
+ if (row == self->more_row)
+ return !self->showing_extra;
+
+ is_extra = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (row), "is-extra"));
+
+ if (!self->showing_extra && is_extra)
+ return FALSE;
+
+ if (!self->filter_words)
+ return TRUE;
+
+ info = g_object_get_data (G_OBJECT (row), "locale-info");
+
+ if (row == info->back_row)
+ return TRUE;
+
+ if (match_all (self->filter_words, info->unaccented_name))
+ return TRUE;
+
+ if (match_all (self->filter_words, info->untranslated_name))
+ return TRUE;
+
+ source_name = g_object_get_data (G_OBJECT (row), "unaccented-name");
+ if (source_name)
+ {
+ if (match_all (self->filter_words, source_name))
+ return TRUE;
+ }
+ else
+ {
+ if (info->default_input_source_row &&
+ match_default_source_in_table (self->filter_words, info->default_input_source_row))
+ {
+ return TRUE;
+ }
+ if (match_source_in_table (self->filter_words, info->layout_rows_by_id))
+ return TRUE;
+ if (match_source_in_table (self->filter_words, info->engine_rows_by_id))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+strvs_differ (gchar **av,
+ gchar **bv)
+{
+ gchar **a, **b;
+
+ for (a = av, b = bv; *a && *b; ++a, ++b)
+ if (!g_str_equal (*a, *b))
+ return TRUE;
+
+ if (*a == NULL && *b == NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+do_filter (CcInputChooser *self)
+{
+ g_auto(GStrv) previous_words = NULL;
+ g_autofree gchar *filter_contents = NULL;
+
+ self->filter_timeout_id = 0;
+
+ filter_contents =
+ cc_util_normalize_casefold_and_unaccent (gtk_editable_get_text (GTK_EDITABLE (self->filter_entry)));
+
+ previous_words = self->filter_words;
+ self->filter_words = g_strsplit_set (g_strstrip (filter_contents), " ", 0);
+
+ if (!self->filter_words[0])
+ {
+ gtk_list_box_invalidate_filter (self->input_sources_listbox);
+ gtk_list_box_set_placeholder (self->input_sources_listbox, NULL);
+ }
+ else if (previous_words == NULL || strvs_differ (self->filter_words, previous_words))
+ {
+ gtk_list_box_invalidate_filter (self->input_sources_listbox);
+ gtk_list_box_set_placeholder (self->input_sources_listbox, self->no_results);
+ }
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+on_filter_entry_search_changed_cb (CcInputChooser *self)
+{
+ if (self->filter_timeout_id == 0)
+ self->filter_timeout_id = g_timeout_add (FILTER_TIMEOUT, (GSourceFunc) do_filter, self);
+}
+
+static void
+show_more (CcInputChooser *self)
+{
+ gtk_widget_show (GTK_WIDGET (self->filter_entry));
+ gtk_widget_grab_focus (GTK_WIDGET (self->filter_entry));
+
+ self->showing_extra = TRUE;
+
+ gtk_list_box_invalidate_filter (self->input_sources_listbox);
+}
+
+static void
+on_input_sources_listbox_row_activated_cb (CcInputChooser *self, GtkListBoxRow *row)
+{
+ gpointer data;
+
+ if (!row)
+ return;
+
+ if (row == self->more_row)
+ {
+ show_more (self);
+ return;
+ }
+
+ data = g_object_get_data (G_OBJECT (row), "back");
+ if (data)
+ {
+ show_locale_rows (self);
+ return;
+ }
+
+ data = g_object_get_data (G_OBJECT (row), "name");
+ if (data)
+ {
+ if (gtk_widget_is_sensitive (GTK_WIDGET (self->add_button)))
+ gtk_dialog_response (GTK_DIALOG (self),
+ gtk_dialog_get_response_for_widget (GTK_DIALOG (self),
+ GTK_WIDGET (self->add_button)));
+ return;
+ }
+
+ data = g_object_get_data (G_OBJECT (row), "locale-info");
+ if (data)
+ {
+ show_input_sources_for_locale (self, (LocaleInfo *) data);
+ return;
+ }
+}
+
+static void
+on_input_sources_listbox_selected_rows_changed_cb (CcInputChooser *self)
+{
+ gboolean sensitive = TRUE;
+ GtkListBoxRow *row;
+
+ row = gtk_list_box_get_selected_row (self->input_sources_listbox);
+ if (!row || g_object_get_data (G_OBJECT (row), "back"))
+ sensitive = FALSE;
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->add_button), sensitive);
+}
+
+static void
+add_default_row (CcInputChooser *self,
+ LocaleInfo *info,
+ const gchar *type,
+ const gchar *id)
+{
+ info->default_input_source_row = input_source_row_new (self, type, id);
+ if (info->default_input_source_row)
+ {
+ gtk_widget_show (GTK_WIDGET (info->default_input_source_row));
+ g_object_ref_sink (GTK_WIDGET (info->default_input_source_row));
+ g_object_set_data (G_OBJECT (info->default_input_source_row), "default", GINT_TO_POINTER (TRUE));
+ g_object_set_data (G_OBJECT (info->default_input_source_row), "locale-info", info);
+ }
+}
+
+static void
+add_rows_to_table (CcInputChooser *self,
+ LocaleInfo *info,
+ GList *list,
+ const gchar *type,
+ const gchar *default_id)
+{
+ GHashTable *table;
+ GtkListBoxRow *row;
+ const gchar *id;
+
+ if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB))
+ table = info->layout_rows_by_id;
+ else if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS))
+ table = info->engine_rows_by_id;
+ else
+ return;
+
+ while (list)
+ {
+ id = (const gchar *) list->data;
+
+ /* The widget for the default input source lives elsewhere */
+ if (g_strcmp0 (id, default_id))
+ {
+ row = input_source_row_new (self, type, id);
+ gtk_widget_show (GTK_WIDGET (row));
+ if (row)
+ {
+ g_object_set_data (G_OBJECT (row), "locale-info", info);
+ g_hash_table_replace (table, (gpointer) id, g_object_ref_sink (row));
+ }
+ }
+ list = list->next;
+ }
+}
+
+static void
+add_row (CcInputChooser *self,
+ LocaleInfo *info,
+ const gchar *type,
+ const gchar *id)
+{
+ GList tmp = { 0 };
+ tmp.data = (gpointer) id;
+ add_rows_to_table (self, info, &tmp, type, NULL);
+}
+
+static void
+add_row_other (CcInputChooser *self,
+ const gchar *type,
+ const gchar *id)
+{
+ LocaleInfo *info = g_hash_table_lookup (self->locales, "");
+ add_row (self, info, type, id);
+}
+
+#ifdef HAVE_IBUS
+static gboolean
+maybe_set_as_default (CcInputChooser *self,
+ LocaleInfo *info,
+ const gchar *engine_id)
+{
+ const gchar *type, *id;
+
+ if (!gnome_get_input_source_from_locale (info->id, &type, &id))
+ return FALSE;
+
+ if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS) &&
+ g_str_equal (id, engine_id) &&
+ info->default_input_source_row == NULL)
+ {
+ add_default_row (self, info, type, id);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+get_ibus_locale_infos (CcInputChooser *self)
+{
+ GHashTableIter iter;
+ LocaleInfo *info;
+ const gchar *engine_id;
+ IBusEngineDesc *engine;
+
+ if (!self->ibus_engines || self->is_login)
+ return;
+
+ g_hash_table_iter_init (&iter, self->ibus_engines);
+ while (g_hash_table_iter_next (&iter, (gpointer *) &engine_id, (gpointer *) &engine))
+ {
+ g_autofree gchar *lang_code = NULL;
+ g_autofree gchar *country_code = NULL;
+ const gchar *ibus_locale = ibus_engine_desc_get_language (engine);
+
+ if (gnome_parse_locale (ibus_locale, &lang_code, &country_code, NULL, NULL) &&
+ lang_code != NULL &&
+ country_code != NULL)
+ {
+ g_autofree gchar *locale = g_strdup_printf ("%s_%s.UTF-8", lang_code, country_code);
+
+ info = g_hash_table_lookup (self->locales, locale);
+ if (info)
+ {
+ const gchar *type, *id;
+
+ if (gnome_get_input_source_from_locale (locale, &type, &id) &&
+ g_str_equal (type, INPUT_SOURCE_TYPE_IBUS) &&
+ g_str_equal (id, engine_id))
+ {
+ add_default_row (self, info, type, id);
+ }
+ else
+ {
+ add_row (self, info, INPUT_SOURCE_TYPE_IBUS, engine_id);
+ }
+ }
+ else
+ {
+ add_row_other (self, INPUT_SOURCE_TYPE_IBUS, engine_id);
+ }
+ }
+ else if (lang_code != NULL)
+ {
+ GHashTableIter iter;
+ GHashTable *locales_for_language;
+ g_autofree gchar *language = NULL;
+
+ /* Most IBus engines only specify the language so we try to
+ add them to all locales for that language. */
+
+ language = gnome_get_language_from_code (lang_code, NULL);
+ if (language)
+ locales_for_language = g_hash_table_lookup (self->locales_by_language, language);
+ else
+ locales_for_language = NULL;
+
+ if (locales_for_language)
+ {
+ g_hash_table_iter_init (&iter, locales_for_language);
+ while (g_hash_table_iter_next (&iter, (gpointer *) &info, NULL))
+ if (!maybe_set_as_default (self, info, engine_id))
+ add_row (self, info, INPUT_SOURCE_TYPE_IBUS, engine_id);
+ }
+ else
+ {
+ add_row_other (self, INPUT_SOURCE_TYPE_IBUS, engine_id);
+ }
+ }
+ else
+ {
+ add_row_other (self, INPUT_SOURCE_TYPE_IBUS, engine_id);
+ }
+ }
+}
+#endif /* HAVE_IBUS */
+
+static void
+add_locale_to_table (GHashTable *table,
+ const gchar *lang_code,
+ LocaleInfo *info)
+{
+ GHashTable *set;
+ g_autofree gchar *language = NULL;
+
+ language = gnome_get_language_from_code (lang_code, NULL);
+
+ set = g_hash_table_lookup (table, language);
+ if (!set)
+ {
+ set = g_hash_table_new (NULL, NULL);
+ g_hash_table_replace (table, g_strdup (language), set);
+ }
+ g_hash_table_add (set, info);
+}
+
+static void
+add_ids_to_set (GHashTable *set,
+ GList *list)
+{
+ while (list)
+ {
+ g_hash_table_add (set, list->data);
+ list = list->next;
+ }
+}
+
+static void
+get_locale_infos (CcInputChooser *self)
+{
+ g_autoptr(GHashTable) layouts_with_locale = NULL;
+ LocaleInfo *info;
+ g_auto(GStrv) locale_ids = NULL;
+ gchar **locale;
+ g_autoptr(GList) all_layouts = NULL;
+ GList *l;
+
+ self->locales = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, locale_info_free);
+ self->locales_by_language = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, (GDestroyNotify) g_hash_table_unref);
+
+ layouts_with_locale = g_hash_table_new (g_str_hash, g_str_equal);
+
+ locale_ids = gnome_get_all_locales ();
+ for (locale = locale_ids; *locale; ++locale)
+ {
+ g_autofree gchar *lang_code = NULL;
+ g_autofree gchar *country_code = NULL;
+ g_autofree gchar *simple_locale = NULL;
+ g_autofree gchar *tmp = NULL;
+ const gchar *type = NULL;
+ const gchar *id = NULL;
+ g_autoptr(GList) language_layouts = NULL;
+
+ if (!gnome_parse_locale (*locale, &lang_code, &country_code, NULL, NULL))
+ continue;
+
+ if (country_code != NULL)
+ simple_locale = g_strdup_printf ("%s_%s.UTF-8", lang_code, country_code);
+ else
+ simple_locale = g_strdup_printf ("%s.UTF-8", lang_code);
+
+ if (g_hash_table_contains (self->locales, simple_locale))
+ continue;
+
+ info = g_new0 (LocaleInfo, 1);
+ info->id = g_strdup (simple_locale);
+ info->name = gnome_get_language_from_locale (simple_locale, NULL);
+ info->unaccented_name = cc_util_normalize_casefold_and_unaccent (info->name);
+ tmp = gnome_get_language_from_locale (simple_locale, "C");
+ info->untranslated_name = cc_util_normalize_casefold_and_unaccent (tmp);
+
+ g_hash_table_replace (self->locales, g_strdup (simple_locale), info);
+ add_locale_to_table (self->locales_by_language, lang_code, info);
+
+ if (gnome_get_input_source_from_locale (simple_locale, &type, &id) &&
+ g_str_equal (type, INPUT_SOURCE_TYPE_XKB))
+ {
+ add_default_row (self, info, type, id);
+ g_hash_table_add (layouts_with_locale, (gpointer) id);
+ }
+
+ /* We don't own these ids */
+ info->layout_rows_by_id = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, g_object_unref);
+ info->engine_rows_by_id = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, g_object_unref);
+
+ language_layouts = gnome_xkb_info_get_layouts_for_language (self->xkb_info, lang_code);
+ add_rows_to_table (self, info, language_layouts, INPUT_SOURCE_TYPE_XKB, id);
+ add_ids_to_set (layouts_with_locale, language_layouts);
+
+ if (country_code != NULL)
+ {
+ g_autoptr(GList) country_layouts = gnome_xkb_info_get_layouts_for_country (self->xkb_info, country_code);
+ add_rows_to_table (self, info, country_layouts, INPUT_SOURCE_TYPE_XKB, id);
+ add_ids_to_set (layouts_with_locale, country_layouts);
+ }
+ }
+
+ /* Add a "Other" locale to hold the remaining input sources */
+ info = g_new0 (LocaleInfo, 1);
+ info->id = g_strdup ("");
+ info->name = g_strdup (C_("Input Source", "Other"));
+ info->unaccented_name = g_strdup ("");
+ info->untranslated_name = g_strdup ("");
+ g_hash_table_replace (self->locales, g_strdup (info->id), info);
+
+ info->layout_rows_by_id = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, g_object_unref);
+ info->engine_rows_by_id = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, g_object_unref);
+
+ all_layouts = gnome_xkb_info_get_all_layouts (self->xkb_info);
+ for (l = all_layouts; l; l = l->next)
+ if (!g_hash_table_contains (layouts_with_locale, l->data))
+ add_row_other (self, INPUT_SOURCE_TYPE_XKB, l->data);
+}
+
+/*
+static gboolean
+on_filter_entry_key_release_event_cb (CcInputChooser *self, GdkEventKey *event)
+{
+ if (event->keyval == GDK_KEY_Escape) {
+ self->showing_extra = FALSE;
+ gtk_entry_set_text (GTK_ENTRY (self->filter_entry), "");
+ gtk_widget_hide (GTK_WIDGET (self->filter_entry));
+ g_clear_pointer (&self->filter_words, g_strfreev);
+ show_locale_rows (self);
+ }
+
+ return FALSE;
+}
+ */
+
+static void
+cc_input_chooser_dispose (GObject *object)
+{
+ CcInputChooser *self = CC_INPUT_CHOOSER (object);
+
+ g_clear_object (&self->more_row);
+ g_clear_object (&self->no_results);
+ g_clear_object (&self->xkb_info);
+ g_clear_pointer (&self->ibus_engines, g_hash_table_unref);
+ g_clear_pointer (&self->locales, g_hash_table_unref);
+ g_clear_pointer (&self->locales_by_language, g_hash_table_unref);
+ g_clear_pointer (&self->filter_words, g_strfreev);
+ g_clear_handle_id (&self->filter_timeout_id, g_source_remove);
+
+ G_OBJECT_CLASS (cc_input_chooser_parent_class)->dispose (object);
+}
+
+void
+cc_input_chooser_class_init (CcInputChooserClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_input_chooser_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/keyboard/cc-input-chooser.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcInputChooser, add_button);
+ gtk_widget_class_bind_template_child (widget_class, CcInputChooser, filter_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcInputChooser, input_sources_listbox);
+ gtk_widget_class_bind_template_child (widget_class, CcInputChooser, login_label);
+ gtk_widget_class_bind_template_child (widget_class, CcInputChooser, scroll_adjustment);
+
+ gtk_widget_class_bind_template_callback (widget_class, on_input_sources_listbox_row_activated_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_input_sources_listbox_selected_rows_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_filter_entry_search_changed_cb);
+ //gtk_widget_class_bind_template_callback (widget_class, on_filter_entry_key_release_event_cb);
+}
+
+void
+cc_input_chooser_init (CcInputChooser *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ gtk_search_entry_set_key_capture_widget (self->filter_entry, GTK_WIDGET (self));
+}
+
+CcInputChooser *
+cc_input_chooser_new (gboolean is_login,
+ GnomeXkbInfo *xkb_info,
+ GHashTable *ibus_engines)
+{
+ CcInputChooser *self;
+
+ self = g_object_new (CC_TYPE_INPUT_CHOOSER,
+ "use-header-bar", 1,
+ NULL);
+
+ self->is_login = is_login;
+ self->xkb_info = g_object_ref (xkb_info);
+ if (ibus_engines)
+ self->ibus_engines = g_hash_table_ref (ibus_engines);
+
+ self->more_row = g_object_ref_sink (more_row_new ());
+ gtk_widget_show (GTK_WIDGET (self->more_row));
+ self->no_results = g_object_ref_sink (no_results_widget_new ());
+ gtk_widget_show (self->no_results);
+
+ gtk_list_box_set_filter_func (self->input_sources_listbox, list_filter, self, NULL);
+ gtk_list_box_set_sort_func (self->input_sources_listbox, list_sort, self, NULL);
+
+ if (self->is_login)
+ gtk_widget_show (GTK_WIDGET (self->login_label));
+
+ get_locale_infos (self);
+#ifdef HAVE_IBUS
+ get_ibus_locale_infos (self);
+#endif /* HAVE_IBUS */
+ show_locale_rows (self);
+
+ return self;
+}
+
+void
+cc_input_chooser_set_ibus_engines (CcInputChooser *self,
+ GHashTable *ibus_engines)
+{
+ g_return_if_fail (CC_IS_INPUT_CHOOSER (self));
+
+#ifdef HAVE_IBUS
+ /* This should only be called once when IBus shows up in case it
+ wasn't up yet when the user opened the input chooser dialog. */
+ g_return_if_fail (self->ibus_engines == NULL);
+
+ self->ibus_engines = ibus_engines;
+ get_ibus_locale_infos (self);
+ show_locale_rows (self);
+#endif /* HAVE_IBUS */
+}
+
+CcInputSource *
+cc_input_chooser_get_source (CcInputChooser *self)
+{
+ GtkListBoxRow *selected;
+ const gchar *t, *i;
+
+ g_return_val_if_fail (CC_IS_INPUT_CHOOSER (self), FALSE);
+
+ selected = gtk_list_box_get_selected_row (self->input_sources_listbox);
+ if (!selected)
+ return NULL;
+
+ t = g_object_get_data (G_OBJECT (selected), "type");
+ i = g_object_get_data (G_OBJECT (selected), "id");
+
+ if (!t || !i)
+ return FALSE;
+
+ if (g_strcmp0 (t, "xkb") == 0)
+ return CC_INPUT_SOURCE (cc_input_source_xkb_new_from_id (self->xkb_info, i));
+ else if (g_strcmp0 (t, "ibus") == 0)
+ return CC_INPUT_SOURCE (cc_input_source_ibus_new (i));
+ else
+ return NULL;
+}
diff --git a/panels/keyboard/cc-input-chooser.h b/panels/keyboard/cc-input-chooser.h
new file mode 100644
index 0000000..8363782
--- /dev/null
+++ b/panels/keyboard/cc-input-chooser.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2013 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "cc-input-source.h"
+
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnome-desktop/gnome-xkb-info.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_INPUT_CHOOSER (cc_input_chooser_get_type ())
+G_DECLARE_FINAL_TYPE (CcInputChooser, cc_input_chooser, CC, INPUT_CHOOSER, GtkDialog)
+
+CcInputChooser *cc_input_chooser_new (gboolean is_login,
+ GnomeXkbInfo *xkb_info,
+ GHashTable *ibus_engines);
+
+void cc_input_chooser_set_ibus_engines (CcInputChooser *chooser,
+ GHashTable *ibus_engines);
+
+CcInputSource *cc_input_chooser_get_source (CcInputChooser *chooser);
+
+G_END_DECLS
diff --git a/panels/keyboard/cc-input-chooser.ui b/panels/keyboard/cc-input-chooser.ui
new file mode 100644
index 0000000..74dd39a
--- /dev/null
+++ b/panels/keyboard/cc-input-chooser.ui
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcInputChooser" parent="GtkDialog">
+ <property name="title" translatable="yes">Add an Input Source</property>
+ <property name="modal">True</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="resizable">True</property>
+ <child type="action">
+ <object class="GtkButton" id="cancel_button">
+ <property name="label" translatable="yes">_Cancel</property>
+ <property name="use_underline">True</property>
+ <property name="valign">center</property>
+ </object>
+ </child>
+ <child type="action">
+ <object class="GtkButton" id="add_button">
+ <property name="label" translatable="yes">_Add</property>
+ <property name="sensitive">False</property>
+ <property name="use_underline">True</property>
+ <property name="valign">center</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">0</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="vexpand">True</property>
+ <property name="hscrollbar-policy">never</property>
+ <property name="propagate-natural-height">True</property>
+ <property name="min-content-height">300</property>
+ <property name="vadjustment">scroll_adjustment</property>
+ <property name="child">
+ <object class="GtkViewport">
+ <property name="scroll-to-focus">True</property>
+ <property name="child">
+ <object class="AdwClamp">
+ <property name="child">
+ <object class="GtkListBox" id="input_sources_listbox">
+ <property name="halign">fill</property>
+ <property name="valign">start</property>
+ <property name="margin-top">24</property>
+ <property name="margin-bottom">24</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <signal name="row-activated" handler="on_input_sources_listbox_row_activated_cb" object="CcInputChooser" swapped="yes" />
+ <signal name="selected-rows-changed" handler="on_input_sources_listbox_selected_rows_changed_cb" object="CcInputChooser" swapped="yes" />
+ <style>
+ <class name="boxed-list" />
+ </style>
+ </object>
+ </property>
+ </object>
+ </property>
+ </object>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparator">
+ <property name="visible" bind-source="filter_entry" bind-property="visible" bind-flags="sync-create"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSearchEntry" id="filter_entry">
+ <property name="visible">False</property>
+ <property name="hexpand">True</property>
+ <property name="margin-start">6</property>
+ <property name="margin-end">6</property>
+ <property name="margin-top">6</property>
+ <property name="margin-bottom">6</property>
+ <accessibility>
+ <property name="label" translatable="yes">Search</property>
+ </accessibility>
+ <signal name="search-changed" handler="on_filter_entry_search_changed_cb" object="CcInputChooser" swapped="yes" />
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="login_label">
+ <property name="visible">False</property>
+ <property name="wrap">True</property>
+ <property name="label" translatable="yes">Input methods can’t be used on the login screen</property>
+ <property name="margin-start">6</property>
+ <property name="margin-end">6</property>
+ <property name="margin-bottom">6</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5" default="true">add_button</action-widget>
+ <action-widget response="-6">cancel_button</action-widget>
+ </action-widgets>
+ </template>
+ <object class="GtkAdjustment" id="scroll_adjustment">
+ </object>
+</interface>
diff --git a/panels/keyboard/cc-input-list-box.c b/panels/keyboard/cc-input-list-box.c
new file mode 100644
index 0000000..5ad9f15
--- /dev/null
+++ b/panels/keyboard/cc-input-list-box.c
@@ -0,0 +1,821 @@
+/* cc-input-list-box.c
+ *
+ * Copyright (C) 2010 Intel, Inc
+ * Copyright (C) 2020 System76, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Sergey Udaltsov <svu@gnome.org>
+ * Ian Douglas Scott <idscott@system76.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnome-desktop/gnome-xkb-info.h>
+
+#include "cc-input-list-box.h"
+#include "cc-input-chooser.h"
+#include "cc-input-row.h"
+#include "cc-input-source-ibus.h"
+#include "cc-input-source-xkb.h"
+
+#ifdef HAVE_IBUS
+#include <ibus.h>
+#endif
+
+#define GNOME_DESKTOP_INPUT_SOURCES_DIR "org.gnome.desktop.input-sources"
+#define KEY_INPUT_SOURCES "sources"
+
+struct _CcInputListBox {
+ AdwBin parent_instance;
+
+ GtkListBoxRow *add_input_row;
+ GtkListBox *listbox;
+ GtkListBoxRow *no_inputs_row;
+
+ GCancellable *cancellable;
+
+ gboolean login;
+ gboolean login_auto_apply;
+ GPermission *permission;
+ GDBusProxy *localed;
+
+ GSettings *input_settings;
+ GnomeXkbInfo *xkb_info;
+#ifdef HAVE_IBUS
+ IBusBus *ibus;
+ GHashTable *ibus_engines;
+#endif
+};
+
+G_DEFINE_TYPE (CcInputListBox, cc_input_list_box, ADW_TYPE_BIN)
+
+typedef struct
+{
+ CcInputListBox *panel;
+ CcInputRow *source;
+ CcInputRow *dest;
+} RowData;
+
+static RowData *
+row_data_new (CcInputListBox *panel, CcInputRow *source, CcInputRow *dest)
+{
+ RowData *data = g_malloc0 (sizeof (RowData));
+ data->panel = panel;
+ data->source = g_object_ref (source);
+ if (dest != NULL)
+ data->dest = g_object_ref (dest);
+ return data;
+}
+
+static void
+row_data_free (RowData *data)
+{
+ g_clear_object (&data->source);
+ g_clear_object (&data->dest);
+ g_free (data);
+}
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (RowData, row_data_free)
+
+static void show_input_chooser (CcInputListBox *self);
+
+#ifdef HAVE_IBUS
+static void
+update_ibus_active_sources (CcInputListBox *self)
+{
+ GtkWidget *child;
+
+ for (child = gtk_widget_get_first_child (GTK_WIDGET (self->listbox));
+ child;
+ child = gtk_widget_get_next_sibling (child)) {
+ CcInputRow *row;
+ CcInputSourceIBus *source;
+ IBusEngineDesc *engine_desc;
+
+ if (!CC_IS_INPUT_ROW (child))
+ continue;
+ row = CC_INPUT_ROW (child);
+
+ if (!CC_IS_INPUT_SOURCE_IBUS (cc_input_row_get_source (row)))
+ continue;
+ source = CC_INPUT_SOURCE_IBUS (cc_input_row_get_source (row));
+
+ engine_desc = g_hash_table_lookup (self->ibus_engines, cc_input_source_ibus_get_engine_name (source));
+ if (engine_desc != NULL)
+ cc_input_source_ibus_set_engine_desc (source, engine_desc);
+ }
+}
+
+static void
+fetch_ibus_engines_result (GObject *object,
+ GAsyncResult *result,
+ CcInputListBox *self)
+{
+ g_autoptr(GList) list = NULL;
+ GList *l;
+ g_autoptr(GError) error = NULL;
+
+ list = ibus_bus_list_engines_async_finish (IBUS_BUS (object), result, &error);
+ if (!list && error) {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Couldn't finish IBus request: %s", error->message);
+ return;
+ }
+
+ /* Maps engine ids to engine description objects */
+ self->ibus_engines = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
+
+ for (l = list; l; l = l->next) {
+ IBusEngineDesc *engine = l->data;
+ const gchar *engine_id = ibus_engine_desc_get_name (engine);
+
+ if (g_str_has_prefix (engine_id, "xkb:"))
+ g_object_unref (engine);
+ else
+ g_hash_table_replace (self->ibus_engines, (gpointer)engine_id, engine);
+ }
+
+ update_ibus_active_sources (self);
+}
+
+static void
+fetch_ibus_engines (CcInputListBox *self)
+{
+ ibus_bus_list_engines_async (self->ibus,
+ -1,
+ self->cancellable,
+ (GAsyncReadyCallback)fetch_ibus_engines_result,
+ self);
+
+ /* We've got everything we needed, don't want to be called again. */
+ g_signal_handlers_disconnect_by_func (self->ibus, fetch_ibus_engines, self);
+}
+
+static void
+maybe_start_ibus (void)
+{
+ /* IBus doesn't export API in the session bus. The only thing
+ * we have there is a well known name which we can use as a
+ * sure-fire way to activate it.
+ */
+ g_bus_unwatch_name (g_bus_watch_name (G_BUS_TYPE_SESSION,
+ IBUS_SERVICE_IBUS,
+ G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
+ NULL,
+ NULL,
+ NULL,
+ NULL));
+}
+
+#endif
+
+static gboolean
+keynav_failed_cb (CcInputListBox *self,
+ GtkDirectionType direction,
+ GtkWidget *list)
+{
+ GtkWidget *toplevel = GTK_WIDGET (gtk_widget_get_root (GTK_WIDGET (self)));
+
+ if (!toplevel)
+ return FALSE;
+
+ if (direction != GTK_DIR_UP && direction != GTK_DIR_DOWN)
+ return FALSE;
+
+ return gtk_widget_child_focus (toplevel, direction == GTK_DIR_UP ?
+ GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD);
+}
+
+static void
+row_settings_cb (CcInputListBox *self,
+ CcInputRow *row)
+{
+ CcInputSourceIBus *source;
+ g_autoptr(GdkAppLaunchContext) ctx = NULL;
+ GDesktopAppInfo *app_info;
+ g_autoptr(GError) error = NULL;
+
+ g_return_if_fail (CC_IS_INPUT_SOURCE_IBUS (cc_input_row_get_source (row)));
+ source = CC_INPUT_SOURCE_IBUS (cc_input_row_get_source (row));
+
+ app_info = cc_input_source_ibus_get_app_info (source);
+ if (app_info == NULL)
+ return;
+
+ ctx = gdk_display_get_app_launch_context (gdk_display_get_default ());
+ gdk_app_launch_context_set_timestamp (ctx, GDK_CURRENT_TIME);
+
+ g_app_launch_context_setenv (G_APP_LAUNCH_CONTEXT (ctx),
+ "IBUS_ENGINE_NAME", cc_input_source_ibus_get_engine_name (source));
+
+ if (!g_app_info_launch (G_APP_INFO (app_info), NULL, G_APP_LAUNCH_CONTEXT (ctx), &error))
+ g_warning ("Failed to launch input source setup: %s", error->message);
+}
+
+static void
+row_layout_cb (CcInputListBox *self,
+ CcInputRow *row)
+{
+ CcInputSource *source;
+ const gchar *layout, *layout_variant;
+ g_autofree gchar *commandline = NULL;
+
+ source = cc_input_row_get_source (row);
+
+ layout = cc_input_source_get_layout (source);
+ layout_variant = cc_input_source_get_layout_variant (source);
+
+ if (layout_variant && layout_variant[0])
+ commandline = g_strdup_printf ("gkbd-keyboard-display -l \"%s\t%s\"",
+ layout, layout_variant);
+ else
+ commandline = g_strdup_printf ("gkbd-keyboard-display -l %s",
+ layout);
+
+ g_spawn_command_line_async (commandline, NULL);
+}
+
+static void move_input (CcInputListBox *self, CcInputRow *source, CcInputRow *dest);
+
+static void
+row_moved_cb (CcInputListBox *self,
+ CcInputRow *dest_row,
+ CcInputRow *row)
+{
+ move_input (self, row, dest_row);
+}
+
+static void remove_input (CcInputListBox *self, CcInputRow *row);
+
+static void
+row_removed_cb (CcInputListBox *self,
+ CcInputRow *row)
+{
+ remove_input (self, row);
+}
+
+static void
+update_input_rows (CcInputListBox *self)
+{
+ GtkWidget *child;
+ guint n_input_rows = 0;
+
+ child = gtk_widget_get_first_child (GTK_WIDGET (self->listbox));
+ while ((child = gtk_widget_get_next_sibling (child)) != NULL)
+ if (CC_IS_INPUT_ROW (child))
+ n_input_rows++;
+
+ for (child = gtk_widget_get_first_child (GTK_WIDGET (self->listbox));
+ child;
+ child = gtk_widget_get_next_sibling (child)) {
+ CcInputRow *row;
+
+ if (!CC_IS_INPUT_ROW (child))
+ continue;
+ row = CC_INPUT_ROW (child);
+
+ cc_input_row_set_removable (row, n_input_rows > 1);
+ cc_input_row_set_draggable (row, n_input_rows > 1);
+ }
+}
+
+static void
+add_input_row (CcInputListBox *self, CcInputSource *source)
+{
+ CcInputRow *row;
+
+ gtk_widget_set_visible (GTK_WIDGET (self->no_inputs_row), FALSE);
+
+ row = cc_input_row_new (source);
+ gtk_widget_show (GTK_WIDGET (row));
+ g_signal_connect_object (row, "show-settings", G_CALLBACK (row_settings_cb), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (row, "show-layout", G_CALLBACK (row_layout_cb), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (row, "move-row", G_CALLBACK (row_moved_cb), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (row, "remove-row", G_CALLBACK (row_removed_cb), self, G_CONNECT_SWAPPED);
+ gtk_list_box_insert (self->listbox, GTK_WIDGET (row), gtk_list_box_row_get_index (self->add_input_row));
+ update_input_rows (self);
+}
+
+static void
+add_input_sources (CcInputListBox *self,
+ GVariant *sources)
+{
+ GVariantIter iter;
+ const gchar *type, *id;
+
+ if (g_variant_n_children (sources) < 1) {
+ gtk_widget_set_visible (GTK_WIDGET (self->no_inputs_row), TRUE);
+ return;
+ }
+
+ g_variant_iter_init (&iter, sources);
+ while (g_variant_iter_next (&iter, "(&s&s)", &type, &id)) {
+ g_autoptr(CcInputSource) source = NULL;
+
+ if (g_str_equal (type, "xkb")) {
+ source = CC_INPUT_SOURCE (cc_input_source_xkb_new_from_id (self->xkb_info, id));
+ } else if (g_str_equal (type, "ibus")) {
+ source = CC_INPUT_SOURCE (cc_input_source_ibus_new (id));
+#ifdef HAVE_IBUS
+ if (self->ibus_engines) {
+ IBusEngineDesc *engine_desc = g_hash_table_lookup (self->ibus_engines, id);
+ if (engine_desc != NULL)
+ cc_input_source_ibus_set_engine_desc (CC_INPUT_SOURCE_IBUS (source), engine_desc);
+ }
+#endif
+ } else {
+ g_warning ("Unhandled input source type '%s'", type);
+ continue;
+ }
+
+ add_input_row (self, source);
+ }
+}
+
+static void
+add_input_sources_from_settings (CcInputListBox *self)
+{
+ g_autoptr(GVariant) sources = NULL;
+ sources = g_settings_get_value (self->input_settings, "sources");
+ add_input_sources (self, sources);
+}
+
+static void
+clear_input_sources (CcInputListBox *self)
+{
+ GtkWidget *child;
+
+ child = gtk_widget_get_first_child (GTK_WIDGET (self->listbox));
+ while (child) {
+ GtkWidget *next = gtk_widget_get_next_sibling (child);
+
+ if (CC_IS_INPUT_ROW (child))
+ gtk_list_box_remove (self->listbox, GTK_WIDGET (child));
+
+ child = next;
+ }
+}
+
+static CcInputRow *
+get_row_by_source (CcInputListBox *self, CcInputSource *source)
+{
+ GtkWidget *child;
+
+ for (child = gtk_widget_get_first_child (GTK_WIDGET (self->listbox));
+ child;
+ child = gtk_widget_get_next_sibling (child)) {
+ CcInputRow *row;
+
+ if (!CC_IS_INPUT_ROW (child))
+ continue;
+ row = CC_INPUT_ROW (child);
+
+ if (cc_input_source_matches (source, cc_input_row_get_source (row)))
+ return row;
+ }
+
+ return NULL;
+}
+
+static void
+input_sources_changed (CcInputListBox *self,
+ const gchar *key)
+{
+ CcInputRow *selected;
+ g_autoptr(CcInputSource) source = NULL;
+
+ selected = CC_INPUT_ROW (gtk_list_box_get_selected_row (self->listbox));
+ if (selected)
+ source = g_object_ref (cc_input_row_get_source (selected));
+ clear_input_sources (self);
+ add_input_sources_from_settings (self);
+ if (source != NULL) {
+ CcInputRow *row = get_row_by_source (self, source);
+ if (row != NULL)
+ gtk_list_box_select_row (self->listbox, GTK_LIST_BOX_ROW (row));
+ }
+}
+
+static void
+set_input_settings (CcInputListBox *self)
+{
+ GVariantBuilder builder;
+ GtkWidget *child;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ss)"));
+
+ for (child = gtk_widget_get_first_child (GTK_WIDGET (self->listbox));
+ child;
+ child = gtk_widget_get_next_sibling (child)) {
+ CcInputRow *row;
+ CcInputSource *source;
+
+ if (!CC_IS_INPUT_ROW (child))
+ continue;
+ row = CC_INPUT_ROW (child);
+ source = cc_input_row_get_source (row);
+
+ if (CC_IS_INPUT_SOURCE_XKB (source)) {
+ g_autofree gchar *id = cc_input_source_xkb_get_id (CC_INPUT_SOURCE_XKB (source));
+ g_variant_builder_add (&builder, "(ss)", "xkb", id);
+ } else if (CC_IS_INPUT_SOURCE_IBUS (source)) {
+ g_variant_builder_add (&builder, "(ss)", "ibus",
+ cc_input_source_ibus_get_engine_name (CC_INPUT_SOURCE_IBUS (source)));
+ }
+ }
+
+ g_settings_set_value (self->input_settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder));
+}
+
+static void set_localed_input (CcInputListBox *self);
+
+static void
+update_input (CcInputListBox *self)
+{
+ if (self->login) {
+ set_localed_input (self);
+ } else {
+ set_input_settings (self);
+ if (self->login_auto_apply)
+ set_localed_input (self);
+ }
+}
+
+static void
+on_chooser_response_cb (GtkDialog *dialog,
+ gint response,
+ CcInputListBox *self)
+{
+
+ if (response == GTK_RESPONSE_OK) {
+ CcInputSource *source;
+
+ source = cc_input_chooser_get_source (CC_INPUT_CHOOSER (dialog));
+ if (source != NULL && get_row_by_source (self, source) == NULL) {
+ add_input_row (self, source);
+ update_input (self);
+ }
+ }
+ gtk_window_destroy (GTK_WINDOW (dialog));
+}
+
+static void
+show_input_chooser (CcInputListBox *self)
+{
+ CcInputChooser *chooser;
+
+ chooser = cc_input_chooser_new (self->login,
+ self->xkb_info,
+#ifdef HAVE_IBUS
+ self->ibus_engines
+#else
+ NULL
+#endif
+ );
+ gtk_window_set_transient_for (GTK_WINDOW (chooser),
+ GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (self))));
+ g_signal_connect (chooser, "response", G_CALLBACK (on_chooser_response_cb), self);
+ gtk_window_present (GTK_WINDOW (chooser));
+}
+
+// Duplicated from cc-region-panel.c
+static gboolean
+permission_acquired (GPermission *permission, GAsyncResult *res, const gchar *action)
+{
+ g_autoptr(GError) error = NULL;
+
+ if (!g_permission_acquire_finish (permission, res, &error)) {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to acquire permission to %s: %s\n", error->message, action);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+add_input_permission_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ CcInputListBox *self = user_data;
+ if (permission_acquired (G_PERMISSION (source), res, "add input"))
+ show_input_chooser (self);
+}
+
+static void
+add_input (CcInputListBox *self)
+{
+ if (!self->login) {
+ show_input_chooser (self);
+ } else if (g_permission_get_allowed (self->permission)) {
+ show_input_chooser (self);
+ } else if (g_permission_get_can_acquire (self->permission)) {
+ g_permission_acquire_async (self->permission,
+ self->cancellable,
+ add_input_permission_cb,
+ self);
+ }
+}
+
+static GtkWidget *
+find_sibling (GtkWidget *child)
+{
+ GtkWidget *sibling;
+
+ for (sibling = gtk_widget_get_next_sibling (child);
+ sibling;
+ sibling = gtk_widget_get_next_sibling (child)) {
+ if (gtk_widget_get_visible (sibling) && gtk_widget_get_child_visible (sibling))
+ return sibling;
+ }
+
+ for (sibling = gtk_widget_get_prev_sibling (child);
+ sibling;
+ sibling = gtk_widget_get_prev_sibling (child)) {
+ if (gtk_widget_get_visible (sibling) && gtk_widget_get_child_visible (sibling))
+ return sibling;
+ }
+
+ return NULL;
+}
+
+static void
+do_remove_input (CcInputListBox *self, CcInputRow *row)
+{
+ GtkWidget *sibling;
+
+ sibling = find_sibling (GTK_WIDGET (row));
+ gtk_list_box_remove (self->listbox, GTK_WIDGET (row));
+ gtk_list_box_select_row (self->listbox, GTK_LIST_BOX_ROW (sibling));
+
+ update_input (self);
+ update_input_rows (self);
+}
+
+static void
+remove_input_permission_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ RowData *data = user_data;
+ if (permission_acquired (G_PERMISSION (source), res, "remove input"))
+ do_remove_input (data->panel, data->source);
+}
+
+static void
+remove_input (CcInputListBox *self, CcInputRow *row)
+{
+ if (!self->login) {
+ do_remove_input (self, row);
+ } else if (g_permission_get_allowed (self->permission)) {
+ do_remove_input (self, row);
+ } else if (g_permission_get_can_acquire (self->permission)) {
+ g_permission_acquire_async (self->permission,
+ self->cancellable,
+ remove_input_permission_cb,
+ row_data_new (self, row, NULL));
+ }
+}
+
+static void
+do_move_input (CcInputListBox *self, CcInputRow *source, CcInputRow *dest)
+{
+ gint dest_index;
+
+ dest_index = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (dest));
+
+ g_object_ref (source);
+ gtk_list_box_remove (self->listbox, GTK_WIDGET (source));
+ gtk_list_box_insert (self->listbox, GTK_WIDGET (source), dest_index);
+ g_object_unref (source);
+
+ update_input (self);
+}
+
+static void
+move_input_permission_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ RowData *data = user_data;
+ if (permission_acquired (G_PERMISSION (source), res, "move input"))
+ do_move_input (data->panel, data->source, data->dest);
+}
+
+static void
+move_input (CcInputListBox *self,
+ CcInputRow *source,
+ CcInputRow *dest)
+{
+ if (!self->login) {
+ do_move_input (self, source, dest);
+ } else if (g_permission_get_allowed (self->permission)) {
+ do_move_input (self, source, dest);
+ } else if (g_permission_get_can_acquire (self->permission)) {
+ g_permission_acquire_async (self->permission,
+ self->cancellable,
+ move_input_permission_cb,
+ row_data_new (self, source, dest));
+ }
+}
+
+static void
+input_row_activated_cb (CcInputListBox *self, GtkListBoxRow *row)
+{
+ if (row == self->add_input_row) {
+ add_input (self);
+ }
+}
+
+static void
+add_input_sources_from_localed (CcInputListBox *self)
+{
+ g_autoptr(GVariant) layout_property = NULL;
+ g_autoptr(GVariant) variant_property = NULL;
+ const gchar *s;
+ g_auto(GStrv) layouts = NULL;
+ g_auto(GStrv) variants = NULL;
+ gint i, n;
+
+ if (!self->localed)
+ return;
+
+ layout_property = g_dbus_proxy_get_cached_property (self->localed, "X11Layout");
+ if (layout_property) {
+ s = g_variant_get_string (layout_property, NULL);
+ layouts = g_strsplit (s, ",", -1);
+ }
+
+ variant_property = g_dbus_proxy_get_cached_property (self->localed, "X11Variant");
+ if (variant_property) {
+ s = g_variant_get_string (variant_property, NULL);
+ if (s && *s)
+ variants = g_strsplit (s, ",", -1);
+ }
+
+ if (variants && variants[0])
+ n = MIN (g_strv_length (layouts), g_strv_length (variants));
+ else if (layouts && layouts[0])
+ n = g_strv_length (layouts);
+ else
+ n = 0;
+
+ for (i = 0; i < n && layouts[i][0]; i++) {
+ const char *variant = variants ? variants[i] : NULL;
+ g_autoptr(CcInputSourceXkb) source = cc_input_source_xkb_new (self->xkb_info, layouts[i], variant);
+ add_input_row (self, CC_INPUT_SOURCE (source));
+ }
+ gtk_widget_set_visible (GTK_WIDGET (self->no_inputs_row), n == 0);
+}
+
+static void
+set_localed_input (CcInputListBox *self)
+{
+ g_autoptr(GString) layouts = NULL;
+ g_autoptr(GString) variants = NULL;
+ GtkWidget *child;
+
+ layouts = g_string_new ("");
+ variants = g_string_new ("");
+
+ for (child = gtk_widget_get_first_child (GTK_WIDGET (self->listbox));
+ child;
+ child = gtk_widget_get_next_sibling (child)) {
+ CcInputRow *row;
+ CcInputSourceXkb *source;
+ g_autofree gchar *id = NULL;
+ const gchar *l, *v;
+
+ if (!CC_IS_INPUT_ROW (child))
+ continue;
+ row = CC_INPUT_ROW (child);
+
+ if (!CC_IS_INPUT_SOURCE_XKB (cc_input_row_get_source (row)))
+ continue;
+ source = CC_INPUT_SOURCE_XKB (cc_input_row_get_source (row));
+
+ id = cc_input_source_xkb_get_id (source);
+ if (gnome_xkb_info_get_layout_info (self->xkb_info, id, NULL, NULL, &l, &v)) {
+ if (layouts->str[0]) {
+ g_string_append_c (layouts, ',');
+ g_string_append_c (variants, ',');
+ }
+ g_string_append (layouts, l);
+ g_string_append (variants, v);
+ }
+ }
+
+ g_dbus_proxy_call (self->localed,
+ "SetX11Keyboard",
+ g_variant_new ("(ssssbb)", layouts->str, "", variants->str, "", TRUE, TRUE),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, NULL, NULL);
+}
+
+static void
+cc_input_list_box_finalize (GObject *object)
+{
+ CcInputListBox *self = CC_INPUT_LIST_BOX (object);
+
+ g_cancellable_cancel (self->cancellable);
+
+ g_clear_object (&self->input_settings);
+ g_clear_object (&self->xkb_info);
+#ifdef HAVE_IBUS
+ g_clear_object (&self->ibus);
+ g_clear_pointer (&self->ibus_engines, g_hash_table_destroy);
+#endif
+
+ G_OBJECT_CLASS (cc_input_list_box_parent_class)->finalize (object);
+}
+
+static void
+cc_input_list_box_class_init (CcInputListBoxClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = cc_input_list_box_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/keyboard/cc-input-list-box.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcInputListBox, add_input_row);
+ gtk_widget_class_bind_template_child (widget_class, CcInputListBox, listbox);
+ gtk_widget_class_bind_template_child (widget_class, CcInputListBox, no_inputs_row);
+
+ gtk_widget_class_bind_template_callback (widget_class, input_row_activated_cb);
+ gtk_widget_class_bind_template_callback (widget_class, keynav_failed_cb);
+}
+
+static void
+cc_input_list_box_init (CcInputListBox *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->login = FALSE;
+ self->login_auto_apply = FALSE;
+ self->localed = NULL;
+ self->permission = NULL;
+
+ self->cancellable = g_cancellable_new();
+
+ self->input_settings = g_settings_new (GNOME_DESKTOP_INPUT_SOURCES_DIR);
+
+ self->xkb_info = gnome_xkb_info_new ();
+
+#ifdef HAVE_IBUS
+ ibus_init ();
+ if (!self->ibus) {
+ self->ibus = ibus_bus_new_async ();
+ if (ibus_bus_is_connected (self->ibus))
+ fetch_ibus_engines (self);
+ else
+ g_signal_connect_object (self->ibus, "connected",
+ G_CALLBACK (fetch_ibus_engines), self,
+ G_CONNECT_SWAPPED);
+ }
+ maybe_start_ibus ();
+#endif
+
+ g_signal_connect_object (self->input_settings, "changed::" KEY_INPUT_SOURCES,
+ G_CALLBACK (input_sources_changed), self, G_CONNECT_SWAPPED);
+
+ add_input_sources_from_settings (self);
+}
+
+void
+cc_input_list_box_set_login (CcInputListBox *self, gboolean login)
+{
+ self->login = login;
+ clear_input_sources (self);
+ if (login)
+ add_input_sources_from_localed (self);
+ else
+ add_input_sources_from_settings (self);
+}
+
+void
+cc_input_list_box_set_login_auto_apply (CcInputListBox *self, gboolean login_auto_apply)
+{
+ self->login_auto_apply = login_auto_apply;
+}
+
+void
+cc_input_list_box_set_localed (CcInputListBox *self, GDBusProxy *localed)
+{
+ self->localed = localed;
+}
+
+void
+cc_input_list_box_set_permission (CcInputListBox *self, GPermission *permission)
+{
+ self->permission = permission;
+}
diff --git a/panels/keyboard/cc-input-list-box.h b/panels/keyboard/cc-input-list-box.h
new file mode 100644
index 0000000..7045053
--- /dev/null
+++ b/panels/keyboard/cc-input-list-box.h
@@ -0,0 +1,43 @@
+/* cc-input-list-box.c
+ *
+ * Copyright (C) 2010 Intel, Inc
+ * Copyright (C) 2020 System76, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Sergey Udaltsov <svu@gnome.org>
+ * Ian Douglas Scott <idscott@system76.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#pragma once
+
+G_BEGIN_DECLS
+
+#include <adwaita.h>
+
+#define CC_TYPE_INPUT_LIST_BOX (cc_input_list_box_get_type ())
+G_DECLARE_FINAL_TYPE (CcInputListBox, cc_input_list_box, CC, INPUT_LIST_BOX, AdwBin)
+
+void cc_input_list_box_set_login (CcInputListBox *box,
+ gboolean login);
+void cc_input_list_box_set_login_auto_apply (CcInputListBox *box,
+ gboolean auto_apply);
+void cc_input_list_box_set_localed (CcInputListBox *box,
+ GDBusProxy *localed);
+void cc_input_list_box_set_permission (CcInputListBox *box,
+ GPermission *permission);
+
+G_END_DECLS
diff --git a/panels/keyboard/cc-input-list-box.ui b/panels/keyboard/cc-input-list-box.ui
new file mode 100644
index 0000000..036cca4
--- /dev/null
+++ b/panels/keyboard/cc-input-list-box.ui
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcInputListBox" parent="AdwBin">
+
+ <child>
+ <object class="GtkListBox" id="listbox">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="selection-mode">none</property>
+ <signal name="row_activated" handler="input_row_activated_cb" object="CcInputListBox" swapped="yes"/>
+ <signal name="keynav_failed" handler="keynav_failed_cb" object="CcInputListBox" swapped="yes"/>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ <child>
+ <object class="GtkListBoxRow" id="no_inputs_row">
+ <property name="selectable">False</property>
+ <property name="activatable">False</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="margin_bottom">8</property>
+ <property name="margin_top">8</property>
+ <property name="label" translatable="yes">No input source selected</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkListBoxRow" id="add_input_row">
+ <property name="selectable">False</property>
+ <child>
+ <object class="GtkImage">
+ <property name="hexpand">True</property>
+ <property name="height_request">50</property>
+ <property name="margin_start">12</property>
+ <property name="margin_end">12</property>
+ <property name="icon-name">list-add-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </template>
+</interface>
diff --git a/panels/keyboard/cc-input-row.c b/panels/keyboard/cc-input-row.c
new file mode 100644
index 0000000..9668824
--- /dev/null
+++ b/panels/keyboard/cc-input-row.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright © 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include "cc-input-row.h"
+#include "cc-input-source-ibus.h"
+
+struct _CcInputRow
+{
+ AdwActionRow parent_instance;
+
+ CcInputSource *source;
+
+ GtkListBox *drag_widget;
+
+ GtkDragSource *drag_source;
+ gdouble drag_x;
+ gdouble drag_y;
+};
+
+G_DEFINE_TYPE (CcInputRow, cc_input_row, ADW_TYPE_ACTION_ROW)
+
+enum
+{
+ SIGNAL_SHOW_SETTINGS,
+ SIGNAL_SHOW_LAYOUT,
+ SIGNAL_MOVE_ROW,
+ SIGNAL_REMOVE_ROW,
+ SIGNAL_LAST
+};
+
+static guint signals[SIGNAL_LAST] = { 0, };
+
+static GdkContentProvider *
+drag_prepare_cb (GtkDragSource *source,
+ double x,
+ double y,
+ CcInputRow *self)
+{
+ self->drag_x = x;
+ self->drag_y = y;
+
+ return gdk_content_provider_new_typed (CC_TYPE_INPUT_ROW, self);
+}
+
+static void
+drag_begin_cb (GtkDragSource *source,
+ GdkDrag *drag,
+ CcInputRow *self)
+{
+ GtkAllocation alloc;
+ CcInputRow *drag_row;
+ GtkWidget *drag_icon;
+
+ gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);
+
+ self->drag_widget = GTK_LIST_BOX (gtk_list_box_new ());
+ gtk_widget_set_size_request (GTK_WIDGET (self->drag_widget), alloc.width, alloc.height);
+
+ drag_row = cc_input_row_new (self->source);
+ gtk_list_box_append (self->drag_widget, GTK_WIDGET (drag_row));
+ gtk_list_box_drag_highlight_row (self->drag_widget, GTK_LIST_BOX_ROW (drag_row));
+
+ drag_icon = gtk_drag_icon_get_for_drag (drag);
+ gtk_drag_icon_set_child (GTK_DRAG_ICON (drag_icon), GTK_WIDGET (self->drag_widget));
+ gdk_drag_set_hotspot (drag, self->drag_x, self->drag_y);
+}
+
+static gboolean
+drop_cb (GtkDropTarget *drop_target,
+ const GValue *value,
+ gdouble x,
+ gdouble y,
+ CcInputRow *self)
+{
+ CcInputRow *source;
+
+ if (!G_VALUE_HOLDS (value, CC_TYPE_INPUT_ROW))
+ return FALSE;
+
+ source = g_value_get_object (value);
+
+ g_signal_emit (source,
+ signals[SIGNAL_MOVE_ROW],
+ 0,
+ self);
+
+ return TRUE;
+}
+
+static void
+move_up_cb (GtkWidget *widget,
+ const char *action_name,
+ GVariant *parameter)
+{
+ CcInputRow *self = CC_INPUT_ROW (widget);
+ GtkListBox *list_box = GTK_LIST_BOX (gtk_widget_get_parent (GTK_WIDGET (self)));
+ gint previous_idx = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (self)) - 1;
+ GtkListBoxRow *previous_row = gtk_list_box_get_row_at_index (list_box, previous_idx);
+
+ if (previous_row == NULL)
+ return;
+
+ g_signal_emit (self,
+ signals[SIGNAL_MOVE_ROW],
+ 0,
+ previous_row);
+}
+
+static void
+move_down_cb (GtkWidget *widget,
+ const char *action_name,
+ GVariant *parameter)
+{
+ CcInputRow *self = CC_INPUT_ROW (widget);
+ GtkListBox *list_box = GTK_LIST_BOX (gtk_widget_get_parent (GTK_WIDGET (self)));
+ gint next_idx = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (self)) + 1;
+ GtkListBoxRow *next_row = gtk_list_box_get_row_at_index (list_box, next_idx);
+
+ if (next_row == NULL)
+ return;
+
+ g_signal_emit (next_row,
+ signals[SIGNAL_MOVE_ROW],
+ 0,
+ self);
+}
+
+static void
+show_settings_cb (GtkWidget *widget,
+ const char *action_name,
+ GVariant *parameter)
+{
+ CcInputRow *self = CC_INPUT_ROW (widget);
+ g_signal_emit (self,
+ signals[SIGNAL_SHOW_SETTINGS],
+ 0);
+}
+
+static void
+show_layout_cb (GtkWidget *widget,
+ const char *action_name,
+ GVariant *parameter)
+{
+ CcInputRow *self = CC_INPUT_ROW (widget);
+ g_signal_emit (self,
+ signals[SIGNAL_SHOW_LAYOUT],
+ 0);
+}
+
+static void
+remove_cb (GtkWidget *widget,
+ const char *action_name,
+ GVariant *parameter)
+{
+ CcInputRow *self = CC_INPUT_ROW (widget);
+ g_signal_emit (self,
+ signals[SIGNAL_REMOVE_ROW],
+ 0);
+}
+
+static void
+cc_input_row_dispose (GObject *object)
+{
+ CcInputRow *self = CC_INPUT_ROW (object);
+
+ g_clear_object (&self->source);
+
+ G_OBJECT_CLASS (cc_input_row_parent_class)->dispose (object);
+}
+
+void
+cc_input_row_class_init (CcInputRowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_input_row_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/keyboard/cc-input-row.ui");
+
+ signals[SIGNAL_SHOW_SETTINGS] =
+ g_signal_new ("show-settings",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE,
+ 0);
+
+ signals[SIGNAL_SHOW_LAYOUT] =
+ g_signal_new ("show-layout",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE,
+ 0);
+
+ signals[SIGNAL_MOVE_ROW] =
+ g_signal_new ("move-row",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE,
+ 1, CC_TYPE_INPUT_ROW);
+
+ signals[SIGNAL_REMOVE_ROW] =
+ g_signal_new ("remove-row",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE,
+ 0);
+
+ gtk_widget_class_install_action (widget_class, "row.move-up", NULL, move_up_cb);
+ gtk_widget_class_install_action (widget_class, "row.move-down", NULL, move_down_cb);
+ gtk_widget_class_install_action (widget_class, "row.show-layout", NULL, show_layout_cb);
+ gtk_widget_class_install_action (widget_class, "row.show-settings", NULL, show_settings_cb);
+ gtk_widget_class_install_action (widget_class, "row.remove", NULL, remove_cb);
+}
+
+void
+cc_input_row_init (CcInputRow *self)
+{
+ GtkDropTarget *drop_target;
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->drag_source = gtk_drag_source_new ();
+ gtk_drag_source_set_actions (self->drag_source, GDK_ACTION_MOVE);
+ g_signal_connect (self->drag_source, "prepare", G_CALLBACK (drag_prepare_cb), self);
+ g_signal_connect (self->drag_source, "drag-begin", G_CALLBACK (drag_begin_cb), self);
+ gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (self->drag_source));
+
+ drop_target = gtk_drop_target_new (CC_TYPE_INPUT_ROW, GDK_ACTION_MOVE);
+ gtk_drop_target_set_preload (drop_target, TRUE);
+ g_signal_connect (drop_target, "drop", G_CALLBACK (drop_cb), self);
+ gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (drop_target));
+}
+
+static void
+label_changed_cb (CcInputRow *self)
+{
+ g_autofree gchar *label = cc_input_source_get_label (self->source);
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self), label);
+}
+
+CcInputRow *
+cc_input_row_new (CcInputSource *source)
+{
+ CcInputRow *self;
+
+ self = g_object_new (CC_TYPE_INPUT_ROW, NULL);
+ self->source = g_object_ref (source);
+
+ g_signal_connect_object (source, "label-changed", G_CALLBACK (label_changed_cb), self, G_CONNECT_SWAPPED);
+ label_changed_cb (self);
+
+ gtk_widget_action_set_enabled (GTK_WIDGET (self), "row.show-settings", CC_IS_INPUT_SOURCE_IBUS (source));
+
+ return self;
+}
+
+CcInputSource *
+cc_input_row_get_source (CcInputRow *self)
+{
+ g_return_val_if_fail (CC_IS_INPUT_ROW (self), NULL);
+ return self->source;
+}
+
+void
+cc_input_row_set_removable (CcInputRow *self,
+ gboolean removable)
+{
+ g_return_if_fail (CC_IS_INPUT_ROW (self));
+ gtk_widget_action_set_enabled (GTK_WIDGET (self), "row.remove", removable);
+}
+
+void
+cc_input_row_set_draggable (CcInputRow *self,
+ gboolean draggable)
+{
+ gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (self->drag_source),
+ draggable ? GTK_PHASE_BUBBLE : GTK_PHASE_NONE);
+}
diff --git a/panels/keyboard/cc-input-row.h b/panels/keyboard/cc-input-row.h
new file mode 100644
index 0000000..666bcb6
--- /dev/null
+++ b/panels/keyboard/cc-input-row.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <adwaita.h>
+#include <gtk/gtk.h>
+#include <gio/gdesktopappinfo.h>
+
+#include "cc-input-source.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_INPUT_ROW (cc_input_row_get_type ())
+G_DECLARE_FINAL_TYPE (CcInputRow, cc_input_row, CC, INPUT_ROW, AdwActionRow)
+
+CcInputRow *cc_input_row_new (CcInputSource *source);
+
+CcInputSource *cc_input_row_get_source (CcInputRow *row);
+
+void cc_input_row_set_removable (CcInputRow *row,
+ gboolean removable);
+
+void cc_input_row_set_draggable (CcInputRow *row,
+ gboolean draggable);
+
+G_END_DECLS
diff --git a/panels/keyboard/cc-input-row.ui b/panels/keyboard/cc-input-row.ui
new file mode 100644
index 0000000..5ce33f4
--- /dev/null
+++ b/panels/keyboard/cc-input-row.ui
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.20"/>
+ <template class="CcInputRow" parent="AdwActionRow">
+ <property name="selectable">False</property>
+ <child type="prefix">
+ <object class="GtkImage">
+ <property name="icon_name">list-drag-handle-symbolic</property>
+ <style>
+ <class name="drag-handle"/>
+ </style>
+ </object>
+ </child>
+ <child type="suffix">
+ <object class="GtkMenuButton">
+ <property name="valign">center</property>
+ <property name="icon_name">view-more-symbolic</property>
+ <property name="menu_model">popover_menu</property>
+ <accessibility>
+ <property name="label" translatable="yes">Options</property>
+ </accessibility>
+ <style>
+ <class name="flat"/>
+ </style>
+ </object>
+ </child>
+ </template>
+ <menu id="popover_menu">
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">Move Up</attribute>
+ <attribute name="action">row.move-up</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Move Down</attribute>
+ <attribute name="action">row.move-down</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">Preferences</attribute>
+ <attribute name="action">row.show-settings</attribute>
+ <attribute name="hidden-when">action-disabled</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">View Keyboard Layout</attribute>
+ <attribute name="action">row.show-layout</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">Remove</attribute>
+ <attribute name="action">row.remove</attribute>
+ <attribute name="hidden-when">action-disabled</attribute>
+ </item>
+ </section>
+ </menu>
+</interface>
diff --git a/panels/keyboard/cc-input-source-ibus.c b/panels/keyboard/cc-input-source-ibus.c
new file mode 100644
index 0000000..1aa1ab8
--- /dev/null
+++ b/panels/keyboard/cc-input-source-ibus.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright © 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cc-input-source-ibus.h"
+#ifdef HAVE_IBUS
+#include "cc-ibus-utils.h"
+#endif
+
+struct _CcInputSourceIBus
+{
+ CcInputSource parent_instance;
+
+ gchar *engine_name;
+#ifdef HAVE_IBUS
+ IBusEngineDesc *engine_desc;
+#endif
+};
+
+G_DEFINE_TYPE (CcInputSourceIBus, cc_input_source_ibus, CC_TYPE_INPUT_SOURCE)
+
+static gchar *
+cc_input_source_ibus_get_label (CcInputSource *source)
+{
+ CcInputSourceIBus *self = CC_INPUT_SOURCE_IBUS (source);
+#ifdef HAVE_IBUS
+ if (self->engine_desc)
+ return g_strdup (engine_get_display_name (self->engine_desc));
+ else
+#endif
+ return g_strdup (self->engine_name);
+}
+
+static gboolean
+cc_input_source_ibus_matches (CcInputSource *source,
+ CcInputSource *source2)
+{
+ if (!CC_IS_INPUT_SOURCE_IBUS (source2))
+ return FALSE;
+
+ return g_strcmp0 (CC_INPUT_SOURCE_IBUS (source)->engine_name, CC_INPUT_SOURCE_IBUS (source2)->engine_name) == 0;
+}
+
+static const gchar *
+cc_input_source_ibus_get_layout (CcInputSource *source)
+{
+#ifdef HAVE_IBUS
+ CcInputSourceIBus *self = CC_INPUT_SOURCE_IBUS (source);
+ if (self->engine_desc != NULL)
+ return ibus_engine_desc_get_layout (self->engine_desc);
+ else
+#endif
+ return NULL;
+}
+
+static const gchar *
+cc_input_source_ibus_get_layout_variant (CcInputSource *source)
+{
+#ifdef HAVE_IBUS
+ CcInputSourceIBus *self = CC_INPUT_SOURCE_IBUS (source);
+ if (self->engine_desc != NULL)
+ return ibus_engine_desc_get_layout_variant (self->engine_desc);
+ else
+#endif
+ return NULL;
+}
+
+static void
+cc_input_source_ibus_dispose (GObject *object)
+{
+ CcInputSourceIBus *self = CC_INPUT_SOURCE_IBUS (object);
+
+ g_clear_pointer (&self->engine_name, g_free);
+#ifdef HAVE_IBUS
+ g_clear_object (&self->engine_desc);
+#endif
+
+ G_OBJECT_CLASS (cc_input_source_ibus_parent_class)->dispose (object);
+}
+
+void
+cc_input_source_ibus_class_init (CcInputSourceIBusClass *klass)
+{
+ CcInputSourceClass *input_source_class = CC_INPUT_SOURCE_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ input_source_class->get_label = cc_input_source_ibus_get_label;
+ input_source_class->matches = cc_input_source_ibus_matches;
+ input_source_class->get_layout = cc_input_source_ibus_get_layout;
+ input_source_class->get_layout_variant = cc_input_source_ibus_get_layout_variant;
+ object_class->dispose = cc_input_source_ibus_dispose;
+}
+
+void
+cc_input_source_ibus_init (CcInputSourceIBus *source)
+{
+}
+
+CcInputSourceIBus *
+cc_input_source_ibus_new (const gchar *engine_name)
+{
+ CcInputSourceIBus *source;
+
+ source = g_object_new (CC_TYPE_INPUT_SOURCE_IBUS, NULL);
+ source->engine_name = g_strdup (engine_name);
+
+ return source;
+}
+
+#ifdef HAVE_IBUS
+void
+cc_input_source_ibus_set_engine_desc (CcInputSourceIBus *source,
+ IBusEngineDesc *engine_desc)
+{
+ g_return_if_fail (CC_IS_INPUT_SOURCE_IBUS (source));
+
+ g_clear_object (&source->engine_desc);
+ source->engine_desc = g_object_ref (engine_desc);
+ cc_input_source_emit_label_changed (CC_INPUT_SOURCE (source));
+}
+#endif
+
+const gchar *
+cc_input_source_ibus_get_engine_name (CcInputSourceIBus *source)
+{
+ g_return_val_if_fail (CC_IS_INPUT_SOURCE_IBUS (source), NULL);
+ return source->engine_name;
+}
+
+GDesktopAppInfo *
+cc_input_source_ibus_get_app_info (CcInputSourceIBus *source)
+{
+ g_auto(GStrv) tokens = NULL;
+ g_autofree gchar *desktop_file_name = NULL;
+
+ g_return_val_if_fail (CC_IS_INPUT_SOURCE_IBUS (source), NULL);
+
+ tokens = g_strsplit (source->engine_name, ":", 2);
+ desktop_file_name = g_strdup_printf ("ibus-setup-%s.desktop", tokens[0]);
+
+ return g_desktop_app_info_new (desktop_file_name);
+}
diff --git a/panels/keyboard/cc-input-source-ibus.h b/panels/keyboard/cc-input-source-ibus.h
new file mode 100644
index 0000000..2c09d01
--- /dev/null
+++ b/panels/keyboard/cc-input-source-ibus.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright © 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <config.h>
+
+#ifdef HAVE_IBUS
+#include <ibus.h>
+#endif
+
+#include <gio/gdesktopappinfo.h>
+
+#include "cc-input-source.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_INPUT_SOURCE_IBUS (cc_input_source_ibus_get_type ())
+G_DECLARE_FINAL_TYPE (CcInputSourceIBus, cc_input_source_ibus, CC, INPUT_SOURCE_IBUS, CcInputSource)
+
+CcInputSourceIBus *cc_input_source_ibus_new (const gchar *engine_name);
+
+#ifdef HAVE_IBUS
+void cc_input_source_ibus_set_engine_desc (CcInputSourceIBus *source,
+ IBusEngineDesc *engine_desc);
+#endif
+
+const gchar *cc_input_source_ibus_get_engine_name (CcInputSourceIBus *source);
+
+GDesktopAppInfo *cc_input_source_ibus_get_app_info (CcInputSourceIBus *source);
+
+G_END_DECLS
diff --git a/panels/keyboard/cc-input-source-xkb.c b/panels/keyboard/cc-input-source-xkb.c
new file mode 100644
index 0000000..2ea30be
--- /dev/null
+++ b/panels/keyboard/cc-input-source-xkb.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright © 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include "cc-input-source-xkb.h"
+
+struct _CcInputSourceXkb
+{
+ CcInputSource parent_instance;
+
+ GnomeXkbInfo *xkb_info;
+ gchar *layout;
+ gchar *variant;
+};
+
+G_DEFINE_TYPE (CcInputSourceXkb, cc_input_source_xkb, CC_TYPE_INPUT_SOURCE)
+
+static gchar *
+cc_input_source_xkb_get_label (CcInputSource *source)
+{
+ CcInputSourceXkb *self = CC_INPUT_SOURCE_XKB (source);
+ g_autofree gchar *id = NULL;
+ const gchar *name;
+
+ id = cc_input_source_xkb_get_id (self);
+ gnome_xkb_info_get_layout_info (self->xkb_info, id, &name, NULL, NULL, NULL);
+ if (name)
+ return g_strdup (name);
+ else
+ return g_strdup (id);
+}
+
+static gboolean
+cc_input_source_xkb_matches (CcInputSource *source,
+ CcInputSource *source2)
+{
+ if (!CC_IS_INPUT_SOURCE_XKB (source2))
+ return FALSE;
+
+ return g_strcmp0 (CC_INPUT_SOURCE_XKB (source)->layout, CC_INPUT_SOURCE_XKB (source2)->layout) == 0 &&
+ g_strcmp0 (CC_INPUT_SOURCE_XKB (source)->variant, CC_INPUT_SOURCE_XKB (source2)->variant) == 0;
+}
+
+static void
+cc_input_source_xkb_dispose (GObject *object)
+{
+ CcInputSourceXkb *self = CC_INPUT_SOURCE_XKB (object);
+
+ g_clear_object (&self->xkb_info);
+ g_clear_pointer (&self->layout, g_free);
+ g_clear_pointer (&self->variant, g_free);
+
+ G_OBJECT_CLASS (cc_input_source_xkb_parent_class)->dispose (object);
+}
+
+static const gchar *
+cc_input_source_xkb_get_layout (CcInputSource *source)
+{
+ return CC_INPUT_SOURCE_XKB (source)->layout;
+}
+
+static const gchar *
+cc_input_source_xkb_get_layout_variant (CcInputSource *source)
+{
+ return CC_INPUT_SOURCE_XKB (source)->variant;
+}
+
+void
+cc_input_source_xkb_class_init (CcInputSourceXkbClass *klass)
+{
+ CcInputSourceClass *input_source_class = CC_INPUT_SOURCE_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ input_source_class->get_label = cc_input_source_xkb_get_label;
+ input_source_class->matches = cc_input_source_xkb_matches;
+ input_source_class->get_layout = cc_input_source_xkb_get_layout;
+ input_source_class->get_layout_variant = cc_input_source_xkb_get_layout_variant;
+ object_class->dispose = cc_input_source_xkb_dispose;
+}
+
+void
+cc_input_source_xkb_init (CcInputSourceXkb *source)
+{
+}
+
+CcInputSourceXkb *
+cc_input_source_xkb_new (GnomeXkbInfo *xkb_info,
+ const gchar *layout,
+ const gchar *variant)
+{
+ CcInputSourceXkb *source;
+
+ source = g_object_new (CC_TYPE_INPUT_SOURCE_XKB, NULL);
+ source->xkb_info = g_object_ref (xkb_info);
+ source->layout = g_strdup (layout);
+ source->variant = g_strdup (variant);
+
+ return source;
+}
+
+CcInputSourceXkb *
+cc_input_source_xkb_new_from_id (GnomeXkbInfo *xkb_info,
+ const gchar *id)
+{
+ g_auto(GStrv) tokens = NULL;
+
+ tokens = g_strsplit (id, "+", 2);
+
+ return cc_input_source_xkb_new (xkb_info, tokens[0], tokens[1]);
+}
+
+gchar *
+cc_input_source_xkb_get_id (CcInputSourceXkb *source)
+{
+ g_return_val_if_fail (CC_IS_INPUT_SOURCE_XKB (source), NULL);
+ if (source->variant != NULL)
+ return g_strdup_printf ("%s+%s", source->layout, source->variant);
+ else
+ return g_strdup (source->layout);
+}
diff --git a/panels/keyboard/cc-input-source-xkb.h b/panels/keyboard/cc-input-source-xkb.h
new file mode 100644
index 0000000..e8886d0
--- /dev/null
+++ b/panels/keyboard/cc-input-source-xkb.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnome-desktop/gnome-xkb-info.h>
+
+#include "cc-input-source.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_INPUT_SOURCE_XKB (cc_input_source_xkb_get_type ())
+G_DECLARE_FINAL_TYPE (CcInputSourceXkb, cc_input_source_xkb, CC, INPUT_SOURCE_XKB, CcInputSource)
+
+CcInputSourceXkb *cc_input_source_xkb_new (GnomeXkbInfo *xkb_info,
+ const gchar *layout,
+ const gchar *variant);
+
+CcInputSourceXkb *cc_input_source_xkb_new_from_id (GnomeXkbInfo *xkb_info,
+ const gchar *id);
+
+gchar *cc_input_source_xkb_get_id (CcInputSourceXkb *source);
+
+G_END_DECLS
diff --git a/panels/keyboard/cc-input-source.c b/panels/keyboard/cc-input-source.c
new file mode 100644
index 0000000..df8db8b
--- /dev/null
+++ b/panels/keyboard/cc-input-source.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright © 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include "cc-input-source.h"
+
+enum
+{
+ SIGNAL_LABEL_CHANGED,
+ SIGNAL_LAST
+};
+
+static guint signals[SIGNAL_LAST] = {0};
+
+G_DEFINE_TYPE (CcInputSource, cc_input_source, G_TYPE_OBJECT)
+
+void
+cc_input_source_class_init (CcInputSourceClass *klass)
+{
+ signals[SIGNAL_LABEL_CHANGED] =
+ g_signal_new ("label-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE,
+ 0);
+}
+
+void
+cc_input_source_init (CcInputSource *source)
+{
+}
+
+void
+cc_input_source_emit_label_changed (CcInputSource *source)
+{
+ g_return_if_fail (CC_IS_INPUT_SOURCE (source));
+ g_signal_emit (source, signals[SIGNAL_LABEL_CHANGED], 0);
+}
+
+gchar *
+cc_input_source_get_label (CcInputSource *source)
+{
+ g_return_val_if_fail (CC_IS_INPUT_SOURCE (source), NULL);
+ return CC_INPUT_SOURCE_GET_CLASS (source)->get_label (source);
+}
+
+gboolean
+cc_input_source_matches (CcInputSource *source,
+ CcInputSource *source2)
+{
+ g_return_val_if_fail (CC_IS_INPUT_SOURCE (source), FALSE);
+ return CC_INPUT_SOURCE_GET_CLASS (source)->matches (source, source2);
+}
+
+const gchar *
+cc_input_source_get_layout (CcInputSource *source)
+{
+ g_return_val_if_fail (CC_IS_INPUT_SOURCE (source), NULL);
+ return CC_INPUT_SOURCE_GET_CLASS (source)->get_layout (source);
+}
+
+const gchar *
+cc_input_source_get_layout_variant (CcInputSource *source)
+{
+ g_return_val_if_fail (CC_IS_INPUT_SOURCE (source), NULL);
+ return CC_INPUT_SOURCE_GET_CLASS (source)->get_layout_variant (source);
+}
diff --git a/panels/keyboard/cc-input-source.h b/panels/keyboard/cc-input-source.h
new file mode 100644
index 0000000..5b7865d
--- /dev/null
+++ b/panels/keyboard/cc-input-source.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright © 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_INPUT_SOURCE (cc_input_source_get_type ())
+G_DECLARE_DERIVABLE_TYPE (CcInputSource, cc_input_source, CC, INPUT_SOURCE, GObject)
+
+struct _CcInputSourceClass
+{
+ GObjectClass parent_class;
+
+ gchar* (*get_label) (CcInputSource *source);
+ gboolean (*matches) (CcInputSource *source,
+ CcInputSource *source2);
+ const gchar* (*get_layout) (CcInputSource *source);
+ const gchar* (*get_layout_variant) (CcInputSource *source);
+};
+
+void cc_input_source_emit_label_changed (CcInputSource *source);
+
+gchar *cc_input_source_get_label (CcInputSource *source);
+
+gboolean cc_input_source_matches (CcInputSource *source,
+ CcInputSource *source2);
+
+const gchar *cc_input_source_get_layout (CcInputSource *source);
+
+const gchar *cc_input_source_get_layout_variant (CcInputSource *source);
+
+G_END_DECLS
diff --git a/panels/keyboard/cc-keyboard-item.c b/panels/keyboard/cc-keyboard-item.c
new file mode 100644
index 0000000..31b134a
--- /dev/null
+++ b/panels/keyboard/cc-keyboard-item.c
@@ -0,0 +1,881 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2011, 2014 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <gtk/gtk.h>
+#include <gio/gio.h>
+#include <glib/gi18n-lib.h>
+
+#include "cc-keyboard-item.h"
+
+#define CUSTOM_KEYS_SCHEMA "org.gnome.settings-daemon.plugins.media-keys.custom-keybinding"
+
+struct _CcKeyboardItem
+{
+ GObject parent_instance;
+
+ CcKeyboardItem *reverse_item;
+ gboolean is_reversed;
+ gboolean hidden;
+
+ CcKeyboardItemType type;
+
+ BindingGroupType group;
+ char *description;
+ gboolean editable;
+ GList *key_combos;
+ GList *default_combos;
+ gboolean can_set_multiple;
+
+ /* GSettings path */
+ char *gsettings_path;
+ gboolean desc_editable;
+ char *command;
+ gboolean cmd_editable;
+
+ /* GSettings */
+ char *schema;
+ char *key;
+ GSettings *settings;
+};
+
+enum
+{
+ PROP_0,
+ PROP_DESCRIPTION,
+ PROP_EDITABLE,
+ PROP_TYPE,
+ PROP_IS_VALUE_DEFAULT,
+ PROP_COMMAND,
+ PROP_KEY_COMBOS
+};
+
+static void cc_keyboard_item_class_init (CcKeyboardItemClass *klass);
+static void cc_keyboard_item_init (CcKeyboardItem *keyboard_item);
+static void cc_keyboard_item_finalize (GObject *object);
+
+G_DEFINE_TYPE (CcKeyboardItem, cc_keyboard_item, G_TYPE_OBJECT)
+
+static const CcKeyCombo EMPTY_COMBO = { 0, 0, 0 };
+
+static gboolean
+combo_equal (CcKeyCombo *a, CcKeyCombo *b)
+{
+ return (a->keyval == b->keyval
+ && a->keycode == b->keycode
+ && a->mask == b->mask);
+}
+
+static gboolean
+combos_contains (GList *combos, CcKeyCombo *needle)
+{
+ for (GList *l = combos; l != NULL; l = l->next)
+ {
+ if (combo_equal (l->data, needle))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+combos_equal (GList *a, GList *b)
+{
+ // Should be efficient enough for any sane number of bindings
+
+ for (GList *l = a; l != NULL; l = l->next)
+ {
+ if (!combos_contains (b, l->data))
+ return FALSE;
+ }
+
+ for (GList *l = b; l != NULL; l = l->next)
+ {
+ if (!combos_contains (a, l->data))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+binding_from_string (const char *str,
+ CcKeyCombo *combo)
+{
+ g_return_val_if_fail (combo != NULL, FALSE);
+ g_autofree guint *keycodes = NULL;
+
+ if (str == NULL || strcmp (str, "disabled") == 0)
+ {
+ memset (combo, 0, sizeof(CcKeyCombo));
+ return TRUE;
+ }
+
+ gtk_accelerator_parse_with_keycode (str,
+ gdk_display_get_default (),
+ &combo->keyval,
+ &keycodes,
+ &combo->mask);
+
+ combo->keycode = (keycodes ? keycodes[0] : 0);
+
+ if (combo->keyval == 0)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+static void
+_set_description (CcKeyboardItem *item,
+ const char *value)
+{
+ g_free (item->description);
+ item->description = g_strdup (value);
+}
+
+const char *
+cc_keyboard_item_get_description (CcKeyboardItem *item)
+{
+ g_return_val_if_fail (CC_IS_KEYBOARD_ITEM (item), NULL);
+
+ return item->description;
+}
+
+gboolean
+cc_keyboard_item_get_desc_editable (CcKeyboardItem *item)
+{
+ g_return_val_if_fail (CC_IS_KEYBOARD_ITEM (item), FALSE);
+
+ return item->desc_editable;
+}
+
+static void
+_set_type (CcKeyboardItem *item,
+ gint value)
+{
+ item->type = value;
+}
+
+static void
+_set_command (CcKeyboardItem *item,
+ const char *value)
+{
+ g_free (item->command);
+ item->command = g_strdup (value);
+}
+
+const char *
+cc_keyboard_item_get_command (CcKeyboardItem *item)
+{
+ g_return_val_if_fail (CC_IS_KEYBOARD_ITEM (item), NULL);
+
+ return item->command;
+}
+
+gboolean
+cc_keyboard_item_get_cmd_editable (CcKeyboardItem *item)
+{
+ g_return_val_if_fail (CC_IS_KEYBOARD_ITEM (item), FALSE);
+
+ return item->cmd_editable;
+}
+
+static void
+cc_keyboard_item_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcKeyboardItem *self;
+
+ self = CC_KEYBOARD_ITEM (object);
+
+ switch (prop_id) {
+ case PROP_DESCRIPTION:
+ _set_description (self, g_value_get_string (value));
+ break;
+ case PROP_COMMAND:
+ _set_command (self, g_value_get_string (value));
+ break;
+ case PROP_TYPE:
+ _set_type (self, g_value_get_int (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_keyboard_item_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcKeyboardItem *self;
+
+ self = CC_KEYBOARD_ITEM (object);
+
+ switch (prop_id) {
+ case PROP_DESCRIPTION:
+ g_value_set_string (value, self->description);
+ break;
+ case PROP_EDITABLE:
+ g_value_set_boolean (value, self->editable);
+ break;
+ case PROP_COMMAND:
+ g_value_set_string (value, self->command);
+ break;
+ case PROP_IS_VALUE_DEFAULT:
+ g_value_set_boolean (value, cc_keyboard_item_is_value_default (self));
+ break;
+ case PROP_KEY_COMBOS:
+ g_value_set_pointer (value, self->key_combos);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_keyboard_item_class_init (CcKeyboardItemClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = cc_keyboard_item_get_property;
+ object_class->set_property = cc_keyboard_item_set_property;
+ object_class->finalize = cc_keyboard_item_finalize;
+
+ g_object_class_install_property (object_class,
+ PROP_DESCRIPTION,
+ g_param_spec_string ("description",
+ "description",
+ "description",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_EDITABLE,
+ g_param_spec_boolean ("editable",
+ NULL,
+ NULL,
+ FALSE,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (object_class,
+ PROP_TYPE,
+ g_param_spec_int ("type",
+ NULL,
+ NULL,
+ CC_KEYBOARD_ITEM_TYPE_NONE,
+ CC_KEYBOARD_ITEM_TYPE_GSETTINGS,
+ CC_KEYBOARD_ITEM_TYPE_NONE,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
+
+ g_object_class_install_property (object_class,
+ PROP_COMMAND,
+ g_param_spec_string ("command",
+ "command",
+ "command",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_IS_VALUE_DEFAULT,
+ g_param_spec_boolean ("is-value-default",
+ "is value default",
+ "is value default",
+ TRUE,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (object_class,
+ PROP_KEY_COMBOS,
+ g_param_spec_pointer ("key-combos",
+ "key combos",
+ "key combos",
+ G_PARAM_READABLE));
+}
+
+static void
+cc_keyboard_item_init (CcKeyboardItem *item)
+{
+}
+
+static void
+cc_keyboard_item_finalize (GObject *object)
+{
+ CcKeyboardItem *item;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (CC_IS_KEYBOARD_ITEM (object));
+
+ item = CC_KEYBOARD_ITEM (object);
+
+ if (item->settings != NULL)
+ g_object_unref (item->settings);
+
+ /* Free memory */
+ g_free (item->gsettings_path);
+ g_free (item->description);
+ g_free (item->command);
+ g_free (item->schema);
+ g_free (item->key);
+ g_list_free_full (item->key_combos, g_free);
+ g_list_free_full (item->default_combos, g_free);
+
+ G_OBJECT_CLASS (cc_keyboard_item_parent_class)->finalize (object);
+}
+
+CcKeyboardItem *
+cc_keyboard_item_new (CcKeyboardItemType type)
+{
+ GObject *object;
+
+ object = g_object_new (CC_TYPE_KEYBOARD_ITEM,
+ "type", type,
+ NULL);
+
+ return CC_KEYBOARD_ITEM (object);
+}
+
+static guint *
+get_above_tab_keysyms (void)
+{
+ guint keycode = 0x29 /* KEY_GRAVE */ + 8;
+ g_autofree guint *keyvals = NULL;
+ GArray *keysyms;
+ int n_entries, i, j;
+
+ keysyms = g_array_new (TRUE, FALSE, sizeof (guint));
+
+ if (!gdk_display_map_keycode (gdk_display_get_default (),
+ keycode,
+ NULL,
+ &keyvals,
+ &n_entries))
+ goto out;
+
+ for (i = 0; i < n_entries; i++)
+ {
+ gboolean found = FALSE;
+
+ for (j = 0; j < keysyms->len; j++)
+ if (g_array_index (keysyms, guint, j) == keyvals[i])
+ {
+ found = TRUE;
+ break;
+ }
+
+ if (!found)
+ g_array_append_val (keysyms, keyvals[i]);
+ }
+
+out:
+ return (guint *)g_array_free (keysyms, FALSE);
+}
+
+/*
+ * translate_above_tab:
+ *
+ * @original_bindings: A list of accelerator strings
+ * @new_bindings: (out): Translated bindings if translation is needed
+ *
+ * Translate accelerator strings that contain the Above_Tab fake keysym
+ * used by mutter to strings that use the real keysyms that correspond
+ * to the key that is located physically above the tab key.
+ *
+ * Returns: %TRUE if strings were translated, %FALSE if @original_bindings
+ * can be used unmodified
+ */
+static gboolean
+translate_above_tab (char **original_bindings,
+ char ***new_bindings)
+{
+ GPtrArray *replaced_bindings;
+ g_autofree guint *above_tab_keysyms = NULL;
+ gboolean needs_translation = FALSE;
+ char **str;
+
+ for (str = original_bindings; *str && !needs_translation; str++)
+ needs_translation = strstr (*str, "Above_Tab") != NULL;
+
+ if (!needs_translation)
+ return FALSE;
+
+ above_tab_keysyms = get_above_tab_keysyms ();
+
+ replaced_bindings = g_ptr_array_new ();
+
+ for (str = original_bindings; *str; str++)
+ {
+ if (strstr (*str, "Above_Tab") == NULL)
+ {
+ g_ptr_array_add (replaced_bindings, g_strdup (*str));
+ }
+ else
+ {
+ g_auto (GStrv) split_str = g_strsplit (*str, "Above_Tab", -1);
+ int i;
+
+ for (i = 0; above_tab_keysyms[i]; i++)
+ {
+ g_autofree char *sym = NULL;
+
+ sym = gtk_accelerator_name (above_tab_keysyms[i], 0);
+ g_ptr_array_add (replaced_bindings, g_strjoinv (sym, split_str));
+ }
+ }
+ g_ptr_array_add (replaced_bindings, NULL);
+ }
+
+ *new_bindings = (char **)g_ptr_array_free (replaced_bindings, FALSE);
+ return TRUE;
+}
+
+static GList *
+variant_get_key_combos (GVariant *variant)
+{
+ GList *combos = NULL;
+ char **translated_bindings, **str;
+ g_auto(GStrv) bindings = NULL;
+
+ if (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING))
+ {
+ bindings = g_malloc0_n (2, sizeof(char *));
+ if (g_strcmp0 (g_variant_get_string (variant, NULL), "") != 0)
+ bindings[0] = g_variant_dup_string (variant, NULL);
+ }
+ else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING_ARRAY))
+ {
+ bindings = g_variant_dup_strv (variant, NULL);
+ }
+
+ if (translate_above_tab (bindings, &translated_bindings))
+ {
+ g_strfreev (bindings);
+ bindings = translated_bindings;
+ }
+
+ for (str = bindings; *str; str++)
+ {
+ g_autofree CcKeyCombo *combo = g_new (CcKeyCombo, 1);
+
+ binding_from_string (*str, combo);
+
+ if (combo->keyval != 0 || combo->keycode != 0 || combo->mask != 0)
+ combos = g_list_prepend (combos, g_steal_pointer (&combo));
+ }
+
+ return g_list_reverse (combos);
+}
+
+static GList *
+settings_get_key_combos (GSettings *settings,
+ const char *key,
+ gboolean use_default)
+{
+ GList *key_combos;
+ g_autoptr(GVariant) variant = NULL;
+
+ if (use_default)
+ variant = g_settings_get_default_value (settings, key);
+ else
+ variant = g_settings_get_value (settings, key);
+ key_combos = variant_get_key_combos (variant);
+
+ return key_combos;
+}
+
+static void
+binding_changed (CcKeyboardItem *item,
+ const char *key)
+{
+ g_list_free_full (item->key_combos, g_free);
+ item->key_combos = settings_get_key_combos (item->settings, item->key, FALSE);
+
+ item->editable = g_settings_is_writable (item->settings, item->key);
+
+ g_object_notify (G_OBJECT (item), "key-combos");
+}
+
+gboolean
+cc_keyboard_item_load_from_gsettings_path (CcKeyboardItem *item,
+ const char *path,
+ gboolean reset)
+{
+ g_autoptr(GVariant) variant = NULL;
+
+ item->schema = g_strdup (CUSTOM_KEYS_SCHEMA);
+ item->gsettings_path = g_strdup (path);
+ item->key = g_strdup ("binding");
+ item->settings = g_settings_new_with_path (item->schema, path);
+ item->editable = g_settings_is_writable (item->settings, item->key);
+ item->desc_editable = g_settings_is_writable (item->settings, "name");
+ item->cmd_editable = g_settings_is_writable (item->settings, "command");
+
+ variant = g_settings_get_value (item->settings, item->key);
+ item->can_set_multiple = g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING_ARRAY);
+
+ if (reset)
+ {
+ g_settings_reset (item->settings, "name");
+ g_settings_reset (item->settings, "command");
+ g_settings_reset (item->settings, "binding");
+ }
+
+ g_settings_bind (item->settings, "name",
+ G_OBJECT (item), "description", G_SETTINGS_BIND_DEFAULT);
+ g_settings_bind (item->settings, "command",
+ G_OBJECT (item), "command", G_SETTINGS_BIND_DEFAULT);
+
+ g_list_free_full (item->key_combos, g_free);
+ item->key_combos = settings_get_key_combos (item->settings, item->key, FALSE);
+
+ g_signal_connect_object (G_OBJECT (item->settings), "changed::binding",
+ G_CALLBACK (binding_changed), item, G_CONNECT_SWAPPED);
+
+ return TRUE;
+}
+
+gboolean
+cc_keyboard_item_load_from_gsettings (CcKeyboardItem *item,
+ const char *description,
+ const char *schema,
+ const char *key)
+{
+ g_autofree char *signal_name = NULL;
+ g_autoptr(GVariant) variant = NULL;
+
+ item->schema = g_strdup (schema);
+ item->key = g_strdup (key);
+ item->description = g_strdup (description);
+
+ item->settings = g_settings_new (item->schema);
+ item->editable = g_settings_is_writable (item->settings, item->key);
+
+ g_list_free_full (item->key_combos, g_free);
+ item->key_combos = settings_get_key_combos (item->settings, item->key, FALSE);
+
+ g_list_free_full (item->default_combos, g_free);
+ item->default_combos = settings_get_key_combos (item->settings, item->key, TRUE);
+
+ variant = g_settings_get_value (item->settings, item->key);
+ item->can_set_multiple = g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING_ARRAY);
+
+ signal_name = g_strdup_printf ("changed::%s", item->key);
+ g_signal_connect_object (G_OBJECT (item->settings), signal_name,
+ G_CALLBACK (binding_changed), item, G_CONNECT_SWAPPED);
+
+ return TRUE;
+}
+
+gboolean
+cc_keyboard_item_equal (CcKeyboardItem *a,
+ CcKeyboardItem *b)
+{
+ if (a->type != b->type)
+ return FALSE;
+ switch (a->type)
+ {
+ case CC_KEYBOARD_ITEM_TYPE_GSETTINGS_PATH:
+ return g_str_equal (a->gsettings_path, b->gsettings_path);
+ case CC_KEYBOARD_ITEM_TYPE_GSETTINGS:
+ return (g_str_equal (a->schema, b->schema) &&
+ g_str_equal (a->key, b->key));
+ default:
+ g_assert_not_reached ();
+ }
+
+}
+
+void
+cc_keyboard_item_add_reverse_item (CcKeyboardItem *item,
+ CcKeyboardItem *reverse_item,
+ gboolean is_reversed)
+{
+ g_return_if_fail (item->key != NULL);
+
+ item->reverse_item = reverse_item;
+ if (reverse_item->reverse_item == NULL)
+ {
+ reverse_item->reverse_item = item;
+ reverse_item->is_reversed = !is_reversed;
+ }
+ else
+ g_warn_if_fail (reverse_item->is_reversed == !!is_reversed);
+
+ item->is_reversed = !!is_reversed;
+}
+
+CcKeyboardItem *
+cc_keyboard_item_get_reverse_item (CcKeyboardItem *item)
+{
+ return item->reverse_item;
+}
+
+
+void
+cc_keyboard_item_set_hidden (CcKeyboardItem *item, gboolean hidden)
+{
+ item->hidden = !!hidden;
+}
+
+
+gboolean
+cc_keyboard_item_is_hidden (CcKeyboardItem *item)
+{
+ return item->hidden;
+}
+
+/**
+ * cc_keyboard_item_is_value_default:
+ * @self: a #CcKeyboardItem
+ *
+ * Retrieves whether the shortcut is the default value or not.
+ *
+ * Returns: %TRUE if the shortcut is the default value, %FALSE otherwise.
+ */
+gboolean
+cc_keyboard_item_is_value_default (CcKeyboardItem *self)
+{
+ g_return_val_if_fail (CC_IS_KEYBOARD_ITEM (self), FALSE);
+
+ /*
+ * When the shortcut is custom, we don't treat it as modified
+ * since we don't know what would be its default value.
+ */
+ if (self->type == CC_KEYBOARD_ITEM_TYPE_GSETTINGS_PATH)
+ return TRUE;
+
+ return combos_equal (self->default_combos, self->key_combos);
+}
+
+/**
+ * cc_keyboard_item_reset:
+ * @self: a #CcKeyboardItem
+ *
+ * Reset the keyboard binding to the default value.
+ */
+void
+cc_keyboard_item_reset (CcKeyboardItem *self)
+{
+ CcKeyboardItem *reverse;
+
+ g_return_if_fail (CC_IS_KEYBOARD_ITEM (self));
+
+ reverse = self->reverse_item;
+
+ g_settings_reset (self->settings, self->key);
+ g_object_notify (G_OBJECT (self), "is-value-default");
+
+ /* Also reset the reverse item */
+ if (reverse)
+ {
+ g_settings_reset (reverse->settings, reverse->key);
+ g_object_notify (G_OBJECT (reverse), "is-value-default");
+ }
+}
+
+GList *
+cc_keyboard_item_get_key_combos (CcKeyboardItem *item)
+{
+ g_return_val_if_fail (CC_IS_KEYBOARD_ITEM (item), NULL);
+ return item->key_combos;
+}
+
+GList *
+cc_keyboard_item_get_default_combos (CcKeyboardItem *item)
+{
+ g_return_val_if_fail (CC_IS_KEYBOARD_ITEM (item), NULL);
+ return item->default_combos;
+}
+
+CcKeyCombo
+cc_keyboard_item_get_primary_combo (CcKeyboardItem *item)
+{
+ g_return_val_if_fail (CC_IS_KEYBOARD_ITEM (item), EMPTY_COMBO);
+ return (item->key_combos) ? *((CcKeyCombo*)item->key_combos->data) : EMPTY_COMBO;
+}
+
+const gchar *
+cc_keyboard_item_get_key (CcKeyboardItem *item)
+{
+ g_return_val_if_fail (CC_IS_KEYBOARD_ITEM (item), NULL);
+ return item->key;
+}
+
+CcKeyboardItemType
+cc_keyboard_item_get_item_type (CcKeyboardItem *item)
+{
+ g_return_val_if_fail (CC_IS_KEYBOARD_ITEM (item), CC_KEYBOARD_ITEM_TYPE_NONE);
+ return item->type;
+}
+
+const gchar *
+cc_keyboard_item_get_gsettings_path (CcKeyboardItem *item)
+{
+ g_return_val_if_fail (CC_IS_KEYBOARD_ITEM (item), NULL);
+ return item->gsettings_path;
+}
+
+GSettings *
+cc_keyboard_item_get_settings (CcKeyboardItem *item)
+{
+ g_return_val_if_fail (CC_IS_KEYBOARD_ITEM (item), NULL);
+ return item->settings;
+}
+
+gboolean
+cc_keyboard_item_can_set_multiple (CcKeyboardItem *item)
+{
+ return item->can_set_multiple;
+}
+
+static gchar*
+combo_get_accelerator (CcKeyCombo *combo)
+{
+ return gtk_accelerator_name_with_keycode (NULL,
+ combo->keyval,
+ combo->keycode,
+ combo->mask);
+}
+
+static void
+cc_keyboard_item_add_key_combo_inner (CcKeyboardItem *self,
+ CcKeyCombo *combo)
+{
+ g_auto(GStrv) strv = NULL;
+ int i;
+
+ if (!self->can_set_multiple)
+ {
+ g_settings_set_string (self->settings, self->key, combo_get_accelerator (combo));
+ }
+ else
+ {
+ strv = g_new0 (gchar*, g_list_length (self->key_combos) + 2);
+
+ i = 0;
+ for (GList *l = self->key_combos; l != NULL; l = l->next, i++)
+ {
+ if (combo_equal (l->data, combo))
+ // This combo is already in the list
+ return;
+ strv[i] = combo_get_accelerator (l->data);
+ }
+ strv[i] = combo_get_accelerator (combo);
+
+ g_settings_set_strv (self->settings, self->key, (const gchar **)strv);
+ }
+
+ binding_changed (self, self->key);
+}
+
+void
+cc_keyboard_item_add_key_combo (CcKeyboardItem *self,
+ CcKeyCombo *combo)
+{
+ CcKeyCombo reverse_combo;
+
+ if (self->reverse_item)
+ {
+ reverse_combo.keyval = combo->keyval;
+ reverse_combo.keycode = combo->keycode;
+ reverse_combo.mask = combo->mask ^ GDK_SHIFT_MASK;
+ cc_keyboard_item_add_key_combo_inner (self->reverse_item, &reverse_combo);
+ }
+
+ cc_keyboard_item_add_key_combo_inner (self, combo);
+}
+
+static void
+cc_keyboard_item_remove_key_combo_inner (CcKeyboardItem *self,
+ CcKeyCombo *combo)
+{
+ g_auto(GStrv) strv = NULL;
+ gboolean found;
+ int i;
+
+ strv = g_new0 (gchar*, g_list_length (self->key_combos) + 1);
+
+ found = FALSE;
+ i = 0;
+ for (GList *l = self->key_combos; l != NULL; l = l->next, i++)
+ {
+ if (combo_equal (l->data, combo))
+ {
+ i--;
+ found = TRUE;
+ }
+ else
+ {
+ strv[i] = combo_get_accelerator (l->data);
+ }
+ }
+
+ if (found)
+ {
+ if (self->can_set_multiple)
+ g_settings_set_strv (self->settings, self->key, (const gchar **)strv);
+ else
+ g_settings_set_string (self->settings, self->key, "");
+ }
+
+ binding_changed (self, self->key);
+}
+
+void
+cc_keyboard_item_remove_key_combo (CcKeyboardItem *self,
+ CcKeyCombo *combo)
+{
+ CcKeyCombo reverse_combo;
+
+ if (self->reverse_item)
+ {
+ reverse_combo.keyval = combo->keyval;
+ reverse_combo.keycode = combo->keycode;
+ reverse_combo.mask = combo->mask ^ GDK_SHIFT_MASK;
+ cc_keyboard_item_remove_key_combo_inner (self->reverse_item, &reverse_combo);
+ }
+
+ cc_keyboard_item_remove_key_combo_inner (self, combo);
+}
+
+void cc_keyboard_item_disable (CcKeyboardItem *self)
+{
+ if (!self->can_set_multiple)
+ {
+ g_settings_set_string (self->settings, self->key, "");
+ if (self->reverse_item)
+ g_settings_set_string (self->reverse_item->settings, self->reverse_item->key, "");
+ }
+ else
+ {
+ g_settings_set_strv (self->settings, self->key, NULL);
+ if (self->reverse_item)
+ g_settings_set_strv (self->reverse_item->settings, self->reverse_item->key, NULL);
+ }
+
+ binding_changed (self, self->key);
+}
diff --git a/panels/keyboard/cc-keyboard-item.h b/panels/keyboard/cc-keyboard-item.h
new file mode 100644
index 0000000..2f4194d
--- /dev/null
+++ b/panels/keyboard/cc-keyboard-item.h
@@ -0,0 +1,112 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_KEYBOARD_ITEM (cc_keyboard_item_get_type ())
+G_DECLARE_FINAL_TYPE (CcKeyboardItem, cc_keyboard_item, CC, KEYBOARD_ITEM, GObject)
+
+typedef enum
+{
+ BINDING_GROUP_SYSTEM,
+ BINDING_GROUP_APPS,
+ BINDING_GROUP_SEPARATOR,
+ BINDING_GROUP_USER,
+} BindingGroupType;
+
+typedef enum
+{
+ CC_KEYBOARD_ITEM_TYPE_NONE = 0,
+ CC_KEYBOARD_ITEM_TYPE_GSETTINGS_PATH,
+ CC_KEYBOARD_ITEM_TYPE_GSETTINGS
+} CcKeyboardItemType;
+
+typedef struct
+{
+ guint keyval;
+ guint keycode;
+ GdkModifierType mask;
+} CcKeyCombo;
+
+CcKeyboardItem* cc_keyboard_item_new (CcKeyboardItemType type);
+
+gboolean cc_keyboard_item_load_from_gsettings_path (CcKeyboardItem *item,
+ const char *path,
+ gboolean reset);
+
+gboolean cc_keyboard_item_load_from_gsettings (CcKeyboardItem *item,
+ const char *description,
+ const char *schema,
+ const char *key);
+
+const char* cc_keyboard_item_get_description (CcKeyboardItem *item);
+
+gboolean cc_keyboard_item_get_desc_editable (CcKeyboardItem *item);
+
+const char* cc_keyboard_item_get_command (CcKeyboardItem *item);
+
+gboolean cc_keyboard_item_get_cmd_editable (CcKeyboardItem *item);
+
+gboolean cc_keyboard_item_equal (CcKeyboardItem *a,
+ CcKeyboardItem *b);
+
+void cc_keyboard_item_add_reverse_item (CcKeyboardItem *item,
+ CcKeyboardItem *reverse_item,
+ gboolean is_reversed);
+
+CcKeyboardItem* cc_keyboard_item_get_reverse_item (CcKeyboardItem *item);
+
+void cc_keyboard_item_set_hidden (CcKeyboardItem *item,
+ gboolean hidden);
+
+gboolean cc_keyboard_item_is_hidden (CcKeyboardItem *item);
+
+gboolean cc_keyboard_item_is_value_default (CcKeyboardItem *self);
+
+void cc_keyboard_item_reset (CcKeyboardItem *self);
+
+GList* cc_keyboard_item_get_key_combos (CcKeyboardItem *self);
+
+GList* cc_keyboard_item_get_default_combos (CcKeyboardItem *self);
+
+CcKeyCombo cc_keyboard_item_get_primary_combo (CcKeyboardItem *self);
+
+const gchar* cc_keyboard_item_get_key (CcKeyboardItem *self);
+
+CcKeyboardItemType cc_keyboard_item_get_item_type (CcKeyboardItem *self);
+
+const gchar* cc_keyboard_item_get_gsettings_path (CcKeyboardItem *self);
+
+GSettings* cc_keyboard_item_get_settings (CcKeyboardItem *self);
+
+gboolean cc_keyboard_item_can_set_multiple (CcKeyboardItem *self);
+
+void cc_keyboard_item_add_key_combo (CcKeyboardItem *self,
+ CcKeyCombo *combo);
+
+void cc_keyboard_item_remove_key_combo (CcKeyboardItem *self,
+ CcKeyCombo *combo);
+void cc_keyboard_item_disable (CcKeyboardItem *self);
+
+G_END_DECLS
diff --git a/panels/keyboard/cc-keyboard-manager.c b/panels/keyboard/cc-keyboard-manager.c
new file mode 100644
index 0000000..04f5653
--- /dev/null
+++ b/panels/keyboard/cc-keyboard-manager.c
@@ -0,0 +1,1050 @@
+/*
+ * Copyright (C) 2010 Intel, Inc
+ * Copyright (C) 2016 Endless, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ * Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+ *
+ */
+
+#include <glib/gi18n.h>
+
+#include "cc-keyboard-manager.h"
+#include "keyboard-shortcuts.h"
+
+#include <gdk/gdk.h>
+#ifdef GDK_WINDOWING_X11
+#include <gdk/x11/gdkx.h>
+#include <X11/Xatom.h>
+#endif
+
+#define BINDINGS_SCHEMA "org.gnome.settings-daemon.plugins.media-keys"
+#define CUSTOM_SHORTCUTS_ID "custom"
+
+struct _CcKeyboardManager
+{
+ GObject parent;
+
+ GtkListStore *sections_store;
+
+ GHashTable *kb_system_sections;
+ GHashTable *kb_apps_sections;
+ GHashTable *kb_user_sections;
+
+ GSettings *binding_settings;
+};
+
+G_DEFINE_TYPE (CcKeyboardManager, cc_keyboard_manager, G_TYPE_OBJECT)
+
+enum
+{
+ SHORTCUT_ADDED,
+ SHORTCUT_CHANGED,
+ SHORTCUT_REMOVED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+/*
+ * Auxiliary methods
+ */
+static void
+free_key_array (GPtrArray *keys)
+{
+ if (keys != NULL)
+ {
+ gint i;
+
+ for (i = 0; i < keys->len; i++)
+ {
+ CcKeyboardItem *item;
+
+ item = g_ptr_array_index (keys, i);
+
+ g_object_unref (item);
+ }
+
+ g_ptr_array_free (keys, TRUE);
+ }
+}
+
+static gboolean
+find_conflict (CcUniquenessData *data,
+ CcKeyboardItem *item)
+{
+ GList *l;
+ gboolean is_conflict = FALSE;
+
+ if (data->orig_item && cc_keyboard_item_equal (data->orig_item, item))
+ return FALSE;
+
+ for (l = cc_keyboard_item_get_key_combos (item); l; l = l->next)
+ {
+ CcKeyCombo *combo = l->data;
+
+ if (data->new_mask != combo->mask)
+ continue;
+
+ if (data->new_keyval != 0)
+ is_conflict = data->new_keyval == combo->keyval;
+ else
+ is_conflict = combo->keyval == 0 && data->new_keycode == combo->keycode;
+
+ if (is_conflict)
+ break;
+ }
+
+ if (is_conflict)
+ data->conflict_item = item;
+
+ return is_conflict;
+}
+
+static gboolean
+compare_keys_for_uniqueness (CcKeyboardItem *current_item,
+ CcUniquenessData *data)
+{
+ CcKeyboardItem *reverse_item;
+
+ /* No conflict for: blanks or ourselves */
+ if (!current_item || data->orig_item == current_item)
+ return FALSE;
+
+ reverse_item = cc_keyboard_item_get_reverse_item (current_item);
+
+ /* When the current item is the reversed shortcut of a main item, simply ignore it */
+ if (reverse_item && cc_keyboard_item_is_hidden (current_item))
+ return FALSE;
+
+ if (find_conflict (data, current_item))
+ return TRUE;
+
+ /* Also check for the reverse item if any */
+ if (reverse_item && find_conflict (data, reverse_item))
+ return TRUE;
+
+ return FALSE;
+}
+
+static gboolean
+check_for_uniqueness (gpointer key,
+ GPtrArray *keys_array,
+ CcUniquenessData *data)
+{
+ guint i;
+
+ for (i = 0; i < keys_array->len; i++)
+ {
+ CcKeyboardItem *item;
+
+ item = keys_array->pdata[i];
+
+ if (compare_keys_for_uniqueness (item, data))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+static GHashTable*
+get_hash_for_group (CcKeyboardManager *self,
+ BindingGroupType group)
+{
+ GHashTable *hash;
+
+ switch (group)
+ {
+ case BINDING_GROUP_SYSTEM:
+ hash = self->kb_system_sections;
+ break;
+ case BINDING_GROUP_APPS:
+ hash = self->kb_apps_sections;
+ break;
+ case BINDING_GROUP_USER:
+ hash = self->kb_user_sections;
+ break;
+ default:
+ hash = NULL;
+ }
+
+ return hash;
+}
+
+static gboolean
+have_key_for_group (CcKeyboardManager *self,
+ int group,
+ const gchar *name)
+{
+ GHashTableIter iter;
+ GPtrArray *keys;
+ gint i;
+
+ g_hash_table_iter_init (&iter, get_hash_for_group (self, group));
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer*) &keys))
+ {
+ for (i = 0; i < keys->len; i++)
+ {
+ CcKeyboardItem *item = g_ptr_array_index (keys, i);
+
+ if (cc_keyboard_item_get_item_type (item) == CC_KEYBOARD_ITEM_TYPE_GSETTINGS &&
+ g_strcmp0 (name, cc_keyboard_item_get_key (item)) == 0)
+ {
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+add_shortcuts (CcKeyboardManager *self)
+{
+ GtkTreeModel *sections_model;
+ GtkTreeIter sections_iter;
+ gboolean can_continue;
+
+ sections_model = GTK_TREE_MODEL (self->sections_store);
+ can_continue = gtk_tree_model_get_iter_first (sections_model, &sections_iter);
+
+ while (can_continue)
+ {
+ BindingGroupType group;
+ GPtrArray *keys;
+ g_autofree gchar *id = NULL;
+ g_autofree gchar *title = NULL;
+ gint i;
+
+ gtk_tree_model_get (sections_model,
+ &sections_iter,
+ SECTION_DESCRIPTION_COLUMN, &title,
+ SECTION_GROUP_COLUMN, &group,
+ SECTION_ID_COLUMN, &id,
+ -1);
+
+ /* Ignore separators */
+ if (group == BINDING_GROUP_SEPARATOR)
+ {
+ can_continue = gtk_tree_model_iter_next (sections_model, &sections_iter);
+ continue;
+ }
+
+ keys = g_hash_table_lookup (get_hash_for_group (self, group), id);
+
+ for (i = 0; i < keys->len; i++)
+ {
+ CcKeyboardItem *item = g_ptr_array_index (keys, i);
+
+ if (!cc_keyboard_item_is_hidden (item))
+ {
+ g_signal_emit (self, signals[SHORTCUT_ADDED],
+ 0,
+ item,
+ id,
+ title);
+ }
+ }
+
+ can_continue = gtk_tree_model_iter_next (sections_model, &sections_iter);
+ }
+}
+
+static void
+append_section (CcKeyboardManager *self,
+ const gchar *title,
+ const gchar *id,
+ BindingGroupType group,
+ const KeyListEntry *keys_list)
+{
+ GtkTreeIter iter;
+ GHashTable *reverse_items;
+ GHashTable *hash;
+ GPtrArray *keys_array;
+ gboolean is_new;
+ gint i;
+
+ hash = get_hash_for_group (self, group);
+
+ if (!hash)
+ return;
+
+ /* Add all CcKeyboardItems for this section */
+ is_new = FALSE;
+ keys_array = g_hash_table_lookup (hash, id);
+ if (keys_array == NULL)
+ {
+ keys_array = g_ptr_array_new ();
+ is_new = TRUE;
+ }
+
+ reverse_items = g_hash_table_new (g_str_hash, g_str_equal);
+
+ for (i = 0; keys_list != NULL && keys_list[i].name != NULL; i++)
+ {
+ CcKeyboardItem *item;
+ gboolean ret;
+
+ if (have_key_for_group (self, group, keys_list[i].name))
+ continue;
+
+ item = cc_keyboard_item_new (keys_list[i].type);
+
+ switch (keys_list[i].type)
+ {
+ case CC_KEYBOARD_ITEM_TYPE_GSETTINGS_PATH:
+ ret = cc_keyboard_item_load_from_gsettings_path (item, keys_list[i].name, FALSE);
+ break;
+
+ case CC_KEYBOARD_ITEM_TYPE_GSETTINGS:
+ ret = cc_keyboard_item_load_from_gsettings (item,
+ keys_list[i].description,
+ keys_list[i].schema,
+ keys_list[i].name);
+ if (ret && keys_list[i].reverse_entry != NULL)
+ {
+ CcKeyboardItem *reverse_item;
+ reverse_item = g_hash_table_lookup (reverse_items,
+ keys_list[i].reverse_entry);
+ if (reverse_item != NULL)
+ {
+ cc_keyboard_item_add_reverse_item (item,
+ reverse_item,
+ keys_list[i].is_reversed);
+ }
+ else
+ {
+ g_hash_table_insert (reverse_items,
+ keys_list[i].name,
+ item);
+ }
+ }
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ if (ret == FALSE)
+ {
+ /* We don't actually want to popup a dialog - just skip this one */
+ g_object_unref (item);
+ continue;
+ }
+
+ cc_keyboard_item_set_hidden (item, keys_list[i].hidden);
+
+ g_ptr_array_add (keys_array, item);
+ }
+
+ g_hash_table_destroy (reverse_items);
+
+ /* Add the keys to the hash table */
+ if (is_new)
+ {
+ g_hash_table_insert (hash, g_strdup (id), keys_array);
+
+ /* Append the section to the left tree view */
+ gtk_list_store_append (GTK_LIST_STORE (self->sections_store), &iter);
+ gtk_list_store_set (GTK_LIST_STORE (self->sections_store),
+ &iter,
+ SECTION_DESCRIPTION_COLUMN, title,
+ SECTION_ID_COLUMN, id,
+ SECTION_GROUP_COLUMN, group,
+ -1);
+ }
+}
+
+static void
+append_sections_from_file (CcKeyboardManager *self,
+ const gchar *path,
+ const char *datadir,
+ gchar **wm_keybindings)
+{
+ KeyList *keylist;
+ KeyListEntry *keys;
+ KeyListEntry key = { 0, 0, 0, 0, 0, 0, 0 };
+ const char *title;
+ int group;
+ guint i;
+
+ keylist = parse_keylist_from_file (path);
+
+ if (keylist == NULL)
+ return;
+
+#define const_strv(s) ((const gchar* const*) s)
+
+ /* If there's no keys to add, or the settings apply to a window manager
+ * that's not the one we're running */
+ if (keylist->entries->len == 0 ||
+ (keylist->wm_name != NULL && !g_strv_contains (const_strv (wm_keybindings), keylist->wm_name)) ||
+ keylist->name == NULL)
+ {
+ g_free (keylist->name);
+ g_free (keylist->package);
+ g_free (keylist->wm_name);
+ g_array_free (keylist->entries, TRUE);
+ g_free (keylist);
+ return;
+ }
+
+#undef const_strv
+
+ /* Empty KeyListEntry to end the array */
+ key.name = NULL;
+ g_array_append_val (keylist->entries, key);
+
+ keys = (KeyListEntry *) g_array_free (keylist->entries, FALSE);
+ if (keylist->package)
+ {
+ g_autofree gchar *localedir = NULL;
+
+ localedir = g_build_filename (datadir, "locale", NULL);
+ bindtextdomain (keylist->package, localedir);
+
+ title = dgettext (keylist->package, keylist->name);
+ } else {
+ title = _(keylist->name);
+ }
+
+ if (keylist->group && strcmp (keylist->group, "system") == 0)
+ group = BINDING_GROUP_SYSTEM;
+ else
+ group = BINDING_GROUP_APPS;
+
+ append_section (self, title, keylist->name, group, keys);
+
+ g_free (keylist->name);
+ g_free (keylist->package);
+ g_free (keylist->wm_name);
+ g_free (keylist->schema);
+ g_free (keylist->group);
+
+ for (i = 0; keys[i].name != NULL; i++)
+ {
+ KeyListEntry *entry = &keys[i];
+ g_free (entry->schema);
+ g_free (entry->description);
+ g_free (entry->name);
+ g_free (entry->reverse_entry);
+ }
+
+ g_free (keylist);
+ g_free (keys);
+}
+
+static void
+append_sections_from_gsettings (CcKeyboardManager *self)
+{
+ g_auto(GStrv) custom_paths = NULL;
+ GArray *entries;
+ KeyListEntry key = { 0, 0, 0, 0, 0, 0, 0 };
+ int i;
+
+ /* load custom shortcuts from GSettings */
+ entries = g_array_new (FALSE, TRUE, sizeof (KeyListEntry));
+
+ custom_paths = g_settings_get_strv (self->binding_settings, "custom-keybindings");
+ for (i = 0; custom_paths[i]; i++)
+ {
+ key.name = g_strdup (custom_paths[i]);
+ if (!have_key_for_group (self, BINDING_GROUP_USER, key.name))
+ {
+ key.type = CC_KEYBOARD_ITEM_TYPE_GSETTINGS_PATH;
+ g_array_append_val (entries, key);
+ }
+ else
+ g_free (key.name);
+ }
+
+ if (entries->len > 0)
+ {
+ KeyListEntry *keys;
+ int i;
+
+ /* Empty KeyListEntry to end the array */
+ key.name = NULL;
+ g_array_append_val (entries, key);
+
+ keys = (KeyListEntry *) entries->data;
+ append_section (self, _("Custom Shortcuts"), CUSTOM_SHORTCUTS_ID, BINDING_GROUP_USER, keys);
+ for (i = 0; i < entries->len; ++i)
+ {
+ g_free (keys[i].name);
+ }
+ }
+ else
+ {
+ append_section (self, _("Custom Shortcuts"), CUSTOM_SHORTCUTS_ID, BINDING_GROUP_USER, NULL);
+ }
+
+ g_array_free (entries, TRUE);
+}
+
+#ifdef GDK_WINDOWING_X11
+static char *
+get_window_manager_property (GdkDisplay *display,
+ Atom atom,
+ Window window)
+{
+ Display *xdisplay;
+ Atom utf8_string;
+ int result;
+ Atom actual_type;
+ int actual_format;
+ unsigned long n_items;
+ unsigned long bytes_after;
+ unsigned char *prop;
+ char *value;
+
+ if (window == None)
+ return NULL;
+
+ xdisplay = gdk_x11_display_get_xdisplay (display);
+ utf8_string = XInternAtom (xdisplay, "UTF8_STRING", False);
+
+ gdk_x11_display_error_trap_push (display);
+
+ result = XGetWindowProperty (xdisplay,
+ window,
+ atom,
+ 0,
+ G_MAXLONG,
+ False,
+ utf8_string,
+ &actual_type,
+ &actual_format,
+ &n_items,
+ &bytes_after,
+ &prop);
+
+ gdk_x11_display_error_trap_pop_ignored (display);
+
+ if (result != Success ||
+ actual_type != utf8_string ||
+ actual_format != 8 ||
+ n_items == 0)
+ {
+ XFree (prop);
+ return NULL;
+ }
+
+ value = g_strndup ((const char *) prop, n_items);
+ XFree (prop);
+
+ if (!g_utf8_validate (value, -1, NULL))
+ {
+ g_free (value);
+ return NULL;
+ }
+
+ return value;
+}
+
+static Window
+get_wm_window (GdkDisplay *display)
+{
+ Display *xdisplay;
+ Atom wm_check;
+ int result;
+ Atom actual_type;
+ int actual_format;
+ unsigned long n_items;
+ unsigned long bytes_after;
+ unsigned char *prop;
+ Window wm_window;
+
+ xdisplay = gdk_x11_display_get_xdisplay (display);
+ wm_check = XInternAtom (xdisplay, "_NET_SUPPORTING_WM_CHECK", False);
+
+ gdk_x11_display_error_trap_push (display);
+
+ result = XGetWindowProperty (xdisplay,
+ XDefaultRootWindow (xdisplay),
+ wm_check,
+ 0,
+ G_MAXLONG,
+ False,
+ XA_WINDOW,
+ &actual_type,
+ &actual_format,
+ &n_items,
+ &bytes_after,
+ &prop);
+
+ gdk_x11_display_error_trap_pop_ignored (display);
+
+ if (result != Success ||
+ actual_type != XA_WINDOW ||
+ n_items == 0)
+ {
+ XFree (prop);
+ return None;
+ }
+
+ wm_window = *(Window *) prop;
+ XFree (prop);
+
+ return wm_window;
+}
+#endif
+
+static GStrv
+get_current_keybindings (void)
+{
+#ifdef GDK_WINDOWING_X11
+ GdkDisplay *display;
+ Display *xdisplay;
+ Atom keybindings_atom;
+ Window wm_window;
+ char *keybindings;
+ GStrv results;
+
+ display = gdk_display_get_default ();
+ if (!GDK_IS_X11_DISPLAY (display))
+ return NULL;
+
+ xdisplay = gdk_x11_display_get_xdisplay (display);
+ keybindings_atom = XInternAtom (xdisplay, "_GNOME_WM_KEYBINDINGS", False);
+
+ wm_window = get_wm_window (display);
+ keybindings = get_window_manager_property (display,
+ keybindings_atom,
+ wm_window);
+
+ if (keybindings != NULL)
+ {
+ GStrv p;
+
+ results = g_strsplit (keybindings, ",", -1);
+
+ for (p = results; p && *p; p++)
+ g_strstrip (*p);
+
+ g_free (keybindings);
+ }
+ else
+ {
+ Atom wm_atom;
+ char *wm_name;
+
+ wm_atom = XInternAtom (xdisplay, "_NET_WM_NAME", False);
+ wm_name = get_window_manager_property (display, wm_atom, wm_window);
+
+ results = g_new0 (char *, 2);
+ results[0] = wm_name ? wm_name : g_strdup ("Unknown");
+ }
+
+ return results;
+#else
+ return NULL;
+#endif
+}
+
+static void
+reload_sections (CcKeyboardManager *self)
+{
+ GHashTable *loaded_files;
+ GDir *dir;
+ gchar *default_wm_keybindings[] = { "Mutter", "GNOME Shell", NULL };
+ g_auto(GStrv) wm_keybindings = NULL;
+ const gchar * const * data_dirs;
+ guint i;
+
+ /* Clear previous models and hash tables */
+ gtk_list_store_clear (GTK_LIST_STORE (self->sections_store));
+
+ g_clear_pointer (&self->kb_system_sections, g_hash_table_destroy);
+ self->kb_system_sections = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ (GDestroyNotify) free_key_array);
+
+ g_clear_pointer (&self->kb_apps_sections, g_hash_table_destroy);
+ self->kb_apps_sections = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ (GDestroyNotify) free_key_array);
+
+ g_clear_pointer (&self->kb_user_sections, g_hash_table_destroy);
+ self->kb_user_sections = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ (GDestroyNotify) free_key_array);
+
+ /* Load WM keybindings */
+ wm_keybindings = get_current_keybindings ();
+
+ if (wm_keybindings == NULL)
+ wm_keybindings = g_strdupv (default_wm_keybindings);
+
+ loaded_files = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ data_dirs = g_get_system_data_dirs ();
+ for (i = 0; data_dirs[i] != NULL; i++)
+ {
+ g_autofree gchar *dir_path = NULL;
+ const gchar *name;
+
+ dir_path = g_build_filename (data_dirs[i], "gnome-control-center", "keybindings", NULL);
+
+ dir = g_dir_open (dir_path, 0, NULL);
+ if (!dir)
+ continue;
+
+ for (name = g_dir_read_name (dir) ; name ; name = g_dir_read_name (dir))
+ {
+ g_autofree gchar *path = NULL;
+
+ if (g_str_has_suffix (name, ".xml") == FALSE)
+ continue;
+
+ if (g_hash_table_lookup (loaded_files, name) != NULL)
+ {
+ g_debug ("Not loading %s, it was already loaded from another directory", name);
+ continue;
+ }
+
+ g_hash_table_insert (loaded_files, g_strdup (name), GINT_TO_POINTER (1));
+ path = g_build_filename (dir_path, name, NULL);
+ append_sections_from_file (self, path, data_dirs[i], wm_keybindings);
+ }
+
+ g_dir_close (dir);
+ }
+
+ g_hash_table_destroy (loaded_files);
+
+ /* Load custom keybindings */
+ append_sections_from_gsettings (self);
+}
+
+/*
+ * Callbacks
+ */
+static void
+cc_keyboard_manager_finalize (GObject *object)
+{
+ CcKeyboardManager *self = (CcKeyboardManager *)object;
+
+ g_clear_pointer (&self->kb_system_sections, g_hash_table_destroy);
+ g_clear_pointer (&self->kb_apps_sections, g_hash_table_destroy);
+ g_clear_pointer (&self->kb_user_sections, g_hash_table_destroy);
+ g_clear_object (&self->binding_settings);
+ g_clear_object (&self->sections_store);
+
+ G_OBJECT_CLASS (cc_keyboard_manager_parent_class)->finalize (object);
+}
+
+static void
+cc_keyboard_manager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+}
+
+static void
+cc_keyboard_manager_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+}
+
+static void
+cc_keyboard_manager_class_init (CcKeyboardManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = cc_keyboard_manager_finalize;
+ object_class->get_property = cc_keyboard_manager_get_property;
+ object_class->set_property = cc_keyboard_manager_set_property;
+
+ /**
+ * CcKeyboardManager:shortcut-added:
+ *
+ * Emitted when a shortcut is added.
+ */
+ signals[SHORTCUT_ADDED] = g_signal_new ("shortcut-added",
+ CC_TYPE_KEYBOARD_MANAGER,
+ G_SIGNAL_RUN_FIRST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 3,
+ CC_TYPE_KEYBOARD_ITEM,
+ G_TYPE_STRING,
+ G_TYPE_STRING);
+
+ /**
+ * CcKeyboardManager:shortcut-changed:
+ *
+ * Emitted when a shortcut is added.
+ */
+ signals[SHORTCUT_CHANGED] = g_signal_new ("shortcut-changed",
+ CC_TYPE_KEYBOARD_MANAGER,
+ G_SIGNAL_RUN_FIRST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 1,
+ CC_TYPE_KEYBOARD_ITEM);
+
+
+ /**
+ * CcKeyboardManager:shortcut-removed:
+ *
+ * Emitted when a shortcut is removed.
+ */
+ signals[SHORTCUT_REMOVED] = g_signal_new ("shortcut-removed",
+ CC_TYPE_KEYBOARD_MANAGER,
+ G_SIGNAL_RUN_FIRST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 1,
+ CC_TYPE_KEYBOARD_ITEM);
+}
+
+static void
+cc_keyboard_manager_init (CcKeyboardManager *self)
+{
+ /* Bindings */
+ self->binding_settings = g_settings_new (BINDINGS_SCHEMA);
+
+ /* Setup the section models */
+ self->sections_store = gtk_list_store_new (SECTION_N_COLUMNS,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_INT);
+}
+
+
+CcKeyboardManager *
+cc_keyboard_manager_new (void)
+{
+ return g_object_new (CC_TYPE_KEYBOARD_MANAGER, NULL);
+}
+
+void
+cc_keyboard_manager_load_shortcuts (CcKeyboardManager *self)
+{
+ g_return_if_fail (CC_IS_KEYBOARD_MANAGER (self));
+
+ reload_sections (self);
+ add_shortcuts (self);
+}
+
+/**
+ * cc_keyboard_manager_create_custom_shortcut:
+ * @self: a #CcKeyboardPanel
+ *
+ * Creates a new temporary keyboard shortcut.
+ *
+ * Returns: (transfer full): a #CcKeyboardItem
+ */
+CcKeyboardItem*
+cc_keyboard_manager_create_custom_shortcut (CcKeyboardManager *self)
+{
+ CcKeyboardItem *item;
+ g_autofree gchar *settings_path = NULL;
+
+ g_return_val_if_fail (CC_IS_KEYBOARD_MANAGER (self), NULL);
+
+ item = cc_keyboard_item_new (CC_KEYBOARD_ITEM_TYPE_GSETTINGS_PATH);
+
+ settings_path = find_free_settings_path (self->binding_settings);
+ cc_keyboard_item_load_from_gsettings_path (item, settings_path, TRUE);
+
+ return item;
+}
+
+/**
+ * cc_keyboard_manager_add_custom_shortcut:
+ * @self: a #CcKeyboardPanel
+ * @item: the #CcKeyboardItem to be added
+ *
+ * Effectively adds the custom shortcut.
+ */
+void
+cc_keyboard_manager_add_custom_shortcut (CcKeyboardManager *self,
+ CcKeyboardItem *item)
+{
+ GPtrArray *keys_array;
+ GHashTable *hash;
+ GVariantBuilder builder;
+ char **settings_paths;
+ int i;
+
+ g_return_if_fail (CC_IS_KEYBOARD_MANAGER (self));
+
+ hash = get_hash_for_group (self, BINDING_GROUP_USER);
+ keys_array = g_hash_table_lookup (hash, CUSTOM_SHORTCUTS_ID);
+
+ if (keys_array == NULL)
+ {
+ keys_array = g_ptr_array_new ();
+ g_hash_table_insert (hash, g_strdup (CUSTOM_SHORTCUTS_ID), keys_array);
+ }
+
+ g_ptr_array_add (keys_array, item);
+
+ settings_paths = g_settings_get_strv (self->binding_settings, "custom-keybindings");
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
+
+ for (i = 0; settings_paths[i]; i++)
+ g_variant_builder_add (&builder, "s", settings_paths[i]);
+
+ g_variant_builder_add (&builder, "s", cc_keyboard_item_get_gsettings_path (item));
+
+ g_settings_set_value (self->binding_settings, "custom-keybindings", g_variant_builder_end (&builder));
+
+ g_signal_emit (self, signals[SHORTCUT_ADDED],
+ 0,
+ item,
+ CUSTOM_SHORTCUTS_ID,
+ _("Custom Shortcuts"));
+}
+
+/**
+ * cc_keyboard_manager_remove_custom_shortcut:
+ * @self: a #CcKeyboardPanel
+ * @item: the #CcKeyboardItem to be added
+ *
+ * Removed the custom shortcut.
+ */
+void
+cc_keyboard_manager_remove_custom_shortcut (CcKeyboardManager *self,
+ CcKeyboardItem *item)
+{
+ GPtrArray *keys_array;
+ GVariantBuilder builder;
+ GSettings *settings;
+ char **settings_paths;
+ int i;
+
+ g_return_if_fail (CC_IS_KEYBOARD_MANAGER (self));
+
+ /* Shortcut not a custom shortcut */
+ g_assert (cc_keyboard_item_get_item_type (item) == CC_KEYBOARD_ITEM_TYPE_GSETTINGS_PATH);
+
+ settings = cc_keyboard_item_get_settings (item);
+ g_settings_delay (settings);
+ g_settings_reset (settings, "name");
+ g_settings_reset (settings, "command");
+ g_settings_reset (settings, "binding");
+ g_settings_apply (settings);
+ g_settings_sync ();
+
+ settings_paths = g_settings_get_strv (self->binding_settings, "custom-keybindings");
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
+
+ for (i = 0; settings_paths[i]; i++)
+ if (strcmp (settings_paths[i], cc_keyboard_item_get_gsettings_path (item)) != 0)
+ g_variant_builder_add (&builder, "s", settings_paths[i]);
+
+ g_settings_set_value (self->binding_settings,
+ "custom-keybindings",
+ g_variant_builder_end (&builder));
+
+ g_strfreev (settings_paths);
+
+ keys_array = g_hash_table_lookup (get_hash_for_group (self, BINDING_GROUP_USER), CUSTOM_SHORTCUTS_ID);
+ g_ptr_array_remove (keys_array, item);
+
+ g_signal_emit (self, signals[SHORTCUT_REMOVED], 0, item);
+}
+
+/**
+ * cc_keyboard_manager_get_collision:
+ * @self: a #CcKeyboardManager
+ * @item: (nullable): a keyboard shortcut
+ * @combo: a #CcKeyCombo
+ *
+ * Retrieves the collision item for the given shortcut.
+ *
+ * Returns: (transfer none)(nullable): the collisioned shortcut
+ */
+CcKeyboardItem*
+cc_keyboard_manager_get_collision (CcKeyboardManager *self,
+ CcKeyboardItem *item,
+ CcKeyCombo *combo)
+{
+ CcUniquenessData data;
+ BindingGroupType i;
+
+ g_return_val_if_fail (CC_IS_KEYBOARD_MANAGER (self), NULL);
+
+ data.orig_item = item;
+ data.new_keyval = combo->keyval;
+ data.new_mask = combo->mask;
+ data.new_keycode = combo->keycode;
+ data.conflict_item = NULL;
+
+ if (combo->keyval == 0 && combo->keycode == 0)
+ return NULL;
+
+ /* Any number of shortcuts can be disabled */
+ for (i = BINDING_GROUP_SYSTEM; i <= BINDING_GROUP_USER && !data.conflict_item; i++)
+ {
+ GHashTable *table;
+
+ table = get_hash_for_group (self, i);
+
+ if (!table)
+ continue;
+
+ g_hash_table_find (table, (GHRFunc) check_for_uniqueness, &data);
+ }
+
+ return data.conflict_item;
+}
+
+/**
+ * cc_keyboard_manager_reset_shortcut:
+ * @self: a #CcKeyboardManager
+ * @item: a #CcKeyboardItem
+ *
+ * Resets the keyboard shortcut managed by @item, and eventually
+ * disables any shortcut that conflicts with the new shortcut's
+ * value.
+ */
+void
+cc_keyboard_manager_reset_shortcut (CcKeyboardManager *self,
+ CcKeyboardItem *item)
+{
+ GList *l;
+
+ g_return_if_fail (CC_IS_KEYBOARD_MANAGER (self));
+ g_return_if_fail (CC_IS_KEYBOARD_ITEM (item));
+
+ /* Disables any shortcut that conflicts with the new shortcut's value */
+ for (l = cc_keyboard_item_get_default_combos (item); l; l = l->next)
+ {
+ CcKeyCombo *combo = l->data;
+ CcKeyboardItem *collision;
+
+ collision = cc_keyboard_manager_get_collision (self, NULL, combo);
+ if (collision)
+ cc_keyboard_item_remove_key_combo (collision, combo);
+ }
+
+ /* Resets the current item */
+ cc_keyboard_item_reset (item);
+}
diff --git a/panels/keyboard/cc-keyboard-manager.h b/panels/keyboard/cc-keyboard-manager.h
new file mode 100644
index 0000000..5de19c0
--- /dev/null
+++ b/panels/keyboard/cc-keyboard-manager.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 Intel, Inc
+ * Copyright (C) 2016 Endless, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ * Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+ *
+ */
+
+#pragma once
+
+#include <glib-object.h>
+
+#include "cc-keyboard-item.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_KEYBOARD_MANAGER (cc_keyboard_manager_get_type ())
+G_DECLARE_FINAL_TYPE (CcKeyboardManager, cc_keyboard_manager, CC, KEYBOARD_MANAGER, GObject)
+
+CcKeyboardManager* cc_keyboard_manager_new (void);
+
+void cc_keyboard_manager_load_shortcuts (CcKeyboardManager *self);
+
+CcKeyboardItem* cc_keyboard_manager_create_custom_shortcut (CcKeyboardManager *self);
+
+void cc_keyboard_manager_add_custom_shortcut (CcKeyboardManager *self,
+ CcKeyboardItem *item);
+
+void cc_keyboard_manager_remove_custom_shortcut (CcKeyboardManager *self,
+ CcKeyboardItem *item);
+
+CcKeyboardItem* cc_keyboard_manager_get_collision (CcKeyboardManager *self,
+ CcKeyboardItem *item,
+ CcKeyCombo *combo);
+
+void cc_keyboard_manager_reset_shortcut (CcKeyboardManager *self,
+ CcKeyboardItem *item);
+
+G_END_DECLS
+
diff --git a/panels/keyboard/cc-keyboard-panel.c b/panels/keyboard/cc-keyboard-panel.c
new file mode 100644
index 0000000..2e91fe7
--- /dev/null
+++ b/panels/keyboard/cc-keyboard-panel.c
@@ -0,0 +1,266 @@
+/* cc-keyboard-panel.c
+ *
+ * Copyright (C) 2010 Intel, Inc
+ * Copyright (C) 2016 Endless, Inc
+ * Copyright (C) 2020 System76, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ * Georges Basile Stavracas Neto <gbsneto@gnome.org>
+ * Ian Douglas Scott <idscott@system76.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <glib/gi18n.h>
+
+#include "cc-keyboard-panel.h"
+#include "cc-keyboard-resources.h"
+#include "cc-keyboard-shortcut-dialog.h"
+#include "cc-input-list-box.h"
+#include "cc-xkb-modifier-dialog.h"
+
+#include "keyboard-shortcuts.h"
+
+struct _CcKeyboardPanel
+{
+ CcPanel parent_instance;
+
+ GtkCheckButton *per_window_source;
+ GtkCheckButton *same_source;
+ GSettings *keybindings_settings;
+
+ GSettings *input_source_settings;
+ AdwPreferencesGroup *input_switch_group;
+ AdwActionRow *alt_chars_row;
+ AdwActionRow *compose_row;
+ GtkWidget *value_alternate_chars;
+ GtkWidget *value_compose;
+
+ AdwActionRow *common_shortcuts_row;
+};
+
+CC_PANEL_REGISTER (CcKeyboardPanel, cc_keyboard_panel)
+
+enum {
+ PROP_0,
+ PROP_PARAMETERS
+};
+
+static const CcXkbModifier LV3_MODIFIER = {
+ "lv3:",
+ N_("Alternate Characters Key"),
+ N_("The alternate characters key can be used to enter additional characters. These are sometimes printed as a third-option on your keyboard."),
+ (CcXkbOption[]){
+ { NC_("keyboard key", "Left Alt"), "lv3:lalt_switch" },
+ { NC_("keyboard key", "Right Alt"), "lv3:ralt_switch" },
+ { NC_("keyboard key", "Left Super"), "lv3:lwin_switch" },
+ { NC_("keyboard key", "Right Super"), "lv3:rwin_switch" },
+ { NC_("keyboard key", "Menu key"), "lv3:menu_switch" },
+ { NC_("keyboard key", "Right Ctrl"), "lv3:switch" },
+ { NULL, NULL }
+ },
+ "lv3:ralt_switch",
+};
+
+static const CcXkbModifier COMPOSE_MODIFIER = {
+ "compose:",
+ N_("Compose Key"),
+ N_("The compose key allows a wide variety of characters to be entered. To use it, press compose then a sequence of characters. "
+ " For example, compose key followed by <b>C</b> and <b>o</b> will enter <b>©</b>, "
+ "<b>a</b> followed by <b>'</b> will enter <b>á</b>."),
+ (CcXkbOption[]){
+ { NC_("keyboard key", "Left Alt"), "compose:lalt" },
+ { NC_("keyboard key", "Right Alt"), "compose:ralt" },
+ { NC_("keyboard key", "Left Super"), "compose:lwin" },
+ { NC_("keyboard key", "Right Super"), "compose:rwin" },
+ { NC_("keyboard key", "Menu key"), "compose:menu" },
+ { NC_("keyboard key", "Right Ctrl"), "compose:rctrl" },
+ { NC_("keyboard key", "Caps Lock"), "compose:caps" },
+ { NC_("keyboard key", "Scroll Lock"), "compose:sclk" },
+ { NC_("keyboard key", "Print Screen"), "compose:prsc" },
+ { NULL, NULL }
+ },
+ NULL,
+};
+
+static void
+special_chars_activated (AdwActionRow *row,
+ CcKeyboardPanel *self)
+{
+ const CcXkbModifier *modifier;
+ GtkWindow *window, *dialog;
+
+ window = GTK_WINDOW (cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (self))));
+
+ if (row == self->alt_chars_row)
+ modifier = &LV3_MODIFIER;
+ else if (row == self->compose_row)
+ modifier = &COMPOSE_MODIFIER;
+ else
+ return;
+
+ dialog = GTK_WINDOW (cc_xkb_modifier_dialog_new (self->input_source_settings, modifier));
+
+ gtk_window_set_transient_for (dialog, window);
+ gtk_widget_show (GTK_WIDGET (dialog));
+}
+
+static void
+keyboard_shortcuts_activated (AdwActionRow *row,
+ CcKeyboardPanel *self)
+{
+ GtkWindow *window;
+ GtkWidget *shortcut_dialog;
+
+ if (row == self->common_shortcuts_row)
+ {
+ window = GTK_WINDOW (cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (self))));
+
+ shortcut_dialog = cc_keyboard_shortcut_dialog_new ();
+ gtk_window_set_transient_for (GTK_WINDOW (shortcut_dialog), window);
+ gtk_widget_show (GTK_WIDGET (shortcut_dialog));
+ }
+}
+
+static void
+cc_keyboard_panel_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id)
+ {
+ case PROP_PARAMETERS:
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static const char *
+cc_keyboard_panel_get_help_uri (CcPanel *panel)
+{
+ return "help:gnome-help/keyboard";
+}
+
+static void
+cc_keyboard_panel_finalize (GObject *object)
+{
+ CcKeyboardPanel *self = CC_KEYBOARD_PANEL (object);
+
+ g_clear_object (&self->input_source_settings);
+ g_clear_object (&self->keybindings_settings);
+
+ G_OBJECT_CLASS (cc_keyboard_panel_parent_class)->finalize (object);
+}
+
+static void
+cc_keyboard_panel_class_init (CcKeyboardPanelClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+
+ panel_class->get_help_uri = cc_keyboard_panel_get_help_uri;
+
+ object_class->set_property = cc_keyboard_panel_set_property;
+ object_class->finalize = cc_keyboard_panel_finalize;
+
+ g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters");
+
+ g_type_ensure (CC_TYPE_INPUT_LIST_BOX);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/keyboard/cc-keyboard-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, input_switch_group);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, per_window_source);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, same_source);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, alt_chars_row);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, compose_row);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, value_alternate_chars);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, value_compose);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, common_shortcuts_row);
+
+ gtk_widget_class_bind_template_callback (widget_class, special_chars_activated);
+ gtk_widget_class_bind_template_callback (widget_class, keyboard_shortcuts_activated);
+}
+
+static gboolean
+translate_switch_input_source (GValue *value,
+ GVariant *variant,
+ gpointer user_data)
+{
+ g_autofree const gchar **strv = NULL;
+ g_autofree gchar *accel_text = NULL;
+ g_autofree gchar *label = NULL;
+ CcKeyCombo combo = { 0 };
+
+ strv = g_variant_get_strv (variant, NULL);
+
+ gtk_accelerator_parse (strv[0] ? strv[0] : "", &combo.keyval, &combo.mask);
+ accel_text = convert_keysym_state_to_string (&combo);
+
+ label = g_strdup_printf (_("Input sources can be switched using the %s "
+ "keyboard shortcut.\nThis can be changed in "
+ "the keyboard shortcut settings."),
+ accel_text);
+
+ g_value_set_string (value, label);
+
+ return TRUE;
+}
+
+static void
+cc_keyboard_panel_init (CcKeyboardPanel *self)
+{
+ g_resources_register (cc_keyboard_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->input_source_settings = g_settings_new ("org.gnome.desktop.input-sources");
+
+ /* "Input Source Switching" section */
+ g_settings_bind (self->input_source_settings, "per-window",
+ self->same_source, "active",
+ G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_INVERT_BOOLEAN);
+ self->keybindings_settings = g_settings_new ("org.gnome.desktop.wm.keybindings");
+ g_settings_bind_with_mapping (self->keybindings_settings, "switch-input-source",
+ self->input_switch_group, "description",
+ G_SETTINGS_BIND_GET,
+ translate_switch_input_source,
+ NULL, NULL, NULL);
+
+ /* "Type Special Characters" section */
+ g_settings_bind_with_mapping (self->input_source_settings,
+ "xkb-options",
+ self->value_alternate_chars,
+ "label",
+ G_SETTINGS_BIND_GET,
+ xcb_modifier_transform_binding_to_label,
+ NULL,
+ (gpointer)&LV3_MODIFIER,
+ NULL);
+ g_settings_bind_with_mapping (self->input_source_settings,
+ "xkb-options",
+ self->value_compose,
+ "label",
+ G_SETTINGS_BIND_GET,
+ xcb_modifier_transform_binding_to_label,
+ NULL,
+ (gpointer)&COMPOSE_MODIFIER,
+ NULL);
+}
diff --git a/panels/keyboard/cc-keyboard-panel.h b/panels/keyboard/cc-keyboard-panel.h
new file mode 100644
index 0000000..3d3076b
--- /dev/null
+++ b/panels/keyboard/cc-keyboard-panel.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2010 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ *
+ */
+
+
+#pragma once
+
+#include <shell/cc-panel.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_KEYBOARD_PANEL (cc_keyboard_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcKeyboardPanel, cc_keyboard_panel, CC, KEYBOARD_PANEL, CcPanel)
+
+G_END_DECLS
diff --git a/panels/keyboard/cc-keyboard-panel.ui b/panels/keyboard/cc-keyboard-panel.ui
new file mode 100644
index 0000000..4975a40
--- /dev/null
+++ b/panels/keyboard/cc-keyboard-panel.ui
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <object class="GtkAdjustment" id="cursor_blink_time_adjustment">
+ <property name="lower">100</property>
+ <property name="upper">2500</property>
+ <property name="value">1000</property>
+ <property name="step_increment">200</property>
+ <property name="page_increment">200</property>
+ </object>
+ <template class="CcKeyboardPanel" parent="CcPanel">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <child type="content">
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Input Sources</property>
+ <property name="description" translatable="yes">Includes keyboard layouts and input methods.</property>
+ <child>
+ <object class="CcInputListBox" id="input_list">
+ <property name="vexpand">False</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup" id="input_switch_group">
+ <property name="title" translatable="yes">Input Source Switching</property>
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Use the _same source for all windows</property>
+ <property name="use-underline">True</property>
+ <property name="activatable-widget">same_source</property>
+ <child type="prefix">
+ <object class="GtkCheckButton" id="same_source">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Switch input sources _individually for each window</property>
+ <property name="use-underline">True</property>
+ <property name="activatable-widget">per_window_source</property>
+ <child type="prefix">
+ <object class="GtkCheckButton" id="per_window_source">
+ <property name="active" bind-source="same_source" bind-flags="sync-create|invert-boolean"/>
+ <property name="valign">center</property>
+ <property name="group">same_source</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Special Character Entry</property>
+ <property name="description" translatable="yes">Methods for entering symbols and letter variants using the keyboard.</property>
+ <child>
+ <object class="AdwActionRow" id="alt_chars_row">
+ <property name="title" translatable="yes">Alternate Characters Key</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="special_chars_activated" object="CcKeyboardPanel" swapped="no" />
+ <child>
+ <object class="GtkLabel" id="value_alternate_chars">
+ <property name="label" translatable="no">Right Alt</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="icon_name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="compose_row">
+ <property name="title" translatable="yes">Compose Key</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="special_chars_activated" object="CcKeyboardPanel" swapped="no" />
+ <child>
+ <object class="GtkLabel" id="value_compose">
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="icon_name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Keyboard Shortcuts</property>
+ <child>
+ <object class="AdwActionRow" id="common_shortcuts_row">
+ <property name="title" translatable="yes">View and Customize Shortcuts</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="keyboard_shortcuts_activated" object="CcKeyboardPanel" swapped="no" />
+ <child>
+ <object class="GtkImage">
+ <property name="icon_name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/keyboard/cc-keyboard-shortcut-dialog.c b/panels/keyboard/cc-keyboard-shortcut-dialog.c
new file mode 100644
index 0000000..15f3dfd
--- /dev/null
+++ b/panels/keyboard/cc-keyboard-shortcut-dialog.c
@@ -0,0 +1,877 @@
+/* cc-keyboard-shortcut-dialog.c
+ *
+ * Copyright (C) 2010 Intel, Inc
+ * Copyright (C) 2016 Endless, Inc
+ * Copyright (C) 2020 System76, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ * Georges Basile Stavracas Neto <gbsneto@gnome.org>
+ * Ian Douglas Scott <idscott@system76.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include <adwaita.h>
+
+#include "cc-keyboard-shortcut-dialog.h"
+#include "cc-keyboard-item.h"
+#include "cc-keyboard-manager.h"
+#include "cc-keyboard-shortcut-editor.h"
+#include "cc-keyboard-shortcut-row.h"
+#include "cc-list-row.h"
+#include "cc-util.h"
+#include "keyboard-shortcuts.h"
+
+#define SHORTCUT_DELIMITERS "+ "
+
+typedef struct {
+ gchar *section_title;
+ gchar *section_id;
+ guint modified_count;
+ GtkLabel *modified_label;
+} SectionRowData;
+
+typedef struct {
+ CcKeyboardItem *item;
+ gchar *section_title;
+ gchar *section_id;
+ SectionRowData *section_data;
+} ShortcutRowData;
+
+struct _CcKeyboardShortcutDialog
+{
+ GtkDialog parent_instance;
+
+ GtkSizeGroup *accelerator_sizegroup;
+ GtkWidget *back_button;
+ GtkListBoxRow *custom_shortcut_add_row;
+ guint custom_shortcut_count;
+ GtkWidget *empty_custom_shortcuts_placeholder;
+ GtkWidget *empty_search_placeholder;
+ GtkHeaderBar *headerbar;
+ GtkStack *header_stack;
+ GtkWidget *reset_all_button;
+ GtkWidget *section_box;
+ GtkSearchEntry *search_entry;
+ GtkListBox *section_listbox;
+ GtkListBoxRow *section_row;
+ GtkWidget *shortcut_box;
+ GtkListBox *shortcut_listbox;
+ GtkStack *stack;
+
+ CcKeyboardManager *manager;
+ GtkWidget *shortcut_editor;
+ GHashTable *sections;
+ };
+
+G_DEFINE_TYPE (CcKeyboardShortcutDialog, cc_keyboard_shortcut_dialog, GTK_TYPE_DIALOG)
+static gboolean
+is_matched_shortcut_present (GtkListBox *listbox,
+ gpointer user_data);
+
+static SectionRowData*
+section_row_data_new (const gchar *section_id,
+ const gchar *section_title,
+ GtkLabel *modified_label)
+{
+ SectionRowData *data;
+
+ data = g_new0 (SectionRowData, 1);
+ data->section_id = g_strdup (section_id);
+ data->section_title = g_strdup (section_title);
+ data->modified_count = 0;
+ data->modified_label = modified_label;
+
+ return data;
+}
+
+static void
+section_row_data_free (SectionRowData *data)
+{
+ g_free (data->section_id);
+ g_free (data->section_title);
+ g_free (data);
+}
+
+static ShortcutRowData*
+shortcut_row_data_new (CcKeyboardItem *item,
+ const gchar *section_id,
+ const gchar *section_title,
+ SectionRowData *section_data)
+{
+ ShortcutRowData *data;
+
+ data = g_new0 (ShortcutRowData, 1);
+ data->item = g_object_ref (item);
+ data->section_id = g_strdup (section_id);
+ data->section_title = g_strdup (section_title);
+ data->section_data = section_data;
+
+ return data;
+}
+
+static void
+shortcut_row_data_free (ShortcutRowData *data)
+{
+ g_object_unref (data->item);
+ g_free (data->section_id);
+ g_free (data->section_title);
+ g_free (data);
+}
+
+static GtkListBoxRow*
+add_section (CcKeyboardShortcutDialog *self,
+ const gchar *section_id,
+ const gchar *section_title)
+{
+ GtkWidget *icon, *modified_label, *row;
+
+ icon = gtk_image_new_from_icon_name ("go-next-symbolic");
+ gtk_widget_add_css_class (icon, "dim-label");
+
+ modified_label = gtk_label_new (NULL);
+ gtk_widget_add_css_class (modified_label, "dim-label");
+
+ row = adw_action_row_new ();
+ gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), TRUE);
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row), _(section_title));
+ //TODO gtk_container_add (GTK_CONTAINER (row), modified_label);
+ //TODO gtk_container_add (GTK_CONTAINER (row), icon);
+
+ g_object_set_data_full (G_OBJECT (row),
+ "data",
+ section_row_data_new (section_id, section_title, GTK_LABEL (modified_label)),
+ (GDestroyNotify)section_row_data_free);
+
+ g_hash_table_insert (self->sections, g_strdup (section_id), row);
+ gtk_list_box_append (self->section_listbox, row);
+
+ return GTK_LIST_BOX_ROW (row);
+}
+
+static void
+set_custom_shortcut_placeholder_visibility (CcKeyboardShortcutDialog *self)
+{
+ SectionRowData *section_data;
+ gboolean is_custom_shortcuts = FALSE;
+
+ if (self->section_row != NULL)
+ {
+ section_data = g_object_get_data (G_OBJECT (self->section_row), "data");
+ is_custom_shortcuts = (strcmp (section_data->section_id, "custom") == 0);
+
+ gtk_stack_set_transition_type (self->stack, GTK_STACK_TRANSITION_TYPE_CROSSFADE);
+ if (is_custom_shortcuts && (self->custom_shortcut_count == 0))
+ gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->empty_custom_shortcuts_placeholder));
+ else
+ gtk_stack_set_visible_child (self->stack, self->shortcut_box);
+ }
+}
+
+static void
+add_item (CcKeyboardShortcutDialog *self,
+ CcKeyboardItem *item,
+ const gchar *section_id,
+ const gchar *section_title)
+{
+ GtkWidget *row;
+ GtkListBoxRow *section_row;
+ SectionRowData *section_data;
+
+ section_row = g_hash_table_lookup (self->sections, section_id);
+ if (section_row == NULL)
+ section_row = add_section (self, section_id, section_title);
+
+ section_data = g_object_get_data (G_OBJECT (section_row), "data");
+
+ row = GTK_WIDGET (cc_keyboard_shortcut_row_new (item,
+ self->manager,
+ CC_KEYBOARD_SHORTCUT_EDITOR (self->shortcut_editor),
+ self->accelerator_sizegroup));
+
+ g_object_set_data_full (G_OBJECT (row),
+ "data",
+ shortcut_row_data_new (item, section_id, section_title, section_data),
+ (GDestroyNotify)shortcut_row_data_free);
+
+ if (strcmp (section_id, "custom") == 0)
+ {
+ self->custom_shortcut_count++;
+ set_custom_shortcut_placeholder_visibility (self);
+ }
+
+ gtk_list_box_append (self->shortcut_listbox, row);
+}
+
+static void
+remove_item (CcKeyboardShortcutDialog *self,
+ CcKeyboardItem *item)
+{
+ GtkWidget *child;
+
+ for (child = gtk_widget_get_first_child (GTK_WIDGET (self->shortcut_listbox));
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ {
+ ShortcutRowData *row_data;
+
+ if (!GTK_IS_LIST_BOX_ROW (child))
+ continue;
+
+ row_data = g_object_get_data (G_OBJECT (child), "data");
+
+ if (row_data && row_data->item == item)
+ {
+ if (strcmp (row_data->section_id, "custom") == 0)
+ {
+ self->custom_shortcut_count--;
+ set_custom_shortcut_placeholder_visibility (self);
+ }
+
+ gtk_list_box_remove (self->shortcut_listbox, child);
+ break;
+ }
+ }
+}
+
+static void
+update_modified_counts (CcKeyboardShortcutDialog *self)
+{
+ SectionRowData *section_data;
+ ShortcutRowData *shortcut_data;
+ g_autofree gchar *modified_text = NULL;
+ GtkWidget *child;
+
+ for (child = gtk_widget_get_first_child (GTK_WIDGET (self->section_listbox));
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ {
+ if (!GTK_IS_LIST_BOX_ROW (child))
+ continue;
+
+ section_data = g_object_get_data (G_OBJECT (child), "data");
+ section_data->modified_count = 0;
+ }
+
+ for (child = gtk_widget_get_first_child (GTK_WIDGET (self->shortcut_listbox));
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ {
+ if (!GTK_IS_LIST_BOX_ROW (child))
+ continue;
+
+ if (GTK_LIST_BOX_ROW (child) == self->custom_shortcut_add_row)
+ continue;
+ shortcut_data = g_object_get_data (G_OBJECT (child), "data");
+ if (!cc_keyboard_item_is_value_default (shortcut_data->item))
+ shortcut_data->section_data->modified_count++;
+ }
+
+ for (child = gtk_widget_get_first_child (GTK_WIDGET (self->section_listbox));
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ {
+ if (!GTK_IS_LIST_BOX_ROW (child))
+ continue;
+
+ section_data = g_object_get_data (G_OBJECT (child), "data");
+ if (section_data->modified_count > 0)
+ {
+ modified_text = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE,
+ "%d modified",
+ "%d modified",
+ section_data->modified_count),
+ section_data->modified_count);
+ gtk_label_set_text (section_data->modified_label, modified_text);
+ }
+ else
+ {
+ gtk_label_set_text (section_data->modified_label, "");
+ }
+ }
+}
+
+static void
+show_section_list (CcKeyboardShortcutDialog *self)
+{
+ if (self->section_row != NULL)
+ gtk_stack_set_transition_type (self->stack, GTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT);
+ else
+ gtk_stack_set_transition_type (self->stack, GTK_STACK_TRANSITION_TYPE_NONE);
+ self->section_row = NULL;
+
+ gtk_stack_set_visible_child (self->stack, self->section_box);
+ gtk_window_set_title (GTK_WINDOW (self), _("Keyboard Shortcuts"));
+ gtk_editable_set_text (GTK_EDITABLE (self->search_entry), "");
+ gtk_stack_set_visible_child (self->header_stack, self->reset_all_button);
+ gtk_widget_set_visible (GTK_WIDGET (self->search_entry), TRUE);
+
+ update_modified_counts (self);
+}
+
+static void
+show_shortcut_list (CcKeyboardShortcutDialog *self)
+{
+ SectionRowData *section_data;
+ gchar *title;
+ gboolean is_custom_shortcuts = FALSE;
+
+ title = _("Keyboard Shortcuts");
+ gtk_stack_set_transition_type (self->stack, GTK_STACK_TRANSITION_TYPE_NONE);
+ if (self->section_row != NULL)
+ {
+ section_data = g_object_get_data (G_OBJECT (self->section_row), "data");
+ title = _(section_data->section_title);
+ is_custom_shortcuts = (strcmp (section_data->section_id, "custom") == 0);
+ gtk_stack_set_transition_type (self->stack, GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT);
+ }
+ gtk_list_box_invalidate_filter (self->shortcut_listbox);
+
+ if (is_custom_shortcuts && (self->custom_shortcut_count == 0))
+ gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->empty_custom_shortcuts_placeholder));
+ else
+ gtk_stack_set_visible_child (self->stack, self->shortcut_box);
+
+ gtk_window_set_title (GTK_WINDOW (self), title);
+ set_custom_shortcut_placeholder_visibility (self);
+ gtk_stack_set_visible_child (self->header_stack, self->back_button);
+ gtk_widget_set_visible (GTK_WIDGET (self->search_entry), self->section_row == NULL);
+
+}
+
+static void
+add_custom_shortcut_clicked_cb (CcKeyboardShortcutDialog *self)
+{
+ CcKeyboardShortcutEditor *editor;
+
+ editor = CC_KEYBOARD_SHORTCUT_EDITOR (self->shortcut_editor);
+
+ cc_keyboard_shortcut_editor_set_mode (editor, CC_SHORTCUT_EDITOR_CREATE);
+ cc_keyboard_shortcut_editor_set_item (editor, NULL);
+
+ gtk_widget_show (self->shortcut_editor);
+}
+
+static void
+section_row_activated (GtkWidget *button,
+ GtkListBoxRow *row,
+ CcKeyboardShortcutDialog *self)
+{
+ self->section_row = row;
+ show_shortcut_list (self);
+}
+
+static void
+shortcut_row_activated (GtkWidget *button,
+ GtkListBoxRow *row,
+ CcKeyboardShortcutDialog *self)
+{
+ CcKeyboardShortcutEditor *editor;
+
+ if (row == self->custom_shortcut_add_row)
+ {
+ add_custom_shortcut_clicked_cb (self);
+ return;
+ }
+
+ editor = CC_KEYBOARD_SHORTCUT_EDITOR (self->shortcut_editor);
+
+ ShortcutRowData *data = g_object_get_data (G_OBJECT (row), "data");
+
+ cc_keyboard_shortcut_editor_set_mode (editor, CC_SHORTCUT_EDITOR_EDIT);
+ cc_keyboard_shortcut_editor_set_item (editor, data->item);
+
+ gtk_widget_show (self->shortcut_editor);
+}
+
+static void
+back_button_clicked_cb (CcKeyboardShortcutDialog *self)
+{
+ show_section_list (self);
+}
+
+static void
+reset_shortcut (CcKeyboardShortcutDialog *self,
+ GtkWidget *row)
+{
+ ShortcutRowData *data;
+
+ if (row == GTK_WIDGET (self->custom_shortcut_add_row))
+ return;
+
+ data = g_object_get_data (G_OBJECT (row), "data");
+
+ /* Don't reset custom shortcuts */
+ if (cc_keyboard_item_get_item_type (data->item) == CC_KEYBOARD_ITEM_TYPE_GSETTINGS_PATH)
+ return;
+
+ /* cc_keyboard_manager_reset_shortcut() already resets conflicting shortcuts,
+ * so no other check is needed here. */
+ cc_keyboard_manager_reset_shortcut (self->manager, data->item);
+}
+
+static void
+on_reset_all_dialog_response_cb (GtkDialog *dialog,
+ gint response,
+ CcKeyboardShortcutDialog *self)
+{
+
+ if (response == GTK_RESPONSE_ACCEPT)
+ {
+ GtkWidget *child;
+
+ for (child = gtk_widget_get_first_child (GTK_WIDGET (self->shortcut_listbox));
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ {
+ if (!GTK_IS_LIST_BOX_ROW (child))
+ continue;
+ if (GTK_LIST_BOX_ROW (child) == self->custom_shortcut_add_row)
+ continue;
+ reset_shortcut (self, child);
+ }
+ }
+
+ gtk_window_destroy (GTK_WINDOW (dialog));
+ update_modified_counts (self);
+}
+
+static void
+reset_all_clicked_cb (CcKeyboardShortcutDialog *self)
+{
+ GtkWidget *dialog, *button;
+
+ dialog = gtk_message_dialog_new (GTK_WINDOW (self),
+ GTK_DIALOG_MODAL | GTK_DIALOG_USE_HEADER_BAR | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_NONE,
+ _("Reset All Shortcuts?"));
+
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ _("Resetting the shortcuts may affect your custom shortcuts. "
+ "This cannot be undone."));
+
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ _("Cancel"), GTK_RESPONSE_CANCEL,
+ _("Reset All"), GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
+
+ /* Make the "Reset All" button destructive */
+ button = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
+ gtk_widget_add_css_class (button, "destructive-action");
+
+ g_signal_connect (dialog, "response", G_CALLBACK (on_reset_all_dialog_response_cb), self);
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+static void
+search_entry_cb (CcKeyboardShortcutDialog *self)
+{
+ gboolean is_shortcut = is_matched_shortcut_present (self->shortcut_listbox, self);
+ const gchar *search_text = gtk_editable_get_text (GTK_EDITABLE (self->search_entry));
+
+ if (!is_shortcut)
+ gtk_stack_set_visible_child (self->stack, self->empty_search_placeholder);
+ else if (g_utf8_strlen (search_text, -1) == 0 && self->section_row == NULL)
+ show_section_list (self);
+ else if (gtk_stack_get_visible_child (self->stack) != self->shortcut_box)
+ show_shortcut_list (self);
+ else
+ gtk_list_box_invalidate_filter (self->shortcut_listbox);
+}
+
+static gboolean
+strv_contains_prefix_or_match (gchar **strv,
+ const gchar *prefix)
+{
+ const struct {
+ const gchar *key;
+ const gchar *untranslated;
+ const gchar *synonym;
+ } key_aliases[] =
+ {
+ { "ctrl", "Ctrl", "ctrl" },
+ { "win", "Super", "super" },
+ { "option", NULL, "alt" },
+ { "command", NULL, "super" },
+ { "apple", NULL, "super" },
+ };
+
+ for (guint i = 0; strv[i]; i++)
+ {
+ if (g_str_has_prefix (strv[i], prefix))
+ return TRUE;
+ }
+
+ for (guint i = 0; i < G_N_ELEMENTS (key_aliases); i++)
+ {
+ g_autofree gchar *alias = NULL;
+ const gchar *synonym;
+
+ if (!g_str_has_prefix (key_aliases[i].key, prefix))
+ continue;
+
+ if (key_aliases[i].untranslated)
+ {
+ const gchar *translated_label;
+
+ /* Steal GTK+'s translation */
+ translated_label = g_dpgettext2 ("gtk40", "keyboard label", key_aliases[i].untranslated);
+ alias = g_utf8_strdown (translated_label, -1);
+ }
+
+ synonym = key_aliases[i].synonym;
+
+ /* If a translation or synonym of the key is in the accelerator, and we typed
+ * the key, also consider that a prefix */
+ if ((alias && g_strv_contains ((const gchar * const *) strv, alias)) ||
+ (synonym && g_strv_contains ((const gchar * const *) strv, synonym)))
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static gboolean
+search_match_shortcut (CcKeyboardItem *item,
+ const gchar *search)
+{
+ g_auto(GStrv) shortcut_tokens = NULL, search_tokens = NULL;
+ g_autofree gchar *normalized_accel = NULL;
+ g_autofree gchar *accel = NULL;
+ gboolean match;
+ GList *key_combos;
+ CcKeyCombo *combo;
+
+ key_combos = cc_keyboard_item_get_key_combos (item);
+ for (GList *l = key_combos; l != NULL; l = l->next)
+ {
+ combo = l->data;
+
+ if (is_empty_binding (combo))
+ continue;
+
+ match = TRUE;
+ accel = convert_keysym_state_to_string (combo);
+ normalized_accel = cc_util_normalize_casefold_and_unaccent (accel);
+
+ shortcut_tokens = g_strsplit_set (normalized_accel, SHORTCUT_DELIMITERS, -1);
+ search_tokens = g_strsplit_set (search, SHORTCUT_DELIMITERS, -1);
+
+ for (guint i = 0; search_tokens[i] != NULL; i++)
+ {
+ const gchar *token;
+
+ /* Strip leading and trailing whitespaces */
+ token = g_strstrip (search_tokens[i]);
+
+ if (g_utf8_strlen (token, -1) == 0)
+ continue;
+
+ match = match && strv_contains_prefix_or_match (shortcut_tokens, token);
+
+ if (!match)
+ break;
+ }
+
+ if (match)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gint
+section_sort_function (GtkListBoxRow *a,
+ GtkListBoxRow *b,
+ gpointer user_data)
+{
+ SectionRowData *a_data, *b_data;
+
+ a_data = g_object_get_data (G_OBJECT (a), "data");
+ b_data = g_object_get_data (G_OBJECT (b), "data");
+
+ /* Put custom shortcuts below everything else */
+ if (g_strcmp0 (a_data->section_id, "custom") == 0)
+ return 1;
+
+ return g_strcmp0 (a_data->section_title, b_data->section_title);
+}
+
+static gint
+shortcut_sort_function (GtkListBoxRow *a,
+ GtkListBoxRow *b,
+ gpointer user_data)
+{
+ CcKeyboardShortcutDialog *self = user_data;
+ ShortcutRowData *a_data, *b_data;
+ gint retval;
+
+ if (a == self->custom_shortcut_add_row)
+ return 1;
+ else if (b == self->custom_shortcut_add_row)
+ return -1;
+
+ a_data = g_object_get_data (G_OBJECT (a), "data");
+ b_data = g_object_get_data (G_OBJECT (b), "data");
+
+ retval = g_strcmp0 (a_data->section_title, b_data->section_title);
+
+ if (retval != 0)
+ return retval;
+
+ return g_strcmp0 (cc_keyboard_item_get_description (a_data->item), cc_keyboard_item_get_description (b_data->item));
+}
+
+static gboolean
+shortcut_filter_function (GtkListBoxRow *row,
+ gpointer userdata)
+{
+ CcKeyboardShortcutDialog *self = userdata;
+ SectionRowData *section_data;
+ ShortcutRowData *data;
+ CcKeyboardItem *item;
+ gboolean retval;
+ g_autofree gchar *search = NULL;
+ g_autofree gchar *name = NULL;
+ g_auto(GStrv) terms = NULL;
+ gboolean is_custom_shortcuts = FALSE;
+ const gchar *search_text;
+
+ if (self->section_row != NULL)
+ {
+ section_data = g_object_get_data (G_OBJECT (self->section_row), "data");
+ is_custom_shortcuts = (strcmp (section_data->section_id, "custom") == 0);
+
+ data = g_object_get_data (G_OBJECT (row), "data");
+ if (data && strcmp (data->section_id, section_data->section_id) != 0)
+ return FALSE;
+ }
+
+ if (row == self->custom_shortcut_add_row)
+ return is_custom_shortcuts;
+
+ search_text = gtk_editable_get_text (GTK_EDITABLE (self->search_entry));
+ if (g_utf8_strlen (search_text, -1) == 0)
+ return TRUE;
+
+ data = g_object_get_data (G_OBJECT (row), "data");
+ item = data->item;
+ name = cc_util_normalize_casefold_and_unaccent (cc_keyboard_item_get_description (item));
+ search = cc_util_normalize_casefold_and_unaccent (search_text);
+ terms = g_strsplit (search, " ", -1);
+
+ for (guint i = 0; terms && terms[i]; i++)
+ {
+ retval = strstr (name, terms[i]) || search_match_shortcut (item, terms[i]);
+ if (!retval)
+ break;
+ }
+
+ return retval;
+}
+
+static gboolean
+is_matched_shortcut_present (GtkListBox* listbox,
+ gpointer user_data)
+{
+ for (gint i = 0; ; i++)
+ {
+ GtkListBoxRow *current = gtk_list_box_get_row_at_index (listbox, i);
+ if (!current)
+ return FALSE;
+ if (shortcut_filter_function (current, user_data))
+ return TRUE;
+ }
+}
+
+static void
+shortcut_header_function (GtkListBoxRow *row,
+ GtkListBoxRow *before,
+ gpointer user_data)
+{
+ CcKeyboardShortcutDialog *self = user_data;
+ gboolean add_header;
+ ShortcutRowData *data, *before_data;
+
+ data = g_object_get_data (G_OBJECT (row), "data");
+
+ if (row == self->custom_shortcut_add_row)
+ {
+
+ add_header = FALSE;
+ }
+ else if (before && before != self->custom_shortcut_add_row)
+ {
+ before_data = g_object_get_data (G_OBJECT (before), "data");
+ add_header = g_strcmp0 (before_data->section_id, data->section_id) != 0;
+ }
+ else
+ {
+ add_header = TRUE;
+ }
+
+ if (self->section_row != NULL)
+ add_header = FALSE;
+
+ if (add_header)
+ {
+ GtkWidget *box, *label, *separator;
+ g_autofree gchar *markup = NULL;
+
+ box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+ if (!before)
+ gtk_widget_set_margin_top (box, 6);
+
+ markup = g_strdup_printf ("<b>%s</b>", _(data->section_title));
+ label = g_object_new (GTK_TYPE_LABEL,
+ "label", markup,
+ "use-markup", TRUE,
+ "xalign", 0.0,
+ "margin-start", 6,
+ NULL);
+ gtk_box_append (GTK_BOX (box), label);
+
+ separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
+ gtk_box_append (GTK_BOX (box), separator);
+
+ gtk_list_box_row_set_header (row, box);
+ }
+ else
+ {
+ gtk_list_box_row_set_header (row, NULL);
+ }
+}
+
+static void
+cc_keyboard_shortcut_dialog_constructed (GObject *object)
+{
+ CcKeyboardShortcutDialog *self = CC_KEYBOARD_SHORTCUT_DIALOG (object);
+
+ G_OBJECT_CLASS (cc_keyboard_shortcut_dialog_parent_class)->constructed (object);
+
+ /* Setup the dialog's transient parent */
+ gtk_window_set_transient_for (GTK_WINDOW (self->shortcut_editor), GTK_WINDOW (self));
+}
+
+static void
+cc_keyboard_shortcut_dialog_finalize (GObject *object)
+{
+ CcKeyboardShortcutDialog *self = CC_KEYBOARD_SHORTCUT_DIALOG (object);
+
+ g_clear_object (&self->manager);
+ g_clear_pointer (&self->sections, g_hash_table_destroy);
+ g_clear_pointer ((GtkWindow**)&self->shortcut_editor, gtk_window_destroy);
+}
+
+static void
+cc_keyboard_shortcut_dialog_class_init (CcKeyboardShortcutDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->constructed = cc_keyboard_shortcut_dialog_constructed;
+ object_class->finalize = cc_keyboard_shortcut_dialog_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/keyboard/cc-keyboard-shortcut-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, accelerator_sizegroup);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, back_button);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, custom_shortcut_add_row);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, empty_custom_shortcuts_placeholder);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, empty_search_placeholder);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, headerbar);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, header_stack);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, reset_all_button);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, search_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, section_listbox);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, section_box);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, shortcut_listbox);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, shortcut_box);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutDialog, stack);
+
+ gtk_widget_class_bind_template_callback (widget_class, add_custom_shortcut_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, back_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, reset_all_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, search_entry_cb);
+ gtk_widget_class_bind_template_callback (widget_class, section_row_activated);
+ gtk_widget_class_bind_template_callback (widget_class, shortcut_row_activated);
+}
+
+static void
+cc_keyboard_shortcut_dialog_init (CcKeyboardShortcutDialog *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ gtk_search_entry_set_key_capture_widget (self->search_entry, GTK_WIDGET (self));
+
+ self->manager = cc_keyboard_manager_new ();
+
+ self->shortcut_editor = cc_keyboard_shortcut_editor_new (self->manager);
+
+ self->sections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ self->section_row = NULL;
+
+ g_signal_connect_object (self->manager,
+ "shortcut-added",
+ G_CALLBACK (add_item),
+ self,
+ G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self->manager,
+ "shortcut-removed",
+ G_CALLBACK (remove_item),
+ self,
+ G_CONNECT_SWAPPED);
+
+ add_section(self, "custom", "Custom Shortcuts");
+ cc_keyboard_manager_load_shortcuts (self->manager);
+
+ gtk_list_box_set_sort_func (GTK_LIST_BOX (self->section_listbox),
+ section_sort_function,
+ self,
+ NULL);
+
+ gtk_list_box_set_filter_func (self->shortcut_listbox,
+ shortcut_filter_function,
+ self,
+ NULL);
+ gtk_list_box_set_header_func (self->shortcut_listbox,
+ shortcut_header_function,
+ self,
+ NULL);
+ gtk_list_box_set_sort_func (GTK_LIST_BOX (self->shortcut_listbox),
+ shortcut_sort_function,
+ self,
+ NULL);
+
+ show_section_list (self);
+}
+
+GtkWidget*
+cc_keyboard_shortcut_dialog_new (void)
+{
+ return g_object_new (CC_TYPE_KEYBOARD_SHORTCUT_DIALOG,
+ "use-header-bar", 1,
+ NULL);
+}
diff --git a/panels/keyboard/cc-keyboard-shortcut-dialog.h b/panels/keyboard/cc-keyboard-shortcut-dialog.h
new file mode 100644
index 0000000..4493dc2
--- /dev/null
+++ b/panels/keyboard/cc-keyboard-shortcut-dialog.h
@@ -0,0 +1,35 @@
+/* cc-keyboard-shortcut-dialog.h
+ *
+ * Copyright (C) 2020 System76, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Ian Douglas Scott <idscott@system76.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_KEYBOARD_SHORTCUT_DIALOG (cc_keyboard_shortcut_dialog_get_type ())
+
+G_DECLARE_FINAL_TYPE (CcKeyboardShortcutDialog, cc_keyboard_shortcut_dialog, CC, KEYBOARD_SHORTCUT_DIALOG, GtkDialog)
+
+GtkWidget* cc_keyboard_shortcut_dialog_new (void);
+
+G_END_DECLS \ No newline at end of file
diff --git a/panels/keyboard/cc-keyboard-shortcut-dialog.ui b/panels/keyboard/cc-keyboard-shortcut-dialog.ui
new file mode 100644
index 0000000..d1c8068
--- /dev/null
+++ b/panels/keyboard/cc-keyboard-shortcut-dialog.ui
@@ -0,0 +1,227 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcKeyboardShortcutDialog" parent="GtkDialog">
+ <property name="modal">True</property>
+ <property name="default-width">600</property>
+
+ <child type="titlebar">
+ <object class="GtkHeaderBar" id="headerbar">
+ <property name="show_title_buttons">True</property>
+ <child>
+ <object class="GtkStack" id="header_stack">
+ <property name="hhomogeneous">False</property>
+ <property name="vhomogeneous">False</property>
+ <property name="transition-type">crossfade</property>
+
+ <child>
+ <object class="GtkButton" id="back_button">
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <property name="icon_name">go-previous-symbolic</property>
+ <property name="use-underline">True</property>
+ <signal name="clicked" handler="back_button_clicked_cb" object="CcKeyboardShortcutDialog" swapped="yes" />
+ <style>
+ <class name="image-button"/>
+ </style>
+ <accessibility>
+ <property name="label">Back</property>
+ </accessibility>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkButton" id="reset_all_button">
+ <property name="label" translatable="yes">Reset All…</property>
+ <property name="tooltip-text" translatable="yes">Reset all shortcuts to their default keybindings</property>
+ <signal name="clicked" handler="reset_all_clicked_cb" object="CcKeyboardShortcutDialog" swapped="yes" />
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="propagate_natural_width">True</property>
+ <property name="propagate_natural_height">True</property>
+ <property name="max_content_height">450</property>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkSearchEntry" id="search_entry">
+ <property name="margin-top">12</property>
+ <property name="width_chars">30</property>
+ <property name="halign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Search</property>
+ </accessibility>
+ <signal name="notify::text" handler="search_entry_cb" object="CcKeyboardShortcutDialog" swapped="yes" />
+ </object>
+ </child>
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="hhomogeneous">False</property>
+ <property name="vhomogeneous">False</property>
+ <child>
+ <object class="GtkBox" id="section_box">
+ <property name="orientation">vertical</property>
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <child>
+ <object class="GtkListBox" id="section_listbox">
+ <property name="selection-mode">none</property>
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <accessibility>
+ <property name="label" translatable="yes">Section</property>
+ </accessibility>
+ <signal name="row-activated" handler="section_row_activated" object="CcKeyboardShortcutDialog" swapped="no" />
+ <style>
+ <class name="boxed-list" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="shortcut_box">
+ <property name="orientation">vertical</property>
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkListBox" id="shortcut_listbox">
+ <property name="selection-mode">none</property>
+ <accessibility>
+ <property name="label" translatable="yes">Shortcuts</property>
+ </accessibility>
+ <style>
+ <class name="boxed-list" />
+ </style>
+ <signal name="row-activated" handler="shortcut_row_activated" object="CcKeyboardShortcutDialog" swapped="no" />
+ <child>
+ <object class="GtkListBoxRow" id="custom_shortcut_add_row">
+ <accessibility>
+ <property name="label" translatable="yes">Add a shortcut</property>
+ </accessibility>
+ <child>
+ <object class="GtkImage">
+ <property name="hexpand">True</property>
+ <property name="icon_name">list-add-symbolic</property>
+ <property name="height_request">48</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="empty_custom_shortcuts_placeholder">
+ <property name="orientation">vertical</property>
+ <property name="margin-top">18</property>
+ <property name="margin-bottom">18</property>
+ <property name="margin-start">18</property>
+ <property name="margin-end">18</property>
+ <property name="spacing">18</property>
+ <property name="valign">center</property>
+ <style>
+ <class name="background"/>
+ </style>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">input-keyboard-symbolic</property>
+ <property name="pixel-size">128</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Add Custom Shortcuts</property>
+ <attributes>
+ <attribute name="weight" value="bold" />
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Set up custom shortcuts for launching apps, running scripts, and more.</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="halign">center</property>
+ <property name="label" translatable="yes">Add Shortcut</property>
+ <style>
+ <class name="suggested-action" />
+ </style>
+ <signal name="clicked" handler="add_custom_shortcut_clicked_cb" object="CcKeyboardShortcutDialog" swapped="yes" />
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="empty_search_placeholder">
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="margin-top">18</property>
+ <property name="margin-bottom">18</property>
+ <property name="margin-start">18</property>
+ <property name="margin-end">18</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkImage">
+ <property name="pixel_size">80</property>
+ <property name="icon_name">edit-find-symbolic</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">No keyboard shortcut found</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ <attribute name="scale" value="1.44"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Try a different search</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </template>
+ <object class="GtkSizeGroup" id="accelerator_sizegroup" />
+</interface>
diff --git a/panels/keyboard/cc-keyboard-shortcut-editor.c b/panels/keyboard/cc-keyboard-shortcut-editor.c
new file mode 100644
index 0000000..66cf024
--- /dev/null
+++ b/panels/keyboard/cc-keyboard-shortcut-editor.c
@@ -0,0 +1,985 @@
+/* cc-keyboard-shortcut-editor.h
+ *
+ * Copyright (C) 2016 Endless, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+ */
+
+#include <glib-object.h>
+#include <glib/gi18n.h>
+
+#include "cc-keyboard-shortcut-editor.h"
+#include "keyboard-shortcuts.h"
+
+struct _CcKeyboardShortcutEditor
+{
+ GtkDialog parent;
+
+ GtkButton *add_button;
+ GtkButton *cancel_button;
+ GtkButton *change_custom_shortcut_button;
+ GtkEntry *command_entry;
+ GtkGrid *custom_grid;
+ GtkShortcutLabel *custom_shortcut_accel_label;
+ GtkStack *custom_shortcut_stack;
+ GtkBox *edit_box;
+ GtkHeaderBar *headerbar;
+ GtkEntry *name_entry;
+ GtkLabel *new_shortcut_conflict_label;
+ GtkButton *remove_button;
+ GtkButton *replace_button;
+ GtkButton *reset_button;
+ GtkButton *reset_custom_button;
+ GtkButton *set_button;
+ GtkShortcutLabel *shortcut_accel_label;
+ GtkLabel *shortcut_conflict_label;
+ GtkBox *standard_box;
+ GtkStack *stack;
+ GtkLabel *top_info_label;
+
+ CcShortcutEditorMode mode;
+
+ CcKeyboardManager *manager;
+ CcKeyboardItem *item;
+ GBinding *reset_item_binding;
+
+ CcKeyboardItem *collision_item;
+
+ /* Custom shortcuts */
+ gboolean system_shortcuts_inhibited;
+ guint grab_idle_id;
+
+ CcKeyCombo *custom_combo;
+ gboolean custom_is_modifier;
+ gboolean edited : 1;
+};
+
+static void command_entry_changed_cb (CcKeyboardShortcutEditor *self);
+static void name_entry_changed_cb (CcKeyboardShortcutEditor *self);
+static void set_button_clicked_cb (CcKeyboardShortcutEditor *self);
+
+G_DEFINE_TYPE (CcKeyboardShortcutEditor, cc_keyboard_shortcut_editor, GTK_TYPE_DIALOG)
+
+enum
+{
+ PROP_0,
+ PROP_KEYBOARD_ITEM,
+ PROP_MANAGER,
+ N_PROPS
+};
+
+typedef enum
+{
+ HEADER_MODE_NONE,
+ HEADER_MODE_ADD,
+ HEADER_MODE_SET,
+ HEADER_MODE_REPLACE,
+ HEADER_MODE_CUSTOM_CANCEL,
+ HEADER_MODE_CUSTOM_EDIT
+} HeaderMode;
+
+typedef enum
+{
+ PAGE_CUSTOM,
+ PAGE_EDIT,
+ PAGE_STANDARD,
+} ShortcutEditorPage;
+
+static GParamSpec *properties [N_PROPS] = { NULL, };
+
+/* Getter and setter for ShortcutEditorPage */
+static ShortcutEditorPage
+get_shortcut_editor_page (CcKeyboardShortcutEditor *self)
+{
+ if (gtk_stack_get_visible_child (self->stack) == GTK_WIDGET (self->edit_box))
+ return PAGE_EDIT;
+
+ if (gtk_stack_get_visible_child (self->stack) == GTK_WIDGET (self->custom_grid))
+ return PAGE_CUSTOM;
+
+ return PAGE_STANDARD;
+}
+
+static void
+set_shortcut_editor_page (CcKeyboardShortcutEditor *self,
+ ShortcutEditorPage page)
+{
+ switch (page)
+ {
+ case PAGE_CUSTOM:
+ gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->custom_grid));
+ break;
+
+ case PAGE_EDIT:
+ gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->edit_box));
+ break;
+
+ case PAGE_STANDARD:
+ gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->standard_box));
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ gtk_widget_set_visible (GTK_WIDGET (self->top_info_label), page != PAGE_CUSTOM);
+}
+
+static void
+apply_custom_item_fields (CcKeyboardShortcutEditor *self,
+ CcKeyboardItem *item)
+{
+ /* Only setup the binding when it was actually edited */
+ if (self->edited)
+ {
+ CcKeyCombo *combo = self->custom_combo;
+
+ cc_keyboard_item_disable (item);
+
+ if (combo->keycode != 0 || combo->keyval != 0 || combo->mask != 0)
+ cc_keyboard_item_add_key_combo (item, combo);
+ }
+
+ /* Set the keyboard shortcut name and command for custom entries */
+ if (cc_keyboard_item_get_item_type (item) == CC_KEYBOARD_ITEM_TYPE_GSETTINGS_PATH)
+ {
+ g_settings_set_string (cc_keyboard_item_get_settings (item),
+ "name",
+ gtk_editable_get_text (GTK_EDITABLE (self->name_entry)));
+ g_settings_set_string (cc_keyboard_item_get_settings (item),
+ "command",
+ gtk_editable_get_text (GTK_EDITABLE (self->command_entry)));
+ }
+}
+
+static void
+clear_custom_entries (CcKeyboardShortcutEditor *self)
+{
+ g_signal_handlers_block_by_func (self->command_entry, command_entry_changed_cb, self);
+ g_signal_handlers_block_by_func (self->name_entry, name_entry_changed_cb, self);
+
+ gtk_editable_set_text (GTK_EDITABLE (self->name_entry), "");
+ gtk_editable_set_text (GTK_EDITABLE (self->command_entry), "");
+
+ gtk_shortcut_label_set_accelerator (GTK_SHORTCUT_LABEL (self->custom_shortcut_accel_label), "");
+ gtk_label_set_label (self->new_shortcut_conflict_label, "");
+ gtk_label_set_label (self->shortcut_conflict_label, "");
+
+ memset (self->custom_combo, 0, sizeof (CcKeyCombo));
+ self->custom_is_modifier = TRUE;
+ self->edited = FALSE;
+
+ self->collision_item = NULL;
+
+ g_signal_handlers_unblock_by_func (self->command_entry, command_entry_changed_cb, self);
+ g_signal_handlers_unblock_by_func (self->name_entry, name_entry_changed_cb, self);
+}
+
+static void
+cancel_editing (CcKeyboardShortcutEditor *self)
+{
+ cc_keyboard_shortcut_editor_set_item (self, NULL);
+ clear_custom_entries (self);
+
+ gtk_widget_hide (GTK_WIDGET (self));
+}
+
+static gboolean
+is_custom_shortcut (CcKeyboardShortcutEditor *self) {
+ return self->item == NULL || cc_keyboard_item_get_item_type (self->item) == CC_KEYBOARD_ITEM_TYPE_GSETTINGS_PATH;
+}
+
+static void
+inhibit_system_shortcuts (CcKeyboardShortcutEditor *self)
+{
+ GtkNative *native;
+ GdkSurface *surface;
+
+ if (self->system_shortcuts_inhibited)
+ return;
+
+ native = gtk_widget_get_native (GTK_WIDGET (self));
+ surface = gtk_native_get_surface (native);
+
+ if (GDK_IS_TOPLEVEL (surface))
+ {
+ gdk_toplevel_inhibit_system_shortcuts (GDK_TOPLEVEL (surface), NULL);
+ self->system_shortcuts_inhibited = TRUE;
+ }
+}
+
+static void
+uninhibit_system_shortcuts (CcKeyboardShortcutEditor *self)
+{
+ GtkNative *native;
+ GdkSurface *surface;
+
+ if (!self->system_shortcuts_inhibited)
+ return;
+
+ native = gtk_widget_get_native (GTK_WIDGET (self));
+ surface = gtk_native_get_surface (native);
+
+ if (GDK_IS_TOPLEVEL (surface))
+ {
+ gdk_toplevel_restore_system_shortcuts (GDK_TOPLEVEL (surface));
+ self->system_shortcuts_inhibited = FALSE;
+ }
+}
+
+static void
+update_shortcut (CcKeyboardShortcutEditor *self)
+{
+ if (!self->item)
+ return;
+
+ /* Setup the binding */
+ apply_custom_item_fields (self, self->item);
+
+ /* Eventually disable the conflict shortcut */
+ if (self->collision_item)
+ cc_keyboard_item_disable (self->collision_item);
+
+ /* Cleanup whatever was set before */
+ clear_custom_entries (self);
+
+ cc_keyboard_shortcut_editor_set_item (self, NULL);
+}
+
+static GtkShortcutLabel*
+get_current_shortcut_label (CcKeyboardShortcutEditor *self)
+{
+ if (is_custom_shortcut (self))
+ return GTK_SHORTCUT_LABEL (self->custom_shortcut_accel_label);
+
+ return GTK_SHORTCUT_LABEL (self->shortcut_accel_label);
+}
+
+static void
+set_header_mode (CcKeyboardShortcutEditor *self,
+ HeaderMode mode)
+{
+ gtk_header_bar_set_show_title_buttons (self->headerbar, mode == HEADER_MODE_CUSTOM_EDIT);
+
+ gtk_widget_set_visible (GTK_WIDGET (self->add_button), mode == HEADER_MODE_ADD);
+ gtk_widget_set_visible (GTK_WIDGET (self->cancel_button), mode != HEADER_MODE_NONE &&
+ mode != HEADER_MODE_CUSTOM_EDIT);
+ gtk_widget_set_visible (GTK_WIDGET (self->replace_button), mode == HEADER_MODE_REPLACE);
+ gtk_widget_set_visible (GTK_WIDGET (self->set_button), mode == HEADER_MODE_SET);
+ gtk_widget_set_visible (GTK_WIDGET (self->remove_button), mode == HEADER_MODE_CUSTOM_EDIT);
+
+ /* By setting the default response, the action button gets the 'suggested-action' applied */
+ switch (mode)
+ {
+ case HEADER_MODE_SET:
+ gtk_dialog_set_default_response (GTK_DIALOG (self), GTK_RESPONSE_APPLY);
+ break;
+
+ case HEADER_MODE_REPLACE:
+ gtk_dialog_set_default_response (GTK_DIALOG (self), GTK_RESPONSE_ACCEPT);
+ break;
+
+ case HEADER_MODE_ADD:
+ gtk_dialog_set_default_response (GTK_DIALOG (self), GTK_RESPONSE_OK);
+ break;
+
+ default:
+ gtk_dialog_set_default_response (GTK_DIALOG (self), GTK_RESPONSE_NONE);
+ }
+}
+
+static void
+setup_custom_shortcut (CcKeyboardShortcutEditor *self)
+{
+ GtkShortcutLabel *shortcut_label;
+ CcKeyboardItem *collision_item;
+ HeaderMode mode;
+ gboolean is_custom, is_accel_empty;
+ gboolean valid, accel_valid;
+ g_autofree char *accel = NULL;
+
+ is_custom = is_custom_shortcut (self);
+ accel_valid = is_valid_binding (self->custom_combo) &&
+ is_valid_accel (self->custom_combo) &&
+ !self->custom_is_modifier;
+
+ is_accel_empty = is_empty_binding (self->custom_combo);
+
+ if (is_accel_empty)
+ accel_valid = TRUE;
+ valid = accel_valid;
+
+ /* Additional checks for custom shortcuts */
+ if (is_custom)
+ {
+ if (accel_valid)
+ {
+ set_shortcut_editor_page (self, PAGE_CUSTOM);
+
+ /* We have to check if the current accelerator is empty in order to
+ * decide if we show the "Set Shortcut" button or the accelerator label */
+ gtk_stack_set_visible_child (self->custom_shortcut_stack,
+ is_accel_empty ? GTK_WIDGET (self->change_custom_shortcut_button) : GTK_WIDGET (self->custom_shortcut_accel_label));
+ gtk_widget_set_visible (GTK_WIDGET (self->reset_custom_button), !is_accel_empty);
+ }
+
+ valid = accel_valid &&
+ gtk_entry_get_text_length (self->name_entry) > 0 &&
+ gtk_entry_get_text_length (self->command_entry) > 0;
+ }
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->replace_button), valid);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->add_button), valid);
+ if (valid)
+ set_header_mode (self, HEADER_MODE_ADD);
+ else
+ set_header_mode (self, is_custom ? HEADER_MODE_CUSTOM_CANCEL : HEADER_MODE_NONE);
+
+ /* Nothing else to do if the shortcut is invalid */
+ if (!accel_valid)
+ return;
+
+ /* Valid shortcut, show it in the standard page */
+ if (!is_custom)
+ set_shortcut_editor_page (self, PAGE_STANDARD);
+
+ shortcut_label = get_current_shortcut_label (self);
+
+ collision_item = cc_keyboard_manager_get_collision (self->manager,
+ self->item,
+ self->custom_combo);
+
+ accel = gtk_accelerator_name (self->custom_combo->keyval, self->custom_combo->mask);
+
+
+ /* Setup the accelerator label */
+ gtk_shortcut_label_set_accelerator (shortcut_label, accel);
+
+ self->edited = TRUE;
+
+ uninhibit_system_shortcuts (self);
+
+ /*
+ * Oops! Looks like the accelerator is already being used, so we
+ * must warn the user and let it be very clear that adding this
+ * shortcut will disable the other.
+ */
+ gtk_widget_set_visible (GTK_WIDGET (self->new_shortcut_conflict_label), collision_item != NULL);
+
+ if (collision_item)
+ {
+ GtkLabel *label;
+ g_autofree gchar *friendly_accelerator = NULL;
+ g_autofree gchar *accelerator_text = NULL;
+ g_autofree gchar *collision_text = NULL;
+
+ friendly_accelerator = convert_keysym_state_to_string (self->custom_combo);
+
+ accelerator_text = g_strdup_printf ("<b>%s</b>", friendly_accelerator);
+ collision_text = g_strdup_printf (_("%s is already being used for %s. If you "
+ "replace it, %s will be disabled"),
+ accelerator_text,
+ cc_keyboard_item_get_description (collision_item),
+ cc_keyboard_item_get_description (collision_item));
+
+ label = is_custom_shortcut (self) ? self->new_shortcut_conflict_label : self->shortcut_conflict_label;
+
+ gtk_label_set_markup (label, collision_text);
+ }
+
+ /*
+ * When there is a collision between the current shortcut and another shortcut,
+ * and we're editing an existing shortcut (rather than creating a new one), setup
+ * the headerbar to display "Cancel" and "Replace". Otherwise, make sure to set
+ * only the close button again.
+ */
+ if (collision_item)
+ {
+ mode = HEADER_MODE_REPLACE;
+ }
+ else
+ {
+ if (self->mode == CC_SHORTCUT_EDITOR_EDIT)
+ mode = is_custom ? HEADER_MODE_CUSTOM_EDIT : HEADER_MODE_SET;
+ else
+ mode = is_custom ? HEADER_MODE_ADD : HEADER_MODE_SET;
+ }
+
+ set_header_mode (self, mode);
+
+ self->collision_item = collision_item;
+}
+
+static void
+add_button_clicked_cb (CcKeyboardShortcutEditor *self)
+{
+ CcKeyboardItem *item;
+
+ item = cc_keyboard_manager_create_custom_shortcut (self->manager);
+
+ /* Apply the custom shortcut setup at the new item */
+ apply_custom_item_fields (self, item);
+
+ /* Eventually disable the conflict shortcut */
+ if (self->collision_item)
+ cc_keyboard_item_disable (self->collision_item);
+
+ /* Cleanup everything once we're done */
+ clear_custom_entries (self);
+
+ cc_keyboard_manager_add_custom_shortcut (self->manager, item);
+
+ gtk_widget_hide (GTK_WIDGET (self));
+}
+
+static void
+cancel_button_clicked_cb (GtkWidget *button,
+ CcKeyboardShortcutEditor *self)
+{
+ cancel_editing (self);
+}
+
+static void
+change_custom_shortcut_button_clicked_cb (CcKeyboardShortcutEditor *self)
+{
+ inhibit_system_shortcuts (self);
+ set_shortcut_editor_page (self, PAGE_EDIT);
+ set_header_mode (self, HEADER_MODE_NONE);
+}
+
+static void
+command_entry_changed_cb (CcKeyboardShortcutEditor *self)
+{
+ setup_custom_shortcut (self);
+}
+
+static void
+name_entry_changed_cb (CcKeyboardShortcutEditor *self)
+{
+ setup_custom_shortcut (self);
+}
+
+static void
+remove_button_clicked_cb (CcKeyboardShortcutEditor *self)
+{
+ gtk_widget_hide (GTK_WIDGET (self));
+
+ cc_keyboard_manager_remove_custom_shortcut (self->manager, self->item);
+}
+
+static void
+replace_button_clicked_cb (CcKeyboardShortcutEditor *self)
+{
+ if (self->mode == CC_SHORTCUT_EDITOR_CREATE)
+ add_button_clicked_cb (self);
+ else
+ set_button_clicked_cb (self);
+}
+
+static void
+reset_custom_clicked_cb (CcKeyboardShortcutEditor *self)
+{
+ if (self->item)
+ cc_keyboard_manager_reset_shortcut (self->manager, self->item);
+
+ gtk_stack_set_visible_child (self->custom_shortcut_stack, GTK_WIDGET (self->change_custom_shortcut_button));
+ gtk_widget_hide (GTK_WIDGET (self->reset_custom_button));
+}
+
+static void
+reset_item_clicked_cb (CcKeyboardShortcutEditor *self)
+{
+ CcKeyCombo combo;
+ gchar *accel;
+
+ /* Reset first, then update the shortcut */
+ cc_keyboard_manager_reset_shortcut (self->manager, self->item);
+
+ combo = cc_keyboard_item_get_primary_combo (self->item);
+ accel = gtk_accelerator_name (combo.keyval, combo.mask);
+ gtk_shortcut_label_set_accelerator (GTK_SHORTCUT_LABEL (self->shortcut_accel_label), accel);
+
+ g_free (accel);
+}
+
+static void
+set_button_clicked_cb (CcKeyboardShortcutEditor *self)
+{
+ update_shortcut (self);
+ gtk_widget_hide (GTK_WIDGET (self));
+}
+
+static void
+setup_keyboard_item (CcKeyboardShortcutEditor *self,
+ CcKeyboardItem *item)
+{
+ CcKeyCombo combo;
+ gboolean is_custom;
+ g_autofree gchar *accel = NULL;
+ g_autofree gchar *description_text = NULL;
+ g_autofree gchar *text = NULL;
+
+ if (!item) {
+ gtk_label_set_text (self->top_info_label, _("Enter the new shortcut"));
+ return;
+ }
+
+ combo = cc_keyboard_item_get_primary_combo (item);
+ is_custom = cc_keyboard_item_get_item_type (item) == CC_KEYBOARD_ITEM_TYPE_GSETTINGS_PATH;
+ accel = gtk_accelerator_name (combo.keyval, combo.mask);
+
+ /* To avoid accidentally thinking we unset the current keybinding, set the values
+ * of the keyboard item that is being edited */
+ self->custom_is_modifier = FALSE;
+ *self->custom_combo = combo;
+
+ /* Headerbar */
+ gtk_window_set_title (GTK_WINDOW (self),
+ is_custom ? _("Set Custom Shortcut") : _("Set Shortcut"));
+
+ set_header_mode (self, is_custom ? HEADER_MODE_CUSTOM_EDIT : HEADER_MODE_NONE);
+
+ gtk_widget_hide (GTK_WIDGET (self->add_button));
+ gtk_widget_hide (GTK_WIDGET (self->cancel_button));
+ gtk_widget_hide (GTK_WIDGET (self->replace_button));
+
+ /* Setup the top label */
+ description_text = g_strdup_printf ("<b>%s</b>", cc_keyboard_item_get_description (item));
+ /* TRANSLATORS: %s is replaced with a description of the keyboard shortcut */
+ text = g_strdup_printf (_("Enter new shortcut to change %s."), description_text);
+
+ gtk_label_set_markup (self->top_info_label, text);
+
+ /* Accelerator labels */
+ gtk_shortcut_label_set_accelerator (self->shortcut_accel_label, accel);
+ gtk_shortcut_label_set_accelerator (self->custom_shortcut_accel_label, accel);
+
+ g_clear_pointer (&self->reset_item_binding, g_binding_unbind);
+ self->reset_item_binding = g_object_bind_property (item,
+ "is-value-default",
+ self->reset_button,
+ "visible",
+ G_BINDING_DEFAULT | G_BINDING_INVERT_BOOLEAN | G_BINDING_SYNC_CREATE);
+
+ /* Setup the custom entries */
+ if (is_custom)
+ {
+ gboolean is_accel_empty;
+
+ g_signal_handlers_block_by_func (self->command_entry, command_entry_changed_cb, self);
+ g_signal_handlers_block_by_func (self->name_entry, name_entry_changed_cb, self);
+
+ /* Name entry */
+ gtk_editable_set_text (GTK_EDITABLE (self->name_entry), cc_keyboard_item_get_description (item));
+ gtk_widget_set_sensitive (GTK_WIDGET (self->name_entry), cc_keyboard_item_get_desc_editable (item));
+
+ /* Command entry */
+ gtk_editable_set_text (GTK_EDITABLE (self->command_entry), cc_keyboard_item_get_command (item));
+ gtk_widget_set_sensitive (GTK_WIDGET (self->command_entry), cc_keyboard_item_get_cmd_editable (item));
+
+ /* If there is no accelerator set for this custom shortcut, show the "Set Shortcut" button. */
+ is_accel_empty = !accel || accel[0] == '\0';
+
+ gtk_stack_set_visible_child (self->custom_shortcut_stack,
+ is_accel_empty ? GTK_WIDGET (self->change_custom_shortcut_button) : GTK_WIDGET (self->custom_shortcut_accel_label));
+
+ gtk_widget_set_visible (GTK_WIDGET (self->reset_custom_button), !is_accel_empty);
+
+ g_signal_handlers_unblock_by_func (self->command_entry, command_entry_changed_cb, self);
+ g_signal_handlers_unblock_by_func (self->name_entry, name_entry_changed_cb, self);
+
+ uninhibit_system_shortcuts (self);
+ }
+
+ /* Show the appropriate view */
+ set_shortcut_editor_page (self, is_custom ? PAGE_CUSTOM : PAGE_EDIT);
+}
+
+static void
+cc_keyboard_shortcut_editor_finalize (GObject *object)
+{
+ CcKeyboardShortcutEditor *self = (CcKeyboardShortcutEditor *)object;
+
+ g_clear_object (&self->item);
+ g_clear_object (&self->manager);
+
+ g_clear_pointer (&self->custom_combo, g_free);
+
+ G_OBJECT_CLASS (cc_keyboard_shortcut_editor_parent_class)->finalize (object);
+}
+
+static void
+cc_keyboard_shortcut_editor_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcKeyboardShortcutEditor *self = CC_KEYBOARD_SHORTCUT_EDITOR (object);
+
+ switch (prop_id)
+ {
+ case PROP_KEYBOARD_ITEM:
+ g_value_set_object (value, self->item);
+ break;
+
+ case PROP_MANAGER:
+ g_value_set_object (value, self->manager);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_keyboard_shortcut_editor_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcKeyboardShortcutEditor *self = CC_KEYBOARD_SHORTCUT_EDITOR (object);
+
+ switch (prop_id)
+ {
+ case PROP_KEYBOARD_ITEM:
+ cc_keyboard_shortcut_editor_set_item (self, g_value_get_object (value));
+ break;
+
+ case PROP_MANAGER:
+ g_set_object (&self->manager, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static gboolean
+on_key_pressed_cb (GtkEventControllerKey *key_controller,
+ guint keyval,
+ guint keycode,
+ GdkModifierType state,
+ CcKeyboardShortcutEditor *self)
+{
+ GdkModifierType real_mask;
+ GdkEvent *event;
+ gboolean editing;
+ gboolean is_modifier;
+ guint keyval_lower;
+
+ /* Being in the "change-shortcut" page is the only check we must
+ * perform to decide if we're editing a shortcut. */
+ editing = get_shortcut_editor_page (self) == PAGE_EDIT;
+
+ if (!editing)
+ return GDK_EVENT_PROPAGATE;
+
+ normalize_keyval_and_mask (keycode, state,
+ gtk_event_controller_key_get_group (key_controller),
+ &keyval_lower, &real_mask);
+
+ event = gtk_event_controller_get_current_event (GTK_EVENT_CONTROLLER (key_controller));
+ is_modifier = gdk_key_event_is_modifier (event);
+
+ /* A single Escape press cancels the editing */
+ if (!is_modifier && real_mask == 0 && keyval_lower == GDK_KEY_Escape)
+ {
+ self->edited = FALSE;
+
+ uninhibit_system_shortcuts (self);
+ cancel_editing (self);
+
+ return GDK_EVENT_STOP;
+ }
+
+ /* Backspace disables the current shortcut */
+ if (!is_modifier && real_mask == 0 && keyval_lower == GDK_KEY_BackSpace)
+ {
+ self->edited = TRUE;
+ self->custom_is_modifier = FALSE;
+ memset (self->custom_combo, 0, sizeof (CcKeyCombo));
+
+ gtk_shortcut_label_set_accelerator (GTK_SHORTCUT_LABEL (self->custom_shortcut_accel_label), "");
+ gtk_shortcut_label_set_accelerator (GTK_SHORTCUT_LABEL (self->shortcut_accel_label), "");
+
+ uninhibit_system_shortcuts (self);
+
+ self->edited = FALSE;
+
+ setup_custom_shortcut (self);
+
+ return GDK_EVENT_STOP;
+ }
+
+ self->custom_is_modifier = is_modifier;
+ self->custom_combo->keycode = keycode;
+ self->custom_combo->keyval = keyval_lower;
+ self->custom_combo->mask = real_mask;
+
+ /* CapsLock isn't supported as a keybinding modifier, so keep it from confusing us */
+ self->custom_combo->mask &= ~GDK_LOCK_MASK;
+
+ setup_custom_shortcut (self);
+
+ return GDK_EVENT_STOP;
+}
+
+static void
+cc_keyboard_shortcut_editor_close (GtkDialog *dialog)
+{
+ CcKeyboardShortcutEditor *self = CC_KEYBOARD_SHORTCUT_EDITOR (dialog);
+
+ if (self->mode == CC_SHORTCUT_EDITOR_EDIT)
+ update_shortcut (self);
+
+ GTK_DIALOG_CLASS (cc_keyboard_shortcut_editor_parent_class)->close (dialog);
+}
+
+static void
+cc_keyboard_shortcut_editor_response (GtkDialog *dialog,
+ gint response_id)
+{
+ CcKeyboardShortcutEditor *self = CC_KEYBOARD_SHORTCUT_EDITOR (dialog);
+
+ if (response_id == GTK_RESPONSE_DELETE_EVENT &&
+ self->mode == CC_SHORTCUT_EDITOR_EDIT)
+ {
+ update_shortcut (self);
+ }
+}
+
+static gboolean
+grab_idle (gpointer data)
+{
+ CcKeyboardShortcutEditor *self = data;
+
+ if (self->item && cc_keyboard_item_get_item_type (self->item) != CC_KEYBOARD_ITEM_TYPE_GSETTINGS_PATH)
+ inhibit_system_shortcuts (self);
+
+ self->grab_idle_id = 0;
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+cc_keyboard_shortcut_editor_show (GtkWidget *widget)
+{
+ CcKeyboardShortcutEditor *self = CC_KEYBOARD_SHORTCUT_EDITOR (widget);
+
+ /* Map before grabbing, so that the window is visible */
+ GTK_WIDGET_CLASS (cc_keyboard_shortcut_editor_parent_class)->show (widget);
+
+ self->grab_idle_id = g_timeout_add (100, grab_idle, self);
+}
+
+static void
+cc_keyboard_shortcut_editor_unrealize (GtkWidget *widget)
+{
+ CcKeyboardShortcutEditor *self = CC_KEYBOARD_SHORTCUT_EDITOR (widget);
+
+ if (self->grab_idle_id) {
+ g_source_remove (self->grab_idle_id);
+ self->grab_idle_id = 0;
+ }
+
+ uninhibit_system_shortcuts (self);
+
+ GTK_WIDGET_CLASS (cc_keyboard_shortcut_editor_parent_class)->unrealize (widget);
+}
+
+static void
+cc_keyboard_shortcut_editor_class_init (CcKeyboardShortcutEditorClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GtkDialogClass *dialog_class = GTK_DIALOG_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = cc_keyboard_shortcut_editor_finalize;
+ object_class->get_property = cc_keyboard_shortcut_editor_get_property;
+ object_class->set_property = cc_keyboard_shortcut_editor_set_property;
+
+ widget_class->show = cc_keyboard_shortcut_editor_show;
+ widget_class->unrealize = cc_keyboard_shortcut_editor_unrealize;
+
+ dialog_class->close = cc_keyboard_shortcut_editor_close;
+ dialog_class->response = cc_keyboard_shortcut_editor_response;
+
+ /**
+ * CcKeyboardShortcutEditor:keyboard-item:
+ *
+ * The current keyboard shortcut being edited.
+ */
+ properties[PROP_KEYBOARD_ITEM] = g_param_spec_object ("keyboard-item",
+ "Keyboard item",
+ "The keyboard item being edited",
+ CC_TYPE_KEYBOARD_ITEM,
+ G_PARAM_READWRITE);
+
+ /**
+ * CcKeyboardShortcutEditor:panel:
+ *
+ * The current keyboard panel.
+ */
+ properties[PROP_MANAGER] = g_param_spec_object ("manager",
+ "Keyboard manager",
+ "The keyboard manager",
+ CC_TYPE_KEYBOARD_MANAGER,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/keyboard/cc-keyboard-shortcut-editor.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, add_button);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, cancel_button);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, change_custom_shortcut_button);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, command_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, custom_grid);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, custom_shortcut_accel_label);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, custom_shortcut_stack);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, edit_box);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, headerbar);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, name_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, new_shortcut_conflict_label);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, remove_button);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, replace_button);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, reset_button);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, reset_custom_button);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, set_button);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, shortcut_accel_label);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, shortcut_conflict_label);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, standard_box);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, stack);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, top_info_label);
+
+ gtk_widget_class_bind_template_callback (widget_class, add_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, cancel_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, change_custom_shortcut_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, command_entry_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, name_entry_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_key_pressed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, remove_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, replace_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, reset_custom_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, reset_item_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, set_button_clicked_cb);
+}
+
+static void
+cc_keyboard_shortcut_editor_init (CcKeyboardShortcutEditor *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->mode = CC_SHORTCUT_EDITOR_EDIT;
+ self->custom_is_modifier = TRUE;
+ self->custom_combo = g_new0 (CcKeyCombo, 1);
+
+ gtk_widget_set_direction (GTK_WIDGET (self->custom_shortcut_accel_label), GTK_TEXT_DIR_LTR);
+ gtk_widget_set_direction (GTK_WIDGET (self->shortcut_accel_label), GTK_TEXT_DIR_LTR);
+}
+
+/**
+ * cc_keyboard_shortcut_editor_new:
+ *
+ * Creates a new #CcKeyboardShortcutEditor.
+ *
+ * Returns: (transfer full): a newly created #CcKeyboardShortcutEditor.
+ */
+GtkWidget*
+cc_keyboard_shortcut_editor_new (CcKeyboardManager *manager)
+{
+ return g_object_new (CC_TYPE_KEYBOARD_SHORTCUT_EDITOR,
+ "manager", manager,
+ "use-header-bar", 1,
+ NULL);
+}
+
+/**
+ * cc_keyboard_shortcut_editor_get_item:
+ * @self: a #CcKeyboardShortcutEditor
+ *
+ * Retrieves the current keyboard shortcut being edited.
+ *
+ * Returns: (transfer none)(nullable): a #CcKeyboardItem
+ */
+CcKeyboardItem*
+cc_keyboard_shortcut_editor_get_item (CcKeyboardShortcutEditor *self)
+{
+ g_return_val_if_fail (CC_IS_KEYBOARD_SHORTCUT_EDITOR (self), NULL);
+
+ return self->item;
+}
+
+/**
+ * cc_keyboard_shortcut_editor_set_item:
+ * @self: a #CcKeyboardShortcutEditor
+ * @item: a #CcKeyboardItem
+ *
+ * Sets the current keyboard shortcut to be edited.
+ */
+void
+cc_keyboard_shortcut_editor_set_item (CcKeyboardShortcutEditor *self,
+ CcKeyboardItem *item)
+{
+ g_return_if_fail (CC_IS_KEYBOARD_SHORTCUT_EDITOR (self));
+
+ setup_keyboard_item (self, item);
+
+ if (!g_set_object (&self->item, item))
+ return;
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_KEYBOARD_ITEM]);
+}
+
+CcShortcutEditorMode
+cc_keyboard_shortcut_editor_get_mode (CcKeyboardShortcutEditor *self)
+{
+ g_return_val_if_fail (CC_IS_KEYBOARD_SHORTCUT_EDITOR (self), 0);
+
+ return self->mode;
+}
+
+void
+cc_keyboard_shortcut_editor_set_mode (CcKeyboardShortcutEditor *self,
+ CcShortcutEditorMode mode)
+{
+ gboolean is_create_mode;
+
+ g_return_if_fail (CC_IS_KEYBOARD_SHORTCUT_EDITOR (self));
+
+ self->mode = mode;
+ is_create_mode = mode == CC_SHORTCUT_EDITOR_CREATE;
+
+ gtk_widget_set_visible (GTK_WIDGET (self->new_shortcut_conflict_label), is_create_mode);
+ gtk_stack_set_visible_child (self->custom_shortcut_stack,
+ is_create_mode ? GTK_WIDGET (self->change_custom_shortcut_button) : GTK_WIDGET (self->custom_shortcut_accel_label));
+
+ if (mode == CC_SHORTCUT_EDITOR_CREATE)
+ {
+ /* Cleanup whatever was set before */
+ clear_custom_entries (self);
+
+ set_header_mode (self, HEADER_MODE_ADD);
+ set_shortcut_editor_page (self, PAGE_CUSTOM);
+ gtk_window_set_title (GTK_WINDOW (self), _("Add Custom Shortcut"));
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->command_entry), TRUE);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->name_entry), TRUE);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->add_button), FALSE);
+
+ gtk_widget_hide (GTK_WIDGET (self->reset_custom_button));
+ }
+}
diff --git a/panels/keyboard/cc-keyboard-shortcut-editor.h b/panels/keyboard/cc-keyboard-shortcut-editor.h
new file mode 100644
index 0000000..963309f
--- /dev/null
+++ b/panels/keyboard/cc-keyboard-shortcut-editor.h
@@ -0,0 +1,52 @@
+/* cc-keyboard-shortcut-editor.h
+ *
+ * Copyright (C) 2016 Endless, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "cc-keyboard-item.h"
+#include "cc-keyboard-manager.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_KEYBOARD_SHORTCUT_EDITOR (cc_keyboard_shortcut_editor_get_type ())
+G_DECLARE_FINAL_TYPE (CcKeyboardShortcutEditor, cc_keyboard_shortcut_editor, CC, KEYBOARD_SHORTCUT_EDITOR, GtkDialog)
+
+typedef enum
+{
+ CC_SHORTCUT_EDITOR_CREATE,
+ CC_SHORTCUT_EDITOR_EDIT
+} CcShortcutEditorMode;
+
+GtkWidget* cc_keyboard_shortcut_editor_new (CcKeyboardManager *manager);
+
+CcKeyboardItem* cc_keyboard_shortcut_editor_get_item (CcKeyboardShortcutEditor *self);
+
+void cc_keyboard_shortcut_editor_set_item (CcKeyboardShortcutEditor *self,
+ CcKeyboardItem *item);
+
+CcShortcutEditorMode cc_keyboard_shortcut_editor_get_mode (CcKeyboardShortcutEditor *self);
+
+void cc_keyboard_shortcut_editor_set_mode (CcKeyboardShortcutEditor *self,
+ CcShortcutEditorMode mode);
+
+G_END_DECLS
+
diff --git a/panels/keyboard/cc-keyboard-shortcut-editor.ui b/panels/keyboard/cc-keyboard-shortcut-editor.ui
new file mode 100644
index 0000000..45a9ac9
--- /dev/null
+++ b/panels/keyboard/cc-keyboard-shortcut-editor.ui
@@ -0,0 +1,288 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.20"/>
+ <template class="CcKeyboardShortcutEditor" parent="GtkDialog">
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="width_request">400</property>
+ <property name="height_request">300</property>
+ <property name="hide-on-close">True</property>
+ <signal name="close" handler="cancel_button_clicked_cb" object="CcKeyboardShortcutEditor" swapped="no" />
+ <child>
+ <object class="GtkEventControllerKey">
+ <property name="propagation-phase">capture</property>
+ <signal name="key-pressed" handler="on_key_pressed_cb" object="CcKeyboardShortcutEditor" swapped="no" />
+ </object>
+ </child>
+
+ <child type="titlebar">
+ <object class="GtkHeaderBar" id="headerbar">
+ <property name="show_title_buttons">True</property>
+ <child>
+ <object class="GtkButton" id="cancel_button">
+ <property name="label" translatable="yes">_Cancel</property>
+ <property name="use-underline">True</property>
+ <signal name="clicked" handler="cancel_button_clicked_cb" object="CcKeyboardShortcutEditor" swapped="no" />
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="remove_button">
+ <property name="label" translatable="yes">_Remove</property>
+ <property name="use-underline">True</property>
+ <property name="valign">end</property>
+ <signal name="clicked" handler="remove_button_clicked_cb" object="CcKeyboardShortcutEditor" swapped="yes" />
+ <style>
+ <class name="destructive-action" />
+ </style>
+ </object>
+ </child>
+ <child type="end">
+ <object class="GtkButton" id="add_button">
+ <property name="label" translatable="yes">_Add</property>
+ <property name="use-underline">True</property>
+ <property name="sensitive">False</property>
+ <signal name="clicked" handler="add_button_clicked_cb" object="CcKeyboardShortcutEditor" swapped="yes" />
+ </object>
+ </child>
+ <child type="end">
+ <object class="GtkButton" id="replace_button">
+ <property name="label" translatable="yes">Re_place</property>
+ <property name="use-underline">True</property>
+ <signal name="clicked" handler="replace_button_clicked_cb" object="CcKeyboardShortcutEditor" swapped="yes" />
+ </object>
+ </child>
+ <child type="end">
+ <object class="GtkButton" id="set_button">
+ <property name="label" translatable="yes">_Set</property>
+ <property name="use-underline">True</property>
+ <signal name="clicked" handler="set_button_clicked_cb" object="CcKeyboardShortcutEditor" swapped="yes" />
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">18</property>
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <child>
+ <object class="GtkLabel" id="top_info_label">
+ <property name="wrap">True</property>
+ <property name="wrap_mode">word-char</property>
+ <property name="width_chars">15</property>
+ <property name="max_width_chars">20</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <child>
+ <object class="GtkBox" id="edit_box">
+ <property name="orientation">vertical</property>
+ <property name="spacing">18</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <child>
+ <object class="GtkPicture">
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="can-shrink">False</property>
+ <property name="file">resource:///org/gnome/control-center/keyboard/enter-keyboard-shortcut.svg</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="wrap">True</property>
+ <property name="label" translatable="yes">Press Esc to cancel or Backspace to disable the keyboard shortcut.</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="standard_box">
+ <property name="hexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">18</property>
+ <child>
+ <object class="GtkCenterBox">
+ <child type="center">
+ <object class="GtkShortcutLabel" id="shortcut_accel_label">
+ <property name="margin-start">18</property>
+ <property name="margin-end">18</property>
+ <property name="halign">center</property>
+ <property name="disabled-text" translatable="yes">Disabled</property>
+ </object>
+ </child>
+ <child type="end">
+ <object class="GtkButton" id="reset_button">
+ <property name="icon-name">edit-clear-symbolic</property>
+ <property name="halign">end</property>
+ <accessibility>
+ <property name="label" translatable="yes">Reset</property>
+ </accessibility>
+ <signal name="clicked" handler="reset_item_clicked_cb" object="CcKeyboardShortcutEditor" swapped="yes" />
+ <style>
+ <class name="flat" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="shortcut_conflict_label">
+ <property name="hexpand">True</property>
+ <property name="wrap">True</property>
+ <property name="wrap_mode">word-char</property>
+ <property name="width_chars">15</property>
+ <property name="max_width_chars">20</property>
+ <property name="xalign">0</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkGrid" id="custom_grid">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">12</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Name</property>
+ <property name="xalign">1</property>
+ <property name="mnemonic_widget">name_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Command</property>
+ <property name="xalign">1</property>
+ <property name="mnemonic_widget">command_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Shortcut</property>
+ <property name="xalign">1</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="new_shortcut_conflict_label">
+ <property name="hexpand">True</property>
+ <property name="wrap">True</property>
+ <property name="wrap_mode">word-char</property>
+ <property name="width_chars">15</property>
+ <property name="max_width_chars">20</property>
+ <property name="xalign">0</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ <property name="column-span">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="name_entry">
+ <property name="hexpand">True</property>
+ <signal name="notify::text" handler="name_entry_changed_cb" object="CcKeyboardShortcutEditor" swapped="yes" />
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ <property name="column-span">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="command_entry">
+ <property name="hexpand">True</property>
+ <signal name="notify::text" handler="command_entry_changed_cb" object="CcKeyboardShortcutEditor" swapped="yes" />
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ <property name="column-span">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="reset_custom_button">
+ <property name="halign">end</property>
+ <property name="icon-name">edit-clear-symbolic</property>
+ <signal name="clicked" handler="reset_custom_clicked_cb" object="CcKeyboardShortcutEditor" swapped="yes" />
+ <accessibility>
+ <property name="label" translatable="yes">Reset</property>
+ </accessibility>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">2</property>
+ </layout>
+ <style>
+ <class name="flat" />
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStack" id="custom_shortcut_stack">
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ <child>
+ <object class="GtkButton" id="change_custom_shortcut_button">
+ <property name="label" translatable="yes">Set Shortcut…</property>
+ <signal name="clicked" handler="change_custom_shortcut_button_clicked_cb" object="CcKeyboardShortcutEditor" swapped="yes" />
+ </object>
+ </child>
+ <child>
+ <object class="GtkShortcutLabel" id="custom_shortcut_accel_label">
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <property name="disabled-text" translatable="yes">None</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <action-widgets>
+ <action-widget response="cancel">cancel_button</action-widget>
+ <action-widget response="accept">replace_button</action-widget>
+ <action-widget response="apply">set_button</action-widget>
+ <action-widget response="ok" default="true">add_button</action-widget>
+ </action-widgets>
+ </template>
+ <object class="GtkSizeGroup">
+ <widgets>
+ <widget name="cancel_button"/>
+ <widget name="add_button"/>
+ <widget name="replace_button"/>
+ <widget name="reset_button"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/panels/keyboard/cc-keyboard-shortcut-row.c b/panels/keyboard/cc-keyboard-shortcut-row.c
new file mode 100644
index 0000000..8abb042
--- /dev/null
+++ b/panels/keyboard/cc-keyboard-shortcut-row.c
@@ -0,0 +1,139 @@
+/* cc-keyboard-shortcut-row.c
+ *
+ * Copyright (C) 2020 System76, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <glib/gi18n.h>
+#include "cc-keyboard-shortcut-row.h"
+#include "keyboard-shortcuts.h"
+
+struct _CcKeyboardShortcutRow
+{
+ AdwActionRow parent_instance;
+
+ GtkLabel *accelerator_label;
+ GtkButton *reset_button;
+ GtkRevealer *reset_revealer;
+
+ CcKeyboardItem *item;
+ CcKeyboardManager *manager;
+ CcKeyboardShortcutEditor *shortcut_editor;
+};
+
+G_DEFINE_TYPE (CcKeyboardShortcutRow, cc_keyboard_shortcut_row, ADW_TYPE_ACTION_ROW)
+
+static void
+reset_shortcut_cb (CcKeyboardShortcutRow *self)
+{
+ cc_keyboard_manager_reset_shortcut (self->manager, self->item);
+}
+
+static void
+cc_keyboard_shortcut_row_class_init (CcKeyboardShortcutRowClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/keyboard/cc-keyboard-shortcut-row.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutRow, accelerator_label);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutRow, reset_button);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutRow, reset_revealer);
+
+ gtk_widget_class_bind_template_callback (widget_class, reset_shortcut_cb);
+}
+
+static void
+cc_keyboard_shortcut_row_init (CcKeyboardShortcutRow *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+shortcut_modified_changed_cb (CcKeyboardShortcutRow *self)
+{
+ gtk_revealer_set_reveal_child (self->reset_revealer,
+ !cc_keyboard_item_is_value_default (self->item));
+}
+
+static gboolean
+transform_binding_to_accel (GBinding *binding,
+ const GValue *from_value,
+ GValue *to_value,
+ gpointer user_data)
+{
+ g_autoptr(CcKeyboardItem) item = NULL;
+ CcKeyCombo combo;
+ gchar *accelerator;
+
+ item = CC_KEYBOARD_ITEM (g_binding_dup_source (binding));
+ combo = cc_keyboard_item_get_primary_combo (item);
+
+ /* Embolden the label when the shortcut is modified */
+ if (!cc_keyboard_item_is_value_default (item))
+ {
+ g_autofree gchar *tmp = NULL;
+
+ tmp = convert_keysym_state_to_string (&combo);
+
+ accelerator = g_strdup_printf ("<b>%s</b>", tmp);
+ }
+ else
+ {
+ accelerator = convert_keysym_state_to_string (&combo);
+ }
+
+ g_value_take_string (to_value, accelerator);
+
+ return TRUE;
+}
+
+CcKeyboardShortcutRow *
+cc_keyboard_shortcut_row_new (CcKeyboardItem *item,
+ CcKeyboardManager *manager,
+ CcKeyboardShortcutEditor *shortcut_editor,
+ GtkSizeGroup *size_group)
+{
+ CcKeyboardShortcutRow *self;
+
+ self = g_object_new (CC_TYPE_KEYBOARD_SHORTCUT_ROW, NULL);
+ self->item = item;
+ self->manager = manager;
+ self->shortcut_editor = shortcut_editor;
+
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self), cc_keyboard_item_get_description (item));
+
+ g_object_bind_property_full (item,
+ "key-combos",
+ self->accelerator_label,
+ "label",
+ G_BINDING_SYNC_CREATE,
+ transform_binding_to_accel,
+ NULL, NULL, NULL);
+
+ gtk_revealer_set_reveal_child (self->reset_revealer,
+ !cc_keyboard_item_is_value_default (item));
+ g_signal_connect_object (item,
+ "notify::key-combos",
+ G_CALLBACK (shortcut_modified_changed_cb),
+ self, G_CONNECT_SWAPPED);
+
+ gtk_size_group_add_widget(size_group,
+ GTK_WIDGET (self->accelerator_label));
+
+ return self;
+}
diff --git a/panels/keyboard/cc-keyboard-shortcut-row.h b/panels/keyboard/cc-keyboard-shortcut-row.h
new file mode 100644
index 0000000..14b68ef
--- /dev/null
+++ b/panels/keyboard/cc-keyboard-shortcut-row.h
@@ -0,0 +1,38 @@
+/* cc-keyboard-shortcut-row.h
+ *
+ * Copyright (C) 2020 System76, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#pragma once
+
+#include <adwaita.h>
+#include "cc-keyboard-item.h"
+#include "cc-keyboard-manager.h"
+#include "cc-keyboard-shortcut-editor.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_KEYBOARD_SHORTCUT_ROW (cc_keyboard_shortcut_row_get_type())
+G_DECLARE_FINAL_TYPE (CcKeyboardShortcutRow, cc_keyboard_shortcut_row, CC, KEYBOARD_SHORTCUT_ROW, AdwActionRow)
+
+CcKeyboardShortcutRow *cc_keyboard_shortcut_row_new (CcKeyboardItem *item,
+ CcKeyboardManager *manager,
+ CcKeyboardShortcutEditor *editor,
+ GtkSizeGroup *size_group);
+
+G_END_DECLS
diff --git a/panels/keyboard/cc-keyboard-shortcut-row.ui b/panels/keyboard/cc-keyboard-shortcut-row.ui
new file mode 100644
index 0000000..98a8a31
--- /dev/null
+++ b/panels/keyboard/cc-keyboard-shortcut-row.ui
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcKeyboardShortcutRow" parent="AdwActionRow">
+ <property name="selectable">False</property>
+ <property name="activatable">True</property>
+ <child>
+ <object class="GtkLabel" id="accelerator_label">
+ <property name="xalign">1.0</property>
+ <property name="use-markup">True</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkRevealer" id = "reset_revealer">
+ <property name="transition-type">slide-right</property>
+ <child>
+ <object class="GtkButton" id="reset_button">
+ <property name="valign">center</property>
+ <property name="icon-name">edit-clear-symbolic</property>
+ <property name="tooltip-text" translatable="yes">Reset the shortcut to its default value</property>
+ <accessibility>
+ <property name="label" translatable="yes">Reset</property>
+ </accessibility>
+ <signal name="clicked" handler="reset_shortcut_cb" swapped="true"/>
+ <style>
+ <class name="flat" />
+ <class name="circular" />
+ <class name="reset-shortcut-button" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/keyboard/cc-xkb-modifier-dialog.c b/panels/keyboard/cc-xkb-modifier-dialog.c
new file mode 100644
index 0000000..da8116e
--- /dev/null
+++ b/panels/keyboard/cc-xkb-modifier-dialog.c
@@ -0,0 +1,355 @@
+/* cc-xkb-modifier-dialog.c
+ *
+ * Copyright 2019 Bastien Nocera <hadess@hadess.net>
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <glib/gi18n.h>
+#include <adwaita.h>
+
+#include "cc-xkb-modifier-dialog.h"
+
+struct _CcXkbModifierDialog
+{
+ GtkDialog parent_instance;
+
+ GtkLabel *description_label;
+ GtkSwitch *enabled_switch;
+ GtkListBox *listbox;
+ GtkListBox *switch_listbox;
+ AdwActionRow *switch_row;
+
+ GSettings *input_source_settings;
+ const CcXkbModifier *modifier;
+ GSList *radio_group;
+};
+
+G_DEFINE_TYPE (CcXkbModifierDialog, cc_xkb_modifier_dialog, GTK_TYPE_DIALOG)
+
+static const gchar *custom_css =
+".xkb-option-button {"
+" padding: 12px;"
+"}";
+
+static const CcXkbOption*
+get_xkb_option_from_name (const CcXkbModifier *modifier, const gchar* name)
+{
+ const CcXkbOption *options = modifier->options;
+ int i;
+
+ for (i = 0; options[i].label && options[i].xkb_option; i++)
+ {
+ if (g_str_equal (name, options[i].xkb_option))
+ return &options[i];
+ }
+
+ return NULL;
+}
+
+static GtkCheckButton *
+get_radio_button_from_xkb_option_name (CcXkbModifierDialog *self,
+ const gchar *name)
+{
+ gchar *xkb_option;
+ GSList *l;
+
+ for (l = self->radio_group; l != NULL; l = l->next)
+ {
+ xkb_option = g_object_get_data (l->data, "xkb-option");
+ if (g_strcmp0 (xkb_option, name) == 0)
+ return l->data;
+ }
+
+ return NULL;
+}
+
+static void
+update_active_radio (CcXkbModifierDialog *self)
+{
+ g_auto(GStrv) options = NULL;
+ GtkCheckButton *rightalt_radio;
+ const CcXkbOption *default_option;
+ guint i;
+
+ options = g_settings_get_strv (self->input_source_settings, "xkb-options");
+
+ for (i = 0; options != NULL && options[i] != NULL; i++)
+ {
+ GtkCheckButton *radio;
+
+ if (!g_str_has_prefix (options[i], self->modifier->prefix))
+ continue;
+
+ radio = get_radio_button_from_xkb_option_name (self, options[i]);
+
+ if (!radio)
+ continue;
+
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (radio), TRUE);
+ gtk_switch_set_active (self->enabled_switch, TRUE);
+ return;
+ }
+
+ if (self->modifier->default_option != NULL)
+ {
+ default_option = get_xkb_option_from_name(self->modifier, self->modifier->default_option);
+ rightalt_radio = get_radio_button_from_xkb_option_name (self, default_option->xkb_option);
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (rightalt_radio), TRUE);
+ gtk_switch_set_active (self->enabled_switch, TRUE);
+ }
+ else
+ {
+ gtk_switch_set_active (self->enabled_switch, FALSE);
+ }
+}
+
+static void
+set_xkb_option (CcXkbModifierDialog *self,
+ gchar *xkb_option)
+{
+ g_autoptr(GPtrArray) array = NULL;
+ g_auto(GStrv) options = NULL;
+ gboolean found;
+ guint i;
+
+ /* Either replace the existing "<modifier>:" option in the string
+ * array, or add the option at the end
+ */
+ array = g_ptr_array_new ();
+ options = g_settings_get_strv (self->input_source_settings, "xkb-options");
+ found = FALSE;
+
+ for (i = 0; options != NULL && options[i] != NULL; i++)
+ {
+ if (g_str_has_prefix (options[i], self->modifier->prefix))
+ {
+ if (!found && xkb_option != NULL)
+ g_ptr_array_add (array, xkb_option);
+ found = TRUE;
+ }
+ else
+ {
+ g_ptr_array_add (array, options[i]);
+ }
+ }
+
+ if (!found && xkb_option != NULL)
+ g_ptr_array_add (array, xkb_option);
+
+ g_ptr_array_add (array, NULL);
+
+ g_settings_set_strv (self->input_source_settings,
+ "xkb-options",
+ (const gchar * const *) array->pdata);
+}
+
+static void
+on_active_radio_changed_cb (CcXkbModifierDialog *self,
+ GtkCheckButton *radio)
+{
+ gchar *xkb_option;
+
+ if (!gtk_check_button_get_active (GTK_CHECK_BUTTON (radio)))
+ return;
+
+ if (!gtk_switch_get_state (self->enabled_switch))
+ return;
+
+ xkb_option = (gchar *)g_object_get_data (G_OBJECT (radio), "xkb-option");
+ set_xkb_option (self, xkb_option);
+}
+
+static void
+on_xkb_options_changed_cb (CcXkbModifierDialog *self)
+{
+ if (self->modifier == NULL)
+ update_active_radio (self);
+}
+
+static gboolean
+enable_switch_changed_cb (GtkSwitch *widget,
+ gboolean state,
+ gpointer user_data)
+{
+ CcXkbModifierDialog *self = user_data;
+ gchar *xkb_option;
+ GSList *l;
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->listbox), state);
+
+ if (state)
+ {
+ for (l = self->radio_group; l != NULL; l = l->next)
+ {
+ if (gtk_check_button_get_active (l->data))
+ {
+ xkb_option = (gchar *)g_object_get_data (l->data, "xkb-option");
+ set_xkb_option (self, xkb_option);
+ break;
+ }
+ }
+ }
+ else
+ {
+ set_xkb_option (self, NULL);
+ }
+
+ return FALSE;
+}
+
+static void
+cc_xkb_modifier_dialog_finalize (GObject *object)
+{
+ CcXkbModifierDialog *self = (CcXkbModifierDialog *)object;
+
+ g_clear_object (&self->input_source_settings);
+
+ G_OBJECT_CLASS (cc_xkb_modifier_dialog_parent_class)->finalize (object);
+}
+
+static void
+cc_xkb_modifier_dialog_class_init (CcXkbModifierDialogClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = cc_xkb_modifier_dialog_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/keyboard/cc-xkb-modifier-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcXkbModifierDialog, description_label);
+ gtk_widget_class_bind_template_child (widget_class, CcXkbModifierDialog, enabled_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcXkbModifierDialog, listbox);
+ gtk_widget_class_bind_template_child (widget_class, CcXkbModifierDialog, switch_listbox);
+ gtk_widget_class_bind_template_child (widget_class, CcXkbModifierDialog, switch_row);
+
+ gtk_widget_class_bind_template_callback (widget_class, enable_switch_changed_cb);
+}
+
+static void
+add_radio_buttons (CcXkbModifierDialog *self)
+{
+ g_autoptr (GSList) group = NULL;
+ GtkWidget *row, *radio_button, *last_button = NULL;
+ CcXkbOption *options = self->modifier->options;
+ int i;
+
+ for (i = 0; options[i].label && options[i].xkb_option; i++)
+ {
+ row = g_object_new (GTK_TYPE_LIST_BOX_ROW,
+ "visible", TRUE,
+ "selectable", FALSE,
+ NULL);
+ gtk_list_box_append (self->listbox, row);
+
+ radio_button = g_object_new (GTK_TYPE_CHECK_BUTTON,
+ "label", g_dpgettext2 (NULL, "keyboard key", options[i].label),
+ "group", last_button,
+ NULL);
+ gtk_widget_add_css_class (radio_button, "xkb-option-button");
+ g_object_set_data (G_OBJECT (radio_button), "xkb-option", options[i].xkb_option);
+ g_signal_connect_object (radio_button, "toggled", (GCallback)on_active_radio_changed_cb, self, G_CONNECT_SWAPPED);
+ gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), radio_button);
+
+ last_button = radio_button;
+ group = g_slist_prepend (group, radio_button);
+ }
+
+ self->radio_group = NULL;
+ if (last_button != NULL)
+ self->radio_group = g_steal_pointer (&group);
+}
+
+static void
+cc_xkb_modifier_dialog_init (CcXkbModifierDialog *self)
+{
+ g_autoptr(GtkCssProvider) provider = NULL;
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ provider = gtk_css_provider_new ();
+ gtk_css_provider_load_from_data (provider, custom_css, -1);
+
+ gtk_style_context_add_provider_for_display (gdk_display_get_default (),
+ GTK_STYLE_PROVIDER (provider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION + 1);
+
+ self->modifier = NULL;
+
+ self->input_source_settings = g_settings_new ("org.gnome.desktop.input-sources");
+ g_signal_connect_object (self->input_source_settings,
+ "changed::xkb-options",
+ G_CALLBACK (on_xkb_options_changed_cb),
+ self, G_CONNECT_SWAPPED);
+}
+
+CcXkbModifierDialog *
+cc_xkb_modifier_dialog_new (GSettings *input_settings,
+ const CcXkbModifier *modifier)
+{
+ CcXkbModifierDialog *self;
+
+ self = g_object_new (CC_TYPE_XKB_MODIFIER_DIALOG,
+ "use-header-bar", TRUE,
+ NULL);
+ self->input_source_settings = g_object_ref (input_settings);
+
+ self->modifier = modifier;
+ gtk_window_set_title (GTK_WINDOW (self), gettext (modifier->title));
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self->switch_row), gettext (modifier->title));
+ gtk_label_set_markup (self->description_label, gettext (modifier->description));
+ gtk_widget_set_visible (GTK_WIDGET (self->switch_listbox), modifier->default_option == NULL);
+ add_radio_buttons (self);
+ update_active_radio (self);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->listbox), gtk_switch_get_state (self->enabled_switch));
+
+ return self;
+}
+
+gboolean
+xcb_modifier_transform_binding_to_label (GValue *value,
+ GVariant *variant,
+ gpointer user_data)
+{
+ const CcXkbModifier *modifier = user_data;
+ const CcXkbOption *entry = NULL;
+ const char **items;
+ guint i;
+
+ items = g_variant_get_strv (variant, NULL);
+
+ for (i = 0; items != NULL && items[i] != NULL; i++)
+ {
+ entry = get_xkb_option_from_name (modifier, items[i]);
+ if (entry != NULL)
+ break;
+ }
+
+ if (entry == NULL && modifier->default_option == NULL)
+ {
+ g_value_set_string (value, _("Disabled"));
+ return TRUE;
+ }
+ else if (entry == NULL)
+ {
+ entry = get_xkb_option_from_name(modifier, modifier->default_option);
+ }
+
+ g_value_set_string (value,
+ g_dpgettext2 (NULL, "keyboard key", entry->label));
+ return TRUE;
+}
diff --git a/panels/keyboard/cc-xkb-modifier-dialog.h b/panels/keyboard/cc-xkb-modifier-dialog.h
new file mode 100644
index 0000000..91efbcd
--- /dev/null
+++ b/panels/keyboard/cc-xkb-modifier-dialog.h
@@ -0,0 +1,49 @@
+/* cc-xkb-modifier-dialog.h
+ *
+ * Copyright 2019 Bastien Nocera <hadess@hadess.net>
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+typedef struct
+{
+ gchar *label;
+ gchar *xkb_option;
+} CcXkbOption;
+
+typedef struct
+{
+ gchar *prefix;
+ gchar *title;
+ gchar *description;
+ CcXkbOption *options;
+ gchar *default_option;
+} CcXkbModifier;
+
+#define CC_TYPE_XKB_MODIFIER_DIALOG (cc_xkb_modifier_dialog_get_type())
+G_DECLARE_FINAL_TYPE (CcXkbModifierDialog, cc_xkb_modifier_dialog, CC, XKB_MODIFIER_DIALOG, GtkDialog)
+
+CcXkbModifierDialog *cc_xkb_modifier_dialog_new (GSettings *input_settings, const CcXkbModifier*);
+
+gboolean xcb_modifier_transform_binding_to_label (GValue*, GVariant*, gpointer);
+
+G_END_DECLS
diff --git a/panels/keyboard/cc-xkb-modifier-dialog.ui b/panels/keyboard/cc-xkb-modifier-dialog.ui
new file mode 100644
index 0000000..e5612ba
--- /dev/null
+++ b/panels/keyboard/cc-xkb-modifier-dialog.ui
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcXkbModifierDialog" parent="GtkDialog">
+ <property name="modal">True</property>
+ <property name="resizable">False</property>
+ <property name="default_width">500</property>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">18</property>
+ <property name="margin-bottom">18</property>
+ <property name="margin-start">18</property>
+ <property name="margin-end">18</property>
+ <property name="spacing">18</property>
+ <property name="orientation">vertical</property>
+
+ <child>
+ <object class="GtkLabel" id="description_label">
+ <property name="margin_top">6</property>
+ <property name="wrap">True</property>
+ <property name="width_chars">40</property>
+ <property name="max_width_chars">40</property>
+ <property name="xalign">0</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkListBox" id="switch_listbox">
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ <child>
+ <object class="AdwActionRow" id="switch_row">
+ <property name="activatable">False</property>
+ <property name="selectable">False</property>
+ <child>
+ <object class="GtkSwitch" id="enabled_switch">
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Enabled</property>
+ </accessibility>
+ <signal name="state-set" handler="enable_switch_changed_cb" object="CcXkbModifierDialog" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkListBox" id="listbox">
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child internal-child="headerbar">
+ <object class="GtkHeaderBar">
+ <property name="show-title-buttons">True</property>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/keyboard/enter-keyboard-shortcut.svg b/panels/keyboard/enter-keyboard-shortcut.svg
new file mode 100644
index 0000000..b7ce2e4
--- /dev/null
+++ b/panels/keyboard/enter-keyboard-shortcut.svg
@@ -0,0 +1,245 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="256"
+ height="72"
+ viewBox="0 0 256 72.000001"
+ id="svg3611"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="enter-keyboard-shortcut.svg">
+ <defs
+ id="defs3613" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.8"
+ inkscape:cx="137.98997"
+ inkscape:cy="34.663602"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ units="px"
+ inkscape:window-width="1366"
+ inkscape:window-height="704"
+ inkscape:window-x="0"
+ inkscape:window-y="27"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata3616">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Camada 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-980.36216)">
+ <g
+ id="g3715"
+ transform="translate(-503.23415,689.94658)">
+ <path
+ d="m 509.66363,325.47627 c 5.53002,1.4185 18.51389,1.4185 24.29359,0 0.80721,-0.19813 1.43306,0.67185 1.50029,1.50028 l 1.99751,13.05863 -1.50028,0 -28.28862,0 -1.50029,0 c 0.66583,-4.35287 1.33167,-8.70575 1.99752,-13.05863 0.12564,-0.82161 0.69518,-1.70681 1.50028,-1.50028 z"
+ id="path27275"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.59999979;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:nodetypes="sssccccss"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 543.62146,325.47627 c 5.53,1.4185 18.51387,1.4185 24.29357,0 0.80721,-0.19813 1.43308,0.67185 1.50029,1.50028 l 1.99753,13.05863 -1.5003,0 -28.28862,0 -1.50029,0 c 0.66583,-4.35287 1.33168,-8.70575 1.99752,-13.05863 0.12564,-0.82161 0.69518,-1.70681 1.5003,-1.50028 z"
+ id="path27277"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.59999979;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:nodetypes="sssccccss"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 577.57927,325.47627 c 5.53,1.4185 18.51387,1.4185 24.29357,0 0.80721,-0.19813 1.43308,0.67185 1.50029,1.50028 l 1.99753,13.05863 -1.5003,0 -28.28862,0 -1.50029,0 c 0.66583,-4.35287 1.33168,-8.70575 1.99752,-13.05863 0.12564,-0.82161 0.6952,-1.70681 1.5003,-1.50028 z"
+ id="path27279"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.59999979;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:nodetypes="sssccccss"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 611.12326,325.47627 c 5.53002,1.4185 18.51389,1.4185 24.29359,0 0.80721,-0.19813 1.43306,0.67185 1.50029,1.50028 l 1.99751,13.05863 -1.50028,0 -28.28862,0 -1.50029,0 c 0.66583,-4.35287 1.33167,-8.70575 1.99752,-13.05863 0.12564,-0.82161 0.69518,-1.70681 1.50028,-1.50028 z"
+ id="path5218"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.59999979;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:nodetypes="sssccccss"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 645.08109,325.47627 c 5.53,1.4185 18.51387,1.4185 24.29357,0 0.80721,-0.19813 1.43308,0.67185 1.50029,1.50028 l 1.99753,13.05863 -1.5003,0 -28.28862,0 -1.50029,0 c 0.66583,-4.35287 1.33168,-8.70575 1.99751,-13.05863 0.12565,-0.82161 0.69519,-1.70681 1.50031,-1.50028 z"
+ id="path5220"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.59999979;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:nodetypes="sssccccss"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 679.0389,325.47627 c 5.53,1.4185 18.51387,1.4185 24.29357,0 0.80721,-0.19813 1.43308,0.67185 1.50029,1.50028 l 1.99753,13.05863 -1.5003,0 -28.28862,0 -1.50029,0 c 0.66583,-4.35287 1.33168,-8.70575 1.99751,-13.05863 0.12565,-0.82161 0.69521,-1.70681 1.50031,-1.50028 z"
+ id="path5222"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.59999979;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:nodetypes="sssccccss"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 712.58289,325.47627 c 5.53002,1.4185 18.51389,1.4185 24.29359,0 0.80721,-0.19813 1.43306,0.67185 1.50029,1.50028 l 1.99751,13.05863 -1.50028,0 -28.28862,0 -1.50029,0 c 0.66583,-4.35287 1.33167,-8.70575 1.99751,-13.05863 0.12565,-0.82161 0.69519,-1.70681 1.50029,-1.50028 z"
+ id="path4829"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.60000002;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:nodetypes="sssccccss"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 516.19044,335.26648 c 5.53002,1.41851 18.51389,1.41851 24.2936,0 0.8072,-0.19812 1.43306,0.67186 1.50028,1.50029 l 1.99752,13.05863 -1.50029,0 -28.28862,0 -1.50029,0 c 0.66584,-4.35288 1.33167,-8.70575 1.99752,-13.05863 0.12564,-0.82161 0.69518,-1.70681 1.50028,-1.50029 z"
+ id="path3662"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.59999979;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:nodetypes="sssccccss"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 550.14827,335.26648 c 5.53,1.41851 18.51387,1.41851 24.29358,0 0.8072,-0.19812 1.43307,0.67186 1.50028,1.50029 l 1.99753,13.05863 -1.5003,0 -28.28862,0 -1.50029,0 c 0.66584,-4.35288 1.33168,-8.70575 1.99752,-13.05863 0.12564,-0.82161 0.69518,-1.70681 1.5003,-1.50029 z"
+ id="path3664"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.59999979;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:nodetypes="sssccccss"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 584.10608,335.26648 c 5.53,1.41851 18.51387,1.41851 24.29357,0 0.80721,-0.19812 1.43308,0.67186 1.50029,1.50029 l 1.99753,13.05863 -1.5003,0 -28.28862,0 -1.50029,0 c 0.66584,-4.35288 1.33168,-8.70575 1.99752,-13.05863 0.12564,-0.82161 0.6952,-1.70681 1.5003,-1.50029 z"
+ id="path3666"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.59999979;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:nodetypes="sssccccss"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 617.65007,335.26648 c 5.53002,1.41851 18.51389,1.41851 24.29359,0 0.80721,-0.19812 1.43306,0.67186 1.50029,1.50029 l 1.99751,13.05863 -1.50028,0 -28.28862,0 -1.50029,0 c 0.66584,-4.35288 1.33167,-8.70575 1.99752,-13.05863 0.12564,-0.82161 0.69518,-1.70681 1.50028,-1.50029 z"
+ id="path3668"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.59999979;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:nodetypes="sssccccss"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 651.6079,335.26648 c 5.53,1.41851 18.51387,1.41851 24.29357,0 0.80721,-0.19812 1.43308,0.67186 1.50029,1.50029 l 1.99753,13.05863 -1.5003,0 -28.28862,0 -1.50029,0 c 0.66583,-4.35288 1.33168,-8.70575 1.99752,-13.05863 0.12564,-0.82161 0.69518,-1.70681 1.5003,-1.50029 z"
+ id="path3670"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.59999979;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:nodetypes="sssccccss"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 685.56571,335.26648 c 5.53,1.41851 18.51387,1.41851 24.29357,0 0.80721,-0.19812 1.43308,0.67186 1.50029,1.50029 l 1.99753,13.05863 -1.5003,0 -28.28862,0 -1.50029,0 c 0.66583,-4.35288 1.33168,-8.70575 1.99752,-13.05863 0.12564,-0.82161 0.6952,-1.70681 1.5003,-1.50029 z"
+ id="path3672"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.59999979;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:nodetypes="sssccccss"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 719.1097,335.26648 c 5.53002,1.41851 18.51389,1.41851 24.29359,0 0.80721,-0.19812 1.43306,0.67186 1.50029,1.50029 l 1.99751,13.05863 -1.50028,0 -28.28862,0 -1.50029,0 c 0.66583,-4.35288 1.33167,-8.70575 1.99752,-13.05863 0.12564,-0.82161 0.69518,-1.70681 1.50028,-1.50029 z"
+ id="path3674"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.60000002;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:nodetypes="sssccccss"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 525.98066,345.0567 c 5.53002,1.4185 18.51389,1.4185 24.29359,0 0.80721,-0.19812 1.43306,0.67185 1.50029,1.50029 l 1.99751,13.05863 -1.50028,0 -28.28862,0 -1.50029,0 c 0.66583,-4.35288 1.33167,-8.70576 1.99752,-13.05863 0.12564,-0.82162 0.69518,-1.70681 1.50028,-1.50029 z"
+ id="path3676"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.59999979;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:nodetypes="sssccccss"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 559.93849,345.0567 c 5.53,1.4185 18.51387,1.4185 24.29357,0 0.80721,-0.19812 1.43308,0.67185 1.50029,1.50029 l 1.99753,13.05863 -1.5003,0 -28.28862,0 -1.50029,0 c 0.66583,-4.35288 1.33168,-8.70576 1.99751,-13.05863 0.12565,-0.82162 0.69519,-1.70681 1.50031,-1.50029 z"
+ id="path3678"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.59999979;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:nodetypes="sssccccss"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 593.8963,345.0567 c 5.53,1.4185 18.51387,1.4185 24.29357,0 0.80721,-0.19812 1.43308,0.67185 1.50029,1.50029 l 1.99753,13.05863 -1.5003,0 -28.28862,0 -1.50029,0 c 0.66583,-4.35288 1.33168,-8.70576 1.99751,-13.05863 0.12565,-0.82162 0.69521,-1.70681 1.50031,-1.50029 z"
+ id="path3680"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.59999979;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:nodetypes="sssccccss"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 627.44029,345.0567 c 5.53002,1.4185 18.51389,1.4185 24.29359,0 0.80721,-0.19812 1.43306,0.67185 1.50029,1.50029 l 1.99751,13.05863 -1.50028,0 -28.28862,0 -1.50029,0 c 0.66583,-4.35288 1.33167,-8.70576 1.99751,-13.05863 0.12565,-0.82162 0.69519,-1.70681 1.50029,-1.50029 z"
+ id="path3682"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.59999979;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:nodetypes="sssccccss"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 661.39812,345.0567 c 5.53,1.4185 18.51387,1.4185 24.29357,0 0.80721,-0.19812 1.43308,0.67185 1.50029,1.50029 l 1.99753,13.05863 -1.5003,0 -28.28863,0 -1.50028,0 c 0.66583,-4.35288 1.33168,-8.70576 1.99751,-13.05863 0.12564,-0.82162 0.69519,-1.70681 1.50031,-1.50029 z"
+ id="path3684"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.59999979;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:nodetypes="sssccccss"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 695.35593,345.0567 c 5.53,1.4185 18.51387,1.4185 24.29357,0 0.8072,-0.19812 1.43308,0.67185 1.50029,1.50029 l 1.99753,13.05863 -1.5003,0 -28.28863,0 -1.50028,0 c 0.66583,-4.35288 1.33168,-8.70576 1.99751,-13.05863 0.12564,-0.82162 0.69521,-1.70681 1.50031,-1.50029 z"
+ id="path3686"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.59999979;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:nodetypes="sssccccss"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 728.89992,345.0567 c 5.53002,1.4185 18.51389,1.4185 24.29359,0 0.8072,-0.19812 1.43306,0.67185 1.50029,1.50029 l 1.99751,13.05863 -1.50028,0 -28.28863,0 -1.50028,0 c 0.66583,-4.35288 1.33166,-8.70576 1.99751,-13.05863 0.12564,-0.82162 0.69519,-1.70681 1.50029,-1.50029 z"
+ id="path3688"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.60000002;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:nodetypes="sssccccss"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g3713"
+ transform="matrix(1.359752,0,0,1.359752,418.09336,-671.08525)">
+ <path
+ d="m 95.250257,715.10933 0,1.09089 c -1.31e-4,0.0113 -5.02e-4,0.0227 0,0.0341 0.01222,0.27812 0.140266,0.55621 0.340902,0.74999 l 5.693061,5.76124 5.65897,-5.76124 c 0.20529,-0.20532 0.30681,-0.49473 0.30681,-0.78413 l 0,-1.09089 -1.09088,0 c -0.28941,0 -0.57881,0.10156 -0.78408,0.30681 l -4.09082,4.15901 -4.124913,-4.15901 c -0.212319,-0.22989 -0.511898,-0.33071 -0.818164,-0.30681 l -1.090886,0 z"
+ id="path3715"
+ style="color:#bebebe;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:'Andale Mono';-inkscape-font-specification:'Andale Mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#000100;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.78124988;marker:none;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <rect
+ height="11.999745"
+ id="rect3717"
+ rx="0"
+ ry="0"
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#000100;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;enable-background:accumulate"
+ transform="scale(-1,1)"
+ width="2.1817718"
+ x="-102.34102"
+ y="708.92743" />
+ </g>
+ <g
+ id="g3740"
+ transform="matrix(1.359752,0,0,1.359752,492.12198,-661.29504)">
+ <path
+ d="m 95.250257,715.10933 0,1.09089 c -1.31e-4,0.0113 -5.02e-4,0.0227 0,0.0341 0.01222,0.27812 0.140266,0.55621 0.340902,0.74999 l 5.693061,5.76124 5.65897,-5.76124 c 0.20529,-0.20532 0.30681,-0.49473 0.30681,-0.78413 l 0,-1.09089 -1.09088,0 c -0.28941,0 -0.57881,0.10156 -0.78408,0.30681 l -4.09082,4.15901 -4.124913,-4.15901 c -0.212319,-0.22989 -0.511898,-0.33071 -0.818164,-0.30681 l -1.090886,0 z"
+ id="path3742"
+ style="color:#bebebe;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:'Andale Mono';-inkscape-font-specification:'Andale Mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#000100;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.78124988;marker:none;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <rect
+ height="11.999745"
+ id="rect3744"
+ rx="0"
+ ry="0"
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#000100;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;enable-background:accumulate"
+ transform="scale(-1,1)"
+ width="2.1817718"
+ x="-102.34102"
+ y="708.92743" />
+ </g>
+ <g
+ id="g3746"
+ transform="matrix(1.359752,0,0,1.359752,593.58161,-661.29504)">
+ <path
+ d="m 95.250257,715.10933 0,1.09089 c -1.31e-4,0.0113 -5.02e-4,0.0227 0,0.0341 0.01222,0.27812 0.140266,0.55621 0.340902,0.74999 l 5.693061,5.76124 5.65897,-5.76124 c 0.20529,-0.20532 0.30681,-0.49473 0.30681,-0.78413 l 0,-1.09089 -1.09088,0 c -0.28941,0 -0.57881,0.10156 -0.78408,0.30681 l -4.09082,4.15901 -4.124913,-4.15901 c -0.212319,-0.22989 -0.511898,-0.33071 -0.818164,-0.30681 l -1.090886,0 z"
+ id="path3748"
+ style="color:#bebebe;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:'Andale Mono';-inkscape-font-specification:'Andale Mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#000100;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.78124988;marker:none;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <rect
+ height="11.999745"
+ id="rect3750"
+ rx="0"
+ ry="0"
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#000100;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;enable-background:accumulate"
+ transform="scale(-1,1)"
+ width="2.1817718"
+ x="-102.34102"
+ y="708.92743" />
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/panels/keyboard/gnome-keybindings.pc.in b/panels/keyboard/gnome-keybindings.pc.in
new file mode 100644
index 0000000..e099b4c
--- /dev/null
+++ b/panels/keyboard/gnome-keybindings.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+datarootdir=@datarootdir@
+datadir=@datadir@
+pkgdatadir=${datadir}/@PACKAGE@
+keysdir=${pkgdatadir}/keybindings
+
+Name: gnome-keybindings
+Description: Keybindings configuration for GNOME applications
+Version: @VERSION@
+
diff --git a/panels/keyboard/gnome-keyboard-panel.desktop.in.in b/panels/keyboard/gnome-keyboard-panel.desktop.in.in
new file mode 100644
index 0000000..872fcaf
--- /dev/null
+++ b/panels/keyboard/gnome-keyboard-panel.desktop.in.in
@@ -0,0 +1,18 @@
+[Desktop Entry]
+Name=Keyboard
+Comment=Change keyboard shortcuts and set your typing preferences, keyboard layouts and input sources
+Exec=gnome-control-center keyboard
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-keyboard-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;HardwareSettings;X-GNOME-Settings-Panel;X-GNOME-DevicesSettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=keyboard
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: Search terms to find the Keyboard panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=Shortcut;Workspace;Window;Resize;Zoom;Contrast;Input;Source;Lock;Volume;
diff --git a/panels/keyboard/icons/meson.build b/panels/keyboard/icons/meson.build
new file mode 100644
index 0000000..384cb71
--- /dev/null
+++ b/panels/keyboard/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-keyboard-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/keyboard/icons/scalable/org.gnome.Settings-keyboard-symbolic.svg b/panels/keyboard/icons/scalable/org.gnome.Settings-keyboard-symbolic.svg
new file mode 100644
index 0000000..0f35d48
--- /dev/null
+++ b/panels/keyboard/icons/scalable/org.gnome.Settings-keyboard-symbolic.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <path d="m 2.5 2 c -1.367188 0 -2.5 1.132812 -2.5 2.5 v 7 c 0 1.367188 1.132812 2.5 2.5 2.5 h 11 c 1.367188 0 2.5 -1.132812 2.5 -2.5 v -7 c 0 -1.367188 -1.132812 -2.5 -2.5 -2.5 z m 0 2 h 1 c 0.277344 0 0.5 0.222656 0.5 0.5 v 1 c 0 0.277344 -0.222656 0.5 -0.5 0.5 h -1 c -0.277344 0 -0.5 -0.222656 -0.5 -0.5 v -1 c 0 -0.242188 0.171875 -0.445312 0.398438 -0.488281 c 0.03125 -0.007813 0.066406 -0.011719 0.101562 -0.011719 z m 3 0 h 1 c 0.277344 0 0.5 0.222656 0.5 0.5 v 1 c 0 0.277344 -0.222656 0.5 -0.5 0.5 h -1 c -0.277344 0 -0.5 -0.222656 -0.5 -0.5 v -1 c 0 -0.277344 0.222656 -0.5 0.5 -0.5 z m 3 0 h 1 c 0.277344 0 0.5 0.222656 0.5 0.5 v 1 c 0 0.277344 -0.222656 0.5 -0.5 0.5 h -1 c -0.277344 0 -0.5 -0.222656 -0.5 -0.5 v -1 c 0 -0.277344 0.222656 -0.5 0.5 -0.5 z m 3 0 h 1 c 0.277344 0 0.5 0.222656 0.5 0.5 v 1 c 0 0.277344 -0.222656 0.5 -0.5 0.5 h -1 c -0.277344 0 -0.5 -0.222656 -0.5 -0.5 v -1 c 0 -0.277344 0.222656 -0.5 0.5 -0.5 z m -8 3 h 1 c 0.277344 0 0.5 0.222656 0.5 0.5 v 1 c 0 0.277344 -0.222656 0.5 -0.5 0.5 h -1 c -0.277344 0 -0.5 -0.222656 -0.5 -0.5 v -1 c 0 -0.277344 0.222656 -0.5 0.5 -0.5 z m 3 0 h 1 c 0.277344 0 0.5 0.222656 0.5 0.5 v 1 c 0 0.277344 -0.222656 0.5 -0.5 0.5 h -1 c -0.277344 0 -0.5 -0.222656 -0.5 -0.5 v -1 c 0 -0.277344 0.222656 -0.5 0.5 -0.5 z m 3 0 h 1 c 0.277344 0 0.5 0.222656 0.5 0.5 v 1 c 0 0.277344 -0.222656 0.5 -0.5 0.5 h -1 c -0.277344 0 -0.5 -0.222656 -0.5 -0.5 v -1 c 0 -0.277344 0.222656 -0.5 0.5 -0.5 z m 3 0 h 1 c 0.277344 0 0.5 0.222656 0.5 0.5 v 1 c 0 0.277344 -0.222656 0.5 -0.5 0.5 h -1 c -0.277344 0 -0.5 -0.222656 -0.5 -0.5 v -1 c 0 -0.277344 0.222656 -0.5 0.5 -0.5 z m -10 3 h 1 c 0.277344 0 0.5 0.222656 0.5 0.5 v 1 c 0 0.277344 -0.222656 0.5 -0.5 0.5 h -1 c -0.277344 0 -0.5 -0.222656 -0.5 -0.5 v -1 c 0 -0.277344 0.222656 -0.5 0.5 -0.5 z m 3 0 h 4 c 0.277344 0 0.5 0.222656 0.5 0.5 v 1 c 0 0.277344 -0.222656 0.5 -0.5 0.5 h -4 c -0.277344 0 -0.5 -0.222656 -0.5 -0.5 v -1 c 0 -0.277344 0.222656 -0.5 0.5 -0.5 z m 6 0 h 1 c 0.277344 0 0.5 0.222656 0.5 0.5 v 1 c 0 0.277344 -0.222656 0.5 -0.5 0.5 h -1 c -0.277344 0 -0.5 -0.222656 -0.5 -0.5 v -1 c 0 -0.277344 0.222656 -0.5 0.5 -0.5 z m 0 0" fill="#2e3436"/>
+</svg>
diff --git a/panels/keyboard/keyboard-shortcuts.c b/panels/keyboard/keyboard-shortcuts.c
new file mode 100644
index 0000000..cfaa11e
--- /dev/null
+++ b/panels/keyboard/keyboard-shortcuts.c
@@ -0,0 +1,450 @@
+/*
+ * Copyright (C) 2010 Intel, Inc
+ * Copyright (C) 2014 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Thomas Wood <thomas.wood@intel.com>
+ * Rodrigo Moya <rodrigo@gnome.org>
+ * Christophe Fergeau <cfergeau@redhat.com>
+ */
+
+#include <config.h>
+
+#include <glib/gi18n.h>
+
+#include "keyboard-shortcuts.h"
+
+#define CUSTOM_KEYS_BASENAME "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings"
+
+static char *
+replace_pictures_folder (const char *description)
+{
+ g_autoptr(GRegex) pictures_regex = NULL;
+ const char *path;
+ g_autofree gchar *dirname = NULL;
+ g_autofree gchar *ret = NULL;
+
+ if (description == NULL)
+ return NULL;
+
+ if (strstr (description, "$PICTURES") == NULL)
+ return g_strdup (description);
+
+ pictures_regex = g_regex_new ("\\$PICTURES", 0, 0, NULL);
+ path = g_get_user_special_dir (G_USER_DIRECTORY_PICTURES);
+ dirname = g_filename_display_basename (path);
+ ret = g_regex_replace (pictures_regex, description, -1,
+ 0, dirname, 0, NULL);
+
+ if (ret == NULL)
+ return g_strdup (description);
+
+ return g_steal_pointer (&ret);
+}
+
+static void
+parse_start_tag (GMarkupParseContext *ctx,
+ const gchar *element_name,
+ const gchar **attr_names,
+ const gchar **attr_values,
+ gpointer user_data,
+ GError **error)
+{
+ KeyList *keylist = (KeyList *) user_data;
+ KeyListEntry key;
+ const char *name, *schema, *description, *package, *context, *orig_description, *reverse_entry;
+ gboolean is_reversed, hidden;
+
+ name = NULL;
+ schema = NULL;
+ package = NULL;
+ context = NULL;
+
+ /* The top-level element, names the section in the tree */
+ if (g_str_equal (element_name, "KeyListEntries"))
+ {
+ const char *wm_name = NULL;
+ const char *group = NULL;
+
+ while (*attr_names && *attr_values)
+ {
+ if (g_str_equal (*attr_names, "name"))
+ {
+ if (**attr_values)
+ name = *attr_values;
+ } else if (g_str_equal (*attr_names, "group")) {
+ if (**attr_values)
+ group = *attr_values;
+ } else if (g_str_equal (*attr_names, "wm_name")) {
+ if (**attr_values)
+ wm_name = *attr_values;
+ } else if (g_str_equal (*attr_names, "schema")) {
+ if (**attr_values)
+ schema = *attr_values;
+ } else if (g_str_equal (*attr_names, "package")) {
+ if (**attr_values)
+ package = *attr_values;
+ }
+ ++attr_names;
+ ++attr_values;
+ }
+
+ if (name)
+ {
+ if (keylist->name)
+ g_warning ("Duplicate section name");
+ g_free (keylist->name);
+ keylist->name = g_strdup (name);
+ }
+ if (wm_name)
+ {
+ if (keylist->wm_name)
+ g_warning ("Duplicate window manager name");
+ g_free (keylist->wm_name);
+ keylist->wm_name = g_strdup (wm_name);
+ }
+ if (package)
+ {
+ if (keylist->package)
+ g_warning ("Duplicate gettext package name");
+ g_free (keylist->package);
+ keylist->package = g_strdup (package);
+ bind_textdomain_codeset (keylist->package, "UTF-8");
+ }
+ if (group)
+ {
+ if (keylist->group)
+ g_warning ("Duplicate group");
+ g_free (keylist->group);
+ keylist->group = g_strdup (group);
+ }
+ if (schema)
+ {
+ if (keylist->schema)
+ g_warning ("Duplicate schema");
+ g_free (keylist->schema);
+ keylist->schema = g_strdup (schema);
+ }
+ return;
+ }
+
+ if (!g_str_equal (element_name, "KeyListEntry")
+ || attr_names == NULL
+ || attr_values == NULL)
+ return;
+
+ schema = NULL;
+ description = NULL;
+ context = NULL;
+ orig_description = NULL;
+ reverse_entry = NULL;
+ is_reversed = FALSE;
+ hidden = FALSE;
+
+ while (*attr_names && *attr_values)
+ {
+ if (g_str_equal (*attr_names, "name"))
+ {
+ /* skip if empty */
+ if (**attr_values)
+ name = *attr_values;
+ } else if (g_str_equal (*attr_names, "schema")) {
+ if (**attr_values) {
+ schema = *attr_values;
+ }
+ } else if (g_str_equal (*attr_names, "description")) {
+ if (**attr_values)
+ orig_description = *attr_values;
+ } else if (g_str_equal (*attr_names, "msgctxt")) {
+ if (**attr_values)
+ context = *attr_values;
+ } else if (g_str_equal (*attr_names, "reverse-entry")) {
+ if (**attr_values)
+ reverse_entry = *attr_values;
+ } else if (g_str_equal (*attr_names, "is-reversed")) {
+ if (g_str_equal (*attr_values, "true"))
+ is_reversed = TRUE;
+ } else if (g_str_equal (*attr_names, "hidden")) {
+ if (g_str_equal (*attr_values, "true"))
+ hidden = TRUE;
+ }
+
+ ++attr_names;
+ ++attr_values;
+ }
+
+ if (name == NULL)
+ return;
+
+ if (schema == NULL &&
+ keylist->schema == NULL) {
+ g_debug ("Ignored GConf keyboard shortcut '%s'", name);
+ return;
+ }
+
+ if (context != NULL)
+ description = g_dpgettext2 (keylist->package, context, orig_description);
+ else
+ description = dgettext (keylist->package, orig_description);
+
+ key.name = g_strdup (name);
+ key.type = CC_KEYBOARD_ITEM_TYPE_GSETTINGS;
+ key.description = replace_pictures_folder (description);
+ key.schema = schema ? g_strdup (schema) : g_strdup (keylist->schema);
+ key.reverse_entry = g_strdup (reverse_entry);
+ key.is_reversed = is_reversed;
+ key.hidden = hidden;
+ g_array_append_val (keylist->entries, key);
+}
+
+static const guint forbidden_keyvals[] = {
+ /* Navigation keys */
+ GDK_KEY_Home,
+ GDK_KEY_Left,
+ GDK_KEY_Up,
+ GDK_KEY_Right,
+ GDK_KEY_Down,
+ GDK_KEY_Page_Up,
+ GDK_KEY_Page_Down,
+ GDK_KEY_End,
+ GDK_KEY_Tab,
+
+ /* Return */
+ GDK_KEY_KP_Enter,
+ GDK_KEY_Return,
+
+ GDK_KEY_Mode_switch
+};
+
+static gboolean
+keyval_is_forbidden (guint keyval)
+{
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS(forbidden_keyvals); i++) {
+ if (keyval == forbidden_keyvals[i])
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gboolean
+is_valid_binding (const CcKeyCombo *combo)
+{
+ if ((combo->mask == 0 || combo->mask == GDK_SHIFT_MASK) && combo->keycode != 0)
+ {
+ guint keyval = combo->keyval;
+
+ if ((keyval >= GDK_KEY_a && keyval <= GDK_KEY_z)
+ || (keyval >= GDK_KEY_A && keyval <= GDK_KEY_Z)
+ || (keyval >= GDK_KEY_0 && keyval <= GDK_KEY_9)
+ || (keyval >= GDK_KEY_kana_fullstop && keyval <= GDK_KEY_semivoicedsound)
+ || (keyval >= GDK_KEY_Arabic_comma && keyval <= GDK_KEY_Arabic_sukun)
+ || (keyval >= GDK_KEY_Serbian_dje && keyval <= GDK_KEY_Cyrillic_HARDSIGN)
+ || (keyval >= GDK_KEY_Greek_ALPHAaccent && keyval <= GDK_KEY_Greek_omega)
+ || (keyval >= GDK_KEY_hebrew_doublelowline && keyval <= GDK_KEY_hebrew_taf)
+ || (keyval >= GDK_KEY_Thai_kokai && keyval <= GDK_KEY_Thai_lekkao)
+ || (keyval >= GDK_KEY_Hangul_Kiyeog && keyval <= GDK_KEY_Hangul_J_YeorinHieuh)
+ || (keyval == GDK_KEY_space && combo->mask == 0)
+ || keyval_is_forbidden (keyval)) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+gboolean
+is_empty_binding (const CcKeyCombo *combo)
+{
+ if (combo->keyval == 0 &&
+ combo->mask == 0 &&
+ combo->keycode == 0)
+ return TRUE;
+ return FALSE;
+}
+
+gboolean
+is_valid_accel (const CcKeyCombo *combo)
+{
+ /* Unlike gtk_accelerator_valid(), we want to allow Tab when combined
+ * with some modifiers (Alt+Tab and friends)
+ */
+ return gtk_accelerator_valid (combo->keyval, combo->mask) ||
+ (combo->keyval == GDK_KEY_Tab && combo->mask != 0);
+}
+
+gchar*
+find_free_settings_path (GSettings *settings)
+{
+ g_auto(GStrv) used_names = NULL;
+ g_autofree gchar *dir = NULL;
+ int i, num, n_names;
+
+ used_names = g_settings_get_strv (settings, "custom-keybindings");
+ n_names = g_strv_length (used_names);
+
+ for (num = 0; dir == NULL; num++)
+ {
+ g_autofree gchar *tmp = NULL;
+ gboolean found = FALSE;
+
+ tmp = g_strdup_printf ("%s/custom%d/", CUSTOM_KEYS_BASENAME, num);
+ for (i = 0; i < n_names && !found; i++)
+ found = strcmp (used_names[i], tmp) == 0;
+
+ if (!found)
+ dir = g_steal_pointer (&tmp);
+ }
+
+ return g_steal_pointer (&dir);
+}
+
+KeyList*
+parse_keylist_from_file (const gchar *path)
+{
+ KeyList *keylist;
+ g_autoptr(GError) err = NULL;
+ g_autofree gchar *buf = NULL;
+ gsize buf_len;
+ guint i;
+
+ g_autoptr(GMarkupParseContext) ctx = NULL;
+ GMarkupParser parser = { parse_start_tag, NULL, NULL, NULL, NULL };
+
+ /* Parse file */
+ if (!g_file_get_contents (path, &buf, &buf_len, &err))
+ return NULL;
+
+ keylist = g_new0 (KeyList, 1);
+ keylist->entries = g_array_new (FALSE, TRUE, sizeof (KeyListEntry));
+ ctx = g_markup_parse_context_new (&parser, 0, keylist, NULL);
+
+ if (!g_markup_parse_context_parse (ctx, buf, buf_len, &err))
+ {
+ g_warning ("Failed to parse '%s': '%s'", path, err->message);
+ g_free (keylist->name);
+ g_free (keylist->package);
+ g_free (keylist->wm_name);
+
+ for (i = 0; i < keylist->entries->len; i++)
+ g_free (((KeyListEntry *) &(keylist->entries->data[i]))->name);
+
+ g_array_free (keylist->entries, TRUE);
+ g_free (keylist);
+ return NULL;
+ }
+
+ return keylist;
+}
+
+/*
+ * Stolen from GtkCellRendererAccel:
+ * https://git.gnome.org/browse/gtk+/tree/gtk/gtkcellrendereraccel.c#n261
+ */
+gchar*
+convert_keysym_state_to_string (const CcKeyCombo *combo)
+{
+ gchar *name;
+
+ if (combo->keyval == 0 && combo->keycode == 0)
+ {
+ /* This label is displayed in a treeview cell displaying
+ * a disabled accelerator key combination.
+ */
+ name = g_strdup (_("Disabled"));
+ }
+ else
+ {
+ name = gtk_accelerator_get_label_with_keycode (NULL, combo->keyval, combo->keycode, combo->mask);
+
+ if (name == NULL)
+ name = gtk_accelerator_name_with_keycode (NULL, combo->keyval, combo->keycode, combo->mask);
+ }
+
+ return name;
+}
+
+/* This adjusts the keyval and modifiers such that it matches how
+ * gnome-shell detects shortcuts, which works as follows:
+ * First for the non-modifier key, the keycode that generates this
+ * keyval at the lowest shift level is determined, which might be a
+ * level > 0, such as for numbers in the num-row in AZERTY.
+ * Next it checks if all the specified modifiers were pressed.
+ */
+void
+normalize_keyval_and_mask (guint keycode,
+ GdkModifierType mask,
+ guint group,
+ guint *out_keyval,
+ GdkModifierType *out_mask)
+{
+ guint unmodified_keyval;
+ guint shifted_keyval;
+ GdkModifierType explicit_modifiers;
+ GdkModifierType used_modifiers;
+
+ /* We want shift to always be included as explicit modifier for
+ * gnome-shell shortcuts. That's because users usually think of
+ * shortcuts as including the shift key rather than being defined
+ * for the shifted keyval.
+ * This helps with num-row keys which have different keyvals on
+ * different layouts for example, but also with keys that have
+ * explicit key codes at shift level 0, that gnome-shell would prefer
+ * over shifted ones, such the DOLLAR key.
+ */
+ explicit_modifiers = gtk_accelerator_get_default_mod_mask () | GDK_SHIFT_MASK;
+ used_modifiers = mask & explicit_modifiers;
+
+ /* Find the base keyval of the pressed key without the explicit
+ * modifiers. */
+ gdk_display_translate_key (gdk_display_get_default (),
+ keycode,
+ mask & ~explicit_modifiers,
+ group,
+ &unmodified_keyval,
+ NULL,
+ NULL,
+ NULL);
+
+ /* Normalize num-row keys to the number value. This allows these
+ * shortcuts to work when switching between AZERTY and layouts where
+ * the numbers are at shift level 0. */
+ gdk_display_translate_key (gdk_display_get_default (),
+ keycode,
+ GDK_SHIFT_MASK | (mask & ~explicit_modifiers),
+ group,
+ &shifted_keyval,
+ NULL,
+ NULL,
+ NULL);
+
+ if (shifted_keyval >= GDK_KEY_0 && shifted_keyval <= GDK_KEY_9)
+ unmodified_keyval = shifted_keyval;
+
+ /* Normalise <Tab> */
+ if (unmodified_keyval == GDK_KEY_ISO_Left_Tab)
+ unmodified_keyval = GDK_KEY_Tab;
+
+ if (unmodified_keyval == GDK_KEY_Sys_Req && (used_modifiers & GDK_ALT_MASK) != 0)
+ {
+ /* HACK: we don't want to use SysRq as a keybinding (but we do
+ * want Alt+Print), so we avoid translation from Alt+Print to SysRq */
+ unmodified_keyval = GDK_KEY_Print;
+ }
+
+ *out_keyval = unmodified_keyval;
+ *out_mask = used_modifiers;
+}
diff --git a/panels/keyboard/keyboard-shortcuts.h b/panels/keyboard/keyboard-shortcuts.h
new file mode 100644
index 0000000..7c9b978
--- /dev/null
+++ b/panels/keyboard/keyboard-shortcuts.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2010 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Thomas Wood <thomas.wood@intel.com>
+ * Rodrigo Moya <rodrigo@gnome.org>
+ */
+
+#include <gtk/gtk.h>
+#include <shell/cc-panel.h>
+
+#include "cc-keyboard-item.h"
+
+typedef struct {
+ /* The untranslated name, combine with ->package to translate */
+ char *name;
+ /* The group of keybindings (system or application) */
+ char *group;
+ /* The gettext package to use to translate the section title */
+ char *package;
+ /* Name of the window manager the keys would apply to */
+ char *wm_name;
+ /* The GSettings schema for the whole file, if any */
+ char *schema;
+ /* an array of KeyListEntry */
+ GArray *entries;
+} KeyList;
+
+typedef struct
+{
+ CcKeyboardItemType type;
+ char *schema; /* GSettings schema name, if any */
+ char *description; /* description for GSettings types */
+ char *name; /* GSettings schema path, or GSettings key name depending on type */
+ char *reverse_entry;
+ gboolean is_reversed;
+ gboolean hidden;
+} KeyListEntry;
+
+typedef struct {
+ CcKeyboardItem *orig_item;
+ CcKeyboardItem *conflict_item;
+ guint new_keyval;
+ GdkModifierType new_mask;
+ guint new_keycode;
+} CcUniquenessData;
+
+enum
+{
+ SECTION_DESCRIPTION_COLUMN,
+ SECTION_ID_COLUMN,
+ SECTION_GROUP_COLUMN,
+ SECTION_N_COLUMNS
+};
+
+gchar* find_free_settings_path (GSettings *settings);
+
+gboolean is_valid_binding (const CcKeyCombo *combo);
+
+gboolean is_empty_binding (const CcKeyCombo *combo);
+
+gboolean is_valid_accel (const CcKeyCombo *combo);
+
+KeyList* parse_keylist_from_file (const gchar *path);
+
+gchar* convert_keysym_state_to_string (const CcKeyCombo *combo);
+
+void normalize_keyval_and_mask (guint keyval,
+ GdkModifierType mask,
+ guint group,
+ guint *out_keyval,
+ GdkModifierType *out_mask);
diff --git a/panels/keyboard/keyboard.gresource.xml b/panels/keyboard/keyboard.gresource.xml
new file mode 100644
index 0000000..a310f05
--- /dev/null
+++ b/panels/keyboard/keyboard.gresource.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/keyboard">
+ <file preprocess="xml-stripblanks">enter-keyboard-shortcut.svg</file>
+ <file preprocess="xml-stripblanks">cc-xkb-modifier-dialog.ui</file>
+ <file preprocess="xml-stripblanks">cc-keyboard-shortcut-row.ui</file>
+ <file preprocess="xml-stripblanks">cc-keyboard-shortcut-dialog.ui</file>
+ <file preprocess="xml-stripblanks">cc-keyboard-panel.ui</file>
+ <file preprocess="xml-stripblanks">cc-keyboard-shortcut-editor.ui</file>
+ <file preprocess="xml-stripblanks">cc-input-chooser.ui</file>
+ <file preprocess="xml-stripblanks">cc-input-row.ui</file>
+ <file preprocess="xml-stripblanks">cc-input-list-box.ui</file>
+ </gresource>
+</gresources>
diff --git a/panels/keyboard/meson.build b/panels/keyboard/meson.build
new file mode 100644
index 0000000..cb88614
--- /dev/null
+++ b/panels/keyboard/meson.build
@@ -0,0 +1,106 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+pc_conf = configuration_data()
+pc_conf.set('prefix', control_center_prefix)
+pc_conf.set('datarootdir', control_center_datadir)
+pc_conf.set('datadir', control_center_datadir)
+pc_conf.set('PACKAGE', meson.project_name())
+pc_conf.set('VERSION', meson.project_version())
+
+pc = 'gnome-keybindings.pc'
+
+configure_file(
+ input: pc + '.in',
+ output: pc,
+ install: true,
+ install_dir: join_paths(control_center_datadir, 'pkgconfig'),
+ configuration: pc_conf
+)
+
+xml_files = [
+ '00-multimedia.xml',
+ '01-input-sources.xml',
+ '01-launchers.xml',
+ '01-system.xml',
+ '50-accessibility.xml'
+]
+
+foreach file: xml_files
+ i18n.merge_file(
+ input: file + '.in',
+ output: file,
+ po_dir: po_dir,
+ data_dirs: its_dir,
+ install: true,
+ install_dir: join_paths(control_center_pkgdatadir, 'keybindings')
+ )
+endforeach
+
+sources = files(
+ 'cc-xkb-modifier-dialog.c',
+ 'cc-keyboard-shortcut-row.c',
+ 'cc-keyboard-shortcut-dialog.c',
+ 'cc-keyboard-panel.c',
+ 'cc-keyboard-item.c',
+ 'cc-keyboard-manager.c',
+ 'cc-keyboard-shortcut-editor.c',
+ 'keyboard-shortcuts.c',
+ 'cc-ibus-utils.c',
+ 'cc-input-chooser.c',
+ 'cc-input-row.c',
+ 'cc-input-source.c',
+ 'cc-input-source-ibus.c',
+ 'cc-input-list-box.c',
+ 'cc-input-source-xkb.c',
+)
+
+resource_data = files(
+ 'enter-keyboard-shortcut.svg',
+ 'cc-keyboard-panel.ui',
+ 'cc-keyboard-shortcut-editor.ui',
+ 'cc-input-chooser.ui',
+)
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname,
+ dependencies: resource_data,
+ export: true
+)
+
+deps = common_deps + [
+ gnome_desktop_dep,
+ x11_dep
+]
+
+if enable_ibus
+ deps += ibus_dep
+endif
+
+keyboard_panel_lib = static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [top_inc, common_inc],
+ dependencies: deps,
+ c_args: cflags
+)
+panels_libs += keyboard_panel_lib
+
+subdir('icons')
diff --git a/panels/location/cc-location-panel.c b/panels/location/cc-location-panel.c
new file mode 100644
index 0000000..4e1077e
--- /dev/null
+++ b/panels/location/cc-location-panel.c
@@ -0,0 +1,427 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2018 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#include "cc-location-panel.h"
+#include "cc-location-resources.h"
+#include "cc-util.h"
+
+#include <adwaita.h>
+#include <gio/gdesktopappinfo.h>
+#include <glib/gi18n.h>
+
+#define LOCATION_ENABLED "enabled"
+#define APP_PERMISSIONS_TABLE "location"
+#define APP_PERMISSIONS_ID "location"
+
+struct _CcLocationPanel
+{
+ CcPanel parent_instance;
+
+ GtkStack *stack;
+ GtkListBox *location_apps_list_box;
+ GtkSwitch *main_switch;
+
+ GSettings *location_settings;
+
+ GDBusProxy *perm_store;
+ GVariant *location_apps_perms;
+ GVariant *location_apps_data;
+ GHashTable *location_app_switches;
+
+ GtkSizeGroup *location_icon_size_group;
+};
+
+CC_PANEL_REGISTER (CcLocationPanel, cc_location_panel)
+
+typedef struct
+{
+ CcLocationPanel *self;
+ GtkWidget *widget;
+ gchar *app_id;
+ gboolean changing_state;
+ gboolean pending_state;
+} LocationAppStateData;
+
+static void
+location_app_state_data_free (LocationAppStateData *data)
+{
+ g_free (data->app_id);
+ g_slice_free (LocationAppStateData, data);
+}
+
+static void
+on_perm_store_set_done (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GVariant) results = NULL;
+ g_autoptr(GError) error = NULL;
+ LocationAppStateData *data;
+
+ results = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
+ res,
+ &error);
+ if (results == NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to store permissions: %s", error->message);
+
+ return;
+ }
+
+ data = (LocationAppStateData *) user_data;
+ data->changing_state = FALSE;
+ gtk_switch_set_state (GTK_SWITCH (data->widget), data->pending_state);
+}
+
+static gboolean
+on_location_app_state_set (GtkSwitch *widget,
+ gboolean state,
+ gpointer user_data)
+{
+ LocationAppStateData *data = (LocationAppStateData *) user_data;
+ CcLocationPanel *self = data->self;
+ GVariant *params;
+ GVariantIter iter;
+ const gchar *key;
+ gchar **value;
+ GVariantBuilder builder;
+
+ if (data->changing_state)
+ return TRUE;
+
+ data->changing_state = TRUE;
+ data->pending_state = state;
+
+ g_variant_iter_init (&iter, self->location_apps_perms);
+ g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
+ while (g_variant_iter_loop (&iter, "{&s^a&s}", &key, &value))
+ {
+ /* It's OK to drop the entry if it's not in expected format */
+ if (g_strv_length (value) < 2)
+ continue;
+
+ if (g_strcmp0 (data->app_id, key) == 0)
+ value[0] = state ? "EXACT" : "NONE";
+
+ g_variant_builder_add (&builder, "{s^as}", key, value);
+ }
+
+ params = g_variant_new ("(sbsa{sas}v)",
+ APP_PERMISSIONS_TABLE,
+ TRUE,
+ APP_PERMISSIONS_ID,
+ &builder,
+ self->location_apps_data);
+
+ g_dbus_proxy_call (self->perm_store,
+ "Set",
+ params,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ on_perm_store_set_done,
+ data);
+
+ return TRUE;
+}
+
+static void
+add_location_app (CcLocationPanel *self,
+ const gchar *app_id,
+ gboolean enabled,
+ gint64 last_used)
+{
+ LocationAppStateData *data;
+ GDesktopAppInfo *app_info;
+ GDateTime *t;
+ GtkWidget *row, *w;
+ GIcon *icon;
+ gchar *last_used_str;
+ gchar *desktop_id;
+
+ w = g_hash_table_lookup (self->location_app_switches, app_id);
+ if (w != NULL)
+ {
+ gtk_switch_set_active (GTK_SWITCH (w), enabled);
+ return;
+ }
+
+ desktop_id = g_strdup_printf ("%s.desktop", app_id);
+ app_info = g_desktop_app_info_new (desktop_id);
+ g_free (desktop_id);
+ if (app_info == NULL)
+ return;
+
+ row = adw_action_row_new ();
+ gtk_list_box_append (self->location_apps_list_box, row);
+
+ icon = g_app_info_get_icon (G_APP_INFO (app_info));
+ w = gtk_image_new_from_gicon (icon);
+ gtk_widget_set_valign (w, GTK_ALIGN_CENTER);
+ gtk_size_group_add_widget (self->location_icon_size_group, w);
+ adw_action_row_add_prefix (ADW_ACTION_ROW (row), w);
+
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row),
+ g_app_info_get_name (G_APP_INFO (app_info)));
+
+ t = g_date_time_new_from_unix_utc (last_used);
+ last_used_str = cc_util_get_smart_date (t);
+ w = gtk_label_new (last_used_str);
+ g_free (last_used_str);
+ gtk_style_context_add_class (gtk_widget_get_style_context (w), "dim-label");
+ gtk_widget_set_margin_start (w, 12);
+ gtk_widget_set_margin_end (w, 12);
+ gtk_widget_set_valign (w, GTK_ALIGN_CENTER);
+ adw_action_row_add_suffix (ADW_ACTION_ROW (row), w);
+
+ w = gtk_switch_new ();
+ gtk_switch_set_active (GTK_SWITCH (w), enabled);
+ gtk_widget_set_valign (w, GTK_ALIGN_CENTER);
+ adw_action_row_add_suffix (ADW_ACTION_ROW (row), w);
+ g_settings_bind (self->location_settings, LOCATION_ENABLED,
+ w, "sensitive",
+ G_SETTINGS_BIND_DEFAULT);
+ g_hash_table_insert (self->location_app_switches,
+ g_strdup (app_id),
+ g_object_ref (w));
+
+ data = g_slice_new (LocationAppStateData);
+ data->self = self;
+ data->app_id = g_strdup (app_id);
+ data->widget = w;
+ data->changing_state = FALSE;
+ g_signal_connect_data (w,
+ "state-set",
+ G_CALLBACK (on_location_app_state_set),
+ data,
+ (GClosureNotify) location_app_state_data_free,
+ 0);
+}
+
+static gboolean
+to_child_name (GBinding *binding,
+ const GValue *from,
+ GValue *to,
+ gpointer user_data)
+{
+ if (g_value_get_boolean (from))
+ g_value_set_string (to, "content");
+ else
+ g_value_set_string (to, "empty");
+ return TRUE;
+}
+
+/* Steals permissions and permissions_data references */
+static void
+update_perm_store (CcLocationPanel *self,
+ GVariant *permissions,
+ GVariant *permissions_data)
+{
+ GVariantIter iter;
+ const gchar *key;
+ gchar **value;
+
+ g_clear_pointer (&self->location_apps_perms, g_variant_unref);
+ self->location_apps_perms = permissions;
+
+ g_clear_pointer (&self->location_apps_data, g_variant_unref);
+ self->location_apps_data = permissions_data;
+
+ g_variant_iter_init (&iter, permissions);
+ while (g_variant_iter_loop (&iter, "{&s^a&s}", &key, &value))
+ {
+ gboolean enabled;
+ gint64 last_used;
+
+ if (g_strv_length (value) < 2)
+ {
+ g_debug ("Permissions for %s in incorrect format, ignoring..", key);
+ continue;
+ }
+
+ enabled = (g_strcmp0 (value[0], "NONE") != 0);
+ last_used = g_ascii_strtoll (value[1], NULL, 10);
+
+ add_location_app (self, key, enabled, last_used);
+ }
+}
+
+static void
+on_perm_store_signal (GDBusProxy *proxy,
+ gchar *sender_name,
+ gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ GVariant *permissions, *permissions_data;
+
+ if (g_strcmp0 (signal_name, "Changed") != 0)
+ return;
+
+ permissions = g_variant_get_child_value (parameters, 4);
+ permissions_data = g_variant_get_child_value (parameters, 3);
+ update_perm_store (user_data, permissions, permissions_data);
+}
+
+static void
+on_perm_store_lookup_done(GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+ GVariant *ret, *permissions, *permissions_data;
+
+ ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
+ res,
+ &error);
+ if (ret == NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed fetch permissions from flatpak permission store: %s",
+ error->message);
+ return;
+ }
+
+ permissions = g_variant_get_child_value (ret, 0);
+ permissions_data = g_variant_get_child_value (ret, 1);
+ update_perm_store (user_data, permissions, permissions_data);
+
+ g_signal_connect_object (source_object,
+ "g-signal",
+ G_CALLBACK (on_perm_store_signal),
+ user_data,
+ 0);
+}
+
+static void
+on_perm_store_ready (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+ CcLocationPanel *self;
+ GDBusProxy *proxy;
+ GVariant *params;
+
+ proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+ if (proxy == NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to connect to flatpak permission store: %s",
+ error->message);
+
+ return;
+ }
+ self = user_data;
+ self->perm_store = proxy;
+
+ params = g_variant_new ("(ss)",
+ APP_PERMISSIONS_TABLE,
+ APP_PERMISSIONS_ID);
+ g_dbus_proxy_call (self->perm_store,
+ "Lookup",
+ params,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ on_perm_store_lookup_done,
+ self);
+}
+
+static void
+cc_location_panel_finalize (GObject *object)
+{
+ CcLocationPanel *self = CC_LOCATION_PANEL (object);
+
+ g_clear_object (&self->location_settings);
+ g_clear_object (&self->perm_store);
+ g_clear_object (&self->location_icon_size_group);
+ g_clear_pointer (&self->location_apps_perms, g_variant_unref);
+ g_clear_pointer (&self->location_apps_data, g_variant_unref);
+ g_clear_pointer (&self->location_app_switches, g_hash_table_unref);
+
+ G_OBJECT_CLASS (cc_location_panel_parent_class)->finalize (object);
+}
+
+static const char *
+cc_location_panel_get_help_uri (CcPanel *panel)
+{
+ return "help:gnome-help/location";
+}
+
+static void
+cc_location_panel_class_init (CcLocationPanelClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ panel_class->get_help_uri = cc_location_panel_get_help_uri;
+
+ object_class->finalize = cc_location_panel_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/location/cc-location-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcLocationPanel, stack);
+ gtk_widget_class_bind_template_child (widget_class, CcLocationPanel, location_apps_list_box);
+ gtk_widget_class_bind_template_child (widget_class, CcLocationPanel, main_switch);
+}
+
+static void
+cc_location_panel_init (CcLocationPanel *self)
+{
+ g_resources_register (cc_location_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->location_icon_size_group = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);
+ self->location_settings = g_settings_new ("org.gnome.system.location");
+
+ g_settings_bind (self->location_settings,
+ LOCATION_ENABLED,
+ self->main_switch,
+ "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_object_bind_property_full (self->main_switch,
+ "active",
+ self->stack,
+ "visible-child-name",
+ G_BINDING_SYNC_CREATE,
+ to_child_name,
+ NULL,
+ NULL, NULL);
+
+ self->location_app_switches = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ g_object_unref);
+
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.freedesktop.impl.portal.PermissionStore",
+ "/org/freedesktop/impl/portal/PermissionStore",
+ "org.freedesktop.impl.portal.PermissionStore",
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ on_perm_store_ready,
+ self);
+}
diff --git a/panels/location/cc-location-panel.h b/panels/location/cc-location-panel.h
new file mode 100644
index 0000000..6f950cc
--- /dev/null
+++ b/panels/location/cc-location-panel.h
@@ -0,0 +1,30 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2018 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_LOCATION_PANEL (cc_location_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcLocationPanel, cc_location_panel, CC, LOCATION_PANEL, CcPanel)
+
+G_END_DECLS
diff --git a/panels/location/cc-location-panel.ui b/panels/location/cc-location-panel.ui
new file mode 100644
index 0000000..ffe03a9
--- /dev/null
+++ b/panels/location/cc-location-panel.ui
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcLocationPanel" parent="CcPanel">
+
+ <child type="titlebar-end">
+ <object class="GtkSwitch" id="main_switch">
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Enabled</property>
+ </accessibility>
+ </object>
+ </child>
+
+ <child type="content">
+ <object class="GtkStack" id="stack">
+
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">empty</property>
+ <property name="child">
+ <object class="AdwStatusPage">
+ <property name="icon-name">location-services-disabled-symbolic</property>
+ <property name="title" translatable="yes">Location Services Turned Off</property>
+ <property name="description" translatable="yes">No applications can obtain location information.</property>
+ </object>
+
+ </property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">content</property>
+ <property name="child">
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="description" translatable="yes">Location services allow applications to know your location. Using Wi-Fi and mobile broadband increases accuracy.
+
+Uses Mozilla Location Service: &lt;a href=&apos;https://location.services.mozilla.com/privacy&apos;&gt;Privacy Policy&lt;/a&gt;
+
+Allow the applications below to determine your location.</property>
+ <child>
+ <object class="GtkListBox" id="location_apps_list_box">
+ <property name="selection-mode">none</property>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+
+ <child type="placeholder">
+ <object class="GtkLabel">
+ <property name="margin_top">18</property>
+ <property name="margin_bottom">18</property>
+ <property name="margin_start">18</property>
+ <property name="margin_end">18</property>
+ <property name="label" translatable="yes">No Applications Have Asked for Location Access</property>
+ <property name="wrap">true</property>
+ <property name="max-width-chars">50</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/location/gnome-location-panel.desktop.in.in b/panels/location/gnome-location-panel.desktop.in.in
new file mode 100644
index 0000000..bb3c220
--- /dev/null
+++ b/panels/location/gnome-location-panel.desktop.in.in
@@ -0,0 +1,19 @@
+[Desktop Entry]
+Name=Location Services
+Comment=Protect your location information
+Exec=gnome-control-center location
+# FIXME
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-location-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-PrivacySettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=privacy
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: Search terms to find the Location panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=location;gps;private;privacy;
diff --git a/panels/location/icons/meson.build b/panels/location/icons/meson.build
new file mode 100644
index 0000000..035ebfc
--- /dev/null
+++ b/panels/location/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-location-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/location/icons/scalable/org.gnome.Settings-location-symbolic.svg b/panels/location/icons/scalable/org.gnome.Settings-location-symbolic.svg
new file mode 100644
index 0000000..002dae9
--- /dev/null
+++ b/panels/location/icons/scalable/org.gnome.Settings-location-symbolic.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <path d="m 8 1 c -2.761719 0 -5 2.238281 -5 5 c 0 0.171875 0.015625 0.332031 0.03125 0.5 s 0.035156 0.335938 0.0625 0.5 c 0.570312 3.511719 2.90625 6.003906 4.90625 8.003906 c 2 -2 4.335938 -4.488281 4.90625 -8.003906 c 0.027344 -0.164062 0.050781 -0.332031 0.0625 -0.5 c 0.015625 -0.167969 0.03125 -0.328125 0.03125 -0.5 c 0 -2.761719 -2.238281 -5 -5 -5 z m 0 3 c 1.105469 0 2 0.894531 2 2 s -0.894531 2 -2 2 s -2 -0.894531 -2 -2 s 0.894531 -2 2 -2 z m 0 0" fill="#2e3436"/>
+</svg>
diff --git a/panels/location/location.gresource.xml b/panels/location/location.gresource.xml
new file mode 100644
index 0000000..02a27aa
--- /dev/null
+++ b/panels/location/location.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/location">
+ <file preprocess="xml-stripblanks">cc-location-panel.ui</file>
+ </gresource>
+</gresources>
diff --git a/panels/location/meson.build b/panels/location/meson.build
new file mode 100644
index 0000000..084b338
--- /dev/null
+++ b/panels/location/meson.build
@@ -0,0 +1,41 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+sources = files('cc-location-panel.c')
+
+resource_data = files('cc-location-panel.ui')
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname,
+ dependencies: resource_data,
+ export: true
+)
+
+cflags += '-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir)
+
+panels_libs += static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [top_inc, common_inc],
+ dependencies: common_deps,
+ c_args: cflags
+)
+
+subdir('icons')
diff --git a/panels/meson.build b/panels/meson.build
new file mode 100644
index 0000000..cb732f2
--- /dev/null
+++ b/panels/meson.build
@@ -0,0 +1,56 @@
+subdir('common')
+
+panels = [
+ 'applications',
+ 'background',
+ 'camera',
+ 'color',
+ 'datetime',
+ 'default-apps',
+ 'diagnostics',
+ 'display',
+ 'firmware-security',
+ 'info-overview',
+ 'keyboard',
+ 'location',
+ 'microphone',
+ 'mouse',
+ 'multitasking',
+ 'notifications',
+ 'online-accounts',
+ 'power',
+ 'printers',
+ 'region',
+ 'removable-media',
+ 'screen',
+ 'search',
+ 'sharing',
+ 'sound',
+ 'universal-access',
+ 'usage',
+ 'user-accounts',
+ 'wwan',
+]
+
+if host_is_linux
+ panels += ['network']
+endif
+
+if host_is_linux_not_s390
+ panels += [
+ 'bluetooth',
+ 'thunderbolt',
+ 'wacom'
+ ]
+endif
+
+panels_list = []
+panels_libs = []
+foreach cappletname: panels
+ cflags = [
+ '-DG_LOG_DOMAIN="@0@-cc-panel"'.format(cappletname),
+ '-DPANEL_ID="@0@"'.format(cappletname)
+ ]
+
+ subdir(cappletname)
+endforeach
diff --git a/panels/microphone/cc-microphone-panel.c b/panels/microphone/cc-microphone-panel.c
new file mode 100644
index 0000000..5b56c24
--- /dev/null
+++ b/panels/microphone/cc-microphone-panel.c
@@ -0,0 +1,413 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2018 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#include "cc-microphone-panel.h"
+#include "cc-microphone-resources.h"
+#include "cc-util.h"
+
+#include <gio/gdesktopappinfo.h>
+#include <glib/gi18n.h>
+
+#define APP_PERMISSIONS_TABLE "devices"
+#define APP_PERMISSIONS_ID "microphone"
+
+struct _CcMicrophonePanel
+{
+ CcPanel parent_instance;
+
+ GtkSwitch *main_switch;
+ GtkListBox *microphone_apps_list_box;
+ GtkStack *stack;
+
+ GSettings *privacy_settings;
+
+ GDBusProxy *perm_store;
+ GVariant *microphone_apps_perms;
+ GVariant *microphone_apps_data;
+ GHashTable *microphone_app_switches;
+
+ GtkSizeGroup *microphone_icon_size_group;
+};
+
+CC_PANEL_REGISTER (CcMicrophonePanel, cc_microphone_panel)
+
+typedef struct
+{
+ CcMicrophonePanel *self;
+ GtkWidget *widget;
+ gchar *app_id;
+ gboolean changing_state;
+ gboolean pending_state;
+} MicrophoneAppStateData;
+
+static void
+microphone_app_state_data_free (MicrophoneAppStateData *data)
+{
+ g_free (data->app_id);
+ g_slice_free (MicrophoneAppStateData, data);
+}
+
+static void
+on_perm_store_set_done (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ MicrophoneAppStateData *data;
+ GVariant *results;
+ GError *error = NULL;
+
+ results = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
+ res,
+ &error);
+ if (results == NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to store permissions: %s", error->message);
+ g_error_free (error);
+
+ return;
+ }
+ g_variant_unref (results);
+
+ data = (MicrophoneAppStateData *) user_data;
+ data->changing_state = FALSE;
+ gtk_switch_set_state (GTK_SWITCH (data->widget), data->pending_state);
+}
+
+static gboolean
+on_microphone_app_state_set (GtkSwitch *widget,
+ gboolean state,
+ gpointer user_data)
+{
+ MicrophoneAppStateData *data = (MicrophoneAppStateData *) user_data;
+ CcMicrophonePanel *self = data->self;
+ GVariant *params;
+ GVariantIter iter;
+ const gchar *key;
+ gchar **value;
+ GVariantBuilder builder;
+
+ if (data->changing_state)
+ return TRUE;
+
+ data->changing_state = TRUE;
+ data->pending_state = state;
+
+ g_variant_iter_init (&iter, self->microphone_apps_perms);
+ g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
+ while (g_variant_iter_loop (&iter, "{&s^a&s}", &key, &value))
+ {
+ if (g_strv_length (value) != 1)
+ /* It's OK to drop the entry if it's not in expected format */
+ continue;
+
+ if (g_strcmp0 (data->app_id, key) == 0)
+ value[0] = state ? "yes" : "no";
+
+ g_variant_builder_add (&builder, "{s^as}", key, value);
+ }
+
+ params = g_variant_new ("(sbsa{sas}v)",
+ APP_PERMISSIONS_TABLE,
+ TRUE,
+ APP_PERMISSIONS_ID,
+ &builder,
+ self->microphone_apps_data);
+
+ g_dbus_proxy_call (self->perm_store,
+ "Set",
+ params,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ on_perm_store_set_done,
+ data);
+
+ return TRUE;
+}
+
+static void
+add_microphone_app (CcMicrophonePanel *self,
+ const gchar *app_id,
+ gboolean enabled)
+{
+ GDesktopAppInfo *app_info;
+ char *desktop_id;
+ GtkWidget *row, *w;
+ GIcon *icon;
+ MicrophoneAppStateData *data;
+
+ w = g_hash_table_lookup (self->microphone_app_switches, app_id);
+ if (w != NULL)
+ {
+ gtk_switch_set_active (GTK_SWITCH (w), enabled);
+
+ return;
+ }
+
+ desktop_id = g_strdup_printf ("%s.desktop", app_id);
+ app_info = g_desktop_app_info_new (desktop_id);
+ g_free (desktop_id);
+ if (app_info == NULL)
+ return;
+
+ row = adw_action_row_new ();
+ gtk_list_box_append (self->microphone_apps_list_box, row);
+
+ icon = g_app_info_get_icon (G_APP_INFO (app_info));
+ w = gtk_image_new_from_gicon (icon);
+ gtk_widget_set_valign (w, GTK_ALIGN_CENTER);
+ gtk_size_group_add_widget (self->microphone_icon_size_group, w);
+ adw_action_row_add_prefix (ADW_ACTION_ROW (row), w);
+
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row),
+ g_app_info_get_name (G_APP_INFO (app_info)));
+
+ w = gtk_switch_new ();
+ gtk_switch_set_active (GTK_SWITCH (w), enabled);
+ gtk_widget_set_valign (w, GTK_ALIGN_CENTER);
+ adw_action_row_add_suffix (ADW_ACTION_ROW (row), w);
+ g_settings_bind (self->privacy_settings,
+ "disable-microphone",
+ w,
+ "sensitive",
+ G_SETTINGS_BIND_INVERT_BOOLEAN);
+ g_hash_table_insert (self->microphone_app_switches,
+ g_strdup (app_id),
+ g_object_ref (w));
+
+ data = g_slice_new (MicrophoneAppStateData);
+ data->self = self;
+ data->app_id = g_strdup (app_id);
+ data->widget = w;
+ data->changing_state = FALSE;
+ g_signal_connect_data (G_OBJECT (w),
+ "state-set",
+ G_CALLBACK (on_microphone_app_state_set),
+ data,
+ (GClosureNotify) microphone_app_state_data_free,
+ 0);
+}
+
+static gboolean
+to_child_name (GBinding *binding,
+ const GValue *from,
+ GValue *to,
+ gpointer user_data)
+{
+ if (g_value_get_boolean (from))
+ g_value_set_string (to, "content");
+ else
+ g_value_set_string (to, "empty");
+ return TRUE;
+}
+
+/* Steals permissions and permissions_data references */
+static void
+update_perm_store (CcMicrophonePanel *self,
+ GVariant *permissions,
+ GVariant *permissions_data)
+{
+ GVariantIter iter;
+ const gchar *key;
+ gchar **value;
+
+ g_clear_pointer (&self->microphone_apps_perms, g_variant_unref);
+ self->microphone_apps_perms = permissions;
+ g_clear_pointer (&self->microphone_apps_data, g_variant_unref);
+ self->microphone_apps_data = permissions_data;
+
+ g_variant_iter_init (&iter, permissions);
+ while (g_variant_iter_loop (&iter, "{&s^a&s}", &key, &value))
+ {
+ gboolean enabled;
+
+ if (g_strv_length (value) != 1)
+ {
+ g_debug ("Permissions for %s in incorrect format, ignoring.", key);
+ continue;
+ }
+
+ enabled = (g_strcmp0 (value[0], "no") != 0);
+
+ add_microphone_app (self, key, enabled);
+ }
+}
+
+static void
+on_perm_store_signal (GDBusProxy *proxy,
+ gchar *sender_name,
+ gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ GVariant *permissions, *permissions_data;
+
+ if (g_strcmp0 (signal_name, "Changed") != 0)
+ return;
+
+ permissions = g_variant_get_child_value (parameters, 4);
+ permissions_data = g_variant_get_child_value (parameters, 3);
+ update_perm_store (user_data, permissions, permissions_data);
+}
+
+static void
+on_perm_store_lookup_done (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcMicrophonePanel *self = user_data;
+ g_autoptr(GError) error = NULL;
+ GVariant *ret, *permissions, *permissions_data;
+
+ ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
+ res,
+ &error);
+ if (ret == NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed fetch permissions from flatpak permission store: %s", error->message);
+ return;
+ }
+
+ permissions = g_variant_get_child_value (ret, 0);
+ permissions_data = g_variant_get_child_value (ret, 1);
+ update_perm_store (user_data, permissions, permissions_data);
+
+ g_signal_connect_object (source_object,
+ "g-signal",
+ G_CALLBACK (on_perm_store_signal),
+ self,
+ 0);
+}
+
+static void
+on_perm_store_ready (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcMicrophonePanel *self;
+ g_autoptr(GError) error = NULL;
+ GDBusProxy *proxy;
+ GVariant *params;
+
+ proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+ if (proxy == NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to connect to flatpak permission store: %s", error->message);
+ return;
+ }
+ self = user_data;
+ self->perm_store = proxy;
+
+ params = g_variant_new ("(ss)",
+ APP_PERMISSIONS_TABLE,
+ APP_PERMISSIONS_ID);
+ g_dbus_proxy_call (self->perm_store,
+ "Lookup",
+ params,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ on_perm_store_lookup_done,
+ self);
+}
+
+static void
+cc_microphone_panel_finalize (GObject *object)
+{
+ CcMicrophonePanel *self = CC_MICROPHONE_PANEL (object);
+
+ g_clear_object (&self->privacy_settings);
+ g_clear_object (&self->perm_store);
+ g_clear_object (&self->microphone_icon_size_group);
+ g_clear_pointer (&self->microphone_apps_perms, g_variant_unref);
+ g_clear_pointer (&self->microphone_apps_data, g_variant_unref);
+ g_clear_pointer (&self->microphone_app_switches, g_hash_table_unref);
+
+ G_OBJECT_CLASS (cc_microphone_panel_parent_class)->finalize (object);
+}
+
+static const char *
+cc_microphone_panel_get_help_uri (CcPanel *panel)
+{
+ return "help:gnome-help/microphone";
+}
+
+static void
+cc_microphone_panel_class_init (CcMicrophonePanelClass *klass)
+{
+ CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ panel_class->get_help_uri = cc_microphone_panel_get_help_uri;
+
+ object_class->finalize = cc_microphone_panel_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/microphone/cc-microphone-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcMicrophonePanel, main_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcMicrophonePanel, stack);
+ gtk_widget_class_bind_template_child (widget_class, CcMicrophonePanel, microphone_apps_list_box);
+}
+
+static void
+cc_microphone_panel_init (CcMicrophonePanel *self)
+{
+ g_resources_register (cc_microphone_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->microphone_icon_size_group = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);
+
+ self->privacy_settings = g_settings_new ("org.gnome.desktop.privacy");
+
+ g_settings_bind (self->privacy_settings,
+ "disable-microphone",
+ self->main_switch,
+ "active",
+ G_SETTINGS_BIND_INVERT_BOOLEAN);
+
+ g_object_bind_property_full (self->main_switch,
+ "active",
+ self->stack,
+ "visible-child-name",
+ G_BINDING_SYNC_CREATE,
+ to_child_name,
+ NULL,
+ NULL, NULL);
+
+ self->microphone_app_switches = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ g_object_unref);
+
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.freedesktop.impl.portal.PermissionStore",
+ "/org/freedesktop/impl/portal/PermissionStore",
+ "org.freedesktop.impl.portal.PermissionStore",
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ on_perm_store_ready,
+ self);
+}
diff --git a/panels/microphone/cc-microphone-panel.h b/panels/microphone/cc-microphone-panel.h
new file mode 100644
index 0000000..7b5aee5
--- /dev/null
+++ b/panels/microphone/cc-microphone-panel.h
@@ -0,0 +1,30 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2018 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_MICROPHONE_PANEL (cc_microphone_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcMicrophonePanel, cc_microphone_panel, CC, MICROPHONE_PANEL, CcPanel)
+
+G_END_DECLS
diff --git a/panels/microphone/cc-microphone-panel.ui b/panels/microphone/cc-microphone-panel.ui
new file mode 100644
index 0000000..96695f1
--- /dev/null
+++ b/panels/microphone/cc-microphone-panel.ui
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcMicrophonePanel" parent="CcPanel">
+
+ <child type="titlebar-end">
+ <object class="GtkSwitch" id="main_switch">
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Enable</property>
+ </accessibility>
+ </object>
+ </child>
+
+ <child type="content">
+ <object class="GtkStack" id="stack">
+
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">empty</property>
+ <property name="child">
+ <object class="AdwStatusPage">
+ <property name="icon-name">microphone-disabled-symbolic</property>
+ <property name="title" translatable="yes">Microphone Turned Off</property>
+ <property name="description" translatable="yes">No applications can record sound.</property>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">content</property>
+ <property name="child">
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="description" translatable="yes">Use of the microphone allows applications to record and listen to audio. Disabling the microphone may cause some applications to not function properly.
+
+Allow the applications below to use your microphone.</property>
+ <child>
+ <object class="GtkListBox" id="microphone_apps_list_box">
+ <property name="can-focus">true</property>
+ <property name="selection-mode">none</property>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+
+ <child type="placeholder">
+ <object class="GtkLabel">
+ <property name="margin-top">18</property>
+ <property name="margin-bottom">18</property>
+ <property name="margin-start">18</property>
+ <property name="margin-end">18</property>
+ <property name="label" translatable="yes">No Applications Have Asked for Microphone Access</property>
+ <property name="wrap">true</property>
+ <property name="max-width-chars">50</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/microphone/gnome-microphone-panel.desktop.in.in b/panels/microphone/gnome-microphone-panel.desktop.in.in
new file mode 100644
index 0000000..1db40c4
--- /dev/null
+++ b/panels/microphone/gnome-microphone-panel.desktop.in.in
@@ -0,0 +1,19 @@
+[Desktop Entry]
+Name=Microphone
+Comment=Protect your conversations
+Exec=gnome-control-center microphone
+# FIXME
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-microphone-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-PrivacySettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=privacy
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: Search terms to find the Microphone panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=microphone;recording;application;privacy;
diff --git a/panels/microphone/icons/meson.build b/panels/microphone/icons/meson.build
new file mode 100644
index 0000000..d7c487d
--- /dev/null
+++ b/panels/microphone/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-microphone-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/microphone/icons/scalable/org.gnome.Settings-microphone-symbolic.svg b/panels/microphone/icons/scalable/org.gnome.Settings-microphone-symbolic.svg
new file mode 100644
index 0000000..55c9407
--- /dev/null
+++ b/panels/microphone/icons/scalable/org.gnome.Settings-microphone-symbolic.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <path d="m 8 0 c -1.660156 0 -3 1.339844 -3 3 v 5 c 0 1.660156 1.339844 3 3 3 s 3 -1.339844 3 -3 v -5 c 0 -1.660156 -1.339844 -3 -3 -3 z m -6 6 v 2.011719 c 0 2.964843 2.164062 5.421875 5 5.898437 v 2.089844 h 2 v -2.089844 c 2.835938 -0.476562 5 -2.933594 5 -5.898437 v -2.011719 h -1.5 v 2.011719 c 0 2.5 -1.992188 4.488281 -4.5 4.488281 s -4.5 -1.988281 -4.5 -4.488281 v -2.011719 z m 0 0" fill="#2e3436"/>
+</svg>
diff --git a/panels/microphone/meson.build b/panels/microphone/meson.build
new file mode 100644
index 0000000..16647a5
--- /dev/null
+++ b/panels/microphone/meson.build
@@ -0,0 +1,41 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+sources = files('cc-microphone-panel.c')
+
+resource_data = files('cc-microphone-panel.ui')
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname,
+ dependencies: resource_data,
+ export: true
+)
+
+cflags += '-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir)
+
+panels_libs += static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [top_inc, common_inc],
+ dependencies: common_deps,
+ c_args: cflags
+)
+
+subdir('icons')
diff --git a/panels/microphone/microphone.gresource.xml b/panels/microphone/microphone.gresource.xml
new file mode 100644
index 0000000..f3f938e
--- /dev/null
+++ b/panels/microphone/microphone.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/microphone">
+ <file preprocess="xml-stripblanks">cc-microphone-panel.ui</file>
+ </gresource>
+</gresources>
diff --git a/panels/mouse/cc-mouse-caps-helper.c b/panels/mouse/cc-mouse-caps-helper.c
new file mode 100644
index 0000000..6658f41
--- /dev/null
+++ b/panels/mouse/cc-mouse-caps-helper.c
@@ -0,0 +1,148 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2015 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Felipe Borges <feborges@redhat.com>
+ */
+
+#include <gdk/x11/gdkx.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/XInput2.h>
+
+#include "cc-mouse-caps-helper.h"
+
+static gboolean
+touchpad_check_capabilities_x11 (gboolean *have_two_finger_scrolling,
+ gboolean *have_edge_scrolling,
+ gboolean *have_tap_to_click)
+{
+ GdkDisplay *gdisplay;
+ Display *display;
+ g_autoptr(GList) devicelist = NULL;
+ GList *l;
+ Atom realtype, prop_scroll_methods, prop_tapping_enabled;
+ int realformat;
+ unsigned long nitems, bytes_after;
+ unsigned char *data;
+
+ gdisplay = gdk_display_get_default ();
+ display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+ prop_scroll_methods = XInternAtom (display, "libinput Scroll Methods Available", False);
+ prop_tapping_enabled = XInternAtom (display, "libinput Tapping Enabled", False);
+ if (!prop_scroll_methods || !prop_tapping_enabled)
+ return FALSE;
+
+ *have_two_finger_scrolling = FALSE;
+ *have_edge_scrolling = FALSE;
+ *have_tap_to_click = FALSE;
+
+ gdk_x11_display_error_trap_push (gdisplay);
+
+ devicelist = gdk_seat_get_devices (gdk_display_get_default_seat (gdk_display_get_default ()),
+ GDK_SEAT_CAPABILITY_ALL_POINTING);
+ for (l = devicelist; l != NULL; l = l->next) {
+ GdkDevice *device = l->data;
+ if (gdk_device_get_source (device) != GDK_SOURCE_TOUCHPAD)
+ continue;
+
+ /* xorg-x11-drv-libinput */
+ if ((XIGetProperty (display, gdk_x11_device_get_id (device), prop_scroll_methods,
+ 0, 2, False, XA_INTEGER, &realtype, &realformat, &nitems,
+ &bytes_after, &data) == Success) && (realtype != None)) {
+ /* Property data is booleans for two-finger, edge, on-button scroll available. */
+
+ if (data[0])
+ *have_two_finger_scrolling = TRUE;
+
+ if (data[1])
+ *have_edge_scrolling = TRUE;
+
+ XFree (data);
+ }
+
+ if ((XIGetProperty (display, gdk_x11_device_get_id (device), prop_tapping_enabled,
+ 0, 1, False, XA_INTEGER, &realtype, &realformat, &nitems,
+ &bytes_after, &data) == Success) && (realtype != None)) {
+ /* Property data is boolean for tapping enabled. */
+ *have_tap_to_click = TRUE;
+
+ XFree (data);
+ }
+ }
+
+ gdk_x11_display_error_trap_pop_ignored (gdisplay);
+
+ return TRUE;
+}
+
+gboolean
+cc_touchpad_check_capabilities (gboolean *have_two_finger_scrolling,
+ gboolean *have_edge_scrolling,
+ gboolean *have_tap_to_click)
+{
+ if (GDK_IS_X11_DISPLAY (gdk_display_get_default ()))
+ return touchpad_check_capabilities_x11 (have_two_finger_scrolling,
+ have_edge_scrolling,
+ have_tap_to_click);
+ /* else we unconditionally show all touchpad knobs */
+ *have_two_finger_scrolling = TRUE;
+ *have_edge_scrolling = TRUE;
+ *have_tap_to_click = TRUE;
+ return FALSE;
+}
+
+gboolean
+cc_synaptics_check (void)
+{
+ GdkDisplay *gdisplay;
+ Display *display;
+ g_autoptr(GList) devicelist = NULL;
+ GList *l;
+ Atom prop, realtype;
+ int realformat;
+ unsigned long nitems, bytes_after;
+ unsigned char *data;
+ gboolean have_synaptics = FALSE;
+
+ if (!GDK_IS_X11_DISPLAY (gdk_display_get_default ()))
+ return FALSE;
+
+ gdisplay = gdk_display_get_default ();
+ display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+ prop = XInternAtom (display, "Synaptics Capabilities", False);
+
+ gdk_x11_display_error_trap_push (gdisplay);
+
+ devicelist = gdk_seat_get_devices (gdk_display_get_default_seat (gdk_display_get_default ()),
+ GDK_SEAT_CAPABILITY_ALL_POINTING);
+ for (l = devicelist; l != NULL; l = l->next) {
+ GdkDevice *device = l->data;
+
+ if ((XIGetProperty (display, gdk_x11_device_get_id (device), prop,
+ 0, 2, False, XA_INTEGER, &realtype, &realformat, &nitems,
+ &bytes_after, &data) == Success) && (realtype != None)) {
+ have_synaptics = TRUE;
+ XFree (data);
+ }
+
+ if (have_synaptics)
+ break;
+ }
+
+ gdk_x11_display_error_trap_pop_ignored (gdisplay);
+
+ return have_synaptics;
+}
diff --git a/panels/mouse/cc-mouse-caps-helper.h b/panels/mouse/cc-mouse-caps-helper.h
new file mode 100644
index 0000000..93d9082
--- /dev/null
+++ b/panels/mouse/cc-mouse-caps-helper.h
@@ -0,0 +1,33 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2015 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Felipe Borges <feborges@redhat.com>
+ */
+
+#pragma once
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+gboolean cc_touchpad_check_capabilities (gboolean *have_two_finger_scrolling,
+ gboolean *have_edge_scrolling,
+ gboolean *have_tap_to_click);
+
+gboolean cc_synaptics_check (void);
+
+G_END_DECLS
diff --git a/panels/mouse/cc-mouse-panel.c b/panels/mouse/cc-mouse-panel.c
new file mode 100644
index 0000000..cdd28ab
--- /dev/null
+++ b/panels/mouse/cc-mouse-panel.c
@@ -0,0 +1,414 @@
+/*
+ * Copyright (C) 2010 Intel, Inc
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Thomas Wood <thomas.wood@intel.com>
+ * Rodrigo Moya <rodrigo@gnome.org>
+ * Ondrej Holy <oholy@redhat.com>
+ *
+ */
+
+#include <gdesktop-enums.h>
+#include <gtk/gtk.h>
+
+#include "cc-mouse-caps-helper.h"
+#include "cc-mouse-panel.h"
+#include "cc-mouse-resources.h"
+#include "cc-mouse-test.h"
+#include "gsd-device-manager.h"
+#include "gsd-input-helper.h"
+
+struct _CcMousePanel
+{
+ CcPanel parent_instance;
+
+ GtkListBoxRow *edge_scrolling_row;
+ GtkSwitch *edge_scrolling_switch;
+ AdwPreferencesGroup *mouse_group;
+ GtkSwitch *mouse_natural_scrolling_switch;
+ GtkScale *mouse_speed_scale;
+ CcMouseTest *mouse_test;
+ GtkBox *primary_button_box;
+ GtkToggleButton *primary_button_left;
+ GtkToggleButton *primary_button_right;
+ AdwPreferencesPage*preferences;
+ GtkStack *stack;
+ GtkListBoxRow *tap_to_click_row;
+ GtkSwitch *tap_to_click_switch;
+ GtkButton *test_button;
+ AdwPreferencesGroup *touchpad_group;
+ GtkListBoxRow *touchpad_natural_scrolling_row;
+ GtkSwitch *touchpad_natural_scrolling_switch;
+ GtkListBoxRow *touchpad_speed_row;
+ GtkScale *touchpad_speed_scale;
+ GtkSwitch *touchpad_toggle_switch;
+ GtkListBoxRow *two_finger_scrolling_row;
+ GtkSwitch *two_finger_scrolling_switch;
+
+ GSettings *mouse_settings;
+ GSettings *touchpad_settings;
+
+ gboolean have_mouse;
+ gboolean have_touchpad;
+ gboolean have_touchscreen;
+ gboolean have_synaptics;
+
+ gboolean left_handed;
+ GtkGesture *left_gesture;
+ GtkGesture *right_gesture;
+};
+
+CC_PANEL_REGISTER (CcMousePanel, cc_mouse_panel)
+
+static void
+setup_touchpad_options (CcMousePanel *self)
+{
+ gboolean edge_scroll_enabled;
+ gboolean two_finger_scroll_enabled;
+ gboolean have_two_finger_scrolling;
+ gboolean have_edge_scrolling;
+ gboolean have_tap_to_click;
+
+ if (self->have_synaptics || !self->have_touchpad) {
+ gtk_widget_hide (GTK_WIDGET (self->touchpad_group));
+ return;
+ }
+
+ cc_touchpad_check_capabilities (&have_two_finger_scrolling, &have_edge_scrolling, &have_tap_to_click);
+
+ gtk_widget_show (GTK_WIDGET (self->touchpad_group));
+
+ gtk_widget_set_visible (GTK_WIDGET (self->two_finger_scrolling_row), have_two_finger_scrolling);
+ gtk_widget_set_visible (GTK_WIDGET (self->edge_scrolling_row), have_edge_scrolling);
+ gtk_widget_set_visible (GTK_WIDGET (self->tap_to_click_row), have_tap_to_click);
+
+ edge_scroll_enabled = g_settings_get_boolean (self->touchpad_settings, "edge-scrolling-enabled");
+ two_finger_scroll_enabled = g_settings_get_boolean (self->touchpad_settings, "two-finger-scrolling-enabled");
+ if (edge_scroll_enabled && two_finger_scroll_enabled)
+ {
+ /* You cunning user set both, but you can only have one set in that UI */
+ gtk_switch_set_active (self->edge_scrolling_switch, FALSE);
+ }
+}
+
+static void
+two_finger_scrolling_changed_event (CcMousePanel *self,
+ gboolean state)
+{
+ /* Updating the setting will cause the "state" of the switch to be updated. */
+ g_settings_set_boolean (self->touchpad_settings, "two-finger-scrolling-enabled", state);
+
+ /* Disable edge scrolling if two-finger scrolling is enabled */
+ if (state && gtk_widget_get_visible (GTK_WIDGET (self->edge_scrolling_row)))
+ gtk_switch_set_active (self->edge_scrolling_switch, FALSE);
+}
+
+static void
+edge_scrolling_changed_event (CcMousePanel *self,
+ gboolean state)
+{
+ /* Updating the setting will cause the "state" of the switch to be updated. */
+ g_settings_set_boolean (self->touchpad_settings, "edge-scrolling-enabled", state);
+
+ /* Disable two-finger scrolling if edge scrolling is enabled */
+ if (state && gtk_widget_get_visible (GTK_WIDGET (self->two_finger_scrolling_row)))
+ gtk_switch_set_active (self->two_finger_scrolling_switch, FALSE);
+}
+
+static gboolean
+get_touchpad_enabled (GSettings *settings)
+{
+ GDesktopDeviceSendEvents send_events;
+
+ send_events = g_settings_get_enum (settings, "send-events");
+
+ return send_events == G_DESKTOP_DEVICE_SEND_EVENTS_ENABLED;
+}
+
+static gboolean
+show_touchpad_enabling_switch (CcMousePanel *self)
+{
+ if (!self->have_touchpad)
+ return FALSE;
+
+ g_debug ("Should we show the touchpad disable switch: have_mouse: %s have_touchscreen: %s\n",
+ self->have_mouse ? "true" : "false",
+ self->have_touchscreen ? "true" : "false");
+
+ /* Let's show the button when a mouse or touchscreen is present */
+ if (self->have_mouse || self->have_touchscreen)
+ return TRUE;
+
+ /* Let's also show when the touchpad is disabled. */
+ if (!get_touchpad_enabled (self->touchpad_settings))
+ return TRUE;
+
+ return FALSE;
+}
+
+static gboolean
+touchpad_enabled_get_mapping (GValue *value,
+ GVariant *variant,
+ gpointer user_data)
+{
+ gboolean enabled;
+
+ enabled = g_strcmp0 (g_variant_get_string (variant, NULL), "enabled") == 0;
+ g_value_set_boolean (value, enabled);
+
+ return TRUE;
+}
+
+static GVariant *
+touchpad_enabled_set_mapping (const GValue *value,
+ const GVariantType *type,
+ gpointer user_data)
+{
+ gboolean enabled;
+
+ enabled = g_value_get_boolean (value);
+
+ return g_variant_new_string (enabled ? "enabled" : "disabled");
+}
+
+static void
+pressed_cb (GtkButton *button)
+{
+ g_signal_emit_by_name (button, "activate");
+}
+
+static void
+handle_secondary_button (CcMousePanel *self,
+ GtkToggleButton *button,
+ GtkGesture *gesture)
+{
+ gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (gesture), FALSE);
+ gtk_gesture_single_set_exclusive (GTK_GESTURE_SINGLE (gesture), TRUE);
+ gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), GDK_BUTTON_SECONDARY);
+ g_signal_connect_swapped (gesture, "pressed", G_CALLBACK (pressed_cb), button);
+ gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (gesture), GTK_PHASE_BUBBLE);
+ gtk_widget_add_controller (GTK_WIDGET (button), GTK_EVENT_CONTROLLER (gesture));
+}
+
+/* Set up the property editors in the dialog. */
+static void
+setup_dialog (CcMousePanel *self)
+{
+ GtkToggleButton *button;
+
+ gtk_widget_set_direction (GTK_WIDGET (self->primary_button_box), GTK_TEXT_DIR_LTR);
+
+ self->left_handed = g_settings_get_boolean (self->mouse_settings, "left-handed");
+ button = self->left_handed ? self->primary_button_right : self->primary_button_left;
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
+
+ g_settings_bind (self->mouse_settings, "left-handed",
+ self->primary_button_left, "active",
+ G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_INVERT_BOOLEAN);
+ g_settings_bind (self->mouse_settings, "left-handed",
+ self->primary_button_right, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ /* Allow changing orientation with either button */
+ button = self->primary_button_right;
+ self->right_gesture = gtk_gesture_click_new ();
+ handle_secondary_button (self, button, self->right_gesture);
+ button = self->primary_button_left;
+ self->left_gesture = gtk_gesture_click_new ();
+ handle_secondary_button (self, button, self->left_gesture);
+
+ g_settings_bind (self->mouse_settings, "natural-scroll",
+ self->mouse_natural_scrolling_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ /* Mouse section */
+ gtk_widget_set_visible (GTK_WIDGET (self->mouse_group), self->have_mouse);
+
+ g_settings_bind (self->mouse_settings, "speed",
+ gtk_range_get_adjustment (GTK_RANGE (self->mouse_speed_scale)), "value",
+ G_SETTINGS_BIND_DEFAULT);
+
+ /* Touchpad section */
+ gtk_widget_set_visible (GTK_WIDGET (self->touchpad_toggle_switch), show_touchpad_enabling_switch (self));
+
+ g_settings_bind_with_mapping (self->touchpad_settings, "send-events",
+ self->touchpad_toggle_switch, "active",
+ G_SETTINGS_BIND_DEFAULT,
+ touchpad_enabled_get_mapping,
+ touchpad_enabled_set_mapping,
+ NULL, NULL);
+ g_settings_bind_with_mapping (self->touchpad_settings, "send-events",
+ self->touchpad_natural_scrolling_row, "sensitive",
+ G_SETTINGS_BIND_GET,
+ touchpad_enabled_get_mapping,
+ touchpad_enabled_set_mapping,
+ NULL, NULL);
+ g_settings_bind_with_mapping (self->touchpad_settings, "send-events",
+ self->touchpad_speed_row, "sensitive",
+ G_SETTINGS_BIND_GET,
+ touchpad_enabled_get_mapping,
+ touchpad_enabled_set_mapping,
+ NULL, NULL);
+ g_settings_bind_with_mapping (self->touchpad_settings, "send-events",
+ self->tap_to_click_row, "sensitive",
+ G_SETTINGS_BIND_GET,
+ touchpad_enabled_get_mapping,
+ touchpad_enabled_set_mapping,
+ NULL, NULL);
+ g_settings_bind_with_mapping (self->touchpad_settings, "send-events",
+ self->two_finger_scrolling_row, "sensitive",
+ G_SETTINGS_BIND_GET,
+ touchpad_enabled_get_mapping,
+ touchpad_enabled_set_mapping,
+ NULL, NULL);
+ g_settings_bind_with_mapping (self->touchpad_settings, "send-events",
+ self->edge_scrolling_row, "sensitive",
+ G_SETTINGS_BIND_GET,
+ touchpad_enabled_get_mapping,
+ touchpad_enabled_set_mapping,
+ NULL, NULL);
+
+ g_settings_bind (self->touchpad_settings, "natural-scroll",
+ self->touchpad_natural_scrolling_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind (self->touchpad_settings, "speed",
+ gtk_range_get_adjustment (GTK_RANGE (self->touchpad_speed_scale)), "value",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind (self->touchpad_settings, "tap-to-click",
+ self->tap_to_click_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind (self->touchpad_settings, "two-finger-scrolling-enabled",
+ self->two_finger_scrolling_switch, "state",
+ G_SETTINGS_BIND_GET);
+
+ g_settings_bind (self->touchpad_settings, "edge-scrolling-enabled",
+ self->edge_scrolling_switch, "state",
+ G_SETTINGS_BIND_GET);
+
+ setup_touchpad_options (self);
+}
+
+/* Callback issued when a button is clicked on the dialog */
+static void
+device_changed (CcMousePanel *self)
+{
+ self->have_touchpad = touchpad_is_present ();
+
+ setup_touchpad_options (self);
+
+ self->have_mouse = mouse_is_present ();
+ gtk_widget_set_visible (GTK_WIDGET (self->mouse_group), self->have_mouse);
+ gtk_widget_set_visible (GTK_WIDGET (self->touchpad_toggle_switch), show_touchpad_enabling_switch (self));
+}
+
+static void
+cc_mouse_panel_dispose (GObject *object)
+{
+ CcMousePanel *self = CC_MOUSE_PANEL (object);
+
+ g_clear_object (&self->mouse_settings);
+ g_clear_object (&self->touchpad_settings);
+
+ G_OBJECT_CLASS (cc_mouse_panel_parent_class)->dispose (object);
+}
+
+static const char *
+cc_mouse_panel_get_help_uri (CcPanel *panel)
+{
+ return "help:gnome-help/mouse";
+}
+
+static void
+test_button_toggled_cb (CcMousePanel *self)
+{
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->test_button)))
+ gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->mouse_test));
+ else
+ gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->preferences));
+}
+
+static void
+cc_mouse_panel_init (CcMousePanel *self)
+{
+ GsdDeviceManager *device_manager;
+
+ g_resources_register (cc_mouse_get_resource ());
+
+ cc_mouse_test_get_type ();
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->mouse_settings = g_settings_new ("org.gnome.desktop.peripherals.mouse");
+ self->touchpad_settings = g_settings_new ("org.gnome.desktop.peripherals.touchpad");
+
+ device_manager = gsd_device_manager_get ();
+ g_signal_connect_object (device_manager, "device-added",
+ G_CALLBACK (device_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (device_manager, "device-removed",
+ G_CALLBACK (device_changed), self, G_CONNECT_SWAPPED);
+
+ self->have_mouse = mouse_is_present ();
+ self->have_touchpad = touchpad_is_present ();
+ self->have_touchscreen = touchscreen_is_present ();
+ self->have_synaptics = cc_synaptics_check ();
+ if (self->have_synaptics)
+ g_warning ("Detected synaptics X driver, please migrate to libinput");
+
+ setup_dialog (self);
+}
+
+static void
+cc_mouse_panel_class_init (CcMousePanelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+
+ panel_class->get_help_uri = cc_mouse_panel_get_help_uri;
+
+ object_class->dispose = cc_mouse_panel_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/mouse/cc-mouse-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcMousePanel, edge_scrolling_row);
+ gtk_widget_class_bind_template_child (widget_class, CcMousePanel, edge_scrolling_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcMousePanel, mouse_group);
+ gtk_widget_class_bind_template_child (widget_class, CcMousePanel, mouse_natural_scrolling_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcMousePanel, mouse_speed_scale);
+ gtk_widget_class_bind_template_child (widget_class, CcMousePanel, mouse_test);
+ gtk_widget_class_bind_template_child (widget_class, CcMousePanel, primary_button_box);
+ gtk_widget_class_bind_template_child (widget_class, CcMousePanel, primary_button_left);
+ gtk_widget_class_bind_template_child (widget_class, CcMousePanel, primary_button_right);
+ gtk_widget_class_bind_template_child (widget_class, CcMousePanel, preferences);
+ gtk_widget_class_bind_template_child (widget_class, CcMousePanel, stack);
+ gtk_widget_class_bind_template_child (widget_class, CcMousePanel, tap_to_click_row);
+ gtk_widget_class_bind_template_child (widget_class, CcMousePanel, tap_to_click_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcMousePanel, test_button);
+ gtk_widget_class_bind_template_child (widget_class, CcMousePanel, touchpad_group);
+ gtk_widget_class_bind_template_child (widget_class, CcMousePanel, touchpad_natural_scrolling_row);
+ gtk_widget_class_bind_template_child (widget_class, CcMousePanel, touchpad_natural_scrolling_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcMousePanel, touchpad_speed_row);
+ gtk_widget_class_bind_template_child (widget_class, CcMousePanel, touchpad_speed_scale);
+ gtk_widget_class_bind_template_child (widget_class, CcMousePanel, touchpad_toggle_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcMousePanel, two_finger_scrolling_row);
+ gtk_widget_class_bind_template_child (widget_class, CcMousePanel, two_finger_scrolling_switch);
+
+ gtk_widget_class_bind_template_callback (widget_class, edge_scrolling_changed_event);
+ gtk_widget_class_bind_template_callback (widget_class, test_button_toggled_cb);
+ gtk_widget_class_bind_template_callback (widget_class, two_finger_scrolling_changed_event);
+}
diff --git a/panels/mouse/cc-mouse-panel.h b/panels/mouse/cc-mouse-panel.h
new file mode 100644
index 0000000..ae83e8e
--- /dev/null
+++ b/panels/mouse/cc-mouse-panel.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2010 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ *
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_MOUSE_PANEL (cc_mouse_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcMousePanel, cc_mouse_panel, CC, MOUSE_PANEL, CcPanel)
+
+G_END_DECLS
diff --git a/panels/mouse/cc-mouse-panel.ui b/panels/mouse/cc-mouse-panel.ui
new file mode 100644
index 0000000..c5d1351
--- /dev/null
+++ b/panels/mouse/cc-mouse-panel.ui
@@ -0,0 +1,219 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcMousePanel" parent="CcPanel">
+
+ <child type="titlebar-end">
+ <object class="GtkToggleButton" id="test_button">
+ <property name="use_underline">True</property>
+ <property name="valign">center</property>
+ <property name="label" translatable="yes">Test Your _Settings</property>
+ <signal name="toggled" handler="test_button_toggled_cb" object="CcMousePanel" swapped="yes"/>
+ <style>
+ <class name="text-button"/>
+ </style>
+ </object>
+ </child>
+
+ <child type="content">
+ <object class="GtkStack" id="stack">
+ <child>
+ <object class="AdwPreferencesPage" id="preferences">
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">General</property>
+ <child>
+ <object class="AdwActionRow" id="primary_button_row">
+ <property name="title" translatable="yes">Primary Button</property>
+ <property name="subtitle" translatable="yes">Sets the order of physical buttons on mice and touchpads.</property>
+ <property name="subtitle-lines">0</property>
+ <child>
+ <object class="GtkBox" id="primary_button_box">
+ <property name="valign">center</property>
+ <property name="homogeneous">True</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <style>
+ <class name="linked"/>
+ </style>
+ <child>
+ <object class="GtkToggleButton" id="primary_button_left">
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Left</property>
+ <property name="height_request">35</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="primary_button_right">
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Right</property>
+ <property name="group">primary_button_left</property>
+ <property name="height_request">35</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup" id="mouse_group">
+ <property name="title" translatable="yes">Mouse</property>
+ <child>
+ <object class="AdwActionRow" id="mouse_row">
+ <property name="title" translatable="yes">Mouse Speed</property>
+ <child>
+ <object class="GtkScale" id="mouse_speed_scale">
+ <property name="adjustment">mouse_speed_adjustment</property>
+ <property name="draw_value">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <accessibility>
+ <property name="label">Mouse speed</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="mouse_natural_scrolling_row">
+ <property name="title" translatable="yes" comments="Translators: This switch reverses the scrolling direction for mices. The term used comes from OS X so use the same translation if possible.">Natural Scrolling</property>
+ <property name="subtitle" translatable="yes">Scrolling moves the content, not the view.</property>
+ <property name="activatable-widget">mouse_natural_scrolling_switch</property>
+ <child>
+ <object class="GtkSwitch" id="mouse_natural_scrolling_switch">
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Natural Scrolling</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup" id="touchpad_group">
+ <property name="title" translatable="yes">Touchpad</property>
+ <child>
+ <object class="AdwActionRow" id="touchpad_toggle_row">
+ <property name="title" translatable="yes">Touchpad</property>
+ <property name="activatable-widget">touchpad_toggle_switch</property>
+ <child>
+ <object class="GtkSwitch" id="touchpad_toggle_switch">
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Touchpad</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="touchpad_natural_scrolling_row">
+ <property name="title" translatable="yes" comments="Translators: This switch reverses the scrolling direction for touchpads. The term used comes from OS X so use the same translation if possible. ">Natural Scrolling</property>
+ <property name="subtitle" translatable="yes">Scrolling moves the content, not the view.</property>
+ <property name="activatable-widget">touchpad_natural_scrolling_switch</property>
+ <child>
+ <object class="GtkSwitch" id="touchpad_natural_scrolling_switch">
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Natural Scrolling</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="touchpad_speed_row">
+ <property name="title" translatable="yes">Touchpad Speed</property>
+ <child>
+ <object class="GtkScale" id="touchpad_speed_scale">
+ <property name="adjustment">touchpad_speed_adjustment</property>
+ <property name="draw_value">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <accessibility>
+ <property name="label">Double-click timeout</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="tap_to_click_row">
+ <property name="visible">False</property>
+ <property name="title" translatable="yes">Tap to Click</property>
+ <property name="activatable-widget">tap_to_click_switch</property>
+ <child>
+ <object class="GtkSwitch" id="tap_to_click_switch">
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Tap to click</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="two_finger_scrolling_row">
+ <property name="visible">False</property>
+ <property name="title" translatable="yes">Two-finger Scrolling</property>
+ <property name="activatable-widget">two_finger_scrolling_switch</property>
+ <child>
+ <object class="GtkSwitch" id="two_finger_scrolling_switch">
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Two-finger Scrolling</property>
+ </accessibility>
+ <signal name="state-set" handler="two_finger_scrolling_changed_event" object="CcMousePanel" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="edge_scrolling_row">
+ <property name="visible">False</property>
+ <property name="title" translatable="yes">Edge Scrolling</property>
+ <property name="activatable-widget">edge_scrolling_switch</property>
+ <child>
+ <object class="GtkSwitch" id="edge_scrolling_switch">
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Edge Scrolling</property>
+ </accessibility>
+ <signal name="state-set" handler="edge_scrolling_changed_event" object="CcMousePanel" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ <child>
+ <object class="CcMouseTest" id="mouse_test">
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GtkAdjustment" id="mouse_speed_adjustment">
+ <property name="lower">-1</property>
+ <property name="upper">1</property>
+ </object>
+ <object class="GtkAdjustment" id="touchpad_speed_adjustment">
+ <property name="lower">-1</property>
+ <property name="upper">1</property>
+ </object>
+ <object class="GtkSizeGroup">
+ <property name="mode">horizontal</property>
+ <widgets>
+ <widget name="mouse_speed_scale"/>
+ <widget name="touchpad_speed_scale"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/panels/mouse/cc-mouse-test.c b/panels/mouse/cc-mouse-test.c
new file mode 100644
index 0000000..145cb74
--- /dev/null
+++ b/panels/mouse/cc-mouse-test.c
@@ -0,0 +1,389 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Written by: Ondrej Holy <oholy@redhat.com>,
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <glib/gi18n.h>
+#include <string.h>
+#include <gdk/gdk.h>
+#include <gdk/x11/gdkx.h>
+#include <math.h>
+
+#include "cc-mouse-test.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+/* Click test button sizes. */
+#define SHADOW_SIZE (10.0 / 180 * size)
+#define SHADOW_SHIFT_Y (-1.0 / 180 * size)
+#define SHADOW_OPACITY (0.15 / 180 * size)
+#define OUTER_CIRCLE_SIZE (22.0 / 180 * size)
+#define ANNULUS_SIZE (6.0 / 180 * size)
+#define INNER_CIRCLE_SIZE (52.0 / 180 * size)
+
+static void setup_information_label (CcMouseTest *self);
+static void setup_scroll_image (CcMouseTest *self);
+
+enum
+{
+ DOUBLE_CLICK_TEST_OFF,
+ DOUBLE_CLICK_TEST_MAYBE,
+ DOUBLE_CLICK_TEST_ON,
+ DOUBLE_CLICK_TEST_STILL_ON,
+ DOUBLE_CLICK_TEST_ALMOST_THERE,
+ DOUBLE_CLICK_TEST_GEGL
+};
+
+struct _CcMouseTest
+{
+ AdwBin parent_instance;
+
+ GtkWidget *button_drawing_area;
+ GtkWidget *information_label;
+ GtkWidget *image;
+ GtkWidget *scrolled_window_adjustment;
+ GtkWidget *viewport;
+
+ guint32 double_click_timestamp;
+ gint double_click_state;
+ gint button_state;
+
+ GSettings *mouse_settings;
+
+ gint information_label_timeout_id;
+ gint button_drawing_area_timeout_id;
+ gint scroll_image_timeout_id;
+};
+
+G_DEFINE_TYPE (CcMouseTest, cc_mouse_test, ADW_TYPE_BIN);
+
+/* Timeout for the double click test */
+
+static gboolean
+test_maybe_timeout (CcMouseTest *self)
+{
+ self->double_click_state = DOUBLE_CLICK_TEST_OFF;
+
+ gtk_widget_queue_draw (self->button_drawing_area);
+
+ self->button_drawing_area_timeout_id = 0;
+
+ return FALSE;
+}
+
+/* Timeout for the information label */
+
+static gboolean
+information_label_timeout (CcMouseTest *self)
+{
+ setup_information_label (self);
+
+ self->information_label_timeout_id = 0;
+
+ return FALSE;
+}
+
+/* Timeout for the scroll image */
+
+static gboolean
+scroll_image_timeout (CcMouseTest *self)
+{
+ setup_scroll_image (self);
+
+ self->scroll_image_timeout_id = 0;
+
+ return FALSE;
+}
+
+/* Set information label */
+
+static void
+setup_information_label (CcMouseTest *self)
+{
+ const gchar *message = NULL;
+ g_autofree gchar *label_text = NULL;
+ gboolean double_click;
+
+ if (self->information_label_timeout_id != 0) {
+ g_source_remove (self->information_label_timeout_id);
+ self->information_label_timeout_id = 0;
+ }
+
+ if (self->double_click_state == DOUBLE_CLICK_TEST_OFF) {
+ gtk_label_set_label (GTK_LABEL (self->information_label), _("Try clicking, double clicking, scrolling"));
+ return;
+ }
+
+ if (self->double_click_state == DOUBLE_CLICK_TEST_GEGL) {
+ message = _("Five clicks, GEGL time!");
+ } else {
+ double_click = (self->double_click_state >= DOUBLE_CLICK_TEST_ON);
+ switch (self->button_state) {
+ case 1:
+ message = (double_click) ? _("Double click, primary button") : _("Single click, primary button");
+ break;
+ case 2:
+ message = (double_click) ? _("Double click, middle button") : _("Single click, middle button");
+ break;
+ case 3:
+ message = (double_click) ? _("Double click, secondary button") : _("Single click, secondary button");
+ break;
+ }
+ }
+
+ label_text = g_strconcat ("<b>", message, "</b>", NULL);
+ gtk_label_set_markup (GTK_LABEL (self->information_label), label_text);
+
+ self->information_label_timeout_id = g_timeout_add (2500, (GSourceFunc) information_label_timeout, self);
+}
+
+/* Update scroll image */
+
+static void
+setup_scroll_image (CcMouseTest *self)
+{
+ const char *resource;
+
+ if (self->scroll_image_timeout_id != 0) {
+ g_source_remove (self->scroll_image_timeout_id);
+ self->scroll_image_timeout_id = 0;
+ }
+
+ if (self->double_click_state == DOUBLE_CLICK_TEST_GEGL)
+ resource = "/org/gnome/control-center/mouse/scroll-test-gegl.svg";
+ else
+ resource = "/org/gnome/control-center/mouse/scroll-test.svg";
+ gtk_picture_set_resource (GTK_PICTURE (self->image), resource);
+
+ if (self->double_click_state != DOUBLE_CLICK_TEST_GEGL)
+ return;
+
+ self->scroll_image_timeout_id = g_timeout_add (5000, (GSourceFunc) scroll_image_timeout, self);
+}
+
+/* Callback issued when the user clicks the double click testing area. */
+
+static void
+button_drawing_area_button_pressed_cb (GtkGestureClick *click_gesture,
+ gint n_press,
+ gdouble x,
+ gdouble y,
+ CcMouseTest *self)
+{
+ guint32 event_time;
+ guint current_button;
+ gint double_click_time;
+
+ current_button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (click_gesture));
+
+ if (current_button > 3)
+ return;
+
+ double_click_time = g_settings_get_int (self->mouse_settings, "double-click");
+
+ if (self->button_drawing_area_timeout_id != 0) {
+ g_source_remove (self->button_drawing_area_timeout_id);
+ self->button_drawing_area_timeout_id = 0;
+ }
+
+ /* Ignore fake double click using different buttons. */
+ if (self->double_click_state != DOUBLE_CLICK_TEST_OFF && self->button_state != current_button)
+ self->double_click_state = DOUBLE_CLICK_TEST_OFF;
+
+ event_time = gtk_event_controller_get_current_event_time (GTK_EVENT_CONTROLLER (click_gesture));
+ switch (self->double_click_state) {
+ case DOUBLE_CLICK_TEST_OFF:
+ self->double_click_state = DOUBLE_CLICK_TEST_MAYBE;
+ self->button_drawing_area_timeout_id = g_timeout_add (double_click_time, (GSourceFunc) test_maybe_timeout, self);
+ break;
+ case DOUBLE_CLICK_TEST_MAYBE:
+ case DOUBLE_CLICK_TEST_ON:
+ case DOUBLE_CLICK_TEST_STILL_ON:
+ case DOUBLE_CLICK_TEST_ALMOST_THERE:
+ if (event_time - self->double_click_timestamp < double_click_time) {
+ self->double_click_state++;
+ self->button_drawing_area_timeout_id = g_timeout_add (2500, (GSourceFunc) test_maybe_timeout, self);
+ } else {
+ test_maybe_timeout (self);
+ }
+ break;
+ case DOUBLE_CLICK_TEST_GEGL:
+ self->double_click_state = DOUBLE_CLICK_TEST_OFF;
+ break;
+ }
+
+ self->double_click_timestamp = event_time;
+
+ gtk_widget_queue_draw (self->button_drawing_area);
+
+ self->button_state = current_button;
+ setup_information_label (self);
+ setup_scroll_image (self);
+}
+
+static void
+button_drawing_area_draw_func (GtkDrawingArea *drawing_area,
+ cairo_t *cr,
+ int width,
+ int height,
+ gpointer user_data)
+{
+ CcMouseTest *self = CC_MOUSE_TEST (user_data);
+ gdouble center_x, center_y, size;
+ GdkRGBA inner_color, outer_color;
+ cairo_pattern_t *pattern;
+
+ size = MAX (MIN (width, height), 1);
+ center_x = width / 2.0;
+ center_y = height / 2.0;
+
+ switch (self->double_click_state) {
+ case DOUBLE_CLICK_TEST_ON:
+ case DOUBLE_CLICK_TEST_STILL_ON:
+ case DOUBLE_CLICK_TEST_ALMOST_THERE:
+ case DOUBLE_CLICK_TEST_GEGL:
+ gdk_rgba_parse (&outer_color, "#729fcf");
+ gdk_rgba_parse (&inner_color, "#729fcf");
+ break;
+ case DOUBLE_CLICK_TEST_MAYBE:
+ gdk_rgba_parse (&outer_color, "#729fcf");
+ gdk_rgba_parse (&inner_color, "#ffffff");
+ break;
+ case DOUBLE_CLICK_TEST_OFF:
+ gdk_rgba_parse (&outer_color, "#ffffff");
+ gdk_rgba_parse (&inner_color, "#ffffff");
+ break;
+ }
+
+ /* Draw shadow. */
+ cairo_rectangle (cr, center_x - size / 2, center_y - size / 2, size, size);
+ pattern = cairo_pattern_create_radial (center_x, center_y, 0, center_x, center_y, size);
+ cairo_pattern_add_color_stop_rgba (pattern, 0.5 - SHADOW_SIZE / size, 0, 0, 0, SHADOW_OPACITY);
+ cairo_pattern_add_color_stop_rgba (pattern, 0.5, 0, 0, 0, 0);
+ cairo_set_source (cr, pattern);
+ cairo_fill (cr);
+
+ /* Draw outer circle. */
+ cairo_set_line_width (cr, OUTER_CIRCLE_SIZE);
+ cairo_arc (cr, center_x, center_y + SHADOW_SHIFT_Y,
+ INNER_CIRCLE_SIZE + ANNULUS_SIZE + OUTER_CIRCLE_SIZE / 2,
+ 0, 2 * G_PI);
+ gdk_cairo_set_source_rgba (cr, &outer_color);
+ cairo_stroke (cr);
+
+ /* Draw inner circle. */
+ cairo_set_line_width (cr, 0);
+ cairo_arc (cr, center_x, center_y + SHADOW_SHIFT_Y,
+ INNER_CIRCLE_SIZE,
+ 0, 2 * G_PI);
+ gdk_cairo_set_source_rgba (cr, &inner_color);
+ cairo_fill (cr);
+}
+
+static void
+setup_dialog (CcMouseTest *self)
+{
+ GtkAdjustment *adjustment;
+ GtkStyleProvider *provider;
+
+ adjustment = GTK_ADJUSTMENT (self->scrolled_window_adjustment);
+ gtk_adjustment_set_value (adjustment,
+ gtk_adjustment_get_upper (adjustment));
+
+ provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
+ gtk_css_provider_load_from_data (GTK_CSS_PROVIDER (provider), "* {background: #26a269;}", -1);
+ gtk_style_context_add_provider (gtk_widget_get_style_context (self->viewport),
+ provider,
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+ g_object_unref (provider);
+}
+
+static void
+cc_mouse_test_finalize (GObject *object)
+{
+ CcMouseTest *self = CC_MOUSE_TEST (object);
+
+ g_clear_object (&self->mouse_settings);
+
+ if (self->information_label_timeout_id != 0) {
+ g_source_remove (self->information_label_timeout_id);
+ self->information_label_timeout_id = 0;
+ }
+
+ if (self->scroll_image_timeout_id != 0) {
+ g_source_remove (self->scroll_image_timeout_id);
+ self->scroll_image_timeout_id = 0;
+ }
+
+ if (self->button_drawing_area_timeout_id != 0) {
+ g_source_remove (self->button_drawing_area_timeout_id);
+ self->button_drawing_area_timeout_id = 0;
+ }
+
+ G_OBJECT_CLASS (cc_mouse_test_parent_class)->finalize (object);
+}
+
+static void
+cc_mouse_test_class_init (CcMouseTestClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = cc_mouse_test_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/mouse/cc-mouse-test.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcMouseTest, button_drawing_area);
+ gtk_widget_class_bind_template_child (widget_class, CcMouseTest, information_label);
+ gtk_widget_class_bind_template_child (widget_class, CcMouseTest, image);
+ gtk_widget_class_bind_template_child (widget_class, CcMouseTest, scrolled_window_adjustment);
+ gtk_widget_class_bind_template_child (widget_class, CcMouseTest, viewport);
+
+ gtk_widget_class_bind_template_callback (widget_class, button_drawing_area_button_pressed_cb);
+}
+
+static void
+cc_mouse_test_init (CcMouseTest *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (self->button_drawing_area),
+ button_drawing_area_draw_func,
+ self, NULL);
+
+ self->double_click_timestamp = 0;
+ self->double_click_state = DOUBLE_CLICK_TEST_OFF;
+ self->button_state = 0;
+
+ self->mouse_settings = g_settings_new ("org.gnome.desktop.peripherals.mouse");
+
+ self->information_label_timeout_id = 0;
+ self->button_drawing_area_timeout_id = 0;
+ self->scroll_image_timeout_id = 0;
+
+ setup_dialog (self);
+}
+
+GtkWidget *
+cc_mouse_test_new (void)
+{
+ return (GtkWidget *) g_object_new (CC_TYPE_MOUSE_TEST, NULL);
+}
diff --git a/panels/mouse/cc-mouse-test.h b/panels/mouse/cc-mouse-test.h
new file mode 100644
index 0000000..dc425f8
--- /dev/null
+++ b/panels/mouse/cc-mouse-test.h
@@ -0,0 +1,32 @@
+/* -*- mode: c; style: linux -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Written by: Ondrej Holy <oholy@redhat.com>
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <adwaita.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_MOUSE_TEST (cc_mouse_test_get_type ())
+G_DECLARE_FINAL_TYPE (CcMouseTest, cc_mouse_test, CC, MOUSE_TEST, AdwBin)
+
+GtkWidget *cc_mouse_test_new (void);
+
+G_END_DECLS
diff --git a/panels/mouse/cc-mouse-test.ui b/panels/mouse/cc-mouse-test.ui
new file mode 100644
index 0000000..c007361
--- /dev/null
+++ b/panels/mouse/cc-mouse-test.ui
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkAdjustment" id="scrolled_window_adjustment">
+ <property name="upper">100</property>
+ <property name="value">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <template class="CcMouseTest" parent="AdwBin">
+ <child>
+ <object class="GtkBox" id="test_widget">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="vadjustment">scrolled_window_adjustment</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">always</property>
+ <property name="max_content_height">440</property>
+ <child>
+ <object class="GtkViewport" id="viewport">
+ <child>
+ <object class="GtkOverlay" id="grid1">
+ <child>
+ <object class="GtkPicture" id="image">
+ <property name="margin_start">25</property>
+ <property name="margin_end">25</property>
+ <property name="can-shrink">False</property>
+ <property name="file">resource:///org/gnome/control-center/mouse/scroll-test.svg</property>
+ </object>
+ </child>
+ <child type="overlay">
+ <object class="GtkDrawingArea" id="button_drawing_area">
+ <property name="width_request">180</property>
+ <property name="height_request">180</property>
+ <property name="valign">end</property>
+ <property name="margin_top">20</property>
+ <property name="margin_bottom">20</property>
+ <child>
+ <object class="GtkGestureClick">
+ <property name="button">0</property>
+ <signal name="pressed" handler="button_drawing_area_button_pressed_cb" object="CcMouseTest" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="information_label">
+ <property name="margin_top">10</property>
+ <property name="margin_bottom">5</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Try clicking, double clicking, scrolling</property>
+ <property name="wrap">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/mouse/gnome-mouse-panel.desktop.in.in b/panels/mouse/gnome-mouse-panel.desktop.in.in
new file mode 100644
index 0000000..2d9ed7c
--- /dev/null
+++ b/panels/mouse/gnome-mouse-panel.desktop.in.in
@@ -0,0 +1,18 @@
+[Desktop Entry]
+Name=Mouse & Touchpad
+Comment=Change your mouse or touchpad sensitivity and select right or left-handed
+Exec=gnome-control-center mouse
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-mouse-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;HardwareSettings;X-GNOME-Settings-Panel;X-GNOME-DevicesSettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=mouse
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: Search terms to find the Mouse and Touchpad panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=Trackpad;Pointer;Click;Tap;Double;Button;Trackball;Scroll;
diff --git a/panels/mouse/icons/meson.build b/panels/mouse/icons/meson.build
new file mode 100644
index 0000000..02e9235
--- /dev/null
+++ b/panels/mouse/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-mouse-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/mouse/icons/scalable/org.gnome.Settings-mouse-symbolic.svg b/panels/mouse/icons/scalable/org.gnome.Settings-mouse-symbolic.svg
new file mode 100644
index 0000000..cdcaa63
--- /dev/null
+++ b/panels/mouse/icons/scalable/org.gnome.Settings-mouse-symbolic.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <path d="m 7.03125 0 c -2.753906 0 -5 2.246094 -5 5 v 6 c 0 2.753906 2.246094 5 5 5 h 1.96875 c 2.753906 0 5 -2.246094 5 -5 v -6 c 0 -2.753906 -2.246094 -5 -5 -5 z m 0 2 h 1.96875 c 1.679688 0 3 1.320312 3 3 v 6 c 0 1.679688 -1.320312 3 -3 3 h -1.96875 c -1.679688 0 -3 -1.320312 -3 -3 v -6 c 0 -1.679688 1.320312 -3 3 -3 z m 0.96875 1 c -0.554688 0 -1 0.445312 -1 1 v 2 c 0 0.554688 0.445312 1 1 1 s 1 -0.445312 1 -1 v -2 c 0 -0.554688 -0.445312 -1 -1 -1 z m 0 0" fill="#2e3436"/>
+</svg>
diff --git a/panels/mouse/meson.build b/panels/mouse/meson.build
new file mode 100644
index 0000000..8ebf3fc
--- /dev/null
+++ b/panels/mouse/meson.build
@@ -0,0 +1,70 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+resource_data = files(
+ 'cc-mouse-panel.ui',
+ 'cc-mouse-test.ui',
+ 'scroll-test-gegl.svg',
+ 'scroll-test.svg'
+)
+
+common_sources = gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname,
+ dependencies: resource_data,
+ export: true
+)
+
+sources = common_sources + files(
+ 'cc-mouse-panel.c',
+ 'cc-mouse-caps-helper.c',
+ 'cc-mouse-test.c',
+)
+
+deps = common_deps + [
+ gnome_settings_dep,
+ libdevice_dep,
+ x11_dep,
+ xi_dep
+]
+
+panels_libs += static_library(
+ cappletname + '-properties',
+ sources: sources,
+ include_directories: top_inc,
+ dependencies: deps,
+ c_args: cflags
+)
+
+test_name = 'test-gnome-mouse-test'
+
+sources = common_sources + files(
+ 'cc-mouse-test.c',
+ test_name + '.c'
+)
+
+executable(
+ test_name,
+ sources,
+ include_directories: top_inc,
+ dependencies: deps,
+ c_args: cflags
+)
+
+subdir('icons')
diff --git a/panels/mouse/mouse.gresource.xml b/panels/mouse/mouse.gresource.xml
new file mode 100644
index 0000000..0568705
--- /dev/null
+++ b/panels/mouse/mouse.gresource.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/mouse">
+ <file preprocess="xml-stripblanks">cc-mouse-panel.ui</file>
+ <file preprocess="xml-stripblanks">cc-mouse-test.ui</file>
+ <file>scroll-test.svg</file>
+ <file>scroll-test-gegl.svg</file>
+ </gresource>
+</gresources>
diff --git a/panels/mouse/scroll-test-gegl.svg b/panels/mouse/scroll-test-gegl.svg
new file mode 100644
index 0000000..81ed22b
--- /dev/null
+++ b/panels/mouse/scroll-test-gegl.svg
@@ -0,0 +1 @@
+<svg width="640" height="1600" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="a"><stop style="stop-color:#eeeeec;stop-opacity:1" offset="0"/><stop style="stop-color:#fff;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="b"><stop style="stop-color:#f57900;stop-opacity:1" offset="0"/><stop style="stop-color:#204a87;stop-opacity:1" offset="1"/></linearGradient></defs><g style="stroke-width:1.09075"><path style="fill:none;stroke:#63452c;stroke-width:21.8151;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M159.305 392.456v-77.297" transform="matrix(.61218 0 0 .61218 69.359 479.233)"/></g><path style="fill:#1a724b;fill-opacity:1;stroke:none;stroke-width:.999996px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M304.117-174.224 221.605 18.303H386.63z" transform="translate(-36.19 666.069) scale(.66774)"/><path style="fill:none;stroke:#3d3846;stroke-width:160;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M102.416-1167.375v321.533a100 100 45 0 0 100 100H345.68a100 100 45 0 1 100 100V399.245a100 100 135 0 1-100 100H185.963a100 100 135 0 0-100 100v247.592a100.119 100.119 45.034 0 0 100 100.12l521.828.62a94.738 94.738 45.034 0 1 94.625 94.737v190.048" transform="translate(27.86 739.504) scale(.66774)"/><path style="fill:none;stroke:#fff;stroke-width:10;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:40,80;stroke-dashoffset:0;stroke-opacity:1" d="M445.681-134.823v-511.02a100 100 45 0 0-100-100H202.416a100 100 45 0 1-100-100V-1167.374M445.68 61.57v337.676a100 100 135 0 1-100 100H185.963a100 100 135 0 0-100 100v247.592a100.119 100.119 45.034 0 0 100 100.12l526.705.625a89.855 89.855 45.034 0 1 89.748 89.855v274.925" transform="translate(27.86 739.504) scale(.66774)"/><g transform="translate(244.77 965.81) scale(.66774)"><path style="fill:none;stroke:#63452c;stroke-width:20;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M157.574 392.456V272.495"/><circle style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1b754c;fill-opacity:1;stroke:none;stroke-width:160;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000;stop-opacity:1" cx="157.574" cy="246.53" r="73.723"/></g><g transform="translate(378.319 965.81) scale(.66774)"><path style="fill:none;stroke:#63452c;stroke-width:20;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M157.574 392.456V272.495"/><circle style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1b754c;fill-opacity:1;stroke:none;stroke-width:160;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000;stop-opacity:1" cx="157.574" cy="246.53" r="73.723"/></g><g transform="matrix(-.41934 0 0 .41934 702.502 1098.89)"><circle style="opacity:1;vector-effect:none;fill:#63452c;fill-opacity:1;stroke:none;stroke-width:31.2335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" cx="760.59" cy="270.262" r="16.398"/><g transform="translate(-2284.074 -1604.387) scale(7.08287)" id="c"><circle style="opacity:1;vector-effect:none;fill:#f6f5f4;fill-opacity:1;stroke:none;stroke-width:5.29167;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" cx="436.72" cy="303.109" r="5.379"/><circle r="3.508" cy="303.109" cx="436.72" style="opacity:1;vector-effect:none;fill:#9a9996;fill-opacity:1;stroke:none;stroke-width:3.45109;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"/><circle style="opacity:1;vector-effect:none;fill:#3d3846;fill-opacity:1;stroke:none;stroke-width:1.28841;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" cx="436.72" cy="303.109" r="1.31"/></g><path d="m801.54 513.675 7.95 28.821" style="fill:#9a9996;stroke:#77767b;stroke-width:7.49604;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path d="m816.9 529.13-7.926 13.468" style="fill:#9a9996;stroke:#c0bfbc;stroke-width:11.2441;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path d="M813.57 498.034c-23.928-3.877-47.532 8.562-57.86 30.493l92.166.176c2.942.17 4.99-2.397 3.358-5.223a54.348 54.348 0 0 0-37.664-25.443z" style="opacity:1;vector-effect:none;fill:#e01b24;fill-opacity:1;stroke:none;stroke-width:37.4802;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"/><path d="M679.629 505.061c5.475 26.176 17.308 36.128 29.152 41.41l-45.716.663-2.32-35.447z" style="fill:#c01c28;fill-opacity:1;stroke:none;stroke-width:1.87401px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path d="M633.3 452.04c-19.064 0-34.41 13.374-34.41 29.985h-2.247a9.378 9.378 0 0 0-9.4 9.4v6.968c0 5.208 4.192 9.4 9.4 9.4h15.87c.871 0 1.698-.154 2.497-.374 5.296 2.895 11.55 4.59 18.29 4.59h30.551c19.064 0 34.413-13.373 34.413-29.984 0-16.611-15.35-29.984-34.413-29.984z" style="opacity:1;vector-effect:none;fill:#63452c;fill-opacity:1;stroke:none;stroke-width:34.4328;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"/><path style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:.514644;fill:none;stroke:none;stroke-width:5.62203;marker:none;enable-background:accumulate" d="M574.594 382.115h239.873v239.873H574.594z"/><ellipse ry="10.397" rx="10.776" cy="498.044" cx="589.586" style="opacity:1;vector-effect:none;fill:#e01b24;fill-opacity:1;stroke:none;stroke-width:30.2472;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"/><path style="fill:none;stroke:#63452c;stroke-width:37.4802;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="m737.553 519.543-15.38-54.384-59.969-20.146"/><circle r="19.677" cy="252.927" cx="715.145" style="opacity:1;vector-effect:none;fill:#63452c;fill-opacity:1;stroke:none;stroke-width:37.4802;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"/><path d="M629.409 446.887c-16.402 0-30.222 10.577-35.105 25.3h125.024c-4.882-14.723-18.702-25.3-35.104-25.3z" style="opacity:1;vector-effect:none;fill:#77767b;fill-opacity:1;stroke:none;stroke-width:37.4802;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"/><path style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#63452c;stroke-width:28.1101;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" d="M702.027 373.332s3.975 26.223 17.562 32.313c13.586 6.09 36.817 4.685 36.817 4.685"/><path d="m728.263 292.282-68.401 139.613" style="fill:none;stroke:#865e3c;stroke-width:93.7005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path d="m747.94 337.258-12.57 25.128" style="fill:#deddda;stroke:#deddda;stroke-width:37.4802;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path d="m719.224 527.564-5.016-55.378-64.653-14.992" style="fill:none;stroke:#865e3c;stroke-width:37.4802;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><circle r="5.856" cy="293.921" cx="741.85" style="opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:none;stroke-width:31.2335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"/><circle style="opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:none;stroke-width:28.7348;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" cx="759.418" cy="300.715" r="5.388"/><circle r="10.776" cy="328.356" cx="755.905" style="opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:none;stroke-width:57.4696;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"/><path d="M774.313 411.281c-20.053 0-27.778 16.256-27.778 36.31 0 8.604 12.695 43.415 13.847 46.607 9.685 26.825-12.857 50.859-38.316 50.859-25.362 0-41.705-1.312-67.05-2.185-5.205-.18-10.337 5.1-10.337 8.817 0 3.717 5.072 1.556 10.28 1.556h70.054c3.878.275 8.205 0 13.323 0 25.41 0 55.517-17.773 55.517-46.624 0-8.037-1.99-15.965-5.786-23.165l-18.7-30.774c-1.54-2.91.487-4.452 1.646-4.452l20.967.172-.165-37.15s-14.417.043-17.501.029z" style="opacity:1;vector-effect:none;fill:#c01c28;fill-opacity:1;stroke:none;stroke-width:37.4802;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"/><use height="100%" width="100%" transform="translate(-186.677)" xlink:href="#c"/><path style="fill:#5e5c64;fill-opacity:1;stroke:none;stroke-width:1.70187px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M619.462 533.936c-6.121 0-11.083 4.962-11.083 11.082.001 6.12 4.963 11.08 11.083 11.08l.787.012 37.798-.075c1.722-3.63 2.892-8.704 3.835-12.223 0 0-18.157-.015-31.441-.176a11.081 11.081 0 0 0-10.98-9.7z"/><rect style="opacity:1;vector-effect:none;fill:#c01c28;fill-opacity:1;stroke:none;stroke-width:16.9557;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" width="54.993" height="29.153" x="587.201" y="481.541" rx="9.069" ry="10.932"/><circle style="opacity:1;vector-effect:none;fill:#9a9996;fill-opacity:1;stroke:none;stroke-width:7.34974;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" cx="621.335" cy="544.809" r="7.471"/><path d="M630.328 481.714a54.512 73.475 35.72 0 0-52.37 27.997 54.512 73.475 35.72 0 0-19.542 34.156h117.982a54.512 73.475 35.72 0 0-11.892-49.452 54.512 73.475 35.72 0 0-34.178-12.701z" style="opacity:1;vector-effect:none;fill:#e01b24;fill-opacity:1;stroke:none;stroke-width:35.1475;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"/><rect ry="0" rx="0" y="411.281" x="774.176" height="37.012" width="17.803" style="opacity:1;vector-effect:none;fill:#fff;fill-opacity:1;stroke:none;stroke-width:37.4802;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"/><rect style="opacity:1;vector-effect:none;fill:#deddda;fill-opacity:1;stroke:none;stroke-width:23.7797;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" width="17.803" height="14.899" x="774.176" y="433.394" rx="0" ry="0"/><path d="M689.846 379.423s7.95 24.235 21.537 30.325 37.48 5.348 37.48 5.348" style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#986a44;stroke-width:28.1101;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"/><path d="M718.325 354.571c5.477 6.725 25.192 16.671 31.369 15.49-8.063-.866-25.128-11.175-29.8-18.649z" style="fill:#c0bfbc;fill-opacity:1;stroke:none;stroke-width:1.87401px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path d="m703.495 450.47-39.39-9.335L706 445.917z" style="fill:#63452c;fill-opacity:.346457;stroke:none;stroke-width:1.28802px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/></g><g style="stroke-width:1.09075"><path style="fill:none;stroke:#63452c;stroke-width:21.8151;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M159.305 392.456v-77.297" transform="matrix(.61218 0 0 .61218 -12.62 227.065)"/></g><path style="fill:#1a724b;fill-opacity:1;stroke:none;stroke-width:.999996px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M304.117-174.224 221.605 18.303H386.63z" transform="translate(-118.168 413.9) scale(.66774)"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#3d3846;stroke-width:160;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000;stop-opacity:1" d="m502.416-47.638 164.618-103.916a326.49 326.49 118.869 0 0 152.21-276.084v-739.737" transform="translate(27.86 739.504) scale(.66774)"/><g transform="translate(2.764 739.504) scale(.66774)"><path style="fill:none;stroke:#63452c;stroke-width:20;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M157.574 392.456V272.495"/><circle style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1b754c;fill-opacity:1;stroke:none;stroke-width:160;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000;stop-opacity:1" cx="157.574" cy="246.53" r="73.723"/></g><g style="stroke-width:1.09075"><path style="fill:none;stroke:#63452c;stroke-width:21.8151;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M159.305 392.456v-77.297" transform="matrix(.61218 0 0 .61218 104.052 534.82)"/></g><path style="fill:#208b5b;fill-opacity:1;stroke:none;stroke-width:.999996px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M304.117-174.224 221.605 18.303H386.63z" transform="translate(-1.496 721.655) scale(.66774)"/><g style="stroke-width:1.09075"><path style="fill:none;stroke:#63452c;stroke-width:21.8151;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M159.305 392.456v-77.297" transform="matrix(.61218 0 0 .61218 48.956 576.018)"/></g><path style="fill:#2cbd7a;fill-opacity:1;stroke:none;stroke-width:.999996px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M243.645-112.527 161.133 80.001h165.023z" transform="translate(-16.212 721.655) scale(.66774)"/><path style="fill:#77767b;stroke:#c0bfbc;stroke-width:3.99999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M552.701-181.649v-105.989" transform="translate(27.86 739.504) scale(.66774)"/><path style="fill:#77767b;stroke:#deddda;stroke-width:3.99999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M544.496 220.043v-98.955" transform="translate(27.86 739.504) scale(.66774)"/><path style="font-variation-settings:normal;opacity:1;fill:#fff;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" transform="rotate(-135 167.087 363.982) scale(.66774)" d="M-481.009 289.025h58.926v58.926h-58.926z"/><path style="font-variation-settings:normal;opacity:1;fill:#f6d32d;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" transform="rotate(-135 167.087 363.982) scale(.66774)" d="M-470.403 299.631h37.713v37.713h-37.713z"/><path style="opacity:1;fill:#e01b24;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stop-color:#000;stop-opacity:1" d="m552.701-271.531-41.667-65.667h83.334z" transform="translate(27.86 739.504) scale(.66774)"/><path style="opacity:1;fill:#fff;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stop-color:#000;stop-opacity:1" d="m564.313-256.492 25.972 40.931 25.973-40.931z" transform="translate(2.764 691.375) scale(.66774)"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#fff;stroke-width:10;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:40,80;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000;stop-opacity:1" d="m622.912-123.702 44.122-27.852a326.49 326.49 118.869 0 0 152.21-276.084v-739.737" transform="translate(27.86 739.504) scale(.66774)"/><g style="stroke-width:1.09075"><path style="fill:none;stroke:#63452c;stroke-width:21.8151;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M159.305 392.456v-77.297" transform="matrix(.61218 0 0 .61218 386.014 741.792)"/></g><path style="fill:#1a724b;fill-opacity:1;stroke:none;stroke-width:.999996px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M304.117-174.224 221.605 18.303H386.63z" transform="translate(280.466 928.627) scale(.66774)"/><g transform="translate(111.222 965.81) scale(.66774)"><path style="fill:none;stroke:#63452c;stroke-width:20;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M157.574 392.456V272.495"/><circle style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1b754c;fill-opacity:1;stroke:none;stroke-width:160;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000;stop-opacity:1" cx="157.574" cy="246.53" r="73.723"/></g><g style="stroke-width:1.09075"><path style="fill:none;stroke:#63452c;stroke-width:21.8151;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M159.305 392.456v-77.297" transform="matrix(.61218 0 0 .61218 419.03 817.966)"/></g><path style="fill:#2cbd7a;fill-opacity:1;stroke:none;stroke-width:.999996px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M243.645-112.527 161.133 80.001h165.023z" transform="translate(353.863 963.604) scale(.66774)"/><g style="stroke-width:1.09075"><path style="fill:none;stroke:#63452c;stroke-width:21.8151;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M159.305 392.456v-77.297" transform="matrix(.61218 0 0 .61218 57.38 267.065)"/></g><path style="fill:#208b5b;fill-opacity:1;stroke:none;stroke-width:.999996px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M304.117-174.224 221.605 18.303H386.63z" transform="translate(-48.168 453.9) scale(.66774)"/><g transform="translate(-30.315 308.044) scale(.66774)"><path style="fill:none;stroke:#63452c;stroke-width:20;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M157.574 392.456V272.495"/><circle style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#2cbd7a;fill-opacity:1;stroke:none;stroke-width:160;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000;stop-opacity:1" cx="157.574" cy="246.53" r="73.723"/></g><g><path style="fill:#5e5c64;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M127.67-785.337v31.247h7.037l8.226-31.203zM94.578-785.337v31.247H87.54l-8.227-31.203z" transform="matrix(1.06303 0 0 1.06303 100.221 1023.04)"/><path style="fill:#707a79;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M92.62-830.64v-31.247h7.036l8.227 31.203z" transform="matrix(1.06303 0 0 1.06303 100.221 1023.04)"/><path style="font-variation-settings:normal;fill:#9a9996;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000" d="M104.62-830.64c-16.794 0-30.324 13.445-30.474 30.201h-.007V-795.25c-.23 5.452-2.673 10.414-6.977 10.414v30.746H74.2l4.697-17.832c1.692-6.311 9.071-12.064 15.672-12.914h48.485l8.107 30.746h7.037v-46.348h-.008c-.15-16.756-13.68-30.2-30.472-30.2z" transform="matrix(1.06303 0 0 1.06303 100.221 1023.04)"/><g transform="matrix(1.06303 0 0 1.06303 108.682 1040.36)"><path style="fill:#deddda;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M165.399-810.538c-.451.17-.939.421-1.445.766-.573.383-1.108.933-1.562 1.645-.464.726-.714 1.62-.71 2.628.052.99.344 1.844.826 2.523.474.67 1.015 1.175 1.582 1.519 1.145.655 2.112.93 2.807 1.037.677.177 1.1.197 1.21.274.058.024.09 0 .062-.06-.037-.07-.03-.188-.034-.38.038-.2.078-.284.146-.311.061-.018.05.025.007.113-.083.21-.535.397-1.13.686-.66.256-1.49.608-2.352 1.213-.444.321-.849.744-1.183 1.252-.35.53-.553 1.16-.596 1.832-.02.687.142 1.295.421 1.796.289.518.652.918 1.042 1.214a5.81 5.81 0 0 0 2.361 1.015c.792.177 1.436.25 1.968.416.684.225 1.172.5 1.482.919.748.96.34 1.835.34 1.835s.816-.636.34-2.165c-.216-.66-.716-1.351-1.497-1.88-.658-.459-1.218-.708-1.905-1.091-.517-.31-1.029-.635-1.24-1.009-.102-.167-.171-.33-.17-.46.005-.119.028-.216.086-.23.034-.018.116-.058.192-.105.08-.051.214-.098.375-.16.307-.138.833-.176 1.566-.343.718-.11 1.654-.375 2.71-1.029.514-.334.998-.814 1.407-1.452.41-.637.644-1.429.643-2.338-.042-.876-.294-1.662-.728-2.303a5.305 5.305 0 0 0-1.442-1.466 9.62 9.62 0 0 0-2.648-1.182c-.629-.246-1.025-.341-1.036-.455-.007-.038.017-.013.112.08.103.103.156.28.195.578-.01.305-.04.499-.134.625-.083.113-.103.16-.097.142.013-.016.095-.047.232-.108.22-.087.45-.152.816-.255.676-.189 1.83-.51 2.814-1.165a5.677 5.677 0 0 0 1.594-1.582c.46-.7.797-1.6.815-2.586a4.907 4.907 0 0 0-.725-2.62c-.43-.706-1-1.253-1.551-1.644-.972-.69-2.146-1.046-2.839-1.248-.683-.2-.929-.269-1.129-.402-.028-.02.073.092.073.092l.169.563-.124.578s-.104.139-.095.132c.095-.075.316-.181.907-.367.607-.192 1.6-.468 2.525-1.003a6.203 6.203 0 0 0 1.558-1.264 5.236 5.236 0 0 0 1.14-2.143c.22-.875.182-1.771-.023-2.548a5.659 5.659 0 0 0-1.001-2.01c-.832-1.074-1.928-1.732-2.818-2.137-.767-.35-1.567-.596-2.158-.821-.535-.204-.771-.335-.93-.474a.739.739 0 0 1-.247-.6.739.739 0 0 1 .324-.56.739.739 0 0 1 .644-.085c.148.05.313.182.41.354.016.029.703-.276 1.426-.49.724-.213 1.464-.364 1.464-.364s.688-.313 1.315-.765c.627-.45 1.17-1.066 1.017-1.335a6.805 6.805 0 0 0-3.696-3.079 6.847 6.847 0 0 0-5.908.771 6.847 6.847 0 0 0-2.983 5.157 6.847 6.847 0 0 0 2.276 5.505c.903.793 1.969 1.274 2.754 1.573.728.277 1.286.437 1.804.672.395.18.527.307.56.35l-.054-.13.007-.454.165-.341s.026-.02-.048.023c-.268.155-.62.253-1.328.476-.724.228-1.83.599-2.817 1.377a5.641 5.641 0 0 0-1.443 1.681 4.942 4.942 0 0 0-.618 2.56c.038.972.383 1.855.843 2.54a5.745 5.745 0 0 0 1.58 1.557c.974.65 2.11.976 2.78 1.171.662.193.866.254 1.045.381.015.011-.099-.126-.099-.126l-.151-.613.171-.602s.114-.127.093-.113c-.19.126-.42.19-1.101.38-.38.105-.906.255-1.406.452z"/><path style="fill:#77767b;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m176.424-847.638-.04-9.858c-.013-3.239-.07-6.966-.804-10.567a29.354 29.354 0 0 0-1.24-4.355 24.968 24.968 0 0 0-3.467-6.375 23.575 23.575 0 0 0-9.394-7.38A25.038 25.038 0 0 0 150-888.127a26.56 26.56 0 0 0-15.19 5.979c-4.506 3.729-7.284 8.59-8.508 13.336-1.487 5.794-.66 11.162.923 15.143 3.54 8.884 9.198 11.052 9.198 11.052s-4.765-3.574-6.34-11.903c-.703-3.708-.514-8.253 1.374-12.573 1.535-3.528 4.238-6.877 7.764-9.103 3.182-2.02 7.111-3.168 11.015-3.06 2.536.077 5.076.648 7.25 1.764a15.12 15.12 0 0 1 5.412 4.623c.845 1.162 1.528 2.504 2.067 3.936.342.92.614 1.88.815 2.87.549 2.689.59 5.426.603 8.608l.04 9.858z"/><path style="fill:#c0bfbc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.1606px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m171.606-843.464-.046-11.441c-.015-3.76-.081-8.085-.934-12.265a34.069 34.069 0 0 0-1.439-5.054 28.979 28.979 0 0 0-4.023-7.398 27.361 27.361 0 0 0-10.903-8.565 29.06 29.06 0 0 0-13.32-2.27 30.825 30.825 0 0 0-17.63 6.94c-5.23 4.327-8.454 9.968-9.875 15.477-1.726 6.725-.766 12.955 1.071 17.575 4.109 10.311 10.675 12.827 10.675 12.827s-5.53-4.148-7.357-13.815c-.817-4.303-.597-9.578 1.593-14.592 1.782-4.095 4.92-7.982 9.012-10.565 3.693-2.344 8.253-3.677 12.783-3.55 2.944.089 5.891.75 8.415 2.046a17.548 17.548 0 0 1 6.281 5.366c.98 1.348 1.774 2.905 2.4 4.567.396 1.07.711 2.183.945 3.33.637 3.122.685 6.3.7 9.992l.046 11.442z"/><path style="fill:#c0bfbc;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stop-color:#000" d="M146.424-847.638h30v40H165Z"/><circle r="3.678" cy="-832.139" cx="-166.549" style="vector-effect:none;fill:#000;fill-opacity:1;stroke:none;stroke-width:19.6145;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" transform="scale(-1 1)"/><circle r="3.678" cy="-832.139" cx="-176.364" style="vector-effect:none;fill:#000;fill-opacity:1;stroke:none;stroke-width:19.6145;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" transform="scale(-1 1)"/></g><path style="font-variation-settings:normal;opacity:1;fill:#9a9996;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" d="M101.493-830.496a10.834 10.834 0 0 1-5.417 9.383 10.834 10.834 0 0 1-10.834 0 10.834 10.834 0 0 1-5.418-9.383" transform="matrix(1.06303 0 0 1.06303 100.221 1023.04)"/></g><g><g style="stroke-width:1.09075"><path style="fill:none;stroke:#63452c;stroke-width:21.8151;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M159.305 392.456v-77.297" transform="matrix(.61218 0 0 .61218 277.38 -32.935)"/></g><path style="fill:#1a724b;fill-opacity:1;stroke:none;stroke-width:.999996px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M304.117-174.224 221.605 18.303H386.63z" transform="translate(171.832 153.9) scale(.66774)"/></g><g><g style="stroke-width:1.09075"><path style="fill:none;stroke:#63452c;stroke-width:21.8151;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M159.305 392.456v-77.297" transform="matrix(.61218 0 0 .61218 357.38 7.065)"/></g><path style="fill:#208b5b;fill-opacity:1;stroke:none;stroke-width:.999996px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M304.117-174.224 221.605 18.303H386.63z" transform="translate(251.832 193.9) scale(.66774)"/></g><g transform="translate(339.685 108.044) scale(.66774)"><path style="fill:none;stroke:#63452c;stroke-width:20;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M157.574 392.456V272.495"/><circle style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#2cbd7a;fill-opacity:1;stroke:none;stroke-width:160;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000;stop-opacity:1" cx="157.574" cy="246.53" r="73.723"/></g><g><g style="stroke-width:1.09075"><path style="fill:none;stroke:#63452c;stroke-width:21.8151;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M159.305 392.456v-77.297" transform="matrix(.61218 0 0 .61218 484.853 661.663)"/></g><path style="fill:#208b5b;fill-opacity:1;stroke:none;stroke-width:.999996px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M304.117-174.224 221.605 18.303H386.63z" transform="translate(379.305 848.498) scale(.66774)"/></g></svg> \ No newline at end of file
diff --git a/panels/mouse/scroll-test.svg b/panels/mouse/scroll-test.svg
new file mode 100644
index 0000000..8614713
--- /dev/null
+++ b/panels/mouse/scroll-test.svg
@@ -0,0 +1 @@
+<svg width="640" height="1600" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="a"><stop style="stop-color:#eeeeec;stop-opacity:1" offset="0"/><stop style="stop-color:#fff;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="b"><stop style="stop-color:#f57900;stop-opacity:1" offset="0"/><stop style="stop-color:#204a87;stop-opacity:1" offset="1"/></linearGradient></defs><g style="stroke-width:1.09075"><path style="fill:none;stroke:#63452c;stroke-width:21.8151;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M159.305 392.456v-77.297" transform="matrix(.61218 0 0 .61218 69.359 479.233)"/></g><path style="fill:#1a724b;fill-opacity:1;stroke:none;stroke-width:.999996px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M304.117-174.224 221.605 18.303H386.63z" transform="translate(-36.19 666.069) scale(.66774)"/><path style="fill:none;stroke:#3d3846;stroke-width:160;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M102.416-1167.375v321.533a100 100 45 0 0 100 100H345.68a100 100 45 0 1 100 100V399.245a100 100 135 0 1-100 100H185.963a100 100 135 0 0-100 100v247.592a100.119 100.119 45.034 0 0 100 100.12l521.828.62a94.738 94.738 45.034 0 1 94.625 94.737v190.048" transform="translate(27.86 739.504) scale(.66774)"/><path style="fill:none;stroke:#fff;stroke-width:10;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:40,80;stroke-dashoffset:0;stroke-opacity:1" d="M445.681-134.823v-511.02a100 100 45 0 0-100-100H202.416a100 100 45 0 1-100-100V-1167.374M445.68 61.57v337.676a100 100 135 0 1-100 100H185.963a100 100 135 0 0-100 100v247.592a100.119 100.119 45.034 0 0 100 100.12l526.705.625a89.855 89.855 45.034 0 1 89.748 89.855v274.925" transform="translate(27.86 739.504) scale(.66774)"/><g transform="translate(244.77 965.81) scale(.66774)"><path style="fill:none;stroke:#63452c;stroke-width:20;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M157.574 392.456V272.495"/><circle style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1b754c;fill-opacity:1;stroke:none;stroke-width:160;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000;stop-opacity:1" cx="157.574" cy="246.53" r="73.723"/></g><g transform="translate(378.319 965.81) scale(.66774)"><path style="fill:none;stroke:#63452c;stroke-width:20;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M157.574 392.456V272.495"/><circle style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1b754c;fill-opacity:1;stroke:none;stroke-width:160;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000;stop-opacity:1" cx="157.574" cy="246.53" r="73.723"/></g><g transform="matrix(-.41934 0 0 .41934 702.502 1098.89)"><circle style="opacity:1;vector-effect:none;fill:#63452c;fill-opacity:1;stroke:none;stroke-width:31.2335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" cx="760.59" cy="270.262" r="16.398"/><g transform="translate(-2284.074 -1604.387) scale(7.08287)" id="c"><circle style="opacity:1;vector-effect:none;fill:#f6f5f4;fill-opacity:1;stroke:none;stroke-width:5.29167;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" cx="436.72" cy="303.109" r="5.379"/><circle r="3.508" cy="303.109" cx="436.72" style="opacity:1;vector-effect:none;fill:#9a9996;fill-opacity:1;stroke:none;stroke-width:3.45109;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"/><circle style="opacity:1;vector-effect:none;fill:#3d3846;fill-opacity:1;stroke:none;stroke-width:1.28841;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" cx="436.72" cy="303.109" r="1.31"/></g><path d="m801.54 513.675 7.95 28.821" style="fill:#9a9996;stroke:#77767b;stroke-width:7.49604;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path d="m816.9 529.13-7.926 13.468" style="fill:#9a9996;stroke:#c0bfbc;stroke-width:11.2441;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path d="M813.57 498.034c-23.928-3.877-47.532 8.562-57.86 30.493l92.166.176c2.942.17 4.99-2.397 3.358-5.223a54.348 54.348 0 0 0-37.664-25.443z" style="opacity:1;vector-effect:none;fill:#e01b24;fill-opacity:1;stroke:none;stroke-width:37.4802;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"/><path d="M679.629 505.061c5.475 26.176 17.308 36.128 29.152 41.41l-45.716.663-2.32-35.447z" style="fill:#c01c28;fill-opacity:1;stroke:none;stroke-width:1.87401px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path d="M633.3 452.04c-19.064 0-34.41 13.374-34.41 29.985h-2.247a9.378 9.378 0 0 0-9.4 9.4v6.968c0 5.208 4.192 9.4 9.4 9.4h15.87c.871 0 1.698-.154 2.497-.374 5.296 2.895 11.55 4.59 18.29 4.59h30.551c19.064 0 34.413-13.373 34.413-29.984 0-16.611-15.35-29.984-34.413-29.984z" style="opacity:1;vector-effect:none;fill:#63452c;fill-opacity:1;stroke:none;stroke-width:34.4328;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"/><path style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:.514644;fill:none;stroke:none;stroke-width:5.62203;marker:none;enable-background:accumulate" d="M574.594 382.115h239.873v239.873H574.594z"/><ellipse ry="10.397" rx="10.776" cy="498.044" cx="589.586" style="opacity:1;vector-effect:none;fill:#e01b24;fill-opacity:1;stroke:none;stroke-width:30.2472;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"/><path style="fill:none;stroke:#63452c;stroke-width:37.4802;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="m737.553 519.543-15.38-54.384-59.969-20.146"/><circle r="19.677" cy="252.927" cx="715.145" style="opacity:1;vector-effect:none;fill:#63452c;fill-opacity:1;stroke:none;stroke-width:37.4802;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"/><path d="M629.409 446.887c-16.402 0-30.222 10.577-35.105 25.3h125.024c-4.882-14.723-18.702-25.3-35.104-25.3z" style="opacity:1;vector-effect:none;fill:#77767b;fill-opacity:1;stroke:none;stroke-width:37.4802;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"/><path style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#63452c;stroke-width:28.1101;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" d="M702.027 373.332s3.975 26.223 17.562 32.313c13.586 6.09 36.817 4.685 36.817 4.685"/><path d="m728.263 292.282-68.401 139.613" style="fill:none;stroke:#865e3c;stroke-width:93.7005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path d="m747.94 337.258-12.57 25.128" style="fill:#deddda;stroke:#deddda;stroke-width:37.4802;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path d="m719.224 527.564-5.016-55.378-64.653-14.992" style="fill:none;stroke:#865e3c;stroke-width:37.4802;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><circle r="5.856" cy="293.921" cx="741.85" style="opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:none;stroke-width:31.2335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"/><circle style="opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:none;stroke-width:28.7348;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" cx="759.418" cy="300.715" r="5.388"/><circle r="10.776" cy="328.356" cx="755.905" style="opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:none;stroke-width:57.4696;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"/><path d="M774.313 411.281c-20.053 0-27.778 16.256-27.778 36.31 0 8.604 12.695 43.415 13.847 46.607 9.685 26.825-12.857 50.859-38.316 50.859-25.362 0-41.705-1.312-67.05-2.185-5.205-.18-10.337 5.1-10.337 8.817 0 3.717 5.072 1.556 10.28 1.556h70.054c3.878.275 8.205 0 13.323 0 25.41 0 55.517-17.773 55.517-46.624 0-8.037-1.99-15.965-5.786-23.165l-18.7-30.774c-1.54-2.91.487-4.452 1.646-4.452l20.967.172-.165-37.15s-14.417.043-17.501.029z" style="opacity:1;vector-effect:none;fill:#c01c28;fill-opacity:1;stroke:none;stroke-width:37.4802;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"/><use height="100%" width="100%" transform="translate(-186.677)" xlink:href="#c"/><path style="fill:#5e5c64;fill-opacity:1;stroke:none;stroke-width:1.70187px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M619.462 533.936c-6.121 0-11.083 4.962-11.083 11.082.001 6.12 4.963 11.08 11.083 11.08l.787.012 37.798-.075c1.722-3.63 2.892-8.704 3.835-12.223 0 0-18.157-.015-31.441-.176a11.081 11.081 0 0 0-10.98-9.7z"/><rect style="opacity:1;vector-effect:none;fill:#c01c28;fill-opacity:1;stroke:none;stroke-width:16.9557;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" width="54.993" height="29.153" x="587.201" y="481.541" rx="9.069" ry="10.932"/><circle style="opacity:1;vector-effect:none;fill:#9a9996;fill-opacity:1;stroke:none;stroke-width:7.34974;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" cx="621.335" cy="544.809" r="7.471"/><path d="M630.328 481.714a54.512 73.475 35.72 0 0-52.37 27.997 54.512 73.475 35.72 0 0-19.542 34.156h117.982a54.512 73.475 35.72 0 0-11.892-49.452 54.512 73.475 35.72 0 0-34.178-12.701z" style="opacity:1;vector-effect:none;fill:#e01b24;fill-opacity:1;stroke:none;stroke-width:35.1475;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"/><rect ry="0" rx="0" y="411.281" x="774.176" height="37.012" width="17.803" style="opacity:1;vector-effect:none;fill:#fff;fill-opacity:1;stroke:none;stroke-width:37.4802;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"/><rect style="opacity:1;vector-effect:none;fill:#deddda;fill-opacity:1;stroke:none;stroke-width:23.7797;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" width="17.803" height="14.899" x="774.176" y="433.394" rx="0" ry="0"/><path d="M689.846 379.423s7.95 24.235 21.537 30.325 37.48 5.348 37.48 5.348" style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#986a44;stroke-width:28.1101;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"/><path d="M718.325 354.571c5.477 6.725 25.192 16.671 31.369 15.49-8.063-.866-25.128-11.175-29.8-18.649z" style="fill:#c0bfbc;fill-opacity:1;stroke:none;stroke-width:1.87401px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path d="m703.495 450.47-39.39-9.335L706 445.917z" style="fill:#63452c;fill-opacity:.346457;stroke:none;stroke-width:1.28802px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/></g><g style="stroke-width:1.09075"><path style="fill:none;stroke:#63452c;stroke-width:21.8151;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M159.305 392.456v-77.297" transform="matrix(.61218 0 0 .61218 -12.62 227.065)"/></g><path style="fill:#1a724b;fill-opacity:1;stroke:none;stroke-width:.999996px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M304.117-174.224 221.605 18.303H386.63z" transform="translate(-118.168 413.9) scale(.66774)"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#3d3846;stroke-width:160;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000;stop-opacity:1" d="m502.416-47.638 164.618-103.916a326.49 326.49 118.869 0 0 152.21-276.084v-739.737" transform="translate(27.86 739.504) scale(.66774)"/><g transform="translate(2.764 739.504) scale(.66774)"><path style="fill:none;stroke:#63452c;stroke-width:20;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M157.574 392.456V272.495"/><circle style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1b754c;fill-opacity:1;stroke:none;stroke-width:160;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000;stop-opacity:1" cx="157.574" cy="246.53" r="73.723"/></g><g style="stroke-width:1.09075"><path style="fill:none;stroke:#63452c;stroke-width:21.8151;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M159.305 392.456v-77.297" transform="matrix(.61218 0 0 .61218 104.052 534.82)"/></g><path style="fill:#208b5b;fill-opacity:1;stroke:none;stroke-width:.999996px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M304.117-174.224 221.605 18.303H386.63z" transform="translate(-1.496 721.655) scale(.66774)"/><g style="stroke-width:1.09075"><path style="fill:none;stroke:#63452c;stroke-width:21.8151;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M159.305 392.456v-77.297" transform="matrix(.61218 0 0 .61218 48.956 576.018)"/></g><path style="fill:#2cbd7a;fill-opacity:1;stroke:none;stroke-width:.999996px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M243.645-112.527 161.133 80.001h165.023z" transform="translate(-16.212 721.655) scale(.66774)"/><path style="fill:#77767b;stroke:#c0bfbc;stroke-width:3.99999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M552.701-181.649v-105.989" transform="translate(27.86 739.504) scale(.66774)"/><path style="fill:#77767b;stroke:#deddda;stroke-width:3.99999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M544.496 220.043v-98.955" transform="translate(27.86 739.504) scale(.66774)"/><path style="font-variation-settings:normal;opacity:1;fill:#fff;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" transform="rotate(-135 167.087 363.982) scale(.66774)" d="M-481.009 289.025h58.926v58.926h-58.926z"/><path style="font-variation-settings:normal;opacity:1;fill:#f6d32d;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" transform="rotate(-135 167.087 363.982) scale(.66774)" d="M-470.403 299.631h37.713v37.713h-37.713z"/><path style="opacity:1;fill:#e01b24;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stop-color:#000;stop-opacity:1" d="m552.701-271.531-41.667-65.667h83.334z" transform="translate(27.86 739.504) scale(.66774)"/><path style="opacity:1;fill:#fff;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stop-color:#000;stop-opacity:1" d="m564.313-256.492 25.972 40.931 25.973-40.931z" transform="translate(2.764 691.375) scale(.66774)"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#fff;stroke-width:10;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:40,80;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000;stop-opacity:1" d="m622.912-123.702 44.122-27.852a326.49 326.49 118.869 0 0 152.21-276.084v-739.737" transform="translate(27.86 739.504) scale(.66774)"/><g style="stroke-width:1.09075"><path style="fill:none;stroke:#63452c;stroke-width:21.8151;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M159.305 392.456v-77.297" transform="matrix(.61218 0 0 .61218 386.014 741.792)"/></g><path style="fill:#1a724b;fill-opacity:1;stroke:none;stroke-width:.999996px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M304.117-174.224 221.605 18.303H386.63z" transform="translate(280.466 928.627) scale(.66774)"/><g transform="translate(111.222 965.81) scale(.66774)"><path style="fill:none;stroke:#63452c;stroke-width:20;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M157.574 392.456V272.495"/><circle style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1b754c;fill-opacity:1;stroke:none;stroke-width:160;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000;stop-opacity:1" cx="157.574" cy="246.53" r="73.723"/></g><g style="stroke-width:1.09075"><path style="fill:none;stroke:#63452c;stroke-width:21.8151;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M159.305 392.456v-77.297" transform="matrix(.61218 0 0 .61218 484.853 661.663)"/></g><path style="fill:#208b5b;fill-opacity:1;stroke:none;stroke-width:.999996px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M304.117-174.224 221.605 18.303H386.63z" transform="translate(379.305 848.498) scale(.66774)"/><g><g style="stroke-width:1.09075"><path style="fill:none;stroke:#63452c;stroke-width:21.8151;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M159.305 392.456v-77.297" transform="matrix(.61218 0 0 .61218 419.03 817.966)"/></g><path style="fill:#2cbd7a;fill-opacity:1;stroke:none;stroke-width:.999996px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M243.645-112.527 161.133 80.001h165.023z" transform="translate(353.863 963.604) scale(.66774)"/></g><g><g style="stroke-width:1.09075"><path style="fill:none;stroke:#63452c;stroke-width:21.8151;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M159.305 392.456v-77.297" transform="matrix(.61218 0 0 .61218 57.38 267.065)"/></g><path style="fill:#208b5b;fill-opacity:1;stroke:none;stroke-width:.999996px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M304.117-174.224 221.605 18.303H386.63z" transform="translate(-48.168 453.9) scale(.66774)"/></g><g transform="translate(-30.315 308.044) scale(.66774)"><path style="fill:none;stroke:#63452c;stroke-width:20;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M157.574 392.456V272.495"/><circle style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#2cbd7a;fill-opacity:1;stroke:none;stroke-width:160;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000;stop-opacity:1" cx="157.574" cy="246.53" r="73.723"/></g><g><g style="stroke-width:1.09075"><path style="fill:none;stroke:#63452c;stroke-width:21.8151;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M159.305 392.456v-77.297" transform="matrix(.61218 0 0 .61218 277.38 -32.935)"/></g><path style="fill:#1a724b;fill-opacity:1;stroke:none;stroke-width:.999996px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M304.117-174.224 221.605 18.303H386.63z" transform="translate(171.832 153.9) scale(.66774)"/></g><g><g style="stroke-width:1.09075"><path style="fill:none;stroke:#63452c;stroke-width:21.8151;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M159.305 392.456v-77.297" transform="matrix(.61218 0 0 .61218 357.38 7.065)"/></g><path style="fill:#208b5b;fill-opacity:1;stroke:none;stroke-width:.999996px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M304.117-174.224 221.605 18.303H386.63z" transform="translate(251.832 193.9) scale(.66774)"/></g><g transform="translate(339.685 108.044) scale(.66774)"><path style="fill:none;stroke:#63452c;stroke-width:20;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M157.574 392.456V272.495"/><circle style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#2cbd7a;fill-opacity:1;stroke:none;stroke-width:160;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000;stop-opacity:1" cx="157.574" cy="246.53" r="73.723"/></g></svg> \ No newline at end of file
diff --git a/panels/mouse/test-gnome-mouse-test.c b/panels/mouse/test-gnome-mouse-test.c
new file mode 100644
index 0000000..ca37f90
--- /dev/null
+++ b/panels/mouse/test-gnome-mouse-test.c
@@ -0,0 +1,24 @@
+#include <config.h>
+#include <gtk/gtk.h>
+
+#include "cc-mouse-resources.h"
+#include "cc-mouse-test.h"
+
+int main (int argc, char **argv)
+{
+ GtkWidget *widget;
+ GtkWidget *window;
+
+ gtk_init ();
+
+ widget = cc_mouse_test_new ();
+
+ window = gtk_window_new ();
+ gtk_window_set_child (GTK_WINDOW (window), widget);
+ gtk_window_present (GTK_WINDOW (window));
+
+ while (g_list_model_get_n_items (gtk_window_get_toplevels ()) > 0)
+ g_main_context_iteration (NULL, TRUE);
+
+ return 0;
+}
diff --git a/panels/multitasking/assets/active-screen-edges-rtl.svg b/panels/multitasking/assets/active-screen-edges-rtl.svg
new file mode 100644
index 0000000..4c2bd1a
--- /dev/null
+++ b/panels/multitasking/assets/active-screen-edges-rtl.svg
@@ -0,0 +1 @@
+<svg width="160" height="94" viewBox="0 0 42.333 24.871" xmlns="http://www.w3.org/2000/svg"><path style="display:inline;vector-effect:none;fill:none;fill-opacity:1;stroke:#3584e4;stroke-width:.529167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" d="M.265.265h41.804v24.342H.265Z"/><path style="display:inline;opacity:.287;vector-effect:none;fill:#3584e4;fill-opacity:1;stroke:none;stroke-width:2.99998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" d="M1.943 5.178v87.681h77.428V77.053h-68.39c-1.662 0-3-1.338-3-3V22.055c0-1.662 1.338-3 3-3h68.39V5.178Z" transform="matrix(.26459 0 0 .26459 0 0)"/><g transform="matrix(-.26458 0 0 .26458 424.372 1156.76)" style="display:inline"><rect ry="3" rx="3" y="-4353.007" x="1520.006" height="58" width="76" style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#3584e4;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none"/><path overflow="visible" font-weight="400" style="color:#bebebe;font-weight:400;line-height:normal;font-family:'Andale Mono';-inkscape-font-specification:'Andale Mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-transform:none;overflow:visible;fill:#3584e4;fill-opacity:1;marker:none" d="M1583-4348.006h1.031c.255.011.51.13.688.313l2.281 2.28 2.312-2.28c.266-.232.447-.307.688-.314h1v1c0 .286-.034.55-.25.75l-2.281 2.282 2.25 2.25c.188.188.281.454.281.72v1h-1c-.265 0-.53-.094-.719-.282l-2.281-2.28-2.281 2.28a1.015 1.015 0 0 1-.719.281h-1v-1c0-.265.093-.53.281-.719l2.281-2.25-2.28-2.28a.909.909 0 0 1-.282-.75z"/><g style="display:inline;fill:#fff;fill-opacity:1;stroke:#3584e4;stroke-opacity:1"><path style="color:#000;display:block;overflow:visible;visibility:visible;fill:#3584e4;fill-opacity:1;fill-rule:nonzero;stroke:#3584e4;stroke-width:.999998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" d="M1545.908-4344.757v26.838l-6.053-5.916-3.46 7.07c-.848 1.914-5.25.376-3.999-2.182l3.423-7.34h-7.64z"/></g></g><path style="fill:#3584e4;fill-opacity:1;stroke-width:.52917;stroke-linejoin:round;stop-color:#000" d="M0 0h42.334v1.852H0z"/></svg> \ No newline at end of file
diff --git a/panels/multitasking/assets/active-screen-edges.svg b/panels/multitasking/assets/active-screen-edges.svg
new file mode 100644
index 0000000..bc249ab
--- /dev/null
+++ b/panels/multitasking/assets/active-screen-edges.svg
@@ -0,0 +1 @@
+<svg width="160" height="94" viewBox="0 0 42.333 24.871" xmlns="http://www.w3.org/2000/svg"><path style="display:inline;vector-effect:none;fill:none;fill-opacity:1;stroke:#3584e4;stroke-width:.529167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" d="M.265.265h41.804v24.342H.265Z"/><path style="display:inline;opacity:.287;vector-effect:none;fill:#3584e4;fill-opacity:1;stroke:none;stroke-width:2.99998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" d="M1.943 5.178v87.681h77.428V77.053h-68.39c-1.662 0-3-1.338-3-3V22.055c0-1.662 1.338-3 3-3h68.39V5.178Z" transform="matrix(.26459 0 0 .26459 0 0)"/><g transform="translate(-400.062 1156.76) scale(.26458)" style="display:inline"><rect ry="3" rx="3" y="-4353.007" x="1520.006" height="58" width="76" style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#3584e4;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none"/><path overflow="visible" font-weight="400" style="color:#bebebe;font-weight:400;line-height:normal;font-family:'Andale Mono';-inkscape-font-specification:'Andale Mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-transform:none;overflow:visible;fill:#3584e4;fill-opacity:1;marker:none" d="M1583-4348.006h1.031c.255.011.51.13.688.313l2.281 2.28 2.312-2.28c.266-.232.447-.307.688-.314h1v1c0 .286-.034.55-.25.75l-2.281 2.282 2.25 2.25c.188.188.281.454.281.72v1h-1c-.265 0-.53-.094-.719-.282l-2.281-2.28-2.281 2.28a1.015 1.015 0 0 1-.719.281h-1v-1c0-.265.093-.53.281-.719l2.281-2.25-2.28-2.28a.909.909 0 0 1-.282-.75z"/><g style="display:inline;fill:#fff;fill-opacity:1;stroke:#3584e4;stroke-opacity:1"><path d="M26.605 2.318v16.44l3.712-3.624 2.122 4.331c.52 1.172 3.22.23 2.452-1.337l-2.099-4.496h4.685z" style="color:#000;display:block;overflow:visible;visibility:visible;fill:#fff;fill-opacity:1;fill-rule:nonzero;stroke:#3584e4;stroke-width:.612915;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" transform="matrix(1.6306 0 0 1.63249 1484.124 -4348.541)"/><path style="color:#000;display:block;overflow:visible;visibility:visible;fill:#3584e4;fill-opacity:1;fill-rule:nonzero;stroke:#3584e4;stroke-width:.612915;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" d="M26.605 2.318v16.44l3.712-3.624 2.122 4.331c.52 1.172 3.22.23 2.452-1.337l-2.099-4.496h4.685z" transform="matrix(1.6306 0 0 1.63249 1484.124 -4348.541)"/></g></g><path style="fill:#3584e4;fill-opacity:1;stroke-width:.52917;stroke-linejoin:round;stop-color:#000" d="M0 0h42.334v1.852H0z"/></svg> \ No newline at end of file
diff --git a/panels/multitasking/assets/hot-corner-rtl.svg b/panels/multitasking/assets/hot-corner-rtl.svg
new file mode 100644
index 0000000..4eb3aba
--- /dev/null
+++ b/panels/multitasking/assets/hot-corner-rtl.svg
@@ -0,0 +1 @@
+<svg width="160" height="94" viewBox="0 0 42.333 24.871" xmlns="http://www.w3.org/2000/svg"><defs><clipPath id="a" clipPathUnits="userSpaceOnUse"><path style="opacity:1;vector-effect:none;fill:#3584e4;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" d="M316-4731.007h162v95H316z"/></clipPath></defs><g style="display:inline"><path style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#3584e4;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" d="M1501.006-3631.007h158v92h-158z" transform="matrix(-.26458 0 0 .26458 439.199 960.969)"/></g><g clip-path="url(#a)" transform="matrix(-.26458 0 0 .26458 125.93 1251.746)" style="display:inline"><path style="color:#000;opacity:.249;fill:#3584e4;stroke-width:.999981;-inkscape-stroke:none" d="M159.96-79.697C115.93-79.697 80.2-43.972 80.2.06a79.352 79.352 0 0 0 13.98 45.082v-5.497C87.212 28.09 83.2 14.546 83.2.061c0-42.411 34.35-76.758 76.76-76.758 42.412 0 76.76 34.347 76.76 76.758 0 42.41-34.348 76.76-76.76 76.76-19.455 0-37.203-7.245-50.728-19.165h-4.402c14.327 13.718 33.742 22.164 55.13 22.164 44.033 0 79.76-35.727 79.76-79.76 0-44.032-35.727-79.757-79.76-79.757z" transform="matrix(-1.00002 0 0 1.00002 475.963 -4731.068)"/><path style="color:#000;opacity:.474;fill:#3584e4;stroke-width:.999981;-inkscape-stroke:none" d="M159.96-49.43c-27.314 0-49.491 22.175-49.491 49.49 0 7.333 1.61 14.287 4.476 20.55l3.178-.245A46.34 46.34 0 0 1 113.47.061c0-25.695 20.798-46.49 46.492-46.49S206.45-25.635 206.45.06c0 25.694-20.796 46.49-46.49 46.49a46.337 46.337 0 0 1-20.357-4.68l-.247 3.18a49.246 49.246 0 0 0 20.604 4.5c27.315 0 49.49-22.175 49.49-49.49 0-27.316-22.175-49.49-49.49-49.49z" transform="matrix(-1.00002 0 0 1.00002 475.963 -4731.068)"/><path style="color:#000;opacity:.705;fill:#3584e4;stroke-width:.999981;-inkscape-stroke:none" d="M159.96-28.297c-15.643 0-28.358 12.713-28.358 28.358 0 7.171 2.676 13.723 7.078 18.72l2.713-.209-.21 2.721c5.005 4.43 11.58 7.127 18.778 7.127 15.644 0 28.357-12.715 28.357-28.36 0-15.644-12.713-28.357-28.357-28.357zm0 3c14.024 0 25.358 11.335 25.358 25.358 0 14.022-11.334 25.359-25.357 25.359S134.6 14.083 134.6.06c0-14.022 11.337-25.357 25.36-25.357z" transform="matrix(-1.00002 0 0 1.00002 475.963 -4731.068)"/><circle r="16.568" cy="-4731.007" cx="316" style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#3584e4;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"/></g><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;stroke:#3584e4;stroke-width:.262885;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:.95;stroke-opacity:1;marker:none;enable-background:accumulate" d="m30.31 9.024 1.341-1.38-2.121-2.123 7.88-.607-.606 7.89-2.122-2.124-3.288 3.292"/><g style="display:inline"><path style="color:#000;display:block;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#3584e4;stroke-width:.612915;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:1.22583,.612915;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" d="M29.691 6.634v16.44l3.712-3.624 2.122 4.331c.52 1.171 3.22.23 2.452-1.337l-2.099-4.497h4.685z" transform="matrix(.42866 0 0 .42916 12.191 7.553)"/></g><path style="fill:#3584e4;fill-opacity:1;stroke-width:.52917;stroke-linejoin:round;stop-color:#000" d="M0 0h42.334v1.852H0z"/></svg> \ No newline at end of file
diff --git a/panels/multitasking/assets/hot-corner.svg b/panels/multitasking/assets/hot-corner.svg
new file mode 100644
index 0000000..66cee2a
--- /dev/null
+++ b/panels/multitasking/assets/hot-corner.svg
@@ -0,0 +1 @@
+<svg width="160" height="94" viewBox="0 0 42.333 24.871" xmlns="http://www.w3.org/2000/svg"><defs><clipPath id="a" clipPathUnits="userSpaceOnUse"><path style="opacity:1;vector-effect:none;fill:#3584e4;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" d="M316-4731.007h162v95H316z"/></clipPath></defs><g style="display:inline"><path style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#3584e4;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" d="M1501.006-3631.007h158v92h-158z" transform="translate(-396.877 960.969) scale(.26458)"/></g><g clip-path="url(#a)" transform="translate(-83.608 1251.746) scale(.26458)" style="display:inline"><path style="color:#000;opacity:.249;fill:#3584e4;stroke-width:.999981;-inkscape-stroke:none" d="M-.002-79.697c-44.032 0-79.76 35.725-79.76 79.758 0 44.032 35.728 79.76 79.76 79.76 21.164 0 40.396-8.27 54.678-21.733v-4.156C40.756 68.058 21.408 76.82-.002 76.82c-42.41 0-76.76-34.349-76.76-76.76 0-42.41 34.35-76.757 76.76-76.757 42.41 0 76.76 34.347 76.76 76.758 0 17.32-5.734 33.29-15.4 46.13l2.085 2.174C73.672 34.955 79.758 18.22 79.758.061c0-44.033-35.728-79.758-79.76-79.758z" transform="matrix(1.00002 0 0 1.00002 316.002 -4731.068)"/><path style="color:#000;opacity:.474;fill:#3584e4;-inkscape-stroke:none" d="M316-4780.498c-27.316 0-49.492 22.176-49.492 49.492s22.176 49.49 49.492 49.49c7.56 0 14.733-1.697 21.146-4.732l-1.283-2.711a46.295 46.295 0 0 1-19.863 4.443c-25.695 0-46.492-20.795-46.492-46.49 0-25.694 20.797-46.492 46.492-46.492 25.695 0 46.492 20.798 46.492 46.492 0 7.094-1.58 13.792-4.416 19.803l2.92.835a49.266 49.266 0 0 0 4.496-20.638c0-27.316-22.176-49.492-49.492-49.492z"/><path style="color:#000;opacity:.705;fill:#3584e4;-inkscape-stroke:none" d="M316-4759.365c-15.644 0-28.36 12.715-28.36 28.36 0 15.644 12.716 28.357 28.36 28.357a28.277 28.277 0 0 0 18.967-7.275l.035-2.145 2.033.082a28.273 28.273 0 0 0 7.324-19.02c0-15.644-12.715-28.36-28.359-28.36zm0 3c14.023 0 25.36 11.336 25.36 25.36a25.247 25.247 0 0 1-7.864 18.355 25.253 25.253 0 0 1-17.496 7.002c-14.023 0-25.36-11.335-25.36-25.358s11.337-25.36 25.36-25.36z"/><circle r="16.568" cy="-4731.007" cx="316" style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#3584e4;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"/></g><g style="display:inline"><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:#3584e4;stroke-width:.612915;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:.95;stroke-opacity:1;marker:none;enable-background:accumulate;fill-opacity:1" d="m275.62 271.75-3.13-3.214 4.95-4.95-18.385-1.414 1.414 18.385 4.95-4.95 7.671 7.672" transform="matrix(.42866 0 0 .42916 -106.135 -107.6)"/><g style="display:inline"><path style="color:#000;display:block;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#3584e4;stroke-width:.612915;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:1.22583,.612915;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" d="M29.691 6.634v16.44l3.712-3.624 2.122 4.331c.52 1.171 3.22.23 2.452-1.337l-2.099-4.497h4.685z" transform="matrix(.42866 0 0 .42916 1.739 7.533)"/></g></g><path style="fill:#3584e4;fill-opacity:1;stroke-width:.52917;stroke-linejoin:round;stop-color:#000" d="M0 0h42.334v1.852H0z"/></svg> \ No newline at end of file
diff --git a/panels/multitasking/assets/workspaces-primary-display.svg b/panels/multitasking/assets/workspaces-primary-display.svg
new file mode 100644
index 0000000..3a3bed7
--- /dev/null
+++ b/panels/multitasking/assets/workspaces-primary-display.svg
@@ -0,0 +1 @@
+<svg width="326" height="94" viewBox="0 0 86.255 24.871" xmlns="http://www.w3.org/2000/svg"><path style="display:inline;opacity:.287;vector-effect:none;fill:#3584e4;fill-opacity:1;stroke:#3584e4;stroke-width:.79375;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" d="M.397.397h41.54v24.078H.397Z"/><path style="display:inline;vector-effect:none;fill:none;fill-opacity:1;stroke:#3584e4;stroke-width:.529167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" d="M.265.265h41.804v24.342H.265Z"/><path style="vector-effect:none;fill:none;fill-opacity:1;stroke:#3584e4;stroke-width:.529162;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" d="M44.186.265H85.99v24.342H44.186z"/><path style="display:inline;opacity:.287;vector-effect:none;fill:#3584e4;fill-opacity:1;stroke:#3584e4;stroke-width:.79375;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" d="M44.318.397h41.54v24.078h-41.54Z"/><rect style="opacity:1;fill:#3584e4;fill-opacity:1;stroke:#ed333b;stroke-width:0;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none" width="33.338" height="19.579" x="48.419" y="2.646" rx="1.323" ry="1.323"/><rect style="opacity:1;fill:#3584e4;fill-opacity:1;stroke:#ed333b;stroke-width:0;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none" width="26.459" height="15.346" x="7.937" y="4.763" rx="1.323" ry="1.323"/><path style="opacity:1;fill:#3584e4;stroke:#ed333b;stroke-width:0;stroke-linecap:round;fill-opacity:1" d="M38.365 4.763h3.44v15.345h-3.44a1.32 1.32 0 0 1-1.323-1.322v-12.7c0-.733.59-1.323 1.323-1.323zM3.969 4.763H.529v15.345h3.44a1.32 1.32 0 0 0 1.323-1.322v-12.7a1.32 1.32 0 0 0-1.323-1.323Z"/><path style="fill:#3584e4;fill-opacity:1;stroke-width:.52917;stroke-linejoin:round;stop-color:#000" d="M0 0h42.334v1.852H0z"/></svg> \ No newline at end of file
diff --git a/panels/multitasking/assets/workspaces-span-displays.svg b/panels/multitasking/assets/workspaces-span-displays.svg
new file mode 100644
index 0000000..571ee10
--- /dev/null
+++ b/panels/multitasking/assets/workspaces-span-displays.svg
@@ -0,0 +1 @@
+<svg width="326" height="94" viewBox="0 0 86.255 24.871" xmlns="http://www.w3.org/2000/svg"><path style="display:inline;opacity:.287;vector-effect:none;fill:#3584e4;fill-opacity:1;stroke:#3584e4;stroke-width:.79375;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" d="M.397.397h41.54v24.078H.397Z"/><path style="display:inline;vector-effect:none;fill:none;fill-opacity:1;stroke:#3584e4;stroke-width:.529167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" d="M.265.265h41.804v24.342H.265Z"/><path style="vector-effect:none;fill:none;fill-opacity:1;stroke:#3584e4;stroke-width:.529162;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" d="M44.186.265H85.99v24.342H44.186z"/><path style="display:inline;opacity:.287;vector-effect:none;fill:#3584e4;fill-opacity:1;stroke:#3584e4;stroke-width:.79375;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" d="M44.318.397h41.54v24.078h-41.54Z"/><rect style="opacity:1;fill:#3584e4;fill-opacity:1;stroke:#ed333b;stroke-width:0;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none" width="26.459" height="15.346" x="7.937" y="4.763" rx="1.323" ry="1.323"/><path style="opacity:1;fill:#3584e4;stroke:#ed333b;stroke-width:0;stroke-linecap:round;fill-opacity:1" d="M38.365 4.763h3.44V20.11h-3.44a1.32 1.32 0 0 1-1.323-1.323v-12.7c0-.733.59-1.323 1.323-1.323zM3.969 4.763H.529V20.11h3.44a1.32 1.32 0 0 0 1.323-1.323v-12.7a1.32 1.32 0 0 0-1.323-1.323z"/><g transform="translate(43.921 -.529)"><rect style="opacity:1;fill:#3584e4;fill-opacity:1;stroke:#ed333b;stroke-width:0;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none" width="26.459" height="15.346" x="7.937" y="5.292" rx="1.323" ry="1.323"/><path style="opacity:1;fill:#3584e4;stroke:#ed333b;stroke-width:0;stroke-linecap:round;fill-opacity:1" d="M38.365 5.292h3.44v15.346h-3.44a1.32 1.32 0 0 1-1.323-1.323v-12.7c0-.733.59-1.323 1.323-1.323zM3.969 5.292H.529v15.346h3.44a1.32 1.32 0 0 0 1.323-1.323v-12.7a1.32 1.32 0 0 0-1.323-1.323z"/></g><g style="stroke-width:.999999"><path style="fill:#3584e4;fill-opacity:1;stroke-width:.52917;stroke-linejoin:round;stop-color:#000" d="M0 0h42.334v1.852H0z"/></g></svg> \ No newline at end of file
diff --git a/panels/multitasking/cc-multitasking-panel.c b/panels/multitasking/cc-multitasking-panel.c
new file mode 100644
index 0000000..db4c47a
--- /dev/null
+++ b/panels/multitasking/cc-multitasking-panel.c
@@ -0,0 +1,161 @@
+/* cc-multitasking-panel.h
+ *
+ * Copyright 2020 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+
+#include "cc-multitasking-panel.h"
+
+#include "cc-multitasking-resources.h"
+#include "cc-multitasking-row.h"
+
+struct _CcMultitaskingPanel
+{
+ CcPanel parent_instance;
+
+ GSettings *interface_settings;
+ GSettings *mutter_settings;
+ GSettings *shell_settings;
+ GSettings *wm_settings;
+
+ GtkPicture *active_screen_edges_picture;
+ GtkSwitch *active_screen_edges_switch;
+ GtkCheckButton *all_workspaces_radio;
+ GtkCheckButton *current_workspace_radio;
+ GtkCheckButton *dynamic_workspaces_radio;
+ GtkCheckButton *fixed_workspaces_radio;
+ GtkPicture *hot_corner_picture;
+ GtkSwitch *hot_corner_switch;
+ GtkSpinButton *number_of_workspaces_spin;
+ GtkCheckButton *workspaces_primary_display_radio;
+ GtkCheckButton *workspaces_span_displays_radio;
+};
+
+CC_PANEL_REGISTER (CcMultitaskingPanel, cc_multitasking_panel)
+
+/* GObject overrides */
+
+static void
+cc_multitasking_panel_finalize (GObject *object)
+{
+ CcMultitaskingPanel *self = (CcMultitaskingPanel *)object;
+
+ g_clear_object (&self->interface_settings);
+ g_clear_object (&self->mutter_settings);
+ g_clear_object (&self->shell_settings);
+ g_clear_object (&self->wm_settings);
+
+ G_OBJECT_CLASS (cc_multitasking_panel_parent_class)->finalize (object);
+}
+
+static void
+cc_multitasking_panel_class_init (CcMultitaskingPanelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ g_type_ensure (CC_TYPE_MULTITASKING_ROW);
+
+ object_class->finalize = cc_multitasking_panel_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/multitasking/cc-multitasking-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, active_screen_edges_picture);
+ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, active_screen_edges_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, all_workspaces_radio);
+ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, current_workspace_radio);
+ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, dynamic_workspaces_radio);
+ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, fixed_workspaces_radio);
+ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, hot_corner_picture);
+ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, hot_corner_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, number_of_workspaces_spin);
+ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, workspaces_primary_display_radio);
+ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, workspaces_span_displays_radio);
+}
+
+static void
+cc_multitasking_panel_init (CcMultitaskingPanel *self)
+{
+ g_resources_register (cc_multitasking_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->interface_settings = g_settings_new ("org.gnome.desktop.interface");
+ g_settings_bind (self->interface_settings,
+ "enable-hot-corners",
+ self->hot_corner_switch,
+ "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ self->mutter_settings = g_settings_new ("org.gnome.mutter");
+
+ if (g_settings_get_boolean (self->mutter_settings, "workspaces-only-on-primary"))
+ gtk_check_button_set_active (self->workspaces_primary_display_radio, TRUE);
+ else
+ gtk_check_button_set_active (self->workspaces_span_displays_radio, TRUE);
+
+ g_settings_bind (self->mutter_settings,
+ "workspaces-only-on-primary",
+ self->workspaces_primary_display_radio,
+ "active",
+ G_SETTINGS_BIND_DEFAULT);
+ g_settings_bind (self->mutter_settings,
+ "edge-tiling",
+ self->active_screen_edges_switch,
+ "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ if (g_settings_get_boolean (self->mutter_settings, "dynamic-workspaces"))
+ gtk_check_button_set_active (self->dynamic_workspaces_radio, TRUE);
+ else
+ gtk_check_button_set_active (self->fixed_workspaces_radio, TRUE);
+
+ g_settings_bind (self->mutter_settings,
+ "dynamic-workspaces",
+ self->dynamic_workspaces_radio,
+ "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ self->wm_settings = g_settings_new ("org.gnome.desktop.wm.preferences");
+ g_settings_bind (self->wm_settings,
+ "num-workspaces",
+ self->number_of_workspaces_spin,
+ "value",
+ G_SETTINGS_BIND_DEFAULT);
+
+ self->shell_settings = g_settings_new ("org.gnome.shell.app-switcher");
+
+ if (g_settings_get_boolean (self->shell_settings, "current-workspace-only"))
+ gtk_check_button_set_active (self->current_workspace_radio, TRUE);
+ else
+ gtk_check_button_set_active (self->all_workspaces_radio, TRUE);
+
+ g_settings_bind (self->shell_settings,
+ "current-workspace-only",
+ self->current_workspace_radio,
+ "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL)
+ {
+ gtk_picture_set_resource (self->hot_corner_picture,
+ "/org/gnome/control-center/multitasking/assets/hot-corner-rtl.svg");
+ gtk_picture_set_resource (self->active_screen_edges_picture,
+ "/org/gnome/control-center/multitasking/assets/active-screen-edges-rtl.svg");
+ }
+}
diff --git a/panels/multitasking/cc-multitasking-panel.h b/panels/multitasking/cc-multitasking-panel.h
new file mode 100644
index 0000000..81e78f0
--- /dev/null
+++ b/panels/multitasking/cc-multitasking-panel.h
@@ -0,0 +1,30 @@
+/* cc-multitasking-panel.h
+ *
+ * Copyright 2020 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_MULTITASKING_PANEL (cc_multitasking_panel_get_type())
+G_DECLARE_FINAL_TYPE (CcMultitaskingPanel, cc_multitasking_panel, CC, MULTITASKING_PANEL, CcPanel)
+
+G_END_DECLS
diff --git a/panels/multitasking/cc-multitasking-panel.ui b/panels/multitasking/cc-multitasking-panel.ui
new file mode 100644
index 0000000..28a5ce0
--- /dev/null
+++ b/panels/multitasking/cc-multitasking-panel.ui
@@ -0,0 +1,229 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcMultitaskingPanel" parent="CcPanel">
+ <child type="content">
+ <object class="AdwPreferencesPage">
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">General</property>
+
+ <!-- Hot Corner -->
+ <child>
+ <object class="CcMultitaskingRow">
+ <property name="activatable-widget">hot_corner_switch</property>
+ <property name="title" translatable="yes">_Hot Corner</property>
+ <property name="subtitle" translatable="yes">Touch the top-left corner to open the Activities Overview.</property>
+ <property name="use_underline">True</property>
+ <child>
+ <object class="GtkSwitch" id="hot_corner_switch">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ <child type="artwork">
+ <object class="GtkPicture" id="hot_corner_picture">
+ <property name="hexpand">True</property>
+ <property name="halign">center</property>
+ <property name="margin-top">18</property>
+ <property name="margin-bottom">18</property>
+ <property name="margin-start">18</property>
+ <property name="margin-end">18</property>
+ <property name="can-shrink">False</property>
+ <property name="file">resource:///org/gnome/control-center/multitasking/assets/hot-corner.svg</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- Active Screen Edges -->
+ <child>
+ <object class="CcMultitaskingRow">
+ <property name="activatable-widget">active_screen_edges_switch</property>
+ <property name="title" translatable="yes">_Active Screen Edges</property>
+ <property name="subtitle" translatable="yes">Drag windows against the top, left, and right screen edges to resize them.</property>
+ <property name="use_underline">True</property>
+ <child>
+ <object class="GtkSwitch" id="active_screen_edges_switch">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ <child type="artwork">
+ <object class="GtkPicture" id="active_screen_edges_picture">
+ <property name="hexpand">True</property>
+ <property name="halign">center</property>
+ <property name="margin-top">18</property>
+ <property name="margin-bottom">18</property>
+ <property name="margin-start">18</property>
+ <property name="margin-end">18</property>
+ <property name="can-shrink">False</property>
+ <property name="file">resource:///org/gnome/control-center/multitasking/assets/active-screen-edges.svg</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Workspaces</property>
+
+ <!-- Dynamic Workspaces -->
+ <child>
+ <object class="CcMultitaskingRow">
+ <property name="activatable-widget">dynamic_workspaces_radio</property>
+ <property name="title" translatable="yes">_Dynamic workspaces</property>
+ <property name="subtitle" translatable="yes">Automatically removes empty workspaces.</property>
+ <property name="use_underline">True</property>
+ <child type="prefix">
+ <object class="GtkCheckButton" id="dynamic_workspaces_radio">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- Fixed Number of Workspaces -->
+ <child>
+ <object class="CcMultitaskingRow">
+ <property name="activatable-widget">fixed_workspaces_radio</property>
+ <property name="title" translatable="yes">_Fixed number of workspaces</property>
+ <property name="subtitle" translatable="yes">Specify a number of permanent workspaces.</property>
+ <property name="use_underline">True</property>
+ <child type="prefix">
+ <object class="GtkCheckButton" id="fixed_workspaces_radio">
+ <property name="valign">center</property>
+ <property name="group">dynamic_workspaces_radio</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- Number of Workspaces -->
+ <child>
+ <object class="CcMultitaskingRow">
+ <property name="sensitive" bind-source="fixed_workspaces_radio" bind-property="active" bind-flags="default|sync-create" />
+ <property name="activatable-widget">number_of_workspaces_spin</property>
+ <property name="title" translatable="yes">_Number of Workspaces</property>
+ <property name="use_underline">True</property>
+ <child>
+ <object class="GtkSpinButton" id="number_of_workspaces_spin">
+ <property name="valign">center</property>
+ <property name="adjustment">workspaces_adjustment</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Multi-Monitor</property>
+
+ <!-- Primary Display -->
+ <child>
+ <object class="CcMultitaskingRow">
+ <property name="activatable-widget">workspaces_primary_display_radio</property>
+ <property name="title" translatable="yes">Workspaces on _primary display only</property>
+ <property name="use_underline">True</property>
+ <child type="prefix">
+ <object class="GtkCheckButton" id="workspaces_primary_display_radio">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ <child type="artwork">
+ <object class="GtkPicture">
+ <property name="hexpand">True</property>
+ <property name="halign">center</property>
+ <property name="margin-top">18</property>
+ <property name="margin-bottom">18</property>
+ <property name="margin-start">18</property>
+ <property name="margin-end">18</property>
+ <property name="can-shrink">False</property>
+ <property name="file">resource:///org/gnome/control-center/multitasking/assets/workspaces-primary-display.svg</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- Span Displays -->
+ <child>
+ <object class="CcMultitaskingRow">
+ <property name="activatable-widget">workspaces_span_displays_radio</property>
+ <property name="title" translatable="yes">Workspaces on all d_isplays</property>
+ <property name="use_underline">True</property>
+ <child type="prefix">
+ <object class="GtkCheckButton" id="workspaces_span_displays_radio">
+ <property name="valign">center</property>
+ <property name="group">workspaces_primary_display_radio</property>
+ </object>
+ </child>
+ <child type="artwork">
+ <object class="GtkPicture">
+ <property name="hexpand">True</property>
+ <property name="halign">center</property>
+ <property name="margin-top">18</property>
+ <property name="margin-bottom">18</property>
+ <property name="margin-start">18</property>
+ <property name="margin-end">18</property>
+ <property name="can-shrink">False</property>
+ <property name="file">resource:///org/gnome/control-center/multitasking/assets/workspaces-span-displays.svg</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Application Switching</property>
+
+ <!-- All Workspaces -->
+ <child>
+ <object class="CcMultitaskingRow">
+ <property name="activatable-widget">all_workspaces_radio</property>
+ <property name="title" translatable="yes">Include applications from all _workspaces</property>
+ <property name="use_underline">True</property>
+ <child type="prefix">
+ <object class="GtkCheckButton" id="all_workspaces_radio">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- Current Workspace -->
+ <child>
+ <object class="CcMultitaskingRow">
+ <property name="activatable-widget">current_workspace_radio</property>
+ <property name="title" translatable="yes">Include applications from the _current workspace only</property>
+ <property name="use_underline">True</property>
+ <child type="prefix">
+ <object class="GtkCheckButton" id="current_workspace_radio">
+ <property name="valign">center</property>
+ <property name="group">all_workspaces_radio</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </template>
+
+ <object class="GtkAdjustment" id="workspaces_adjustment">
+ <property name="lower">1.0</property>
+ <property name="step-increment">1.0</property>
+ <property name="value">4.0</property>
+ <!-- 36 is the maximum value allowed by Mutter -->
+ <property name="upper">36.0</property>
+ </object>
+</interface>
diff --git a/panels/multitasking/cc-multitasking-row.c b/panels/multitasking/cc-multitasking-row.c
new file mode 100644
index 0000000..9524fba
--- /dev/null
+++ b/panels/multitasking/cc-multitasking-row.c
@@ -0,0 +1,572 @@
+/* cc-multitasking-row.c
+ *
+ * Copyright 2018 Purism SPC
+ * 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "cc-multitasking-row.h"
+
+struct _CcMultitaskingRow
+{
+ AdwPreferencesRow parent;
+
+ GtkBox *artwork_box;
+ GtkBox *header;
+ GtkImage *image;
+ GtkBox *prefixes;
+ GtkLabel *subtitle;
+ GtkBox *suffixes;
+ GtkLabel *title;
+ GtkBox *title_box;
+
+ GtkWidget *previous_parent;
+
+ gboolean use_underline;
+ gint title_lines;
+ gint subtitle_lines;
+ GtkWidget *activatable_widget;
+};
+
+static GtkBuildableIface *parent_buildable_iface;
+
+static void cc_multitasking_row_buildable_init (GtkBuildableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (CcMultitaskingRow, cc_multitasking_row, ADW_TYPE_PREFERENCES_ROW,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, cc_multitasking_row_buildable_init))
+
+enum
+{
+ PROP_0,
+ PROP_ICON_NAME,
+ PROP_ACTIVATABLE_WIDGET,
+ PROP_SUBTITLE,
+ PROP_USE_UNDERLINE,
+ PROP_TITLE_LINES,
+ PROP_SUBTITLE_LINES,
+ N_PROPS,
+};
+
+enum
+{
+ SIGNAL_ACTIVATED,
+ SIGNAL_LAST_SIGNAL,
+};
+
+static GParamSpec *props[N_PROPS] = { NULL, };
+static guint signals[SIGNAL_LAST_SIGNAL] = { 0, };
+
+static void
+row_activated_cb (CcMultitaskingRow *self,
+ GtkListBoxRow *row)
+{
+ /* No need to use GTK_LIST_BOX_ROW() for a pointer comparison. */
+ if ((GtkListBoxRow *) self == row)
+ cc_multitasking_row_activate (self);
+}
+
+static void
+parent_cb (CcMultitaskingRow *self)
+{
+ GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (self));
+
+ if (self->previous_parent != NULL)
+ {
+ g_signal_handlers_disconnect_by_func (self->previous_parent,
+ G_CALLBACK (row_activated_cb),
+ self);
+ self->previous_parent = NULL;
+ }
+
+ if (parent == NULL || !GTK_IS_LIST_BOX (parent))
+ return;
+
+ self->previous_parent = parent;
+ g_signal_connect_swapped (parent, "row-activated", G_CALLBACK (row_activated_cb), self);
+}
+
+static void
+update_subtitle_visibility (CcMultitaskingRow *self)
+{
+ gtk_widget_set_visible (GTK_WIDGET (self->subtitle),
+ gtk_label_get_text (self->subtitle) != NULL &&
+ g_strcmp0 (gtk_label_get_text (self->subtitle), "") != 0);
+}
+
+static void
+cc_multitasking_row_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcMultitaskingRow *self = CC_MULTITASKING_ROW (object);
+
+ switch (prop_id)
+ {
+ case PROP_ICON_NAME:
+ g_value_set_string (value, cc_multitasking_row_get_icon_name (self));
+ break;
+ case PROP_ACTIVATABLE_WIDGET:
+ g_value_set_object (value, (GObject *) cc_multitasking_row_get_activatable_widget (self));
+ break;
+ case PROP_SUBTITLE:
+ g_value_set_string (value, cc_multitasking_row_get_subtitle (self));
+ break;
+ case PROP_SUBTITLE_LINES:
+ g_value_set_int (value, cc_multitasking_row_get_subtitle_lines (self));
+ break;
+ case PROP_TITLE_LINES:
+ g_value_set_int (value, cc_multitasking_row_get_title_lines (self));
+ break;
+ case PROP_USE_UNDERLINE:
+ g_value_set_boolean (value, cc_multitasking_row_get_use_underline (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_multitasking_row_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcMultitaskingRow *self = CC_MULTITASKING_ROW (object);
+
+ switch (prop_id)
+ {
+ case PROP_ICON_NAME:
+ cc_multitasking_row_set_icon_name (self, g_value_get_string (value));
+ break;
+ case PROP_ACTIVATABLE_WIDGET:
+ cc_multitasking_row_set_activatable_widget (self, (GtkWidget*) g_value_get_object (value));
+ break;
+ case PROP_SUBTITLE:
+ cc_multitasking_row_set_subtitle (self, g_value_get_string (value));
+ break;
+ case PROP_SUBTITLE_LINES:
+ cc_multitasking_row_set_subtitle_lines (self, g_value_get_int (value));
+ break;
+ case PROP_TITLE_LINES:
+ cc_multitasking_row_set_title_lines (self, g_value_get_int (value));
+ break;
+ case PROP_USE_UNDERLINE:
+ cc_multitasking_row_set_use_underline (self, g_value_get_boolean (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_multitasking_row_dispose (GObject *object)
+{
+ CcMultitaskingRow *self = CC_MULTITASKING_ROW (object);
+
+ if (self->previous_parent != NULL) {
+ g_signal_handlers_disconnect_by_func (self->previous_parent, G_CALLBACK (row_activated_cb), self);
+ self->previous_parent = NULL;
+ }
+
+ cc_multitasking_row_set_activatable_widget (self, NULL);
+ g_clear_pointer ((GtkWidget**)&self->header, gtk_widget_unparent);
+
+ G_OBJECT_CLASS (cc_multitasking_row_parent_class)->dispose (object);
+}
+
+static void
+cc_multitasking_row_class_init (CcMultitaskingRowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->get_property = cc_multitasking_row_get_property;
+ object_class->set_property = cc_multitasking_row_set_property;
+ object_class->dispose = cc_multitasking_row_dispose;
+
+ props[PROP_ICON_NAME] =
+ g_param_spec_string ("icon-name",
+ "Icon name",
+ "Icon name",
+ "",
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ props[PROP_ACTIVATABLE_WIDGET] =
+ g_param_spec_object ("activatable-widget",
+ "Activatable widget",
+ "The widget to be activated when the row is activated",
+ GTK_TYPE_WIDGET,
+ G_PARAM_READWRITE);
+
+ props[PROP_SUBTITLE] =
+ g_param_spec_string ("subtitle",
+ "Subtitle",
+ "Subtitle",
+ "",
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ props[PROP_USE_UNDERLINE] =
+ g_param_spec_boolean ("use-underline",
+ "Use underline",
+ "If set, an underline in the text indicates the next character should be used for the mnemonic accelerator key",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
+ props[PROP_TITLE_LINES] =
+ g_param_spec_int ("title-lines",
+ "Number of title lines",
+ "The desired number of title lines",
+ 0, G_MAXINT,
+ 1,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
+ props[PROP_SUBTITLE_LINES] =
+ g_param_spec_int ("subtitle-lines",
+ "Number of subtitle lines",
+ "The desired number of subtitle lines",
+ 0, G_MAXINT,
+ 1,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
+ g_object_class_install_properties (object_class, N_PROPS, props);
+
+ signals[SIGNAL_ACTIVATED] =
+ g_signal_new ("activated",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 0);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/multitasking/cc-multitasking-row.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingRow, artwork_box);
+ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingRow, header);
+ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingRow, image);
+ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingRow, prefixes);
+ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingRow, subtitle);
+ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingRow, suffixes);
+ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingRow, title);
+ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingRow, title_box);
+}
+
+static gboolean
+string_is_not_empty (GBinding *binding,
+ const GValue *from_value,
+ GValue *to_value,
+ gpointer user_data)
+{
+ const gchar *string = g_value_get_string (from_value);
+
+ g_value_set_boolean (to_value, string != NULL && g_strcmp0 (string, "") != 0);
+
+ return TRUE;
+}
+
+static void
+cc_multitasking_row_init (CcMultitaskingRow *self)
+{
+ self->title_lines = 1;
+ self->subtitle_lines = 1;
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ g_object_bind_property_full (self, "title",
+ self->title, "visible",
+ G_BINDING_SYNC_CREATE,
+ string_is_not_empty,
+ NULL, NULL, NULL);
+
+ update_subtitle_visibility (self);
+
+ g_signal_connect (self, "notify::parent", G_CALLBACK (parent_cb), NULL);
+}
+
+static void
+cc_multitasking_row_buildable_add_child (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *type)
+{
+ CcMultitaskingRow *self = CC_MULTITASKING_ROW (buildable);
+
+ if (!self->header)
+ parent_buildable_iface->add_child (buildable, builder, child, type);
+ else if (type && strcmp (type, "prefix") == 0)
+ cc_multitasking_row_add_prefix (self, GTK_WIDGET (child));
+ else if (type && strcmp (type, "artwork") == 0)
+ cc_multitasking_row_add_artwork (self, GTK_WIDGET (child));
+ else if (!type && GTK_IS_WIDGET (child))
+ {
+ gtk_box_append (self->suffixes, GTK_WIDGET (child));
+ gtk_widget_show (GTK_WIDGET (self->suffixes));
+ }
+ else
+ parent_buildable_iface->add_child (buildable, builder, child, type);
+}
+
+static void
+cc_multitasking_row_buildable_init (GtkBuildableIface *iface)
+{
+ parent_buildable_iface = g_type_interface_peek_parent (iface);
+ iface->add_child = cc_multitasking_row_buildable_add_child;
+}
+
+const gchar *
+cc_multitasking_row_get_subtitle (CcMultitaskingRow *self)
+{
+ g_return_val_if_fail (CC_IS_MULTITASKING_ROW (self), NULL);
+
+ return gtk_label_get_text (self->subtitle);
+}
+
+void
+cc_multitasking_row_set_subtitle (CcMultitaskingRow *self,
+ const gchar *subtitle)
+{
+ g_return_if_fail (CC_IS_MULTITASKING_ROW (self));
+
+ if (g_strcmp0 (gtk_label_get_text (self->subtitle), subtitle) == 0)
+ return;
+
+ gtk_label_set_text (self->subtitle, subtitle);
+ gtk_widget_set_visible (GTK_WIDGET (self->subtitle),
+ subtitle != NULL && g_strcmp0 (subtitle, "") != 0);
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SUBTITLE]);
+}
+
+const gchar *
+cc_multitasking_row_get_icon_name (CcMultitaskingRow *self)
+{
+ g_return_val_if_fail (CC_IS_MULTITASKING_ROW (self), NULL);
+
+ return gtk_image_get_icon_name (self->image);
+}
+
+void
+cc_multitasking_row_set_icon_name (CcMultitaskingRow *self,
+ const gchar *icon_name)
+{
+ const gchar *old_icon_name;
+
+ g_return_if_fail (CC_IS_MULTITASKING_ROW (self));
+
+ old_icon_name = gtk_image_get_icon_name (self->image);
+ if (g_strcmp0 (old_icon_name, icon_name) == 0)
+ return;
+
+ gtk_image_set_from_icon_name (self->image, icon_name);
+ gtk_widget_set_visible (GTK_WIDGET (self->image),
+ icon_name != NULL && g_strcmp0 (icon_name, "") != 0);
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ICON_NAME]);
+}
+
+GtkWidget *
+cc_multitasking_row_get_activatable_widget (CcMultitaskingRow *self)
+{
+ g_return_val_if_fail (CC_IS_MULTITASKING_ROW (self), NULL);
+
+ return self->activatable_widget;
+}
+
+static void
+activatable_widget_weak_notify (gpointer data,
+ GObject *where_the_object_was)
+{
+ CcMultitaskingRow *self = CC_MULTITASKING_ROW (data);
+
+ self->activatable_widget = NULL;
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ACTIVATABLE_WIDGET]);
+}
+
+void
+cc_multitasking_row_set_activatable_widget (CcMultitaskingRow *self,
+ GtkWidget *widget)
+{
+ g_return_if_fail (CC_IS_MULTITASKING_ROW (self));
+ g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
+
+ if (self->activatable_widget == widget)
+ return;
+
+ if (self->activatable_widget)
+ g_object_weak_unref (G_OBJECT (self->activatable_widget),
+ activatable_widget_weak_notify,
+ self);
+
+ self->activatable_widget = widget;
+
+ if (self->activatable_widget != NULL) {
+ g_object_weak_ref (G_OBJECT (self->activatable_widget),
+ activatable_widget_weak_notify,
+ self);
+ gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (self), TRUE);
+ gtk_accessible_update_relation (GTK_ACCESSIBLE (self->activatable_widget),
+ GTK_ACCESSIBLE_RELATION_LABELLED_BY, self->title, NULL,
+ GTK_ACCESSIBLE_RELATION_DESCRIBED_BY, self->subtitle, NULL,
+ -1);
+
+ }
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ACTIVATABLE_WIDGET]);
+}
+
+gboolean
+cc_multitasking_row_get_use_underline (CcMultitaskingRow *self)
+{
+ g_return_val_if_fail (CC_IS_MULTITASKING_ROW (self), FALSE);
+
+ return self->use_underline;
+}
+
+void
+cc_multitasking_row_set_use_underline (CcMultitaskingRow *self,
+ gboolean use_underline)
+{
+ g_return_if_fail (CC_IS_MULTITASKING_ROW (self));
+
+ use_underline = !!use_underline;
+
+ if (self->use_underline == use_underline)
+ return;
+
+ self->use_underline = use_underline;
+ adw_preferences_row_set_use_underline (ADW_PREFERENCES_ROW (self), self->use_underline);
+ gtk_label_set_use_underline (self->title, self->use_underline);
+ gtk_label_set_use_underline (self->subtitle, self->use_underline);
+ gtk_label_set_mnemonic_widget (self->title, GTK_WIDGET (self));
+ gtk_label_set_mnemonic_widget (self->subtitle, GTK_WIDGET (self));
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_USE_UNDERLINE]);
+}
+
+gint
+cc_multitasking_row_get_title_lines (CcMultitaskingRow *self)
+{
+ g_return_val_if_fail (CC_IS_MULTITASKING_ROW (self), 0);
+
+ return self->title_lines;
+}
+
+void
+cc_multitasking_row_set_title_lines (CcMultitaskingRow *self,
+ gint title_lines)
+{
+ g_return_if_fail (CC_IS_MULTITASKING_ROW (self));
+ g_return_if_fail (title_lines >= 0);
+
+ if (self->title_lines == title_lines)
+ return;
+
+ self->title_lines = title_lines;
+
+ gtk_label_set_lines (self->title, title_lines);
+ gtk_label_set_ellipsize (self->title, title_lines == 0 ? PANGO_ELLIPSIZE_NONE : PANGO_ELLIPSIZE_END);
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TITLE_LINES]);
+}
+
+gint
+cc_multitasking_row_get_subtitle_lines (CcMultitaskingRow *self)
+{
+ g_return_val_if_fail (CC_IS_MULTITASKING_ROW (self), 0);
+
+ return self->subtitle_lines;
+}
+
+void
+cc_multitasking_row_set_subtitle_lines (CcMultitaskingRow *self,
+ gint subtitle_lines)
+{
+ g_return_if_fail (CC_IS_MULTITASKING_ROW (self));
+ g_return_if_fail (subtitle_lines >= 0);
+
+ if (self->subtitle_lines == subtitle_lines)
+ return;
+
+ self->subtitle_lines = subtitle_lines;
+
+ gtk_label_set_lines (self->subtitle, subtitle_lines);
+ gtk_label_set_ellipsize (self->subtitle, subtitle_lines == 0 ? PANGO_ELLIPSIZE_NONE : PANGO_ELLIPSIZE_END);
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SUBTITLE_LINES]);
+}
+
+void
+cc_multitasking_row_add_prefix (CcMultitaskingRow *self,
+ GtkWidget *widget)
+{
+ g_return_if_fail (CC_IS_MULTITASKING_ROW (self));
+ g_return_if_fail (GTK_IS_WIDGET (self));
+
+ gtk_box_append (self->prefixes, widget);
+ gtk_widget_show (GTK_WIDGET (self->prefixes));
+}
+
+void
+cc_multitasking_row_add_artwork (CcMultitaskingRow *self,
+ GtkWidget *widget)
+{
+ g_return_if_fail (CC_IS_MULTITASKING_ROW (self));
+ g_return_if_fail (GTK_IS_WIDGET (self));
+
+ /* HACK: the artwork box pushes the title too much to the top, so we
+ * need to compensate this here.
+ */
+ gtk_widget_set_margin_top (GTK_WIDGET (self->header), 12);
+
+ gtk_box_append (self->artwork_box, widget);
+ gtk_widget_show (GTK_WIDGET (self->artwork_box));
+}
+
+void
+cc_multitasking_row_activate (CcMultitaskingRow *self)
+{
+ g_return_if_fail (CC_IS_MULTITASKING_ROW (self));
+
+ if (self->activatable_widget)
+ gtk_widget_mnemonic_activate (self->activatable_widget, FALSE);
+
+ g_signal_emit (self, signals[SIGNAL_ACTIVATED], 0);
+}
+
+void
+cc_multitasking_row_remove (CcMultitaskingRow *self,
+ GtkWidget *child)
+{
+ GtkWidget *parent;
+
+ g_return_if_fail (CC_IS_MULTITASKING_ROW (self));
+ g_return_if_fail (GTK_IS_WIDGET (child));
+
+ parent = gtk_widget_get_parent (child);
+
+ if (parent == GTK_WIDGET (self->prefixes))
+ gtk_box_remove (self->prefixes, child);
+ else if (parent == GTK_WIDGET (self->suffixes))
+ gtk_box_remove (self->suffixes, child);
+ else if (parent == GTK_WIDGET (self->artwork_box))
+ gtk_box_remove (self->artwork_box, child);
+ else
+ g_warning ("%p is not a child of %p", child, self);
+}
+
diff --git a/panels/multitasking/cc-multitasking-row.h b/panels/multitasking/cc-multitasking-row.h
new file mode 100644
index 0000000..c70dd08
--- /dev/null
+++ b/panels/multitasking/cc-multitasking-row.h
@@ -0,0 +1,66 @@
+/* cc-multitasking-row.h
+ *
+ * Copyright 2018 Purism SPC
+ * 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <adwaita.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_MULTITASKING_ROW (cc_multitasking_row_get_type())
+G_DECLARE_FINAL_TYPE (CcMultitaskingRow, cc_multitasking_row, CC, MULTITASKING_ROW, AdwPreferencesRow)
+
+const gchar *cc_multitasking_row_get_subtitle (CcMultitaskingRow *self);
+void cc_multitasking_row_set_subtitle (CcMultitaskingRow *self,
+ const gchar *subtitle);
+
+const gchar *cc_multitasking_row_get_icon_name (CcMultitaskingRow *self);
+void cc_multitasking_row_set_icon_name (CcMultitaskingRow *self,
+ const gchar *icon_name);
+
+GtkWidget *cc_multitasking_row_get_activatable_widget (CcMultitaskingRow *self);
+void cc_multitasking_row_set_activatable_widget (CcMultitaskingRow *self,
+ GtkWidget *widget);
+
+gboolean cc_multitasking_row_get_use_underline (CcMultitaskingRow *self);
+void cc_multitasking_row_set_use_underline (CcMultitaskingRow *self,
+ gboolean use_underline);
+
+gint cc_multitasking_row_get_title_lines (CcMultitaskingRow *self);
+void cc_multitasking_row_set_title_lines (CcMultitaskingRow *self,
+ gint title_lines);
+
+gint cc_multitasking_row_get_subtitle_lines (CcMultitaskingRow *self);
+void cc_multitasking_row_set_subtitle_lines (CcMultitaskingRow *self,
+ gint subtitle_lines);
+
+void cc_multitasking_row_add_prefix (CcMultitaskingRow *self,
+ GtkWidget *widget);
+
+void cc_multitasking_row_add_artwork (CcMultitaskingRow *self,
+ GtkWidget *widget);
+
+void cc_multitasking_row_activate (CcMultitaskingRow *self);
+
+void cc_multitasking_row_remove (CcMultitaskingRow *self,
+ GtkWidget *child);
+
+G_END_DECLS
diff --git a/panels/multitasking/cc-multitasking-row.ui b/panels/multitasking/cc-multitasking-row.ui
new file mode 100644
index 0000000..2e41951
--- /dev/null
+++ b/panels/multitasking/cc-multitasking-row.ui
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcMultitaskingRow" parent="AdwPreferencesRow">
+ <property name="activatable">False</property>
+ <accessibility>
+ <relation name="labelled-by">title</relation>
+ </accessibility>
+ <child>
+ <object class="GtkBox" id="header">
+ <property name="orientation">vertical</property>
+ <property name="valign">center</property>
+ <style>
+ <class name="header"/>
+ </style>
+
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">12</property>
+ <property name="valign">center</property>
+ <property name="vexpand">True</property>
+
+ <child>
+ <object class="GtkBox" id="prefixes">
+ <property name="spacing">12</property>
+ <property name="visible">False</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage" id="image">
+ <property name="pixel_size">32</property>
+ <property name="valign">center</property>
+ <property name="visible">False</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="title_box">
+ <property name="halign">start</property>
+ <property name="orientation">vertical</property>
+ <property name="valign">center</property>
+ <style>
+ <class name="title"/>
+ </style>
+ <child>
+ <object class="GtkLabel" id="title">
+ <property name="ellipsize">end</property>
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <property name="label" bind-source="CcMultitaskingRow" bind-property="title" bind-flags="sync-create"/>
+ <property name="lines">1</property>
+ <property name="wrap">True</property>
+ <property name="wrap-mode">word-char</property>
+ <property name="xalign">0</property>
+ <style>
+ <class name="title"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="subtitle">
+ <property name="ellipsize">end</property>
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <property name="lines">2</property>
+ <property name="wrap">True</property>
+ <property name="wrap-mode">word-char</property>
+ <property name="xalign">0</property>
+ <style>
+ <class name="subtitle"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="suffixes">
+ <property name="spacing">12</property>
+ <property name="visible">False</property>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkBox" id="artwork_box">
+ <property name="visible">False</property>
+ <property name="hexpand">True</property>
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <style>
+ <class name="frame" />
+ <class name="background" />
+ </style>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/multitasking/gnome-multitasking-panel.desktop.in.in b/panels/multitasking/gnome-multitasking-panel.desktop.in.in
new file mode 100644
index 0000000..c8f0fe8
--- /dev/null
+++ b/panels/multitasking/gnome-multitasking-panel.desktop.in.in
@@ -0,0 +1,14 @@
+[Desktop Entry]
+Name=Multitasking
+Comment=Manage preferences for productivity and multitasking
+Exec=gnome-control-center multitasking
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-multitasking-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-PersonalizationSettings;
+OnlyShowIn=GNOME;
+# Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=Multitasking;Multitask;Productivity;Customize;Desktop;Hot Corner;Workspaces;
diff --git a/panels/multitasking/icons/meson.build b/panels/multitasking/icons/meson.build
new file mode 100644
index 0000000..b274dd1
--- /dev/null
+++ b/panels/multitasking/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-multitasking-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/multitasking/icons/scalable/org.gnome.Settings-multitasking-symbolic.svg b/panels/multitasking/icons/scalable/org.gnome.Settings-multitasking-symbolic.svg
new file mode 100644
index 0000000..50b8a84
--- /dev/null
+++ b/panels/multitasking/icons/scalable/org.gnome.Settings-multitasking-symbolic.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <path d="m 6 0 c -1.644531 0 -3 1.355469 -3 3 v 10 c 0 1.644531 1.355469 3 3 3 h 4 c 1.644531 0 3 -1.355469 3 -3 v -10 c 0 -1.644531 -1.355469 -3 -3 -3 z m 0 2 h 4 c 0.570312 0 1 0.429688 1 1 v 10 c 0 0.570312 -0.429688 1 -1 1 h -4 c -0.570312 0 -1 -0.429688 -1 -1 v -10 c 0 -0.570312 0.429688 -1 1 -1 z m -5 1 c -0.554688 0 -1 0.445312 -1 1 v 8 c 0 0.554688 0.445312 1 1 1 s 1 -0.445312 1 -1 v -8 c 0 -0.554688 -0.445312 -1 -1 -1 z m 14 0 c -0.554688 0 -1 0.445312 -1 1 v 8 c 0 0.554688 0.445312 1 1 1 s 1 -0.445312 1 -1 v -8 c 0 -0.554688 -0.445312 -1 -1 -1 z m 0 0" fill="#2e3436"/>
+</svg>
diff --git a/panels/multitasking/meson.build b/panels/multitasking/meson.build
new file mode 100644
index 0000000..53fd0d8
--- /dev/null
+++ b/panels/multitasking/meson.build
@@ -0,0 +1,48 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+sources = files(
+ 'cc-multitasking-panel.c',
+ 'cc-multitasking-row.c',
+)
+
+resource_data = files(
+ 'cc-multitasking-panel.ui',
+)
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname,
+ dependencies: resource_data,
+ export: true
+)
+
+cflags += [
+ '-DDATADIR="@0@"'.format(control_center_datadir)
+]
+
+panels_libs += static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [ top_inc, common_inc ],
+ dependencies: common_deps,
+ c_args: cflags
+)
+
+subdir('icons')
diff --git a/panels/multitasking/multitasking.gresource.xml b/panels/multitasking/multitasking.gresource.xml
new file mode 100644
index 0000000..df47764
--- /dev/null
+++ b/panels/multitasking/multitasking.gresource.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/multitasking">
+ <file preprocess="xml-stripblanks">cc-multitasking-panel.ui</file>
+ <file preprocess="xml-stripblanks">cc-multitasking-row.ui</file>
+
+ <!-- Assets -->
+ <file>assets/active-screen-edges.svg</file>
+ <file>assets/active-screen-edges-rtl.svg</file>
+ <file>assets/hot-corner.svg</file>
+ <file>assets/hot-corner-rtl.svg</file>
+ <file>assets/workspaces-primary-display.svg</file>
+ <file>assets/workspaces-span-displays.svg</file>
+ </gresource>
+</gresources>
diff --git a/panels/network/cc-network-panel.c b/panels/network/cc-network-panel.c
new file mode 100644
index 0000000..aa271fd
--- /dev/null
+++ b/panels/network/cc-network-panel.c
@@ -0,0 +1,806 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010-2012 Richard Hughes <richard@hughsie.com>
+ * Copyright (C) 2012 Thomas Bechtold <thomasbechtold@jpberlin.de>
+ * Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include <stdlib.h>
+
+#include "shell/cc-object-storage.h"
+
+#include "cc-network-panel.h"
+#include "cc-network-resources.h"
+
+#include <NetworkManager.h>
+
+#include "net-device-bluetooth.h"
+#include "net-device-ethernet.h"
+#include "net-device-mobile.h"
+#include "net-device-wifi.h"
+#include "net-proxy.h"
+#include "net-vpn.h"
+
+#include "panel-common.h"
+
+#include "network-dialogs.h"
+#include "connection-editor/net-connection-editor.h"
+
+#include <libmm-glib.h>
+
+typedef enum {
+ OPERATION_NULL,
+ OPERATION_SHOW_DEVICE,
+ OPERATION_CONNECT_MOBILE
+} CmdlineOperation;
+
+struct _CcNetworkPanel
+{
+ CcPanel parent;
+
+ GPtrArray *bluetooth_devices;
+ GPtrArray *ethernet_devices;
+ GPtrArray *mobile_devices;
+ GPtrArray *vpns;
+ GHashTable *nm_device_to_device;
+
+ NMClient *client;
+ MMManager *modem_manager;
+ gboolean updating_device;
+
+ /* widgets */
+ GtkWidget *box_bluetooth;
+ GtkWidget *box_proxy;
+ GtkWidget *box_vpn;
+ GtkWidget *box_wired;
+ GtkWidget *container_bluetooth;
+ GtkWidget *empty_listbox;
+ GtkWidget *vpn_stack;
+
+ /* wireless dialog stuff */
+ CmdlineOperation arg_operation;
+ gchar *arg_device;
+ gchar *arg_access_point;
+ gboolean operation_done;
+};
+
+enum {
+ PROP_0,
+ PROP_PARAMETERS
+};
+
+static void handle_argv (CcNetworkPanel *self);
+
+CC_PANEL_REGISTER (CcNetworkPanel, cc_network_panel)
+
+static void
+cc_network_panel_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static CmdlineOperation
+cmdline_operation_from_string (const gchar *string)
+{
+ if (g_strcmp0 (string, "connect-3g") == 0)
+ return OPERATION_CONNECT_MOBILE;
+ if (g_strcmp0 (string, "show-device") == 0)
+ return OPERATION_SHOW_DEVICE;
+
+ g_warning ("Invalid additional argument %s", string);
+ return OPERATION_NULL;
+}
+
+static void
+reset_command_line_args (CcNetworkPanel *self)
+{
+ self->arg_operation = OPERATION_NULL;
+ g_clear_pointer (&self->arg_device, g_free);
+ g_clear_pointer (&self->arg_access_point, g_free);
+}
+
+static gboolean
+verify_argv (CcNetworkPanel *self,
+ const char **args)
+{
+ switch (self->arg_operation) {
+ case OPERATION_CONNECT_MOBILE:
+ case OPERATION_SHOW_DEVICE:
+ if (self->arg_device == NULL) {
+ g_warning ("Operation %s requires an object path", args[0]);
+ return FALSE;
+ }
+ default:
+ return TRUE;
+ }
+}
+
+static GPtrArray *
+variant_av_to_string_array (GVariant *array)
+{
+ GVariantIter iter;
+ GVariant *v;
+ GPtrArray *strv;
+ gsize count;
+ count = g_variant_iter_init (&iter, array);
+ strv = g_ptr_array_sized_new (count + 1);
+ while (g_variant_iter_next (&iter, "v", &v)) {
+ g_ptr_array_add (strv, (gpointer)g_variant_get_string (v, NULL));
+ g_variant_unref (v);
+ }
+ g_ptr_array_add (strv, NULL); /* NULL-terminate the strv data array */
+ return strv;
+}
+
+static void
+cc_network_panel_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcNetworkPanel *self = CC_NETWORK_PANEL (object);
+
+ switch (property_id) {
+ case PROP_PARAMETERS: {
+ GVariant *parameters;
+
+ reset_command_line_args (self);
+
+ parameters = g_value_get_variant (value);
+ if (parameters) {
+ g_autoptr(GPtrArray) array = NULL;
+ const gchar **args;
+ array = variant_av_to_string_array (parameters);
+ args = (const gchar **) array->pdata;
+
+ g_debug ("Invoked with operation %s", args[0]);
+
+ if (args[0])
+ self->arg_operation = cmdline_operation_from_string (args[0]);
+ if (args[0] && args[1])
+ self->arg_device = g_strdup (args[1]);
+ if (args[0] && args[1] && args[2])
+ self->arg_access_point = g_strdup (args[2]);
+
+ if (verify_argv (self, (const char **) args) == FALSE) {
+ reset_command_line_args (self);
+ return;
+ }
+ g_debug ("Calling handle_argv() after setting property");
+ handle_argv (self);
+ }
+ break;
+ }
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+cc_network_panel_dispose (GObject *object)
+{
+ CcNetworkPanel *self = CC_NETWORK_PANEL (object);
+
+ g_clear_object (&self->client);
+ g_clear_object (&self->modem_manager);
+
+ g_clear_pointer (&self->bluetooth_devices, g_ptr_array_unref);
+ g_clear_pointer (&self->ethernet_devices, g_ptr_array_unref);
+ g_clear_pointer (&self->mobile_devices, g_ptr_array_unref);
+ g_clear_pointer (&self->vpns, g_ptr_array_unref);
+ g_clear_pointer (&self->nm_device_to_device, g_hash_table_destroy);
+
+ G_OBJECT_CLASS (cc_network_panel_parent_class)->dispose (object);
+}
+
+static void
+cc_network_panel_finalize (GObject *object)
+{
+ CcNetworkPanel *self = CC_NETWORK_PANEL (object);
+
+ reset_command_line_args (self);
+
+ G_OBJECT_CLASS (cc_network_panel_parent_class)->finalize (object);
+}
+
+static const char *
+cc_network_panel_get_help_uri (CcPanel *self)
+{
+ return "help:gnome-help/net";
+}
+
+static void
+panel_refresh_device_titles (CcNetworkPanel *self)
+{
+ g_autoptr(GPtrArray) ndarray = NULL;
+ g_autoptr(GPtrArray) nmdarray = NULL;
+ GtkWidget **devices;
+ NMDevice **nm_devices;
+ g_auto(GStrv) titles = NULL;
+ guint i, num_devices;
+
+ ndarray = g_ptr_array_new ();
+ nmdarray = g_ptr_array_new ();
+ for (i = 0; i < self->bluetooth_devices->len; i++) {
+ NetDeviceBluetooth *device = g_ptr_array_index (self->bluetooth_devices, i);
+ g_ptr_array_add (ndarray, device);
+ g_ptr_array_add (nmdarray, net_device_bluetooth_get_device (device));
+ }
+ for (i = 0; i < self->ethernet_devices->len; i++) {
+ NetDeviceEthernet *device = g_ptr_array_index (self->ethernet_devices, i);
+ g_ptr_array_add (ndarray, device);
+ g_ptr_array_add (nmdarray, net_device_ethernet_get_device (device));
+ }
+ for (i = 0; i < self->mobile_devices->len; i++) {
+ NetDeviceMobile *device = g_ptr_array_index (self->mobile_devices, i);
+ g_ptr_array_add (ndarray, device);
+ g_ptr_array_add (nmdarray, net_device_mobile_get_device (device));
+ }
+
+ if (ndarray->len == 0)
+ return;
+
+ devices = (GtkWidget **)ndarray->pdata;
+ nm_devices = (NMDevice **)nmdarray->pdata;
+ num_devices = ndarray->len;
+
+ titles = nm_device_disambiguate_names (nm_devices, num_devices);
+ for (i = 0; i < num_devices; i++) {
+ if (NM_IS_DEVICE_BT (nm_devices[i]))
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (devices[i]), nm_device_bt_get_name (NM_DEVICE_BT (nm_devices[i])));
+ else if (NET_IS_DEVICE_ETHERNET (devices[i]))
+ adw_preferences_group_set_title (ADW_PREFERENCES_GROUP (devices[i]), titles[i]);
+ else if (NET_IS_DEVICE_MOBILE (devices[i]))
+ net_device_mobile_set_title (NET_DEVICE_MOBILE (devices[i]), titles[i]);
+ }
+}
+
+static gboolean
+handle_argv_for_device (CcNetworkPanel *self,
+ NMDevice *device)
+{
+ GtkWidget *toplevel = cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (self)));
+
+ if (self->arg_operation == OPERATION_NULL)
+ return TRUE;
+
+ if (g_strcmp0 (nm_object_get_path (NM_OBJECT (device)), self->arg_device) == 0) {
+ if (self->arg_operation == OPERATION_CONNECT_MOBILE) {
+ cc_network_panel_connect_to_3g_network (toplevel, self->client, device);
+
+ reset_command_line_args (self); /* done */
+ return TRUE;
+ } else if (self->arg_operation == OPERATION_SHOW_DEVICE) {
+ reset_command_line_args (self); /* done */
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static gboolean
+handle_argv_for_connection (CcNetworkPanel *self,
+ NMConnection *connection)
+{
+ if (self->arg_operation == OPERATION_NULL)
+ return TRUE;
+ if (self->arg_operation != OPERATION_SHOW_DEVICE)
+ return FALSE;
+
+ if (g_strcmp0 (nm_connection_get_path (connection), self->arg_device) == 0) {
+ reset_command_line_args (self);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+static void
+handle_argv (CcNetworkPanel *self)
+{
+ gint i;
+
+ if (self->arg_operation == OPERATION_NULL)
+ return;
+
+ for (i = 0; i < self->bluetooth_devices->len; i++) {
+ NetDeviceBluetooth *device = g_ptr_array_index (self->bluetooth_devices, i);
+ if (handle_argv_for_device (self, net_device_bluetooth_get_device (device)))
+ return;
+ }
+ for (i = 0; i < self->ethernet_devices->len; i++) {
+ NetDeviceEthernet *device = g_ptr_array_index (self->ethernet_devices, i);
+ if (handle_argv_for_device (self, net_device_ethernet_get_device (device)))
+ return;
+ }
+ for (i = 0; i < self->mobile_devices->len; i++) {
+ NetDeviceMobile *device = g_ptr_array_index (self->mobile_devices, i);
+ if (handle_argv_for_device (self, net_device_mobile_get_device (device)))
+ return;
+ }
+ for (i = 0; i < self->vpns->len; i++) {
+ NetVpn *vpn = g_ptr_array_index (self->vpns, i);
+ if (handle_argv_for_connection (self, net_vpn_get_connection (vpn)))
+ return;
+ }
+
+ g_debug ("Could not handle argv operation, no matching device yet?");
+}
+
+static void
+update_vpn_section (CcNetworkPanel *self)
+{
+ gtk_stack_set_visible_child (GTK_STACK (self->vpn_stack),
+ self->vpns->len == 0 ? self->empty_listbox : self->box_vpn);
+}
+
+static void
+update_bluetooth_section (CcNetworkPanel *self)
+{
+ gtk_widget_set_visible (self->container_bluetooth, self->bluetooth_devices->len > 0);
+}
+
+static gboolean
+wwan_panel_supports_modem (GDBusObject *object)
+{
+ MMObject *mm_object;
+ MMModem *modem;
+ MMModemCapability capability, supported_capabilities;
+
+ g_assert (G_IS_DBUS_OBJECT (object));
+
+ supported_capabilities = MM_MODEM_CAPABILITY_GSM_UMTS | MM_MODEM_CAPABILITY_LTE;
+#if MM_CHECK_VERSION (1,14,0)
+ supported_capabilities |= MM_MODEM_CAPABILITY_5GNR;
+#endif
+
+ mm_object = MM_OBJECT (object);
+ modem = mm_object_get_modem (mm_object);
+ capability = mm_modem_get_current_capabilities (modem);
+
+ return capability & supported_capabilities;
+}
+
+static void
+panel_add_device (CcNetworkPanel *self, NMDevice *device)
+{
+ NMDeviceType type;
+ NetDeviceEthernet *device_ethernet;
+ NetDeviceMobile *device_mobile;
+ NetDeviceBluetooth *device_bluetooth;
+ g_autoptr(GDBusObject) modem_object = NULL;
+
+ /* does already exist */
+ if (g_hash_table_lookup (self->nm_device_to_device, device) != NULL)
+ return;
+
+ type = nm_device_get_device_type (device);
+
+ g_debug ("device %s type %i path %s",
+ nm_device_get_udi (device), type, nm_object_get_path (NM_OBJECT (device)));
+
+ /* map the NMDeviceType to the GType, or ignore */
+ switch (type) {
+ case NM_DEVICE_TYPE_ETHERNET:
+ case NM_DEVICE_TYPE_INFINIBAND:
+ device_ethernet = net_device_ethernet_new (self->client, device);
+ gtk_box_append (GTK_BOX (self->box_wired), GTK_WIDGET (device_ethernet));
+ g_ptr_array_add (self->ethernet_devices, device_ethernet);
+ g_hash_table_insert (self->nm_device_to_device, device, device_ethernet);
+ break;
+ case NM_DEVICE_TYPE_MODEM:
+ if (g_str_has_prefix (nm_device_get_udi (device), "/org/freedesktop/ModemManager1/Modem/")) {
+ if (self->modem_manager == NULL) {
+ g_warning ("Cannot grab information for modem at %s: No ModemManager support",
+ nm_device_get_udi (device));
+ return;
+ }
+
+ modem_object = g_dbus_object_manager_get_object (G_DBUS_OBJECT_MANAGER (self->modem_manager),
+ nm_device_get_udi (device));
+ if (modem_object == NULL) {
+ g_warning ("Cannot grab information for modem at %s: Not found",
+ nm_device_get_udi (device));
+ return;
+ }
+
+ /* This will be handled by cellular panel */
+ if (wwan_panel_supports_modem (modem_object))
+ return;
+ }
+
+ device_mobile = net_device_mobile_new (self->client, device, modem_object);
+ gtk_box_append (GTK_BOX (self->box_wired), GTK_WIDGET (device_mobile));
+ g_ptr_array_add (self->mobile_devices, device_mobile);
+ g_hash_table_insert (self->nm_device_to_device, device, device_mobile);
+ break;
+ case NM_DEVICE_TYPE_BT:
+ device_bluetooth = net_device_bluetooth_new (self->client, device);
+ gtk_list_box_append (GTK_LIST_BOX (self->box_bluetooth), GTK_WIDGET (device_bluetooth));
+ g_ptr_array_add (self->bluetooth_devices, device_bluetooth);
+ g_hash_table_insert (self->nm_device_to_device, device, device_bluetooth);
+
+ /* Update the device_bluetooth section if we're adding a bluetooth
+ * device. This is a temporary solution though, for these will
+ * be handled by the future Mobile Broadband panel */
+ update_bluetooth_section (self);
+ break;
+
+ /* For Wi-Fi and VPN we handle connections separately; we correctly manage
+ * them, but not here.
+ */
+ case NM_DEVICE_TYPE_WIFI:
+ case NM_DEVICE_TYPE_TUN:
+ /* And the rest we simply cannot deal with currently. */
+ default:
+ return;
+ }
+}
+
+static void
+panel_remove_device (CcNetworkPanel *self, NMDevice *device)
+{
+ GtkWidget *net_device;
+
+ net_device = g_hash_table_lookup (self->nm_device_to_device, device);
+ if (net_device == NULL)
+ return;
+
+ g_ptr_array_remove (self->bluetooth_devices, net_device);
+ g_ptr_array_remove (self->ethernet_devices, net_device);
+ g_ptr_array_remove (self->mobile_devices, net_device);
+ g_hash_table_remove (self->nm_device_to_device, device);
+
+ gtk_box_remove (GTK_BOX (gtk_widget_get_parent (net_device)), net_device);
+
+ /* update vpn widgets */
+ update_vpn_section (self);
+
+ /* update device_bluetooth widgets */
+ update_bluetooth_section (self);
+}
+
+static void
+connection_state_changed (CcNetworkPanel *self)
+{
+}
+
+static void
+active_connections_changed (CcNetworkPanel *self)
+{
+ const GPtrArray *connections;
+ int i, j;
+
+ g_debug ("Active connections changed:");
+ connections = nm_client_get_active_connections (self->client);
+ for (i = 0; connections && (i < connections->len); i++) {
+ NMActiveConnection *connection;
+ const GPtrArray *devices;
+
+ connection = g_ptr_array_index (connections, i);
+ g_debug (" %s", nm_object_get_path (NM_OBJECT (connection)));
+ devices = nm_active_connection_get_devices (connection);
+ for (j = 0; devices && j < devices->len; j++)
+ g_debug (" %s", nm_device_get_udi (g_ptr_array_index (devices, j)));
+ if (NM_IS_VPN_CONNECTION (connection))
+ g_debug (" VPN base connection: %s", nm_active_connection_get_specific_object_path (connection));
+
+ if (g_object_get_data (G_OBJECT (connection), "has-state-changed-handler") == NULL) {
+ g_signal_connect_object (connection, "notify::state",
+ G_CALLBACK (connection_state_changed), self, G_CONNECT_SWAPPED);
+ g_object_set_data (G_OBJECT (connection), "has-state-changed-handler", GINT_TO_POINTER (TRUE));
+ }
+ }
+}
+
+static void
+device_managed_cb (CcNetworkPanel *self, GParamSpec *pspec, NMDevice *device)
+{
+ if (!nm_device_get_managed (device))
+ return;
+
+ panel_add_device (self, device);
+ panel_refresh_device_titles (self);
+}
+
+static void
+device_added_cb (CcNetworkPanel *self, NMDevice *device)
+{
+ g_debug ("New device added");
+
+ if (nm_device_get_managed (device))
+ device_managed_cb (self, NULL, device);
+ else
+ g_signal_connect_object (device, "notify::managed", G_CALLBACK (device_managed_cb), self, G_CONNECT_SWAPPED);
+}
+
+static void
+device_removed_cb (CcNetworkPanel *self, NMDevice *device)
+{
+ g_debug ("Device removed");
+ panel_remove_device (self, device);
+ panel_refresh_device_titles (self);
+
+ g_signal_handlers_disconnect_by_func (device,
+ G_CALLBACK (device_managed_cb),
+ self);
+}
+
+static void
+manager_running (CcNetworkPanel *self)
+{
+ const GPtrArray *devices;
+ int i;
+
+ /* clear all devices we added */
+ if (!nm_client_get_nm_running (self->client)) {
+ g_debug ("NM disappeared");
+ goto out;
+ }
+
+ g_debug ("coldplugging devices");
+ devices = nm_client_get_devices (self->client);
+ if (devices == NULL) {
+ g_debug ("No devices to add");
+ return;
+ }
+ for (i = 0; i < devices->len; i++) {
+ NMDevice *device = g_ptr_array_index (devices, i);
+ device_added_cb (self, device);
+ }
+out:
+ panel_refresh_device_titles (self);
+
+ g_debug ("Calling handle_argv() after cold-plugging devices");
+ handle_argv (self);
+}
+
+static void
+panel_add_vpn_device (CcNetworkPanel *self, NMConnection *connection)
+{
+ NetVpn *net_vpn;
+ guint i;
+
+ /* does already exist */
+ for (i = 0; i < self->vpns->len; i++) {
+ net_vpn = g_ptr_array_index (self->vpns, i);
+ if (net_vpn_get_connection (net_vpn) == connection)
+ return;
+ }
+
+ net_vpn = net_vpn_new (self->client, connection);
+ gtk_list_box_append (GTK_LIST_BOX (self->box_vpn), GTK_WIDGET (net_vpn));
+
+ /* store in the devices array */
+ g_ptr_array_add (self->vpns, net_vpn);
+
+ /* update vpn widgets */
+ update_vpn_section (self);
+}
+
+static void
+add_connection (CcNetworkPanel *self, NMConnection *connection)
+{
+ NMSettingConnection *s_con;
+ const gchar *type, *iface;
+
+ s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection,
+ NM_TYPE_SETTING_CONNECTION));
+ type = nm_setting_connection_get_connection_type (s_con);
+ iface = nm_connection_get_interface_name (connection);
+ if (g_strcmp0 (type, "vpn") != 0 && iface == NULL)
+ return;
+
+ /* Don't add the libvirtd bridge to the UI */
+ if (g_strcmp0 (nm_setting_connection_get_interface_name (s_con), "virbr0") == 0)
+ return;
+
+ g_debug ("add %s/%s remote connection: %s",
+ type, g_type_name_from_instance ((GTypeInstance*)connection),
+ nm_connection_get_path (connection));
+ if (!iface)
+ panel_add_vpn_device (self, connection);
+}
+
+static void
+client_connection_removed_cb (CcNetworkPanel *self, NMConnection *connection)
+{
+ guint i;
+
+ for (i = 0; i < self->vpns->len; i++) {
+ NetVpn *vpn = g_ptr_array_index (self->vpns, i);
+ if (net_vpn_get_connection (vpn) == connection) {
+ g_ptr_array_remove (self->vpns, vpn);
+ gtk_list_box_remove (GTK_LIST_BOX (self->box_vpn), GTK_WIDGET (vpn));
+ update_vpn_section (self);
+ return;
+ }
+ }
+}
+
+static void
+panel_check_network_manager_version (CcNetworkPanel *self)
+{
+ const gchar *version;
+
+ /* parse running version */
+ version = nm_client_get_version (self->client);
+ if (version == NULL) {
+ GtkWidget *box;
+ GtkWidget *label;
+ g_autofree gchar *markup = NULL;
+
+ box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 20);
+ gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
+ gtk_widget_set_vexpand (box, TRUE);
+ adw_bin_set_child (ADW_BIN (self), box);
+
+ label = gtk_label_new (_("Oops, something has gone wrong. Please contact your software vendor."));
+ gtk_widget_set_vexpand (label, TRUE);
+ gtk_label_set_wrap (GTK_LABEL (label), TRUE);
+ gtk_widget_set_valign (label, GTK_ALIGN_END);
+ gtk_box_append (GTK_BOX (box), label);
+
+ markup = g_strdup_printf ("<small><tt>%s</tt></small>",
+ _("NetworkManager needs to be running."));
+ label = gtk_label_new (NULL);
+ gtk_widget_set_vexpand (label, TRUE);
+ gtk_label_set_markup (GTK_LABEL (label), markup);
+ gtk_label_set_wrap (GTK_LABEL (label), TRUE);
+ gtk_widget_set_valign (label, GTK_ALIGN_START);
+ gtk_box_append (GTK_BOX (box), label);
+ } else {
+ manager_running (self);
+ }
+}
+
+static void
+create_connection_cb (GtkWidget *button,
+ CcNetworkPanel *self)
+{
+ NetConnectionEditor *editor;
+
+ editor = net_connection_editor_new (NULL, NULL, NULL, self->client);
+ gtk_window_set_transient_for (GTK_WINDOW (editor),
+ GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (self))));
+ gtk_window_present (GTK_WINDOW (editor));
+}
+
+static void
+cc_network_panel_map (GtkWidget *widget)
+{
+ GTK_WIDGET_CLASS (cc_network_panel_parent_class)->map (widget);
+
+ /* is the user compiling against a new version, but not running
+ * the daemon? */
+ panel_check_network_manager_version (CC_NETWORK_PANEL (widget));
+}
+
+
+static void
+cc_network_panel_class_init (CcNetworkPanelClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+
+ panel_class->get_help_uri = cc_network_panel_get_help_uri;
+
+ widget_class->map = cc_network_panel_map;
+
+ object_class->get_property = cc_network_panel_get_property;
+ object_class->set_property = cc_network_panel_set_property;
+ object_class->dispose = cc_network_panel_dispose;
+ object_class->finalize = cc_network_panel_finalize;
+
+ g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters");
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/cc-network-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcNetworkPanel, box_bluetooth);
+ gtk_widget_class_bind_template_child (widget_class, CcNetworkPanel, box_proxy);
+ gtk_widget_class_bind_template_child (widget_class, CcNetworkPanel, box_vpn);
+ gtk_widget_class_bind_template_child (widget_class, CcNetworkPanel, box_wired);
+ gtk_widget_class_bind_template_child (widget_class, CcNetworkPanel, container_bluetooth);
+ gtk_widget_class_bind_template_child (widget_class, CcNetworkPanel, empty_listbox);
+ gtk_widget_class_bind_template_child (widget_class, CcNetworkPanel, vpn_stack);
+
+ gtk_widget_class_bind_template_callback (widget_class, create_connection_cb);
+}
+
+static void
+cc_network_panel_init (CcNetworkPanel *self)
+{
+ g_autoptr(GDBusConnection) system_bus = NULL;
+ g_autoptr(GError) error = NULL;
+ const GPtrArray *connections;
+ NetProxy *proxy;
+ guint i;
+
+ g_resources_register (cc_network_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->bluetooth_devices = g_ptr_array_new ();
+ self->ethernet_devices = g_ptr_array_new ();
+ self->mobile_devices = g_ptr_array_new ();
+ self->vpns = g_ptr_array_new ();
+ self->nm_device_to_device = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ /* add the virtual proxy device */
+ proxy = net_proxy_new ();
+ gtk_box_append (GTK_BOX (self->box_proxy), GTK_WIDGET (proxy));
+
+ /* Create and store a NMClient instance if it doesn't exist yet */
+ if (!cc_object_storage_has_object (CC_OBJECT_NMCLIENT)) {
+ g_autoptr(NMClient) client = nm_client_new (NULL, NULL);
+ cc_object_storage_add_object (CC_OBJECT_NMCLIENT, client);
+ }
+
+ /* use NetworkManager client */
+ self->client = cc_object_storage_get_object (CC_OBJECT_NMCLIENT);
+
+ g_signal_connect_object (self->client, "notify::nm-running" ,
+ G_CALLBACK (manager_running), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->client, "notify::active-connections",
+ G_CALLBACK (active_connections_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->client, "device-added",
+ G_CALLBACK (device_added_cb), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->client, "device-removed",
+ G_CALLBACK (device_removed_cb), self, G_CONNECT_SWAPPED);
+
+ /* Setup ModemManager client */
+ system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (system_bus == NULL) {
+ g_warning ("Error connecting to system D-Bus: %s",
+ error->message);
+ } else {
+ self->modem_manager = mm_manager_new_sync (system_bus,
+ G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
+ NULL,
+ &error);
+ if (self->modem_manager == NULL)
+ g_warning ("Error connecting to ModemManager: %s",
+ error->message);
+ }
+
+ /* add remote settings such as VPN settings as virtual devices */
+ g_signal_connect_object (self->client, NM_CLIENT_CONNECTION_ADDED,
+ G_CALLBACK (add_connection), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->client, NM_CLIENT_CONNECTION_REMOVED,
+ G_CALLBACK (client_connection_removed_cb), self, G_CONNECT_SWAPPED);
+
+ /* Cold-plug existing connections */
+ connections = nm_client_get_connections (self->client);
+ if (connections) {
+ for (i = 0; i < connections->len; i++)
+ add_connection (self, connections->pdata[i]);
+ }
+
+ g_debug ("Calling handle_argv() after cold-plugging connections");
+ handle_argv (self);
+}
diff --git a/panels/network/cc-network-panel.h b/panels/network/cc-network-panel.h
new file mode 100644
index 0000000..9141ad0
--- /dev/null
+++ b/panels/network/cc-network-panel.h
@@ -0,0 +1,30 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2010 Richard Hughes <richard@hughsie.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_NETWORK_PANEL cc_network_panel_get_type()
+
+G_DECLARE_FINAL_TYPE (CcNetworkPanel, cc_network_panel, CC, NETWORK_PANEL, CcPanel)
+
+G_END_DECLS
diff --git a/panels/network/cc-network-panel.ui b/panels/network/cc-network-panel.ui
new file mode 100644
index 0000000..1ae1009
--- /dev/null
+++ b/panels/network/cc-network-panel.ui
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcNetworkPanel" parent="CcPanel">
+
+ <child type="content">
+ <object class="AdwPreferencesPage">
+ <!-- Each group below will contain GtkStacks from the NetDevices -->
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="GtkBox" id="box_wired">
+ <property name="orientation">vertical</property>
+ <property name="spacing">24</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup" id="container_bluetooth">
+ <property name="visible">False</property>
+ <property name="title" translatable="yes">Other Devices</property>
+ <child>
+ <object class="GtkListBox" id="box_bluetooth">
+ <property name="selection_mode">none</property>
+ <accessibility>
+ <property name="label" translatable="yes">Other Devices</property>
+ </accessibility>
+ <style>
+ <class name="boxed-list" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGRoup">
+ <property name="title" translatable="yes">VPN</property>
+ <property name="header-suffix">
+ <object class="GtkButton">
+ <property name="icon_name">list-add-symbolic</property>
+ <accessibility>
+ <property name="label" translatable="yes">Add connection</property>
+ </accessibility>
+ <style>
+ <class name="flat" />
+ </style>
+ <signal name="clicked" handler="create_connection_cb" object="CcNetworkPanel" swapped="no" />
+ </object>
+ </property>
+ <child>
+ <object class="GtkStack" id="vpn_stack">
+ <child>
+ <!-- "Not set up" row -->
+ <object class="GtkListBox" id="empty_listbox">
+ <property name="selection_mode">none</property>
+ <style>
+ <class name="boxed-list" />
+ </style>
+ <child>
+ <object class="AdwActionRow">
+ <property name="activatable">False</property>
+ <property name="title" translatable="yes">Not set up</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkListBox" id="box_vpn">
+ <property name="selection_mode">none</property>
+ <accessibility>
+ <property name="label" translatable="yes">VPN</property>
+ </accessibility>
+ <style>
+ <class name="boxed-list" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="GtkBox" id="box_proxy">
+ <property name="orientation">vertical</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/cc-qr-code.c b/panels/network/cc-qr-code.c
new file mode 100644
index 0000000..8bb8a14
--- /dev/null
+++ b/panels/network/cc-qr-code.c
@@ -0,0 +1,186 @@
+/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */
+/* cc-qr-code.c
+ *
+ * Copyright 2019 Purism SPC
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "cc-qr-code"
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "cc-qr-code.h"
+#include "qrcodegen.c"
+
+/**
+ * SECTION: cc-qr_code
+ * @title: CcQrCode
+ * @short_description: A Simple QR Code wrapper around libqrencode
+ * @include: "cc-qr-code.h"
+ *
+ * Generate a QR image from a given text.
+ */
+
+#define BYTES_PER_R8G8B8 3
+
+struct _CcQrCode
+{
+ GObject parent_instance;
+
+ gchar *text;
+ GdkTexture *texture;
+ gint size;
+};
+
+G_DEFINE_TYPE (CcQrCode, cc_qr_code, G_TYPE_OBJECT)
+
+
+static void
+cc_qr_code_finalize (GObject *object)
+{
+ CcQrCode *self = (CcQrCode *)object;
+
+ g_clear_object (&self->texture);
+ g_clear_pointer (&self->text, g_free);
+
+ G_OBJECT_CLASS (cc_qr_code_parent_class)->finalize (object);
+}
+
+static void
+cc_qr_code_class_init (CcQrCodeClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = cc_qr_code_finalize;
+}
+
+static void
+cc_qr_code_init (CcQrCode *self)
+{
+}
+
+CcQrCode *
+cc_qr_code_new (void)
+{
+ return g_object_new (CC_TYPE_QR_CODE, NULL);
+}
+
+gboolean
+cc_qr_code_set_text (CcQrCode *self,
+ const gchar *text)
+{
+ g_return_val_if_fail (CC_IS_QR_CODE (self), FALSE);
+ g_return_val_if_fail (!text || *text, FALSE);
+
+ if (g_strcmp0 (text, self->text) == 0)
+ return FALSE;
+
+ g_clear_object (&self->texture);
+ g_free (self->text);
+ self->text = g_strdup (text);
+
+ return TRUE;
+}
+
+static void
+cc_fill_pixel (GByteArray *array,
+ guint8 value,
+ int pixel_size)
+{
+ guint i;
+
+ for (i = 0; i < pixel_size; i++) {
+ g_byte_array_append (array, &value, 1); /* R */
+ g_byte_array_append (array, &value, 1); /* G */
+ g_byte_array_append (array, &value, 1); /* B */
+ }
+}
+
+GdkPaintable *
+cc_qr_code_get_paintable (CcQrCode *self,
+ gint size)
+{
+ uint8_t qr_code[qrcodegen_BUFFER_LEN_FOR_VERSION (qrcodegen_VERSION_MAX)];
+ uint8_t temp_buf[qrcodegen_BUFFER_LEN_FOR_VERSION (qrcodegen_VERSION_MAX)];
+ g_autoptr(GBytes) bytes = NULL;
+ GByteArray *qr_matrix;
+ gint pixel_size, qr_size, total_size;
+ gint column, row, i;
+ gboolean success = FALSE;
+
+ g_return_val_if_fail (CC_IS_QR_CODE (self), NULL);
+ g_return_val_if_fail (size > 0, NULL);
+
+ if (!self->text || !*self->text)
+ {
+ g_warn_if_reached ();
+ cc_qr_code_set_text (self, "invalid text");
+ }
+
+ if (self->texture && self->size == size)
+ return GDK_PAINTABLE (self->texture);
+
+ self->size = size;
+
+ success = qrcodegen_encodeText (self->text,
+ temp_buf,
+ qr_code,
+ qrcodegen_Ecc_LOW,
+ qrcodegen_VERSION_MIN,
+ qrcodegen_VERSION_MAX,
+ qrcodegen_Mask_AUTO,
+ FALSE);
+
+ if (!success)
+ return NULL;
+
+ qr_size = qrcodegen_getSize(qr_code);
+ pixel_size = MAX (1, size / (qr_size));
+ total_size = qr_size * pixel_size;
+ qr_matrix = g_byte_array_sized_new (total_size * total_size * pixel_size * BYTES_PER_R8G8B8);
+
+ for (column = 0; column < total_size; column++)
+ {
+ for (i = 0; i < pixel_size; i++)
+ {
+ for (row = 0; row < total_size / pixel_size; row++)
+ {
+ if (qrcodegen_getModule (qr_code, column, row))
+ cc_fill_pixel (qr_matrix, 0x00, pixel_size);
+ else
+ cc_fill_pixel (qr_matrix, 0xff, pixel_size);
+ }
+ }
+ }
+
+ bytes = g_byte_array_free_to_bytes (qr_matrix);
+
+ g_clear_object (&self->texture);
+ self->texture = gdk_memory_texture_new (total_size,
+ total_size,
+ GDK_MEMORY_R8G8B8,
+ bytes,
+ total_size * BYTES_PER_R8G8B8);
+
+ return GDK_PAINTABLE (self->texture);
+}
diff --git a/panels/network/cc-qr-code.h b/panels/network/cc-qr-code.h
new file mode 100644
index 0000000..844dd2a
--- /dev/null
+++ b/panels/network/cc-qr-code.h
@@ -0,0 +1,43 @@
+/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */
+/* cc-qr-code.h
+ *
+ * Copyright 2019 Purism SPC
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <glib-object.h>
+#include <cairo.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_QR_CODE (cc_qr_code_get_type ())
+
+G_DECLARE_FINAL_TYPE (CcQrCode, cc_qr_code, CC, QR_CODE, GObject)
+
+CcQrCode *cc_qr_code_new (void);
+gboolean cc_qr_code_set_text (CcQrCode *self,
+ const gchar *text);
+GdkPaintable *cc_qr_code_get_paintable (CcQrCode *self,
+ gint size);
+
+G_END_DECLS
diff --git a/panels/network/cc-wifi-connection-list.c b/panels/network/cc-wifi-connection-list.c
new file mode 100644
index 0000000..6a11d20
--- /dev/null
+++ b/panels/network/cc-wifi-connection-list.c
@@ -0,0 +1,799 @@
+/*
+ * Copyright © 2018 Red Hat Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cc-wifi-connection-list.h"
+#include "cc-wifi-connection-row.h"
+
+struct _CcWifiConnectionList
+{
+ AdwBin parent_instance;
+
+ GtkListBox *listbox;
+
+ guint freeze_count;
+ gboolean updating;
+
+ gboolean checkable;
+ gboolean hide_unavailable;
+ gboolean show_aps;
+
+ NMClient *client;
+ NMDeviceWifi *device;
+
+ NMConnection *last_active;
+
+ GPtrArray *connections;
+ GPtrArray *connections_row;
+
+ /* AP SSID cache stores the APs SSID used for assigning it to a row.
+ * This is necessary to efficiently remove it when its SSID changes.
+ *
+ * Note that we only group APs that cannot be assigned to a connection
+ * by the SSID. In principle this is wrong, because other attributes may
+ * be different rendering them separate networks.
+ * In practice this will almost never happen, and if it does, we just
+ * show and select the strongest AP.
+ */
+ GHashTable *ap_ssid_cache;
+ GHashTable *ssid_to_row;
+};
+
+static void on_device_ap_added_cb (CcWifiConnectionList *self,
+ NMAccessPoint *ap,
+ NMDeviceWifi *device);
+static void on_device_ap_removed_cb (CcWifiConnectionList *self,
+ NMAccessPoint *ap,
+ NMDeviceWifi *device);
+static void on_row_configured_cb (CcWifiConnectionList *self,
+ CcWifiConnectionRow *row);
+
+G_DEFINE_TYPE (CcWifiConnectionList, cc_wifi_connection_list, ADW_TYPE_BIN)
+
+enum
+{
+ PROP_0,
+ PROP_CHECKABLE,
+ PROP_HIDE_UNAVAILABLE,
+ PROP_SHOW_APS,
+ PROP_CLIENT,
+ PROP_DEVICE,
+ PROP_LAST
+};
+
+static GParamSpec *props [PROP_LAST];
+
+static GBytes*
+new_hashable_ssid (GBytes *ssid)
+{
+ GBytes *res;
+ const guint8 *data;
+ gsize size;
+
+ /* This is what nm_utils_same_ssid does, but returning it so that we can
+ * use the result in other ways (i.e. hash table lookups). */
+ data = g_bytes_get_data ((GBytes*) ssid, &size);
+ if (data[size-1] == '\0')
+ size -= 1;
+ res = g_bytes_new (data, size);
+
+ return res;
+}
+
+static gboolean
+connection_ignored (NMConnection *connection)
+{
+ NMSettingWireless *sw;
+
+ /* Ignore AP and adhoc modes (i.e. accept infrastructure or empty) */
+ sw = nm_connection_get_setting_wireless (connection);
+ if (!sw)
+ return TRUE;
+ if (g_strcmp0 (nm_setting_wireless_get_mode (sw), "adhoc") == 0 ||
+ g_strcmp0 (nm_setting_wireless_get_mode (sw), "ap") == 0)
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static CcWifiConnectionRow*
+cc_wifi_connection_list_row_add (CcWifiConnectionList *self,
+ NMConnection *connection,
+ NMAccessPoint *ap,
+ gboolean known_connection)
+{
+ CcWifiConnectionRow *res;
+ g_autoptr(GPtrArray) aps = NULL;
+
+ if (ap)
+ {
+ aps = g_ptr_array_new ();
+ g_ptr_array_add (aps, ap);
+ }
+
+ res = cc_wifi_connection_row_new (self->device,
+ connection,
+ aps,
+ self->checkable,
+ known_connection);
+ gtk_list_box_append (self->listbox, GTK_WIDGET (res));
+
+ g_signal_connect_object (res, "configure", G_CALLBACK (on_row_configured_cb), self, G_CONNECT_SWAPPED);
+
+ g_signal_emit_by_name (self, "add-row", res);
+
+ return res;
+}
+
+static void
+clear_widget (CcWifiConnectionList *self)
+{
+ const GPtrArray *aps;
+ GHashTableIter iter;
+ CcWifiConnectionRow *row;
+ gint i;
+
+ /* Clear everything; disconnect all AP signals first */
+ aps = nm_device_wifi_get_access_points (self->device);
+ for (i = 0; i < aps->len; i++)
+ g_signal_handlers_disconnect_by_data (g_ptr_array_index (aps, i), self);
+
+ /* Remove all AP only rows */
+ g_hash_table_iter_init (&iter, self->ssid_to_row);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer*) &row))
+ {
+ g_hash_table_iter_remove (&iter);
+ g_signal_emit_by_name (self, "remove-row", row);
+ gtk_list_box_remove (self->listbox, GTK_WIDGET (row));
+ }
+
+ /* Remove all connection rows */
+ for (i = 0; i < self->connections_row->len; i++)
+ {
+ if (!g_ptr_array_index (self->connections_row, i))
+ continue;
+
+ row = g_ptr_array_index (self->connections_row, i);
+ g_ptr_array_index (self->connections_row, i) = NULL;
+ g_signal_emit_by_name (self, "remove-row", row);
+ gtk_list_box_remove (self->listbox, GTK_WIDGET (row));
+ }
+
+ /* Reset the internal state */
+ g_ptr_array_set_size (self->connections, 0);
+ g_ptr_array_set_size (self->connections_row, 0);
+ g_hash_table_remove_all (self->ssid_to_row);
+ g_hash_table_remove_all (self->ap_ssid_cache);
+}
+
+static void
+update_connections (CcWifiConnectionList *self)
+{
+ const GPtrArray *aps;
+ const GPtrArray *acs_client;
+ g_autoptr(GPtrArray) acs = NULL;
+ NMActiveConnection *ac;
+ NMConnection *ac_con = NULL;
+ gint i;
+
+ /* We don't want full UI rebuilds during some UI interactions, so allow freezing the list. */
+ if (self->freeze_count > 0)
+ return;
+
+ /* Prevent recursion (maybe move this into an idle handler instead?) */
+ if (self->updating)
+ return;
+ self->updating = TRUE;
+
+ clear_widget (self);
+
+ /* Copy the new connections; also create a row if we show unavailable
+ * connections */
+ acs_client = nm_client_get_connections (self->client);
+
+ acs = g_ptr_array_new_full (acs_client->len + 1, NULL);
+ for (i = 0; i < acs_client->len; i++)
+ g_ptr_array_add (acs, g_ptr_array_index (acs_client, i));
+
+ ac = nm_device_get_active_connection (NM_DEVICE (self->device));
+ if (ac)
+ ac_con = NM_CONNECTION (nm_active_connection_get_connection (ac));
+
+ if (ac_con && !g_ptr_array_find (acs, ac_con, NULL))
+ {
+ g_debug ("Adding remote connection for active connection");
+ g_ptr_array_add (acs, g_object_ref (ac_con));
+ }
+
+ for (i = 0; i < acs->len; i++)
+ {
+ NMConnection *con;
+
+ con = g_ptr_array_index (acs, i);
+ if (connection_ignored (con))
+ continue;
+
+ g_ptr_array_add (self->connections, g_object_ref (con));
+ if (self->hide_unavailable && con != ac_con)
+ g_ptr_array_add (self->connections_row, NULL);
+ else
+ g_ptr_array_add (self->connections_row,
+ cc_wifi_connection_list_row_add (self, con,
+ NULL, TRUE));
+ }
+
+ /* Coldplug all known APs again */
+ aps = nm_device_wifi_get_access_points (self->device);
+ for (i = 0; i < aps->len; i++)
+ on_device_ap_added_cb (self, g_ptr_array_index (aps, i), self->device);
+
+ self->updating = FALSE;
+}
+
+static void
+on_row_configured_cb (CcWifiConnectionList *self, CcWifiConnectionRow *row)
+{
+ g_signal_emit_by_name (self, "configure", row);
+}
+
+static void
+on_access_point_property_changed (CcWifiConnectionList *self,
+ GParamSpec *pspec,
+ NMAccessPoint *ap)
+{
+ CcWifiConnectionRow *row;
+ GBytes *ssid;
+ gboolean has_connection = FALSE;
+ gint i;
+
+ /* If the SSID changed then the AP needs to be added/removed from rows.
+ * Do this by simulating an AP addition/removal. */
+ if (g_str_equal (pspec->name, NM_ACCESS_POINT_SSID))
+ {
+ g_debug ("Simulating add/remove for SSID change");
+ on_device_ap_removed_cb (self, ap, self->device);
+ on_device_ap_added_cb (self, ap, self->device);
+ return;
+ }
+
+ /* Otherwise, find all rows that contain the AP and update it. Do this by
+ * first searching all rows with connections, and then looking it up in the
+ * SSID rows if not found. */
+ for (i = 0; i < self->connections_row->len; i++)
+ {
+ row = g_ptr_array_index (self->connections_row, i);
+ if (row && cc_wifi_connection_row_has_access_point (row, ap))
+ {
+ cc_wifi_connection_row_update (row);
+ has_connection = TRUE;
+ }
+ }
+
+ if (!self->show_aps || has_connection)
+ return;
+
+ ssid = g_hash_table_lookup (self->ap_ssid_cache, ap);
+ if (!ssid)
+ return;
+
+ row = g_hash_table_lookup (self->ssid_to_row, ssid);
+ if (!row)
+ g_assert_not_reached ();
+ else
+ cc_wifi_connection_row_update (row);
+}
+
+static void
+on_device_ap_added_cb (CcWifiConnectionList *self,
+ NMAccessPoint *ap,
+ NMDeviceWifi *device)
+{
+ g_autoptr(GPtrArray) connections = NULL;
+ NM80211ApSecurityFlags rsn_flags;
+ CcWifiConnectionRow *row;
+ GBytes *ap_ssid;
+ g_autoptr(GBytes) ssid = NULL;
+ guint i, j;
+
+ g_signal_connect_object (ap, "notify",
+ G_CALLBACK (on_access_point_property_changed),
+ self, G_CONNECT_SWAPPED);
+
+ connections = nm_access_point_filter_connections (ap, self->connections);
+
+ /* If this is the active AP, then add the active connection to the list. This
+ * is a workaround because nm_access_pointer_filter_connections() will not
+ * include it otherwise.
+ * So it seems like the dummy AP entry that NM creates internally is not actually
+ * compatible with the connection that is being activated.
+ */
+ if (ap == nm_device_wifi_get_active_access_point (device))
+ {
+ NMActiveConnection *ac;
+ NMConnection *ac_con;
+
+ ac = nm_device_get_active_connection (NM_DEVICE (self->device));
+
+ if (ac)
+ {
+ guint idx;
+
+ ac_con = NM_CONNECTION (nm_active_connection_get_connection (ac));
+
+ if (!g_ptr_array_find (connections, ac_con, NULL) &&
+ g_ptr_array_find (self->connections, ac_con, &idx))
+ {
+ g_debug ("Adding active connection to list of valid connections for AP");
+ g_ptr_array_add (connections, g_object_ref (ac_con));
+ }
+ }
+ }
+
+ /* Add the AP to all connection related rows, creating the row if neccessary. */
+ for (i = 0; i < connections->len; i++)
+ {
+ gboolean found = g_ptr_array_find (self->connections, g_ptr_array_index (connections, i), &j);
+
+ g_assert (found);
+
+ row = g_ptr_array_index (self->connections_row, j);
+ if (!row)
+ row = cc_wifi_connection_list_row_add (self, g_ptr_array_index (connections, i), NULL, TRUE);
+ cc_wifi_connection_row_add_access_point (row, ap);
+ g_ptr_array_index (self->connections_row, j) = row;
+ }
+
+ if (connections->len > 0)
+ return;
+
+ if (!self->show_aps)
+ return;
+
+ /* The AP is not compatible to any known connection, generate an entry for the
+ * SSID or add to existing one. However, not for hidden APs that don't have an SSID
+ * or a hidden OWE transition network.
+ */
+ ap_ssid = nm_access_point_get_ssid (ap);
+ if (ap_ssid == NULL)
+ return;
+
+ /* Skip OWE-TM network with OWE RSN */
+ rsn_flags = nm_access_point_get_rsn_flags (ap);
+ if (rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_OWE && rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)
+ return;
+
+ ssid = new_hashable_ssid (ap_ssid);
+
+ g_hash_table_insert (self->ap_ssid_cache, ap, g_bytes_ref (ssid));
+
+ row = g_hash_table_lookup (self->ssid_to_row, ssid);
+ if (!row)
+ {
+ row = cc_wifi_connection_list_row_add (self, NULL, ap, FALSE);
+
+ g_hash_table_insert (self->ssid_to_row, g_bytes_ref (ssid), row);
+ }
+ else
+ {
+ cc_wifi_connection_row_add_access_point (row, ap);
+ }
+}
+
+static void
+on_device_ap_removed_cb (CcWifiConnectionList *self,
+ NMAccessPoint *ap,
+ NMDeviceWifi *device)
+{
+ CcWifiConnectionRow *row;
+ g_autoptr(GBytes) ssid = NULL;
+ gboolean found = FALSE;
+ gint i;
+
+ g_signal_handlers_disconnect_by_data (ap, self);
+
+ /* Find any connection related row with the AP and remove the AP from it. Remove the
+ * row if it was the last AP and we are hiding unavailable connections. */
+ for (i = 0; i < self->connections_row->len; i++)
+ {
+ row = g_ptr_array_index (self->connections_row, i);
+ if (row && cc_wifi_connection_row_remove_access_point (row, ap))
+ {
+ found = TRUE;
+
+ if (self->hide_unavailable)
+ {
+ g_ptr_array_index (self->connections_row, i) = NULL;
+ g_signal_emit_by_name (self, "remove-row", row);
+ gtk_list_box_remove (self->listbox, GTK_WIDGET (row));
+ }
+ }
+ }
+
+ if (found || !self->show_aps)
+ return;
+
+ /* If the AP was inserted into a row without a connection, then we will get an
+ * SSID for it here. */
+ g_hash_table_steal_extended (self->ap_ssid_cache, ap, NULL, (gpointer*) &ssid);
+ if (!ssid)
+ return;
+
+ /* And we can update the row (possibly removing it) */
+ row = g_hash_table_lookup (self->ssid_to_row, ssid);
+ g_assert (row != NULL);
+
+ if (cc_wifi_connection_row_remove_access_point (row, ap))
+ {
+ g_hash_table_remove (self->ssid_to_row, ssid);
+ g_signal_emit_by_name (self, "remove-row", row);
+ gtk_list_box_remove (self->listbox, GTK_WIDGET (row));
+ }
+}
+
+static void
+on_client_connection_added_cb (CcWifiConnectionList *self,
+ NMConnection *connection,
+ NMClient *client)
+{
+ if (!nm_device_connection_compatible (NM_DEVICE (self->device), connection, NULL))
+ return;
+
+ if (connection_ignored (connection))
+ return;
+
+ /* The approach we take to handle connection changes is to do a full rebuild.
+ * It happens seldom enough to make this feasible.
+ */
+ update_connections (self);
+}
+
+static void
+on_client_connection_removed_cb (CcWifiConnectionList *self,
+ NMConnection *connection,
+ NMClient *client)
+{
+ if (!g_ptr_array_find (self->connections, connection, NULL))
+ return;
+
+ /* The approach we take to handle connection changes is to do a full rebuild.
+ * It happens seldom enough to make this feasible.
+ */
+ update_connections (self);
+}
+
+static void
+on_device_state_changed_cb (CcWifiConnectionList *self,
+ GParamSpec *pspec,
+ NMDeviceWifi *device)
+{
+ NMActiveConnection *ac;
+ NMConnection *connection = NULL;
+ guint idx;
+
+ ac = nm_device_get_active_connection (NM_DEVICE (self->device));
+ if (ac)
+ connection = NM_CONNECTION (nm_active_connection_get_connection (ac));
+
+ /* Just update the corresponding row if the AC is still the same. */
+ if (self->last_active == connection &&
+ g_ptr_array_find (self->connections, connection, &idx) &&
+ g_ptr_array_index (self->connections_row, idx))
+ {
+ cc_wifi_connection_row_update (g_ptr_array_index (self->connections_row, idx));
+ return;
+ }
+
+ /* Give up and do a full update. */
+ update_connections (self);
+ self->last_active = connection;
+}
+
+static void
+on_device_active_ap_changed_cb (CcWifiConnectionList *self,
+ GParamSpec *pspec,
+ NMDeviceWifi *device)
+{
+ NMAccessPoint *ap;
+ /* We need to make sure the active AP is grouped with the active connection.
+ * Do so by simply removing and adding it.
+ *
+ * This is necessary because the AP is added before this property
+ * is updated. */
+ ap = nm_device_wifi_get_active_access_point (self->device);
+ if (ap)
+ {
+ g_debug ("Simulating add/remove for active AP change");
+ on_device_ap_removed_cb (self, ap, self->device);
+ on_device_ap_added_cb (self, ap, self->device);
+ }
+}
+
+static void
+cc_wifi_connection_list_dispose (GObject *object)
+{
+ CcWifiConnectionList *self = (CcWifiConnectionList *)object;
+
+ /* Prevent any further updates; clear_widget must not indirectly recurse
+ * through updates_connections */
+ self->updating = TRUE;
+
+ /* Drop all external references */
+ clear_widget (self);
+
+ G_OBJECT_CLASS (cc_wifi_connection_list_parent_class)->dispose (object);
+}
+
+static void
+cc_wifi_connection_list_finalize (GObject *object)
+{
+ CcWifiConnectionList *self = (CcWifiConnectionList *)object;
+
+ g_clear_object (&self->client);
+ g_clear_object (&self->device);
+
+ g_clear_pointer (&self->connections, g_ptr_array_unref);
+ g_clear_pointer (&self->connections_row, g_ptr_array_unref);
+ g_clear_pointer (&self->ssid_to_row, g_hash_table_unref);
+ g_clear_pointer (&self->ap_ssid_cache, g_hash_table_unref);
+
+ G_OBJECT_CLASS (cc_wifi_connection_list_parent_class)->finalize (object);
+}
+
+static void
+cc_wifi_connection_list_constructed (GObject *object)
+{
+ CcWifiConnectionList *self = (CcWifiConnectionList *)object;
+
+ G_OBJECT_CLASS (cc_wifi_connection_list_parent_class)->constructed (object);
+
+ g_assert (self->client);
+ g_assert (self->device);
+
+ g_signal_connect_object (self->client, "connection-added",
+ G_CALLBACK (on_client_connection_added_cb),
+ self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->client, "connection-removed",
+ G_CALLBACK (on_client_connection_removed_cb),
+ self, G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self->device, "access-point-added",
+ G_CALLBACK (on_device_ap_added_cb),
+ self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->device, "access-point-removed",
+ G_CALLBACK (on_device_ap_removed_cb),
+ self, G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self->device, "notify::state",
+ G_CALLBACK (on_device_state_changed_cb),
+ self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->device, "notify::active-connection",
+ G_CALLBACK (on_device_state_changed_cb),
+ self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->device, "notify::active-access-point",
+ G_CALLBACK (on_device_active_ap_changed_cb),
+ self, G_CONNECT_SWAPPED);
+ on_device_state_changed_cb (self, NULL, self->device);
+
+ /* Simulate a change notification on the available connections.
+ * This uses the implementation detail that the list is rebuild
+ * completely in this case. */
+ update_connections (self);
+}
+
+static void
+cc_wifi_connection_list_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcWifiConnectionList *self = CC_WIFI_CONNECTION_LIST (object);
+
+ switch (prop_id)
+ {
+ case PROP_CHECKABLE:
+ g_value_set_boolean (value, self->checkable);
+ break;
+
+ case PROP_HIDE_UNAVAILABLE:
+ g_value_set_boolean (value, self->hide_unavailable);
+ break;
+
+ case PROP_SHOW_APS:
+ g_value_set_boolean (value, self->show_aps);
+ break;
+
+ case PROP_CLIENT:
+ g_value_set_object (value, self->client);
+ break;
+
+ case PROP_DEVICE:
+ g_value_set_object (value, self->device);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_wifi_connection_list_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcWifiConnectionList *self = CC_WIFI_CONNECTION_LIST (object);
+
+ switch (prop_id)
+ {
+ case PROP_CHECKABLE:
+ self->checkable = g_value_get_boolean (value);
+ break;
+
+ case PROP_HIDE_UNAVAILABLE:
+ self->hide_unavailable = g_value_get_boolean (value);
+ break;
+
+ case PROP_SHOW_APS:
+ self->show_aps = g_value_get_boolean (value);
+ break;
+
+ case PROP_CLIENT:
+ self->client = g_value_dup_object (value);
+ break;
+
+ case PROP_DEVICE:
+ self->device = g_value_dup_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_wifi_connection_list_class_init (CcWifiConnectionListClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructed = cc_wifi_connection_list_constructed;
+ object_class->dispose = cc_wifi_connection_list_dispose;
+ object_class->finalize = cc_wifi_connection_list_finalize;
+ object_class->get_property = cc_wifi_connection_list_get_property;
+ object_class->set_property = cc_wifi_connection_list_set_property;
+
+ props[PROP_CHECKABLE] =
+ g_param_spec_boolean ("checkable", "checkable",
+ "Passed to the created rows to show/hide the checkbox for deletion",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ props[PROP_HIDE_UNAVAILABLE] =
+ g_param_spec_boolean ("hide-unavailable", "HideUnavailable",
+ "Whether to show or hide unavailable connections",
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ props[PROP_SHOW_APS] =
+ g_param_spec_boolean ("show-aps", "ShowAPs",
+ "Whether to show available SSIDs/APs without a connection",
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ props[PROP_CLIENT] =
+ g_param_spec_object ("client", "NMClient",
+ "The NM Client",
+ NM_TYPE_CLIENT,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ props[PROP_DEVICE] =
+ g_param_spec_object ("device", "WiFi Device",
+ "The WiFi Device for this connection list",
+ NM_TYPE_DEVICE_WIFI,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class,
+ PROP_LAST,
+ props);
+
+ g_signal_new ("configure",
+ CC_TYPE_WIFI_CONNECTION_LIST,
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE, 1, CC_TYPE_WIFI_CONNECTION_ROW);
+ g_signal_new ("add-row",
+ CC_TYPE_WIFI_CONNECTION_LIST,
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE, 1, CC_TYPE_WIFI_CONNECTION_ROW);
+ g_signal_new ("remove-row",
+ CC_TYPE_WIFI_CONNECTION_LIST,
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE, 1, CC_TYPE_WIFI_CONNECTION_ROW);
+}
+
+static void
+cc_wifi_connection_list_init (CcWifiConnectionList *self)
+{
+ self->listbox = GTK_LIST_BOX (gtk_list_box_new ());
+ gtk_list_box_set_selection_mode (GTK_LIST_BOX (self->listbox), GTK_SELECTION_NONE);
+ gtk_widget_set_valign (GTK_WIDGET (self->listbox), GTK_ALIGN_START);
+ gtk_widget_add_css_class (GTK_WIDGET (self->listbox), "boxed-list");
+ adw_bin_set_child (ADW_BIN (self), GTK_WIDGET (self->listbox));
+
+ self->hide_unavailable = TRUE;
+ self->show_aps = TRUE;
+
+ self->connections = g_ptr_array_new_with_free_func (g_object_unref);
+ self->connections_row = g_ptr_array_new ();
+ self->ssid_to_row = g_hash_table_new_full (g_bytes_hash, g_bytes_equal,
+ (GDestroyNotify) g_bytes_unref, NULL);
+ self->ap_ssid_cache = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, (GDestroyNotify) g_bytes_unref);
+}
+
+CcWifiConnectionList *
+cc_wifi_connection_list_new (NMClient *client,
+ NMDeviceWifi *device,
+ gboolean hide_unavailable,
+ gboolean show_aps,
+ gboolean checkable)
+{
+ return g_object_new (CC_TYPE_WIFI_CONNECTION_LIST,
+ "client", client,
+ "device", device,
+ "hide-unavailable", hide_unavailable,
+ "show-aps", show_aps,
+ "checkable", checkable,
+ NULL);
+}
+
+void
+cc_wifi_connection_list_freeze (CcWifiConnectionList *self)
+{
+ g_return_if_fail (CC_WIFI_CONNECTION_LIST (self));
+
+ if (self->freeze_count == 0)
+ g_debug ("wifi connection list has been frozen");
+
+ self->freeze_count += 1;
+}
+
+void
+cc_wifi_connection_list_thaw (CcWifiConnectionList *self)
+{
+ g_return_if_fail (CC_WIFI_CONNECTION_LIST (self));
+
+ g_return_if_fail (self->freeze_count > 0);
+
+ self->freeze_count -= 1;
+
+ if (self->freeze_count == 0)
+ {
+ g_debug ("wifi connection list has been thawed");
+ update_connections (self);
+ }
+}
+
+GtkListBox *
+cc_wifi_connection_list_get_list_box (CcWifiConnectionList *self)
+{
+ g_return_val_if_fail (CC_IS_WIFI_CONNECTION_LIST (self), NULL);
+
+ return self->listbox;
+}
diff --git a/panels/network/cc-wifi-connection-list.h b/panels/network/cc-wifi-connection-list.h
new file mode 100644
index 0000000..eeec65f
--- /dev/null
+++ b/panels/network/cc-wifi-connection-list.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2018 Red Hat Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <adwaita.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_WIFI_CONNECTION_LIST (cc_wifi_connection_list_get_type())
+
+G_DECLARE_FINAL_TYPE (CcWifiConnectionList, cc_wifi_connection_list, CC, WIFI_CONNECTION_LIST, AdwBin)
+
+CcWifiConnectionList *cc_wifi_connection_list_new (NMClient *client,
+ NMDeviceWifi *device,
+ gboolean hide_unavailable,
+ gboolean show_aps,
+ gboolean checkable);
+
+
+void cc_wifi_connection_list_freeze (CcWifiConnectionList *list);
+void cc_wifi_connection_list_thaw (CcWifiConnectionList *list);
+
+GtkListBox *cc_wifi_connection_list_get_list_box (CcWifiConnectionList *self);
+
+G_END_DECLS
diff --git a/panels/network/cc-wifi-connection-row.c b/panels/network/cc-wifi-connection-row.c
new file mode 100644
index 0000000..608dda6
--- /dev/null
+++ b/panels/network/cc-wifi-connection-row.c
@@ -0,0 +1,678 @@
+/*
+ * Copyright © 2018 Red Hat Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib/gi18n.h>
+#include <config.h>
+#include "cc-wifi-connection-row.h"
+
+struct _CcWifiConnectionRow
+{
+ AdwActionRow parent_instance;
+
+ gboolean constructed;
+
+ gboolean checkable;
+ gboolean checked;
+
+ NMDeviceWifi *device;
+ GPtrArray *aps;
+ NMConnection *connection;
+ gboolean known_connection;
+
+ GtkLabel *active_label;
+ GtkCheckButton *checkbutton;
+ GtkSpinner *connecting_spinner;
+ GtkImage *encrypted_icon;
+ GtkButton *options_button;
+ GtkImage *strength_icon;
+};
+
+enum
+{
+ PROP_0,
+ PROP_CHECKABLE,
+ PROP_CHECKED,
+ PROP_DEVICE,
+ PROP_APS,
+ PROP_CONNECTION,
+ PROP_KNOWN_CONNECTION,
+ PROP_LAST
+};
+
+typedef enum
+{
+ NM_AP_SEC_UNKNOWN,
+ NM_AP_SEC_NONE,
+ NM_AP_SEC_WEP,
+ NM_AP_SEC_WPA,
+ NM_AP_SEC_WPA2,
+ NM_AP_SEC_SAE,
+ NM_AP_SEC_OWE,
+ NM_AP_SEC_OWE_TM
+} NMAccessPointSecurity;
+
+G_DEFINE_TYPE (CcWifiConnectionRow, cc_wifi_connection_row, ADW_TYPE_ACTION_ROW)
+
+static GParamSpec *props[PROP_LAST];
+
+static void configure_clicked_cb (CcWifiConnectionRow *self);
+
+static NMAccessPointSecurity
+get_access_point_security (NMAccessPoint *ap)
+{
+ NM80211ApFlags flags;
+ NM80211ApSecurityFlags wpa_flags;
+ NM80211ApSecurityFlags rsn_flags;
+ NMAccessPointSecurity type;
+
+ flags = nm_access_point_get_flags (ap);
+ wpa_flags = nm_access_point_get_wpa_flags (ap);
+ rsn_flags = nm_access_point_get_rsn_flags (ap);
+
+ if (!(flags & NM_802_11_AP_FLAGS_PRIVACY) &&
+ wpa_flags == NM_802_11_AP_SEC_NONE &&
+ rsn_flags == NM_802_11_AP_SEC_NONE)
+ {
+ type = NM_AP_SEC_NONE;
+ }
+ else if ((flags & NM_802_11_AP_FLAGS_PRIVACY) &&
+ wpa_flags == NM_802_11_AP_SEC_NONE &&
+ rsn_flags == NM_802_11_AP_SEC_NONE)
+ {
+ type = NM_AP_SEC_WEP;
+ }
+ else if (!(flags & NM_802_11_AP_FLAGS_PRIVACY) &&
+ wpa_flags != NM_802_11_AP_SEC_NONE &&
+ rsn_flags != NM_802_11_AP_SEC_NONE)
+ {
+ type = NM_AP_SEC_WPA;
+ }
+#if NM_CHECK_VERSION(1,20,6)
+ else if (rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_SAE)
+ {
+ type = NM_AP_SEC_SAE;
+ }
+#endif
+#if NM_CHECK_VERSION(1,24,0)
+ else if (rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_OWE)
+ {
+ type = NM_AP_SEC_OWE;
+ }
+#endif
+#if NM_CHECK_VERSION(1,26,0)
+ else if (rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)
+ {
+ type = NM_AP_SEC_OWE_TM;
+ }
+#endif
+ else
+ {
+ type = NM_AP_SEC_WPA2;
+ }
+
+ return type;
+}
+
+static NMAccessPointSecurity
+get_connection_security (NMConnection *con)
+{
+ NMSettingWirelessSecurity *sws;
+ const gchar *key_mgmt;
+
+ sws = nm_connection_get_setting_wireless_security (con);
+ g_debug ("getting security from %p", sws);
+ if (!sws)
+ return NM_AP_SEC_NONE;
+
+ key_mgmt = nm_setting_wireless_security_get_key_mgmt (sws);
+ g_debug ("key management is %s", key_mgmt);
+
+ if (!key_mgmt)
+ return NM_AP_SEC_NONE;
+ else if (g_str_equal (key_mgmt, "none"))
+ return NM_AP_SEC_WEP;
+ else if (g_str_equal (key_mgmt, "ieee8021x"))
+ return NM_AP_SEC_WEP;
+ else if (g_str_equal (key_mgmt, "wpa-eap"))
+ return NM_AP_SEC_WPA2;
+ else if (strncmp (key_mgmt, "wpa-", 4) == 0)
+ return NM_AP_SEC_WPA;
+ else if (g_str_equal (key_mgmt, "sae"))
+ return NM_AP_SEC_SAE;
+ else if (g_str_equal (key_mgmt, "owe"))
+ return NM_AP_SEC_OWE;
+ else
+ return NM_AP_SEC_UNKNOWN;
+}
+
+static void
+update_ui (CcWifiConnectionRow *self)
+{
+ GBytes *ssid;
+ g_autofree gchar *title = NULL;
+ NMActiveConnection *active_connection = NULL;
+ gboolean active;
+ gboolean connecting;
+ NMAccessPointSecurity security = NM_AP_SEC_UNKNOWN;
+ NMAccessPoint *best_ap;
+ guint8 strength = 0;
+ NMActiveConnectionState state;
+
+ g_assert (self->device);
+ g_assert (self->connection || self->aps->len > 0);
+
+ best_ap = cc_wifi_connection_row_best_access_point (self);
+
+ if (self->connection)
+ {
+ active_connection = nm_device_get_active_connection (NM_DEVICE (self->device));
+ if (active_connection &&
+ NM_CONNECTION (nm_active_connection_get_connection (active_connection)) != self->connection)
+ active_connection = NULL;
+ }
+
+ if (self->connection)
+ {
+ NMSettingWireless *sw;
+ const gchar *name = NULL;
+ g_autofree gchar *ssid_str = NULL;
+ gchar *ssid_pos;
+
+ sw = nm_connection_get_setting_wireless (self->connection);
+
+ ssid = nm_setting_wireless_get_ssid (sw);
+ ssid_str = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid));
+ name = nm_connection_get_id (NM_CONNECTION (self->connection));
+
+ ssid_pos = strstr (name, ssid_str);
+ if (ssid_pos == name && strlen (name) == strlen (ssid_str))
+ {
+ title = g_markup_escape_text (name, -1);
+ }
+ else if (ssid_pos)
+ {
+ g_autofree gchar *before = g_strndup (name, ssid_pos - name);
+ g_autofree gchar *after = g_strndup (ssid_pos + strlen (ssid_str), strlen(ssid_pos) - strlen(ssid_str));
+ title = g_markup_printf_escaped ("<i>%s</i>%s<i>%s</i>",
+ before, ssid_str, after);
+ }
+ else
+ {
+ /* TRANSLATORS: This happens when the connection name does not contain the SSID. */
+ title = g_markup_printf_escaped (C_("Wi-Fi Connection", "%s (SSID: %s)"),
+ name, ssid_str);
+ }
+
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self), title);
+ }
+ else
+ {
+ g_autofree char *title_escaped = NULL;
+
+ ssid = nm_access_point_get_ssid (best_ap);
+ title = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid));
+ title_escaped = g_markup_escape_text (title, -1);
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self), title_escaped);
+ }
+
+ if (active_connection)
+ {
+ state = nm_active_connection_get_state (active_connection);
+
+ active = state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED;
+ connecting = state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING;
+ }
+ else
+ {
+ active = FALSE;
+ connecting = FALSE;
+ }
+
+ if (self->connection)
+ security = get_connection_security (self->connection);
+
+ if (best_ap != NULL)
+ {
+ security = get_access_point_security (best_ap);
+ strength = nm_access_point_get_strength (best_ap);
+ }
+
+ gtk_widget_set_visible (GTK_WIDGET (self->connecting_spinner), connecting);
+ if (connecting)
+ {
+ gtk_spinner_start (self->connecting_spinner);
+ }
+ else
+ {
+ gtk_spinner_stop (self->connecting_spinner);
+ }
+
+ gtk_widget_set_visible (GTK_WIDGET (self->active_label), active);
+ gtk_widget_set_visible (GTK_WIDGET (self->options_button), active || connecting || self->known_connection);
+
+ if (security != NM_AP_SEC_UNKNOWN && security != NM_AP_SEC_NONE && security != NM_AP_SEC_OWE && security != NM_AP_SEC_OWE_TM)
+ {
+ const gchar *icon_name = "lock-small-symbolic";
+
+ gtk_widget_set_child_visible (GTK_WIDGET (self->encrypted_icon), TRUE);
+ if (security == NM_AP_SEC_WEP)
+ {
+ icon_name = "warning-small-symbolic";
+ gtk_widget_set_tooltip_text (GTK_WIDGET (self->encrypted_icon), _("Insecure network (WEP)"));
+ }
+ else if (security == NM_AP_SEC_WPA)
+ {
+ gtk_widget_set_tooltip_text (GTK_WIDGET (self->encrypted_icon), _("Secure network (WPA)"));
+ }
+ else if (security == NM_AP_SEC_WPA2)
+ {
+ gtk_widget_set_tooltip_text (GTK_WIDGET (self->encrypted_icon), _("Secure network (WPA2)"));
+ }
+ else if (security == NM_AP_SEC_SAE)
+ {
+ gtk_widget_set_tooltip_text (GTK_WIDGET (self->encrypted_icon), _("Secure network (WPA3)"));
+ }
+ else
+ {
+ gtk_widget_set_tooltip_text (GTK_WIDGET (self->encrypted_icon), _("Secure network"));
+ }
+
+ gtk_image_set_from_icon_name (self->encrypted_icon, icon_name);
+ }
+ else
+ {
+ gtk_widget_set_child_visible (GTK_WIDGET (self->encrypted_icon), FALSE);
+ }
+
+ if (best_ap)
+ {
+ gchar *icon_name;
+
+ if (strength < 20)
+ icon_name = "network-wireless-signal-none-symbolic";
+ else if (strength < 40)
+ icon_name = "network-wireless-signal-weak-symbolic";
+ else if (strength < 50)
+ icon_name = "network-wireless-signal-ok-symbolic";
+ else if (strength < 80)
+ icon_name = "network-wireless-signal-good-symbolic";
+ else
+ icon_name = "network-wireless-signal-excellent-symbolic";
+
+ g_object_set (self->strength_icon, "icon-name", icon_name, NULL);
+ gtk_widget_set_child_visible (GTK_WIDGET (self->strength_icon), TRUE);
+ }
+ else
+ {
+ gtk_widget_set_child_visible (GTK_WIDGET (self->strength_icon), FALSE);
+ }
+}
+
+static void
+cc_wifi_connection_row_constructed (GObject *object)
+{
+ CcWifiConnectionRow *self = CC_WIFI_CONNECTION_ROW (object);
+
+ G_OBJECT_CLASS (cc_wifi_connection_row_parent_class)->constructed (object);
+
+ /* Reparent the label into the checkbox */
+ gtk_widget_set_visible (GTK_WIDGET (self->checkbutton), self->checkable);
+
+ update_ui (CC_WIFI_CONNECTION_ROW (object));
+}
+
+static void
+cc_wifi_connection_row_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcWifiConnectionRow *self = CC_WIFI_CONNECTION_ROW (object);
+ GPtrArray *ptr_array;
+ gint i;
+
+ switch (prop_id)
+ {
+ case PROP_CHECKABLE:
+ g_value_set_boolean (value, self->checkable);
+ break;
+
+ case PROP_CHECKED:
+ g_value_set_boolean (value, self->checked);
+ break;
+
+ case PROP_DEVICE:
+ g_value_set_object (value, self->device);
+ break;
+
+ case PROP_APS:
+ ptr_array = g_ptr_array_new_full (self->aps->len, NULL);
+ for (i = 0; i < self->aps->len; i++)
+ g_ptr_array_add (ptr_array, g_ptr_array_index (self->aps, i));
+
+ g_value_take_boxed (value, ptr_array);
+ break;
+
+ case PROP_CONNECTION:
+ g_value_set_object (value, self->connection);
+ break;
+
+ case PROP_KNOWN_CONNECTION:
+ g_value_set_boolean (value, self->known_connection);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_wifi_connection_row_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcWifiConnectionRow *self = CC_WIFI_CONNECTION_ROW (object);
+ GPtrArray *ptr_array;
+ gint i;
+
+ switch (prop_id)
+ {
+ case PROP_CHECKABLE:
+ self->checkable = g_value_get_boolean (value);
+ break;
+
+ case PROP_CHECKED:
+ self->checked = g_value_get_boolean (value);
+ break;
+
+ case PROP_DEVICE:
+ self->device = g_value_dup_object (value);
+ break;
+
+ case PROP_APS:
+ ptr_array = g_value_get_boxed (value);
+ g_ptr_array_set_size (self->aps, 0);
+
+ if (ptr_array)
+ {
+ for (i = 0; i < ptr_array->len; i++)
+ g_ptr_array_add (self->aps, g_object_ref (g_ptr_array_index (ptr_array, i)));
+ }
+ if (self->constructed)
+ update_ui (self);
+ break;
+
+ case PROP_CONNECTION:
+ self->connection = g_value_dup_object (value);
+ break;
+
+ case PROP_KNOWN_CONNECTION:
+ self->known_connection = g_value_get_boolean (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_wifi_connection_row_finalize (GObject *object)
+{
+ CcWifiConnectionRow *self = CC_WIFI_CONNECTION_ROW (object);
+
+ g_clear_object (&self->device);
+ g_clear_pointer (&self->aps, g_ptr_array_unref);
+ g_clear_object (&self->connection);
+
+ G_OBJECT_CLASS (cc_wifi_connection_row_parent_class)->finalize (object);
+}
+
+
+void
+cc_wifi_connection_row_class_init (CcWifiConnectionRowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->constructed = cc_wifi_connection_row_constructed;
+ object_class->get_property = cc_wifi_connection_row_get_property;
+ object_class->set_property = cc_wifi_connection_row_set_property;
+ object_class->finalize = cc_wifi_connection_row_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/cc-wifi-connection-row.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcWifiConnectionRow, active_label);
+ gtk_widget_class_bind_template_child (widget_class, CcWifiConnectionRow, checkbutton);
+ gtk_widget_class_bind_template_child (widget_class, CcWifiConnectionRow, connecting_spinner);
+ gtk_widget_class_bind_template_child (widget_class, CcWifiConnectionRow, encrypted_icon);
+ gtk_widget_class_bind_template_child (widget_class, CcWifiConnectionRow, options_button);
+ gtk_widget_class_bind_template_child (widget_class, CcWifiConnectionRow, strength_icon);
+
+ gtk_widget_class_bind_template_callback (widget_class, configure_clicked_cb);
+
+ props[PROP_CHECKABLE] = g_param_spec_boolean ("checkable", "checkable",
+ "Whether to show a checkbox to select the row",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ props[PROP_CHECKED] = g_param_spec_boolean ("checked", "Checked",
+ "Whether the row is selected by checking it",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ props[PROP_DEVICE] = g_param_spec_object ("device", "WiFi Device",
+ "The WiFi Device for this connection/ap",
+ NM_TYPE_DEVICE_WIFI,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ props[PROP_APS] = g_param_spec_boxed ("aps", "Access Points",
+ "The access points for this connection (may be empty if a connection is given)",
+ G_TYPE_PTR_ARRAY,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ props[PROP_CONNECTION] = g_param_spec_object ("connection", "Connection",
+ "The NMConnection (may be NULL if there is an AP)",
+ NM_TYPE_CONNECTION,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ props[PROP_KNOWN_CONNECTION] = g_param_spec_boolean ("known-connection", "Known Connection",
+ "Whether this row is a known connection or not",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class,
+ PROP_LAST,
+ props);
+
+ g_signal_new ("configure",
+ CC_TYPE_WIFI_CONNECTION_ROW,
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+
+}
+
+static void
+configure_clicked_cb (CcWifiConnectionRow *self)
+{
+ g_signal_emit_by_name (self, "configure");
+}
+
+void
+cc_wifi_connection_row_init (CcWifiConnectionRow *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->aps = g_ptr_array_new_with_free_func (g_object_unref);
+
+ g_object_bind_property (self, "checked",
+ self->checkbutton, "active",
+ G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+}
+
+CcWifiConnectionRow *
+cc_wifi_connection_row_new (NMDeviceWifi *device,
+ NMConnection *connection,
+ GPtrArray *aps,
+ gboolean checkable,
+ gboolean known_connection)
+{
+ return g_object_new (CC_TYPE_WIFI_CONNECTION_ROW,
+ "device", device,
+ "connection", connection,
+ "aps", aps,
+ "checkable", checkable,
+ "known-connection", known_connection,
+ NULL);
+}
+
+gboolean
+cc_wifi_connection_row_get_checkable (CcWifiConnectionRow *self)
+{
+ g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (self), FALSE);
+
+ return self->checkable;
+}
+
+gboolean
+cc_wifi_connection_row_get_checked (CcWifiConnectionRow *self)
+{
+ g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (self), FALSE);
+
+ return self->checked;
+}
+
+NMDeviceWifi*
+cc_wifi_connection_row_get_device (CcWifiConnectionRow *self)
+{
+ g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (self), NULL);
+
+ return self->device;
+}
+
+const GPtrArray*
+cc_wifi_connection_row_get_access_points (CcWifiConnectionRow *self)
+{
+ g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (self), NULL);
+
+ return self->aps;
+}
+
+NMConnection*
+cc_wifi_connection_row_get_connection (CcWifiConnectionRow *self)
+{
+ g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (self), NULL);
+
+ return self->connection;
+}
+
+void
+cc_wifi_connection_row_set_checked (CcWifiConnectionRow *self,
+ gboolean value)
+{
+ g_return_if_fail (CC_WIFI_CONNECTION_ROW (self));
+
+ self->checked = value;
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CHECKED]);
+}
+
+NMAccessPoint*
+cc_wifi_connection_row_best_access_point (CcWifiConnectionRow *self)
+{
+ NMAccessPoint *best_ap = NULL;
+ NMAccessPoint *active_ap = NULL;
+ guint8 strength = 0;
+ gint i;
+
+ g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (self), NULL);
+
+ if (self->aps->len == 0)
+ return NULL;
+
+ active_ap = nm_device_wifi_get_active_access_point (self->device);
+
+ for (i = 0; i < self->aps->len; i++)
+ {
+ NMAccessPoint *cur;
+ guint8 cur_strength;
+
+ cur = g_ptr_array_index (self->aps, i);
+
+ /* Prefer the active AP in all cases */
+ if (cur == active_ap)
+ return cur;
+
+ cur_strength = nm_access_point_get_strength (cur);
+ /* Use if we don't have an AP, this is the current AP, or it is better */
+ if (!best_ap || cur_strength > strength)
+ {
+ best_ap = cur;
+ strength = cur_strength;
+ }
+ }
+
+ return best_ap;
+}
+
+void
+cc_wifi_connection_row_add_access_point (CcWifiConnectionRow *self,
+ NMAccessPoint *ap)
+{
+ g_return_if_fail (CC_WIFI_CONNECTION_ROW (self));
+
+ g_ptr_array_add (self->aps, g_object_ref (ap));
+ update_ui (self);
+}
+
+gboolean
+cc_wifi_connection_row_remove_access_point (CcWifiConnectionRow *self,
+ NMAccessPoint *ap)
+{
+ g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (self), FALSE);
+
+ if (!g_ptr_array_remove (self->aps, g_object_ref (ap)))
+ return FALSE;
+
+ /* Object might be invalid; this is alright if it is deleted right away */
+ if (self->aps->len > 0 || self->connection)
+ {
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_APS]);
+ update_ui (self);
+ }
+
+ return self->aps->len == 0;
+}
+
+gboolean
+cc_wifi_connection_row_has_access_point (CcWifiConnectionRow *self,
+ NMAccessPoint *ap)
+{
+ g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (self), FALSE);
+
+ return g_ptr_array_find (self->aps, ap, NULL);
+}
+
+void
+cc_wifi_connection_row_update (CcWifiConnectionRow *self)
+{
+ update_ui (self);
+
+ gtk_list_box_row_changed (GTK_LIST_BOX_ROW (self));
+
+}
+
diff --git a/panels/network/cc-wifi-connection-row.h b/panels/network/cc-wifi-connection-row.h
new file mode 100644
index 0000000..4d6f7ba
--- /dev/null
+++ b/panels/network/cc-wifi-connection-row.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 2018 Red Hat Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <adwaita.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+typedef struct _CcWifiConnectionRow CcWifiConnectionRow;
+
+#define CC_TYPE_WIFI_CONNECTION_ROW (cc_wifi_connection_row_get_type ())
+G_DECLARE_FINAL_TYPE (CcWifiConnectionRow, cc_wifi_connection_row, CC, WIFI_CONNECTION_ROW, AdwActionRow)
+
+CcWifiConnectionRow *cc_wifi_connection_row_new (NMDeviceWifi *device,
+ NMConnection *connection,
+ GPtrArray *aps,
+ gboolean checkable,
+ gboolean known_connection);
+
+gboolean cc_wifi_connection_row_get_checkable (CcWifiConnectionRow *row);
+gboolean cc_wifi_connection_row_get_checked (CcWifiConnectionRow *row);
+NMDeviceWifi *cc_wifi_connection_row_get_device (CcWifiConnectionRow *row);
+const GPtrArray *cc_wifi_connection_row_get_access_points (CcWifiConnectionRow *row);
+NMConnection *cc_wifi_connection_row_get_connection (CcWifiConnectionRow *row);
+
+void cc_wifi_connection_row_set_checked (CcWifiConnectionRow *row,
+ gboolean value);
+
+NMAccessPoint *cc_wifi_connection_row_best_access_point (CcWifiConnectionRow *row);
+void cc_wifi_connection_row_add_access_point (CcWifiConnectionRow *row,
+ NMAccessPoint *ap);
+gboolean cc_wifi_connection_row_remove_access_point (CcWifiConnectionRow *row,
+ NMAccessPoint *ap);
+gboolean cc_wifi_connection_row_has_access_point (CcWifiConnectionRow *row,
+ NMAccessPoint *ap);
+
+void cc_wifi_connection_row_update (CcWifiConnectionRow *row);
+G_END_DECLS
diff --git a/panels/network/cc-wifi-connection-row.ui b/panels/network/cc-wifi-connection-row.ui
new file mode 100644
index 0000000..d02dfe6
--- /dev/null
+++ b/panels/network/cc-wifi-connection-row.ui
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
+<interface>
+ <requires lib="gtk+" version="3.20"/>
+ <template class="CcWifiConnectionRow" parent="AdwActionRow">
+ <property name="activatable">True</property>
+ <child type="prefix">
+ <object class="GtkBox">
+ <property name="valign">center</property>
+ <property name="margin_end">6</property>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton">
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <property name="margin_end">6</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage" id="strength_icon">
+ <property name="icon_name">network-wireless-signal-excellent-symbolic</property>
+ <property name="icon_size">1</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage" id="encrypted_icon">
+ <property name="valign">end</property>
+ <property name="pixel-size">8</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child type="suffix">
+ <object class="GtkBox">
+ <property name="valign">center</property>
+ <property name="margin_start">6</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="active_label">
+ <property name="margin_end">6</property>
+ <property name="label" translatable="yes">Connected</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSpinner" id="connecting_spinner">
+ <property name="name">connecting_spinner</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="options_button">
+ <property name="name">options_button</property>
+ <property name="icon_name">emblem-system-symbolic</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <signal name="clicked" handler="configure_clicked_cb" object="CcWifiConnectionRow" swapped="yes"/>
+ <accessibility>
+ <property name="label" translatable="yes">Options…</property>
+ </accessibility>
+ <style>
+ <class name="flat"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </template>
+</interface>
diff --git a/panels/network/cc-wifi-hotspot-dialog.c b/panels/network/cc-wifi-hotspot-dialog.c
new file mode 100644
index 0000000..0610e24
--- /dev/null
+++ b/panels/network/cc-wifi-hotspot-dialog.c
@@ -0,0 +1,553 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-wifi-hotspot-dialog.c
+ *
+ * Copyright 2019 Purism SPC
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "cc-wifi-hotspot-dialog"
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include <libmm-glib.h>
+
+#include "cc-wifi-hotspot-dialog.h"
+#include "cc-network-resources.h"
+#include "ui-helpers.h"
+
+/**
+ * @short_description: WWAN network type selection dialog
+ */
+
+struct _CcWifiHotspotDialog
+{
+ GtkDialog parent_instance;
+
+ GtkLabel *connection_label;
+ GtkEntry *name_entry;
+ GtkEntry *password_entry;
+ GtkLabel *error_label;
+ GtkButton *ok_button;
+
+ GCancellable *cancellable;
+
+ NMDeviceWifi *device;
+ NMConnection *connection;
+ gchar *host_name;
+ gboolean wpa_supported; /* WPA/WPA2 supported */
+};
+
+G_DEFINE_TYPE (CcWifiHotspotDialog, cc_wifi_hotspot_dialog, GTK_TYPE_DIALOG)
+
+static gchar *
+get_random_wpa_key (void)
+{
+ gchar *key;
+ gint i;
+
+ key = g_malloc (10 * sizeof (key));
+ for (i = 0; i < 8; i++)
+ {
+ gint c = 0;
+ /* too many non alphanumeric characters are hard to remember for humans */
+ while (!g_ascii_isalnum (c))
+ c = g_random_int_range (33, 126);
+
+ key[i] = (gchar) c;
+ }
+ key[i] = '\0';
+
+ return key;
+}
+
+static gchar *
+get_random_wep_key (void)
+{
+ const gchar *hexdigits = "0123456789abcdef";
+ gchar *key;
+ gint i;
+
+ key = g_malloc (12 * sizeof (key));
+
+ /* generate a 10-digit hex WEP key */
+ for (i = 0; i < 10; i++)
+ {
+ gint digit;
+ digit = g_random_int_range (0, 16);
+ key[i] = hexdigits[digit];
+ }
+
+ key[i] = '\0';
+
+ return key;
+}
+
+static void
+wifi_hotspot_dialog_update_main_label (CcWifiHotspotDialog *self)
+{
+ NMAccessPoint *ap;
+ GBytes *ssid = NULL;
+ g_autofree gchar *active_ssid = NULL;
+ g_autofree gchar *escape = NULL;
+ g_autofree gchar *ssid_text = NULL;
+ g_autofree gchar *label = NULL;
+
+ g_assert (CC_IS_WIFI_HOTSPOT_DIALOG (self));
+
+ gtk_label_set_markup (self->connection_label, "");
+
+ if (!self->device)
+ return;
+
+ ap = nm_device_wifi_get_active_access_point (self->device);
+
+ if (ap)
+ ssid = nm_access_point_get_ssid (ap);
+ if (ssid)
+ active_ssid = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid));
+
+ if (!active_ssid || !*active_ssid)
+ return;
+
+ escape = g_markup_escape_text (active_ssid, -1);
+ ssid_text = g_strdup_printf ("<b>%s</b>", escape);
+ /* TRANSLATORS: ‘%s’ is a Wi-Fi Network(SSID) name */
+ label = g_strdup_printf (_("Turning on the hotspot will disconnect from %s, "
+ "and it will not be possible to access the internet through Wi-Fi."), ssid_text);
+ gtk_label_set_markup (self->connection_label, label);
+}
+
+static void
+get_secrets_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer data)
+{
+ CcWifiHotspotDialog *self;
+ g_autoptr(GVariant) secrets = NULL;
+ NMSettingWirelessSecurity *security_setting;
+ const gchar *key;
+ g_autoptr(GError) error = NULL;
+
+ secrets = nm_remote_connection_get_secrets_finish (NM_REMOTE_CONNECTION (source_object), res, &error);
+ if (!secrets)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Could not get secrets: %s", error->message);
+ return;
+ }
+
+ self = CC_WIFI_HOTSPOT_DIALOG (data);
+
+ nm_connection_update_secrets (self->connection,
+ NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+ secrets, &error);
+ if (error)
+ {
+ g_warning ("Error updating secrets: %s", error->message);
+ return;
+ }
+
+ security_setting = nm_connection_get_setting_wireless_security (self->connection);
+ if (self->wpa_supported)
+ key = nm_setting_wireless_security_get_psk (security_setting);
+ else
+ key = nm_setting_wireless_security_get_wep_key (security_setting, 0);
+
+ if (key)
+ gtk_editable_set_text (GTK_EDITABLE (self->password_entry), key);
+
+ nm_connection_clear_secrets (self->connection);
+}
+
+static void
+wifi_hotspot_dialog_update_entries (CcWifiHotspotDialog *self)
+{
+ NMSettingWireless *setting;
+ GBytes *ssid;
+ g_autofree gchar *ssid_text = NULL;
+
+ g_assert (CC_IS_WIFI_HOTSPOT_DIALOG (self));
+
+ gtk_editable_set_text (GTK_EDITABLE (self->name_entry), "");
+ gtk_editable_set_text (GTK_EDITABLE (self->password_entry), "");
+
+ if (!self->connection)
+ return;
+
+ setting = nm_connection_get_setting_wireless (self->connection);
+
+ ssid = nm_setting_wireless_get_ssid (setting);
+ ssid_text = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid));
+
+ if (!ssid_text && self->host_name)
+ ssid_text = g_strdup (self->host_name);
+
+ if (ssid_text)
+ gtk_editable_set_text (GTK_EDITABLE (self->name_entry), ssid_text);
+
+ if (!NM_IS_REMOTE_CONNECTION (self->connection))
+ return;
+
+ /* Secrets may not be already loaded, we have to manually load it. */
+ nm_remote_connection_get_secrets_async (NM_REMOTE_CONNECTION (self->connection),
+ NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+ self->cancellable,
+ get_secrets_cb,
+ self);
+}
+
+static gboolean
+hotspot_password_is_valid (CcWifiHotspotDialog *self,
+ const gchar *password)
+{
+ g_assert (CC_IS_WIFI_HOTSPOT_DIALOG (self));
+
+ if (!self->device)
+ return FALSE;
+
+ if (!password || !*password)
+ return TRUE;
+
+ if (self->wpa_supported)
+ return nm_utils_wpa_psk_valid (password);
+ else
+ return nm_utils_wep_key_valid (password, NM_WEP_KEY_TYPE_KEY);
+}
+
+static void
+hotspot_entry_changed_cb (CcWifiHotspotDialog *self)
+{
+ const gchar *ssid, *password, *error_label;
+ gboolean valid_ssid, valid_password;
+
+ g_assert (CC_IS_WIFI_HOTSPOT_DIALOG (self));
+
+ valid_ssid = valid_password = FALSE;
+ ssid = gtk_editable_get_text (GTK_EDITABLE (self->name_entry));
+ password = gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+
+ if (ssid && *ssid)
+ {
+ valid_ssid = TRUE;
+ widget_unset_error (GTK_WIDGET (self->name_entry));
+ }
+ else
+ widget_set_error (GTK_WIDGET (self->name_entry));
+
+ valid_password = hotspot_password_is_valid (self, password);
+
+ if (valid_password)
+ {
+ error_label = "";
+ widget_unset_error (GTK_WIDGET (self->password_entry));
+ }
+ else
+ {
+ if (strlen (password) < 8)
+ {
+ error_label = _("Must have a minimum of 8 characters");
+ }
+ else
+ {
+ guint max_chars = self->wpa_supported ? 63 : 16;
+ error_label = g_strdup_printf (ngettext ("Must have a maximum of %d character",
+ "Must have a maximum of %d characters", max_chars), max_chars);
+ }
+
+ widget_set_error (GTK_WIDGET(self->password_entry));
+ }
+
+ gtk_label_set_label (self->error_label, error_label);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->ok_button),
+ valid_ssid && valid_password);
+}
+
+static void
+generate_password_clicked_cb (CcWifiHotspotDialog *self)
+{
+ g_autofree gchar *key = NULL;
+
+ g_assert (CC_IS_WIFI_HOTSPOT_DIALOG (self));
+
+ if (self->wpa_supported)
+ key = get_random_wpa_key ();
+ else
+ key = get_random_wep_key ();
+
+ gtk_editable_set_text (GTK_EDITABLE (self->password_entry), key);
+}
+
+static void
+hotspot_update_wireless_settings (CcWifiHotspotDialog *self)
+{
+ NMSettingWireless *setting;
+ g_autoptr(GBytes) ssid = NULL;
+ const gchar *ssid_text;
+ NMDeviceWifiCapabilities capabilities;
+
+ g_assert (CC_IS_WIFI_HOTSPOT_DIALOG (self));
+
+ if (nm_connection_get_setting_wireless (self->connection) == NULL)
+ nm_connection_add_setting (self->connection, nm_setting_wireless_new ());
+
+ setting = nm_connection_get_setting_wireless (self->connection);
+
+ capabilities = nm_device_wifi_get_capabilities (self->device);
+ if (capabilities & NM_WIFI_DEVICE_CAP_AP)
+ g_object_set (setting, "mode", "ap", NULL);
+ else
+ g_object_set (setting, "mode", "adhoc", NULL);
+
+ ssid_text = gtk_editable_get_text (GTK_EDITABLE (self->name_entry));
+ ssid = g_bytes_new (ssid_text, strlen (ssid_text));
+ g_object_set (setting, "ssid", ssid, NULL);
+}
+
+static void
+hotspot_update_wireless_security_settings (CcWifiHotspotDialog *self)
+{
+ NMSettingWirelessSecurity *setting;
+ const gchar *value, *key_type;
+
+ g_assert (CC_IS_WIFI_HOTSPOT_DIALOG (self));
+
+ if (nm_connection_get_setting_wireless_security (self->connection) == NULL)
+ nm_connection_add_setting (self->connection, nm_setting_wireless_security_new ());
+
+ setting = nm_connection_get_setting_wireless_security (self->connection);
+ nm_setting_wireless_security_clear_protos (setting);
+ nm_setting_wireless_security_clear_pairwise (setting);
+ nm_setting_wireless_security_clear_groups (setting);
+ value = gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+
+ if (self->wpa_supported)
+ key_type = "psk";
+ else
+ key_type = "wep-key0";
+
+ if (self->wpa_supported)
+ g_object_set (setting, "key-mgmt", "wpa-psk", NULL);
+ else
+ g_object_set (setting,
+ "key-mgmt", "none",
+ "wep-key-type", NM_WEP_KEY_TYPE_KEY,
+ NULL);
+
+ if (!value || !*value)
+ {
+ g_autofree gchar *key = NULL;
+
+ if (self->wpa_supported)
+ key = get_random_wpa_key ();
+ else
+ key = get_random_wep_key ();
+
+ g_object_set (setting, key_type, key, NULL);
+ }
+ else
+ g_object_set (setting, key_type, value, NULL);
+
+ if (self->wpa_supported)
+ {
+ NMDeviceWifiCapabilities caps;
+
+ caps = nm_device_wifi_get_capabilities (self->device);
+
+ if (caps & NM_WIFI_DEVICE_CAP_RSN)
+ {
+ nm_setting_wireless_security_add_proto (setting, "rsn");
+ nm_setting_wireless_security_add_pairwise (setting, "ccmp");
+ nm_setting_wireless_security_add_group (setting, "ccmp");
+ }
+ else if (caps & NM_WIFI_DEVICE_CAP_WPA)
+ {
+ nm_setting_wireless_security_add_proto (setting, "wpa");
+ nm_setting_wireless_security_add_pairwise (setting, "tkip");
+ nm_setting_wireless_security_add_group (setting, "tkip");
+ }
+ }
+}
+
+static void
+cc_wifi_hotspot_dialog_finalize (GObject *object)
+{
+ CcWifiHotspotDialog *self = (CcWifiHotspotDialog *)object;
+
+ g_cancellable_cancel(self->cancellable);
+ g_clear_object (&self->cancellable);
+ g_clear_pointer (&self->host_name, g_free);
+ g_clear_object (&self->device);
+ g_clear_object (&self->connection);
+
+ G_OBJECT_CLASS (cc_wifi_hotspot_dialog_parent_class)->finalize (object);
+}
+
+static void
+cc_wifi_hotspot_dialog_show (GtkWidget *widget)
+{
+ CcWifiHotspotDialog *self = (CcWifiHotspotDialog *)widget;
+ g_warn_if_fail (self->device != NULL);
+
+ gtk_widget_grab_focus (GTK_WIDGET (self->ok_button));
+ wifi_hotspot_dialog_update_entries (self);
+
+ if (!self->connection)
+ if (self->host_name)
+ gtk_editable_set_text (GTK_EDITABLE (self->name_entry), self->host_name);
+
+ GTK_WIDGET_CLASS (cc_wifi_hotspot_dialog_parent_class)->show (widget);
+}
+
+static void
+cc_wifi_hotspot_dialog_response (GtkDialog *dialog,
+ gint response_id)
+{
+ CcWifiHotspotDialog *self = CC_WIFI_HOTSPOT_DIALOG (dialog);
+ NMSetting *setting;
+
+ if (response_id != GTK_RESPONSE_APPLY)
+ return;
+
+ if (!self->connection)
+ self->connection = NM_CONNECTION (nm_simple_connection_new ());
+
+ if (nm_connection_get_setting_connection (self->connection) == NULL)
+ {
+ setting = nm_setting_connection_new ();
+ g_object_set (setting,
+ "type", "802-11-wireless",
+ "id", "Hotspot",
+ "autoconnect", FALSE,
+ NULL);
+ nm_connection_add_setting (self->connection, setting);
+ }
+
+ if (nm_connection_get_setting_ip4_config (self->connection) == NULL)
+ {
+ setting = nm_setting_ip4_config_new ();
+ g_object_set (setting, "method", "shared", NULL);
+ nm_connection_add_setting (self->connection, setting);
+ }
+
+ hotspot_update_wireless_settings (self);
+ hotspot_update_wireless_security_settings (self);
+}
+
+static void
+cc_wifi_hotspot_dialog_class_init (CcWifiHotspotDialogClass *klass)
+{
+ GtkDialogClass *dialog_class = GTK_DIALOG_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = cc_wifi_hotspot_dialog_finalize;
+
+ widget_class->show = cc_wifi_hotspot_dialog_show;
+ dialog_class->response = cc_wifi_hotspot_dialog_response;
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/control-center/network/cc-wifi-hotspot-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcWifiHotspotDialog, connection_label);
+ gtk_widget_class_bind_template_child (widget_class, CcWifiHotspotDialog, name_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcWifiHotspotDialog, password_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcWifiHotspotDialog, error_label);
+ gtk_widget_class_bind_template_child (widget_class, CcWifiHotspotDialog, ok_button);
+
+ gtk_widget_class_bind_template_callback (widget_class, hotspot_entry_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, generate_password_clicked_cb);
+}
+
+static void
+cc_wifi_hotspot_dialog_init (CcWifiHotspotDialog *self)
+{
+ self->cancellable = g_cancellable_new ();
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+CcWifiHotspotDialog *
+cc_wifi_hotspot_dialog_new (GtkWindow *parent_window)
+{
+ g_return_val_if_fail (GTK_IS_WINDOW (parent_window), NULL);
+
+ return g_object_new (CC_TYPE_WIFI_HOTSPOT_DIALOG,
+ "use-header-bar", TRUE,
+ "transient-for", parent_window,
+ NULL);
+}
+
+void
+cc_wifi_hotspot_dialog_set_hostname (CcWifiHotspotDialog *self,
+ const gchar *host_name)
+{
+ g_return_if_fail (CC_IS_WIFI_HOTSPOT_DIALOG (self));
+
+ g_clear_pointer (&self->host_name, g_free);
+ self->host_name = g_strdup (host_name);
+}
+
+void
+cc_wifi_hotspot_dialog_set_device (CcWifiHotspotDialog *self,
+ NMDeviceWifi *device)
+{
+ g_return_if_fail (CC_IS_WIFI_HOTSPOT_DIALOG (self));
+ g_return_if_fail (NM_IS_DEVICE_WIFI (device));
+
+ g_set_object (&self->device, device);
+
+ if (device)
+ {
+ NMDeviceWifiCapabilities caps;
+
+ caps = nm_device_wifi_get_capabilities (device);
+ self->wpa_supported = FALSE;
+
+ if (caps & NM_WIFI_DEVICE_CAP_AP)
+ if (caps & (NM_WIFI_DEVICE_CAP_RSN | NM_WIFI_DEVICE_CAP_WPA))
+ self->wpa_supported = TRUE;
+ }
+
+ wifi_hotspot_dialog_update_main_label (self);
+}
+
+NMConnection *
+cc_wifi_hotspot_dialog_get_connection (CcWifiHotspotDialog *self)
+{
+ g_return_val_if_fail (CC_IS_WIFI_HOTSPOT_DIALOG (self), NULL);
+
+ return self->connection;
+}
+
+void
+cc_wifi_hotspot_dialog_set_connection (CcWifiHotspotDialog *self,
+ NMConnection *connection)
+{
+ NMSettingWireless *setting;
+
+ g_return_if_fail (CC_IS_WIFI_HOTSPOT_DIALOG (self));
+ g_return_if_fail (NM_IS_CONNECTION (connection));
+
+ setting = nm_connection_get_setting_wireless (connection);
+ g_return_if_fail (setting);
+
+ g_set_object (&self->connection, connection);
+}
diff --git a/panels/network/cc-wifi-hotspot-dialog.h b/panels/network/cc-wifi-hotspot-dialog.h
new file mode 100644
index 0000000..29a326d
--- /dev/null
+++ b/panels/network/cc-wifi-hotspot-dialog.h
@@ -0,0 +1,44 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* wifi-hotspot-dialog.h
+ *
+ * Copyright 2019 Purism SPC
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_WIFI_HOTSPOT_DIALOG (cc_wifi_hotspot_dialog_get_type())
+G_DECLARE_FINAL_TYPE (CcWifiHotspotDialog, cc_wifi_hotspot_dialog, CC, WIFI_HOTSPOT_DIALOG, GtkDialog)
+
+CcWifiHotspotDialog *cc_wifi_hotspot_dialog_new (GtkWindow *parent_window);
+void cc_wifi_hotspot_dialog_set_hostname (CcWifiHotspotDialog *self,
+ const gchar *host_name);
+void cc_wifi_hotspot_dialog_set_device (CcWifiHotspotDialog *self,
+ NMDeviceWifi *device);
+NMConnection *cc_wifi_hotspot_dialog_get_connection (CcWifiHotspotDialog *self);
+void cc_wifi_hotspot_dialog_set_connection (CcWifiHotspotDialog *self,
+ NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/cc-wifi-hotspot-dialog.ui b/panels/network/cc-wifi-hotspot-dialog.ui
new file mode 100644
index 0000000..1a69c46
--- /dev/null
+++ b/panels/network/cc-wifi-hotspot-dialog.ui
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcWifiHotspotDialog" parent="GtkDialog">
+ <property name="title" translatable="yes">Turn On Wi-Fi Hotspot?</property>
+ <property name="modal">1</property>
+ <property name="destroy-with-parent">1</property>
+ <property name="hide-on-close">True</property>
+
+ <child internal-child="headerbar">
+ <object class="GtkHeaderBar">
+ <property name="show-title-buttons">0</property>
+ </object>
+ </child>
+
+ <child internal-child="content_area">
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="margin-top">30</property>
+ <property name="margin-bottom">30</property>
+ <property name="margin-start">30</property>
+ <property name="margin-end">30</property>
+ <property name="spacing">20</property>
+
+ <child>
+ <object class="GtkLabel" id="label">
+ <property name="wrap">1</property>
+ <property name="max-width-chars">50</property>
+ <property name="label" translatable="yes">Wi-Fi hotspot allows others to share your internet connection, by creating a Wi-Fi network that they can connect to. To do this, you must have an internet connection through a source other than Wi-Fi.</property>
+ <property name="xalign">0.0</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="connection_label">
+ <property name="margin-bottom">18</property>
+ <property name="wrap">1</property>
+ <property name="max-width-chars">40</property>
+ <property name="use-markup">1</property>
+ <property name="xalign">0.0</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkGrid">
+ <property name="row-spacing">6</property>
+ <property name="column-spacing">12</property>
+
+ <!-- Hotspot SSID Name -->
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Network Name</property>
+ <property name="halign">end</property>
+ <property name="mnemonic_widget">name_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="name_entry">
+ <property name="hexpand">1</property>
+ <property name="max-length">64</property>
+ <signal name="changed" handler="hotspot_entry_changed_cb" swapped="yes" />
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Hotspot Password -->
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Password</property>
+ <property name="halign">end</property>
+ <property name="mnemonic_widget">password_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="password_entry">
+ <property name="max-length">64</property>
+ <property name="secondary-icon-name">view-refresh-symbolic</property>
+ <property name="secondary-icon-tooltip-text" translatable="yes">Generate Random Password</property>
+ <property name="placeholder-text" translatable="yes">Autogenerate Password</property>
+ <signal name="icon-press" handler="generate_password_clicked_cb" swapped="yes" />
+ <signal name="changed" handler="hotspot_entry_changed_cb" swapped="yes" />
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Error Label -->
+ <child>
+ <object class="GtkLabel" id="error_label">
+ <property name="halign">start</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ <style>
+ <class name="dim-label" />
+ </style>
+ <attributes>
+ <attribute name="scale" value="0.83"/>
+ </attributes>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child type="action">
+ <object class="GtkButton" id="cancel_button">
+ <property name="use-underline">1</property>
+ <property name="label" translatable="yes">_Cancel</property>
+ </object>
+ </child>
+ <child type="action">
+ <object class="GtkButton" id="ok_button">
+ <property name="use-underline">1</property>
+ <property name="label" translatable="yes">_Turn On</property>
+ </object>
+ </child>
+
+ <action-widgets>
+ <action-widget response="cancel">cancel_button</action-widget>
+ <action-widget response="apply" default="true">ok_button</action-widget>
+ </action-widgets>
+ </template>
+</interface>
diff --git a/panels/network/cc-wifi-panel.c b/panels/network/cc-wifi-panel.c
new file mode 100644
index 0000000..e53bae7
--- /dev/null
+++ b/panels/network/cc-wifi-panel.c
@@ -0,0 +1,1079 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2017 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "cc-network-resources.h"
+#include "cc-wifi-panel.h"
+#include "cc-qr-code.h"
+#include "net-device-wifi.h"
+#include "network-dialogs.h"
+#include "panel-common.h"
+#include "cc-list-row.h"
+
+#include "shell/cc-application.h"
+#include "shell/cc-debug.h"
+#include "shell/cc-object-storage.h"
+
+#include <glib/gi18n.h>
+#include <NetworkManager.h>
+
+#define QR_IMAGE_SIZE 180
+
+typedef enum
+{
+ OPERATION_NULL,
+ OPERATION_SHOW_DEVICE,
+ OPERATION_CREATE_WIFI,
+ OPERATION_CONNECT_HIDDEN,
+ OPERATION_CONNECT_8021X
+} CmdlineOperation;
+
+struct _CcWifiPanel
+{
+ CcPanel parent;
+
+ /* RFKill (Airplane Mode) */
+ GDBusProxy *rfkill_proxy;
+ CcListRow *rfkill_row;
+ GtkWidget *rfkill_widget;
+
+ /* Main widgets */
+ GtkStack *center_stack;
+ GtkStack *header_stack;
+ GtkBox *hotspot_box;
+ GtkLabel *list_label;
+ GtkStack *main_stack;
+ GtkWidget *spinner;
+ GtkStack *stack;
+ GtkPicture *wifi_qr_image;
+ CcQrCode *qr_code;
+
+ NMClient *client;
+
+ GPtrArray *devices;
+
+ GBinding *spinner_binding;
+
+ /* Command-line arguments */
+ CmdlineOperation arg_operation;
+ gchar *arg_device;
+ gchar *arg_access_point;
+};
+
+static void rfkill_switch_notify_activate_cb (CcListRow *rfkill_row,
+ GParamSpec *pspec,
+ CcWifiPanel *self);
+
+static void update_devices_names (CcWifiPanel *self);
+
+G_DEFINE_TYPE (CcWifiPanel, cc_wifi_panel, CC_TYPE_PANEL)
+
+enum
+{
+ PROP_0,
+ PROP_PARAMETERS,
+ N_PROPS
+};
+
+/* Static init function */
+
+static void
+update_panel_visibility (NMClient *client)
+{
+ const GPtrArray *devices;
+ CcApplication *application;
+ gboolean visible;
+ guint i;
+
+ CC_TRACE_MSG ("Updating Wi-Fi panel visibility");
+
+ devices = nm_client_get_devices (client);
+ visible = FALSE;
+
+ for (i = 0; devices && i < devices->len; i++)
+ {
+ NMDevice *device = g_ptr_array_index (devices, i);
+
+ visible |= NM_IS_DEVICE_WIFI (device);
+
+ if (visible)
+ break;
+ }
+
+ /* Set the new visibility */
+ application = CC_APPLICATION (g_application_get_default ());
+ cc_shell_model_set_panel_visibility (cc_application_get_model (application),
+ "wifi",
+ visible ? CC_PANEL_VISIBLE : CC_PANEL_VISIBLE_IN_SEARCH);
+
+ g_debug ("Wi-Fi panel visible: %s", visible ? "yes" : "no");
+}
+
+void
+cc_wifi_panel_static_init_func (void)
+{
+ g_autoptr(NMClient) client = NULL;
+
+ g_debug ("Monitoring NetworkManager for Wi-Fi devices");
+
+ /* Create and store a NMClient instance if it doesn't exist yet */
+ if (!cc_object_storage_has_object (CC_OBJECT_NMCLIENT))
+ {
+ g_autoptr(NMClient) new_client = nm_client_new (NULL, NULL);
+ cc_object_storage_add_object (CC_OBJECT_NMCLIENT, new_client);
+ }
+
+ client = cc_object_storage_get_object (CC_OBJECT_NMCLIENT);
+
+ /* Update the panel visibility and monitor for changes */
+
+ g_signal_connect (client, "device-added", G_CALLBACK (update_panel_visibility), NULL);
+ g_signal_connect (client, "device-removed", G_CALLBACK (update_panel_visibility), NULL);
+
+ update_panel_visibility (client);
+}
+
+/* Auxiliary methods */
+
+static gchar *
+escape_string (const gchar *str,
+ gboolean quote)
+{
+ GString *string;
+ const char *next;
+
+ if (!str)
+ return NULL;
+
+ string = g_string_new ("");
+ if (quote)
+ g_string_append_c (string, '"');
+
+ while ((next = strpbrk (str, "\\;,:\"")))
+ {
+ g_string_append_len (string, str, next - str);
+ g_string_append_c (string, '\\');
+ g_string_append_c (string, *next);
+ str = next + 1;
+ }
+
+ g_string_append (string, str);
+ if (quote)
+ g_string_append_c (string, '"');
+
+ return g_string_free (string, FALSE);
+}
+
+static const gchar *
+get_connection_security_type (NMConnection *c)
+{
+ NMSettingWirelessSecurity *setting;
+ const char *key_mgmt;
+
+ g_return_val_if_fail (c, "nopass");
+
+ setting = nm_connection_get_setting_wireless_security (c);
+
+ if (!setting)
+ return "nopass";
+
+ key_mgmt = nm_setting_wireless_security_get_key_mgmt (setting);
+
+ /* No IEEE 802.1x */
+ if (g_strcmp0 (key_mgmt, "none") == 0)
+ return "WEP";
+
+ if (g_strcmp0 (key_mgmt, "wpa-none") == 0 ||
+ g_strcmp0 (key_mgmt, "wpa-psk") == 0)
+ return "WPA";
+
+ return "nopass";
+}
+
+static gchar *
+get_wifi_password (NMConnection *c)
+{
+ NMSettingWirelessSecurity *setting;
+ g_autoptr(GVariant) secrets = NULL;
+ g_autoptr(GError) error = NULL;
+ const gchar *sec_type, *password;
+ gint wep_index;
+
+ g_assert (NM_IS_REMOTE_CONNECTION (c));
+
+ sec_type = get_connection_security_type (c);
+ setting = nm_connection_get_setting_wireless_security (c);
+
+ if (g_str_equal (sec_type, "nopass"))
+ return NULL;
+
+ secrets = nm_remote_connection_get_secrets (NM_REMOTE_CONNECTION (c),
+ NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+ NULL, &error);
+ if (!error)
+ nm_connection_update_secrets (c,
+ NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+ secrets, &error);
+ if (error)
+ {
+ g_warning ("Error: %s", error->message);
+ return NULL;
+ }
+
+ if (g_str_equal (sec_type, "WEP"))
+ {
+ wep_index = nm_setting_wireless_security_get_wep_tx_keyidx (setting);
+ password = nm_setting_wireless_security_get_wep_key (setting, wep_index);
+ }
+ else
+ {
+ password = nm_setting_wireless_security_get_psk (setting);
+ }
+
+ return escape_string (password, FALSE);
+}
+
+/* Generate a string representing the hotspot @connection
+ * An example generated text:
+ * WIFI:S:hotspot;T:WPA;P:my-valid-pass;H:true;
+ * Where,
+ * S = ssid, T = security, P = password, H = hidden (Optional)
+ *
+ * See https://github.com/zxing/zxing/wiki/Barcode-Contents#wi-fi-network-config-android-ios-11
+ */
+static gchar *
+get_qr_string_for_hotspot (NMClient *nm_client,
+ NMConnection *c)
+{
+ NMSettingWireless *setting;
+ g_autofree char *ssid_text = NULL;
+ g_autofree char *escaped_ssid = NULL;
+ g_autofree char *password_str = NULL;
+ GString *string;
+ GBytes *ssid;
+ gboolean hidden;
+
+ g_assert (NM_IS_CLIENT (nm_client));
+ g_assert (NM_IS_REMOTE_CONNECTION (c));
+
+ setting = nm_connection_get_setting_wireless (c);
+ ssid = nm_setting_wireless_get_ssid (setting);
+
+ if (!ssid)
+ return NULL;
+
+ string = g_string_new ("WIFI:S:");
+
+ /* SSID */
+ ssid_text = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL),
+ g_bytes_get_size (ssid));
+ escaped_ssid = escape_string (ssid_text, FALSE);
+ g_string_append (string, escaped_ssid);
+ g_string_append_c (string, ';');
+
+ /* Security type */
+ g_string_append (string, "T:");
+ g_string_append (string, get_connection_security_type (c));
+ g_string_append_c (string, ';');
+
+ /* Password */
+ g_string_append (string, "P:");
+ password_str = get_wifi_password (c);
+ if (password_str)
+ g_string_append (string, password_str);
+ g_string_append_c (string, ';');
+
+ /* WiFi Hidden */
+ hidden = nm_setting_wireless_get_hidden (setting);
+ if (hidden)
+ g_string_append (string, "H:true");
+ g_string_append_c (string, ';');
+
+ return g_string_free (string, FALSE);
+}
+
+static NMConnection *
+wifi_device_get_hotspot (CcWifiPanel *self,
+ NMDevice *device)
+{
+ NMSettingIPConfig *ip4_setting;
+ NMConnection *c;
+
+ g_assert (CC_IS_WIFI_PANEL (self));
+ g_assert (NM_IS_DEVICE (device));
+
+ if (nm_device_get_active_connection (device) == NULL)
+ return NULL;
+
+ c = net_device_get_find_connection (self->client, device);
+ if (c == NULL)
+ return NULL;
+
+ ip4_setting = nm_connection_get_setting_ip4_config (c);
+ if (g_strcmp0 (nm_setting_ip_config_get_method (ip4_setting),
+ NM_SETTING_IP4_CONFIG_METHOD_SHARED) != 0)
+ return NULL;
+
+ return c;
+}
+
+static void
+wifi_panel_update_qr_image_cb (CcWifiPanel *self)
+{
+ NetDeviceWifi *child;
+ NMConnection *hotspot;
+ NMDevice *device;
+
+ g_assert (CC_IS_WIFI_PANEL (self));
+
+ child = NET_DEVICE_WIFI (gtk_stack_get_visible_child (self->stack));
+ device = net_device_wifi_get_device (child);
+ hotspot = wifi_device_get_hotspot (self, device);
+
+ if (hotspot)
+ {
+ g_autofree gchar *str = NULL;
+
+ if (!self->qr_code)
+ self->qr_code = cc_qr_code_new ();
+
+ str = get_qr_string_for_hotspot (self->client, hotspot);
+ if (cc_qr_code_set_text (self->qr_code, str))
+ {
+ GdkPaintable *paintable;
+ gint scale;
+
+ scale = gtk_widget_get_scale_factor (GTK_WIDGET (self->wifi_qr_image));
+ paintable = cc_qr_code_get_paintable (self->qr_code, QR_IMAGE_SIZE * scale);
+ gtk_picture_set_paintable (self->wifi_qr_image, paintable);
+ }
+ }
+
+ gtk_widget_set_visible (GTK_WIDGET (self->hotspot_box), hotspot != NULL);
+ gtk_widget_set_opacity (GTK_WIDGET (self->list_label), hotspot == NULL);
+ gtk_widget_set_opacity (GTK_WIDGET (self->spinner), hotspot == NULL);
+}
+
+static void
+add_wifi_device (CcWifiPanel *self,
+ NMDevice *device)
+{
+ GtkWidget *header_widget;
+ NetDeviceWifi *net_device;
+
+ /* Create the NetDevice */
+ net_device = net_device_wifi_new (CC_PANEL (self),
+ self->client,
+ device);
+ gtk_widget_show (GTK_WIDGET (net_device));
+
+ /* And add to the header widgets */
+ header_widget = net_device_wifi_get_header_widget (net_device);
+
+ gtk_stack_add_named (self->header_stack, header_widget, nm_device_get_udi (device));
+
+ /* Setup custom title properties */
+ g_ptr_array_add (self->devices, net_device);
+
+ update_devices_names (self);
+
+ /* Needs to be added after the device is added to the self->devices array */
+ gtk_stack_add_titled (self->stack, GTK_WIDGET (net_device),
+ nm_device_get_udi (device),
+ nm_device_get_description (device));
+ g_signal_connect_object (device, "state-changed",
+ G_CALLBACK (wifi_panel_update_qr_image_cb),
+ self,
+ G_CONNECT_SWAPPED);
+}
+
+static void
+remove_wifi_device (CcWifiPanel *self,
+ NMDevice *device)
+{
+ GtkWidget *child;
+ const gchar *id;
+ guint i;
+
+ id = nm_device_get_udi (device);
+
+ /* Remove from the devices list */
+ for (i = 0; i < self->devices->len; i++)
+ {
+ NetDeviceWifi *net_device = g_ptr_array_index (self->devices, i);
+
+ if (net_device_wifi_get_device (net_device) == device)
+ {
+ g_ptr_array_remove (self->devices, net_device);
+ break;
+ }
+ }
+
+ /* Disconnect the signal to prevent assertion crash */
+ g_signal_handlers_disconnect_by_func (device,
+ G_CALLBACK (wifi_panel_update_qr_image_cb),
+ self);
+
+ /* Destroy all stack pages related to this device */
+ child = gtk_stack_get_child_by_name (self->stack, id);
+ gtk_stack_remove (self->stack, child);
+
+ child = gtk_stack_get_child_by_name (self->header_stack, id);
+ gtk_stack_remove (self->header_stack, child);
+
+ /* Update the title widget */
+ update_devices_names (self);
+}
+
+static void
+check_main_stack_page (CcWifiPanel *self)
+{
+ const gchar *nm_version;
+ gboolean airplane_mode_active;
+ gboolean wireless_enabled;
+
+ nm_version = nm_client_get_version (self->client);
+ wireless_enabled = nm_client_wireless_get_enabled (self->client);
+ airplane_mode_active = cc_list_row_get_active (self->rfkill_row);
+
+ if (!nm_version)
+ gtk_stack_set_visible_child_name (self->main_stack, "nm-not-running");
+ else if (!wireless_enabled && airplane_mode_active)
+ gtk_stack_set_visible_child_name (self->main_stack, "airplane-mode");
+ else if (!wireless_enabled || self->devices->len == 0)
+ gtk_stack_set_visible_child_name (self->main_stack, "no-wifi-devices");
+ else
+ gtk_stack_set_visible_child_name (self->main_stack, "wifi-connections");
+}
+
+static void
+load_wifi_devices (CcWifiPanel *self)
+{
+ const GPtrArray *devices;
+ guint i;
+
+ devices = nm_client_get_devices (self->client);
+
+ /* Cold-plug existing devices */
+ if (devices)
+ {
+ for (i = 0; i < devices->len; i++)
+ {
+ NMDevice *device;
+
+ device = g_ptr_array_index (devices, i);
+ if (!NM_IS_DEVICE_WIFI (device) || !nm_device_get_managed (device))
+ continue;
+ add_wifi_device (self, device);
+ }
+ }
+
+ check_main_stack_page (self);
+}
+
+static inline gboolean
+get_cached_rfkill_property (CcWifiPanel *self,
+ const gchar *property)
+{
+ g_autoptr(GVariant) result = NULL;
+
+ result = g_dbus_proxy_get_cached_property (self->rfkill_proxy, property);
+ return result ? g_variant_get_boolean (result) : FALSE;
+}
+
+static void
+sync_airplane_mode_switch (CcWifiPanel *self)
+{
+ gboolean enabled, should_show, hw_enabled;
+
+ enabled = get_cached_rfkill_property (self, "HasAirplaneMode");
+ should_show = get_cached_rfkill_property (self, "ShouldShowAirplaneMode");
+
+ gtk_widget_set_visible (GTK_WIDGET (self->rfkill_widget), enabled && should_show);
+ if (!enabled || !should_show)
+ return;
+
+ enabled = get_cached_rfkill_property (self, "AirplaneMode");
+ hw_enabled = get_cached_rfkill_property (self, "HardwareAirplaneMode");
+
+ enabled |= hw_enabled;
+
+ if (enabled != cc_list_row_get_active (self->rfkill_row))
+ {
+ g_signal_handlers_block_by_func (self->rfkill_row,
+ rfkill_switch_notify_activate_cb,
+ self);
+ g_object_set (self->rfkill_row, "active", enabled, NULL);
+ check_main_stack_page (self);
+ g_signal_handlers_unblock_by_func (self->rfkill_row,
+ rfkill_switch_notify_activate_cb,
+ self);
+ }
+
+ cc_list_row_set_switch_sensitive (self->rfkill_row, !hw_enabled);
+
+ check_main_stack_page (self);
+}
+
+static void
+update_devices_names (CcWifiPanel *self)
+{
+ guint number_of_devices = self->devices->len;
+
+ if (number_of_devices == 1)
+ {
+ GtkWidget *title_widget;
+ NetDeviceWifi *net_device;
+
+ net_device = g_ptr_array_index (self->devices, 0);
+ title_widget = net_device_wifi_get_title_widget (net_device);
+
+ gtk_stack_add_named (self->center_stack, title_widget, "single");
+ gtk_stack_set_visible_child_name (self->center_stack, "single");
+
+ net_device_wifi_set_title (net_device, _("Wi-Fi"));
+ }
+ else
+ {
+ GtkWidget *single_page_widget;
+ guint i;
+
+ for (i = 0; i < number_of_devices; i++)
+ {
+ NetDeviceWifi *net_device;
+ NMDevice *device;
+
+ net_device = g_ptr_array_index (self->devices, i);
+ device = net_device_wifi_get_device (net_device);
+
+ net_device_wifi_set_title (net_device, nm_device_get_description (device));
+ }
+
+ /* Remove the widget at the "single" page */
+ single_page_widget = gtk_stack_get_child_by_name (self->center_stack, "single");
+
+ if (single_page_widget)
+ {
+ g_object_ref (single_page_widget);
+ gtk_stack_remove (self->center_stack, single_page_widget);
+ g_object_unref (single_page_widget);
+ }
+
+ /* Show the stack-switcher page */
+ gtk_stack_set_visible_child_name (self->center_stack, "many");
+ }
+}
+
+/* Command-line arguments */
+
+static void
+reset_command_line_args (CcWifiPanel *self)
+{
+ self->arg_operation = OPERATION_NULL;
+ g_clear_pointer (&self->arg_device, g_free);
+ g_clear_pointer (&self->arg_access_point, g_free);
+}
+
+static gboolean
+handle_argv_for_device (CcWifiPanel *self, NetDeviceWifi *net_device)
+{
+ GtkWidget *toplevel;
+ NMDevice *device;
+ gboolean ret;
+
+ toplevel = cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (self)));
+ device = net_device_wifi_get_device (net_device);
+ ret = FALSE;
+
+ if (self->arg_operation == OPERATION_CREATE_WIFI)
+ {
+ cc_network_panel_create_wifi_network (toplevel, self->client);
+ ret = TRUE;
+ }
+ else if (self->arg_operation == OPERATION_CONNECT_HIDDEN)
+ {
+ cc_network_panel_connect_to_hidden_network (toplevel, self->client);
+ ret = TRUE;
+ }
+ else if (g_str_equal (nm_object_get_path (NM_OBJECT (device)), self->arg_device))
+ {
+ if (self->arg_operation == OPERATION_CONNECT_8021X)
+ {
+ cc_network_panel_connect_to_8021x_network (toplevel,
+ self->client,
+ device,
+ self->arg_access_point);
+ ret = TRUE;
+ }
+ else if (self->arg_operation == OPERATION_SHOW_DEVICE)
+ {
+ gtk_stack_set_visible_child_name (self->stack, nm_device_get_udi (device));
+ ret = TRUE;
+ }
+ }
+
+ if (ret)
+ reset_command_line_args (self);
+
+ return ret;
+}
+
+static void
+handle_argv (CcWifiPanel *self)
+{
+ guint i;
+
+ if (self->arg_operation == OPERATION_NULL)
+ return;
+
+ for (i = 0; i < self->devices->len; i++)
+ {
+ if (handle_argv_for_device (self, g_ptr_array_index (self->devices, i)))
+ break;
+ }
+}
+
+static GPtrArray *
+variant_av_to_string_array (GVariant *array)
+{
+ GVariantIter iter;
+ GVariant *v;
+ GPtrArray *strv;
+ gsize count;
+
+ count = g_variant_iter_init (&iter, array);
+ strv = g_ptr_array_sized_new (count + 1);
+
+ while (g_variant_iter_next (&iter, "v", &v))
+ {
+ g_ptr_array_add (strv, (gpointer) g_variant_get_string (v, NULL));
+ g_variant_unref (v);
+ }
+
+ g_ptr_array_add (strv, NULL); /* NULL-terminate the strv data array */
+ return strv;
+}
+
+static gboolean
+verify_argv (CcWifiPanel *self,
+ const char **args)
+{
+ switch (self->arg_operation)
+ {
+ case OPERATION_CONNECT_8021X:
+ case OPERATION_SHOW_DEVICE:
+ if (!self->arg_device)
+ {
+ g_warning ("Operation %s requires an object path", args[0]);
+ return FALSE;
+ }
+ default:
+ return TRUE;
+ }
+}
+
+/* Callbacks */
+
+static void
+device_state_changed_cb (CcWifiPanel *self, GParamSpec *pspec, NMDevice *device)
+{
+ const gchar *id;
+
+ id = nm_device_get_udi (device);
+ /* Don't add a device that has already been added */
+ if (!NM_IS_DEVICE_WIFI (device) || !id)
+ return;
+
+ if (nm_device_get_managed (device))
+ {
+ if (gtk_stack_get_child_by_name (self->stack, id))
+ return;
+ add_wifi_device (self, device);
+ check_main_stack_page (self);
+ }
+ else
+ {
+ if (!gtk_stack_get_child_by_name (self->stack, id))
+ return;
+ remove_wifi_device (self, device);
+ check_main_stack_page (self);
+ }
+}
+
+static void
+device_added_cb (CcWifiPanel *self, NMDevice *device)
+{
+ if (!NM_IS_DEVICE_WIFI (device))
+ return;
+
+ if (nm_device_get_managed (device))
+ {
+ add_wifi_device (self, device);
+ check_main_stack_page (self);
+ }
+
+ g_signal_connect_object (device,
+ "notify::state",
+ G_CALLBACK (device_state_changed_cb),
+ self,
+ G_CONNECT_SWAPPED);
+}
+
+static void
+device_removed_cb (CcWifiPanel *self, NMDevice *device)
+{
+ const gchar *id;
+
+ if (!NM_IS_DEVICE_WIFI (device))
+ return;
+
+ id = nm_device_get_udi (device);
+ /* Don't remove a device that has already been removed */
+ if (!gtk_stack_get_child_by_name (self->stack, id))
+ return;
+
+ remove_wifi_device (self, device);
+ check_main_stack_page (self);
+
+ g_signal_handlers_disconnect_by_func (device,
+ G_CALLBACK (device_state_changed_cb),
+ self);
+}
+
+static void
+wireless_enabled_cb (CcWifiPanel *self)
+{
+ check_main_stack_page (self);
+}
+
+static void
+on_rfkill_proxy_properties_changed_cb (CcWifiPanel *self)
+{
+ g_debug ("Rfkill properties changed");
+
+ sync_airplane_mode_switch (self);
+}
+
+static void
+rfkill_proxy_acquired_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcWifiPanel *self;
+ GDBusProxy *proxy;
+ g_autoptr(GError) error = NULL;
+
+ proxy = cc_object_storage_create_dbus_proxy_finish (res, &error);
+
+ if (error)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_printerr ("Error creating rfkill proxy: %s\n", error->message);
+
+ return;
+ }
+
+ self = CC_WIFI_PANEL (user_data);
+
+ self->rfkill_proxy = proxy;
+
+ g_signal_connect_object (proxy,
+ "g-properties-changed",
+ G_CALLBACK (on_rfkill_proxy_properties_changed_cb),
+ self,
+ G_CONNECT_SWAPPED);
+
+ sync_airplane_mode_switch (self);
+}
+
+static void
+rfkill_switch_notify_activate_cb (CcListRow *row,
+ GParamSpec *pspec,
+ CcWifiPanel *self)
+{
+ gboolean enable;
+
+ enable = cc_list_row_get_active (row);
+
+ g_dbus_proxy_call (self->rfkill_proxy,
+ "org.freedesktop.DBus.Properties.Set",
+ g_variant_new_parsed ("('org.gnome.SettingsDaemon.Rfkill',"
+ "'AirplaneMode', %v)",
+ g_variant_new_boolean (enable)),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ NULL,
+ NULL);
+}
+
+static void
+on_stack_visible_child_changed_cb (GtkStack *stack,
+ GParamSpec *pspec,
+ CcWifiPanel *self)
+{
+ const gchar *visible_device_id = NULL;
+ guint i;
+
+ wifi_panel_update_qr_image_cb (self);
+
+ /* Remove previous bindings */
+ g_clear_pointer (&self->spinner_binding, g_binding_unbind);
+
+ visible_device_id = gtk_stack_get_visible_child_name (stack);
+ for (i = 0; i < self->devices->len; i++)
+ {
+ NetDeviceWifi *net_device = g_ptr_array_index (self->devices, i);
+
+ if (g_strcmp0 (nm_device_get_udi (net_device_wifi_get_device (net_device)), visible_device_id) == 0)
+ {
+ self->spinner_binding = g_object_bind_property (net_device,
+ "scanning",
+ self->spinner,
+ "spinning",
+ G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
+ break;
+ }
+ }
+}
+
+static void
+on_stop_hotspot_dialog_response_cb (GtkDialog *dialog,
+ gint response,
+ CcWifiPanel *self)
+{
+ if (response == GTK_RESPONSE_OK)
+ {
+ NetDeviceWifi *child;
+
+ child = NET_DEVICE_WIFI (gtk_stack_get_visible_child (self->stack));
+ net_device_wifi_turn_off_hotspot (child);
+ }
+
+ gtk_window_destroy (GTK_WINDOW (dialog));
+}
+
+static void
+hotspot_stop_clicked_cb (CcWifiPanel *self)
+{
+ GtkWidget *dialog;
+ GtkNative *native;
+
+ g_assert (CC_IS_WIFI_PANEL (self));
+
+ native = gtk_widget_get_native (GTK_WIDGET (self));
+ dialog = gtk_message_dialog_new (GTK_WINDOW (native),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_OTHER,
+ GTK_BUTTONS_NONE,
+ _("Stop hotspot and disconnect any users?"));
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Stop Hotspot"), GTK_RESPONSE_OK,
+ NULL);
+
+ g_signal_connect (dialog, "response", G_CALLBACK (on_stop_hotspot_dialog_response_cb), self);
+ gtk_window_present (GTK_WINDOW (dialog));
+
+}
+
+/* Overrides */
+
+static const gchar *
+cc_wifi_panel_get_help_uri (CcPanel *panel)
+{
+ return "help:gnome-help/net-wireless";
+}
+
+static void
+cc_wifi_panel_finalize (GObject *object)
+{
+ CcWifiPanel *self = (CcWifiPanel *)object;
+
+ g_clear_object (&self->client);
+ g_clear_object (&self->rfkill_proxy);
+
+ g_clear_pointer (&self->devices, g_ptr_array_unref);
+
+ reset_command_line_args (self);
+
+ G_OBJECT_CLASS (cc_wifi_panel_parent_class)->finalize (object);
+}
+
+static void
+cc_wifi_panel_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+}
+
+static void
+cc_wifi_panel_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcWifiPanel *self = CC_WIFI_PANEL (object);
+ GVariant *parameters;
+
+ switch (prop_id)
+ {
+ case PROP_PARAMETERS:
+ reset_command_line_args (self);
+
+ parameters = g_value_get_variant (value);
+
+ if (parameters)
+ {
+ g_autoptr(GPtrArray) array = NULL;
+ const gchar **args;
+
+ array = variant_av_to_string_array (parameters);
+ args = (const gchar **) array->pdata;
+
+ if (args[0])
+ {
+ if (g_str_equal (args[0], "create-wifi"))
+ self->arg_operation = OPERATION_CREATE_WIFI;
+ else if (g_str_equal (args[0], "connect-hidden-wifi"))
+ self->arg_operation = OPERATION_CONNECT_HIDDEN;
+ else if (g_str_equal (args[0], "connect-8021x-wifi"))
+ self->arg_operation = OPERATION_CONNECT_8021X;
+ else if (g_str_equal (args[0], "show-device"))
+ self->arg_operation = OPERATION_SHOW_DEVICE;
+ else
+ self->arg_operation = OPERATION_NULL;
+ }
+
+ if (args[0] && args[1])
+ self->arg_device = g_strdup (args[1]);
+ if (args[0] && args[1] && args[2])
+ self->arg_access_point = g_strdup (args[2]);
+
+ if (!verify_argv (self, (const char **) args))
+ {
+ reset_command_line_args (self);
+ return;
+ }
+
+ handle_argv (self);
+ }
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_wifi_panel_class_init (CcWifiPanelClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+
+ panel_class->get_help_uri = cc_wifi_panel_get_help_uri;
+
+ object_class->finalize = cc_wifi_panel_finalize;
+ object_class->get_property = cc_wifi_panel_get_property;
+ object_class->set_property = cc_wifi_panel_set_property;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/cc-wifi-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcWifiPanel, center_stack);
+ gtk_widget_class_bind_template_child (widget_class, CcWifiPanel, header_stack);
+ gtk_widget_class_bind_template_child (widget_class, CcWifiPanel, hotspot_box);
+ gtk_widget_class_bind_template_child (widget_class, CcWifiPanel, list_label);
+ gtk_widget_class_bind_template_child (widget_class, CcWifiPanel, main_stack);
+ gtk_widget_class_bind_template_child (widget_class, CcWifiPanel, rfkill_row);
+ gtk_widget_class_bind_template_child (widget_class, CcWifiPanel, rfkill_widget);
+ gtk_widget_class_bind_template_child (widget_class, CcWifiPanel, spinner);
+ gtk_widget_class_bind_template_child (widget_class, CcWifiPanel, stack);
+ gtk_widget_class_bind_template_child (widget_class, CcWifiPanel, wifi_qr_image);
+
+ gtk_widget_class_bind_template_callback (widget_class, rfkill_switch_notify_activate_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_stack_visible_child_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, hotspot_stop_clicked_cb);
+
+ g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters");
+}
+
+static void
+cc_wifi_panel_init (CcWifiPanel *self)
+{
+ g_autoptr(GtkCssProvider) provider = NULL;
+
+ g_resources_register (cc_network_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->devices = g_ptr_array_new ();
+
+ /* Create and store a NMClient instance if it doesn't exist yet */
+ if (!cc_object_storage_has_object (CC_OBJECT_NMCLIENT))
+ {
+ g_autoptr(NMClient) client = nm_client_new (NULL, NULL);
+ cc_object_storage_add_object (CC_OBJECT_NMCLIENT, client);
+ }
+
+ /* Load NetworkManager */
+ self->client = cc_object_storage_get_object (CC_OBJECT_NMCLIENT);
+
+ g_signal_connect_object (self->client,
+ "device-added",
+ G_CALLBACK (device_added_cb),
+ self,
+ G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self->client,
+ "device-removed",
+ G_CALLBACK (device_removed_cb),
+ self,
+ G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self->client,
+ "notify::wireless-enabled",
+ G_CALLBACK (wireless_enabled_cb),
+ self,
+ G_CONNECT_SWAPPED);
+
+ /* Load Wi-Fi devices */
+ load_wifi_devices (self);
+
+ /* Acquire Airplane Mode proxy */
+ cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "org.gnome.SettingsDaemon.Rfkill",
+ "/org/gnome/SettingsDaemon/Rfkill",
+ "org.gnome.SettingsDaemon.Rfkill",
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ rfkill_proxy_acquired_cb,
+ self);
+
+ /* Handle comment-line arguments after loading devices */
+ handle_argv (self);
+
+ /* use custom CSS */
+ provider = gtk_css_provider_new ();
+ gtk_css_provider_load_from_resource (provider, "/org/gnome/control-center/network/wifi-panel.css");
+ gtk_style_context_add_provider_for_display (gdk_display_get_default (),
+ GTK_STYLE_PROVIDER (provider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+}
diff --git a/panels/network/cc-wifi-panel.h b/panels/network/cc-wifi-panel.h
new file mode 100644
index 0000000..20b6e34
--- /dev/null
+++ b/panels/network/cc-wifi-panel.h
@@ -0,0 +1,32 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2017 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_WIFI_PANEL (cc_wifi_panel_get_type())
+
+G_DECLARE_FINAL_TYPE (CcWifiPanel, cc_wifi_panel, CC, WIFI_PANEL, CcPanel)
+
+void cc_wifi_panel_static_init_func (void);
+
+G_END_DECLS
diff --git a/panels/network/cc-wifi-panel.ui b/panels/network/cc-wifi-panel.ui
new file mode 100644
index 0000000..572ef0e
--- /dev/null
+++ b/panels/network/cc-wifi-panel.ui
@@ -0,0 +1,326 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcWifiPanel" parent="CcPanel">
+
+ <child type="titlebar">
+ <object class="AdwHeaderBar" id="titlebar">
+ <property name="show-end-title-buttons">True</property>
+ <property name="show-start-title-buttons" bind-source="CcWifiPanel" bind-property="folded" bind-flags="default|sync-create" />
+ <child type="start">
+ <object class="GtkButton">
+ <property name="visible" bind-source="CcWifiPanel" bind-property="folded" bind-flags="default|sync-create" />
+ <property name="icon-name">go-previous-symbolic</property>
+ <property name="action-name">window.navigate</property>
+ <property name="action-target">0</property> <!-- 0: ADW_NAVIGATION_DIRECTION_BACK -->
+ <accessibility>
+ <property name="label" translatable="yes">Back</property>
+ </accessibility>
+ </object>
+ </child>
+
+ <!-- Center Widget -->
+ <property name="title-widget">
+ <object class="GtkStack" id="center_stack">
+ <property name="halign">center</property>
+ <property name="hhomogeneous">False</property>
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">many</property>
+ <property name="child">
+ <object class="GtkStackSwitcher">
+ <property name="stack">stack</property>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </property>
+
+ <!-- End Stack -->
+ <child type="end">
+ <object class="GtkStack" id="header_stack">
+ <property name="halign">end</property>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child type="content">
+ <object class="GtkScrolledWindow">
+ <property name="hscrollbar-policy">never</property>
+ <child>
+ <object class="AdwClamp">
+ <property name="margin_top">32</property>
+ <property name="margin_bottom">32</property>
+ <property name="margin_start">12</property>
+ <property name="margin_end">12</property>
+
+ <child>
+ <object class="GtkBox">
+ <property name="hexpand">True</property>
+ <property name="orientation">vertical</property>
+
+ <!-- Airplane Mode -->
+ <child>
+ <object class="GtkListBox" id="rfkill_widget">
+ <property name="margin_bottom">32</property>
+ <property name="selection-mode">none</property>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ <child>
+ <object class="CcListRow" id="rfkill_row">
+ <property name="show-switch">True</property>
+ <property name="title" translatable="yes">Airplane Mode</property>
+ <property name="subtitle" translatable="yes">Disables Wi-Fi, Bluetooth and mobile broadband</property>
+ <signal name="notify::active" handler="rfkill_switch_notify_activate_cb" object="CcWifiPanel" swapped="no" />
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkStack" id="main_stack">
+ <property name="hhomogeneous">False</property>
+ <property name="vhomogeneous">False</property>
+ <property name="transition_type">crossfade</property>
+
+ <!-- "No Wi-Fi Adapter" page -->
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">no-wifi-devices</property>
+ <property name="child">
+ <object class="GtkBox">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkImage">
+ <property name="icon_name">network-wireless-no-route-symbolic</property>
+ <property name="pixel_size">256</property>
+ <property name="margin-bottom">18</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="wrap">True</property>
+ <property name="label" translatable="yes">No Wi-Fi Adapter Found</property>
+ <attributes>
+ <attribute name="weight" value="bold" />
+ <attribute name="scale" value="1.2" />
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="wrap">True</property>
+ <property name="label" translatable="yes">Make sure you have a Wi-Fi adapter plugged and turned on</property>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <!-- "Airplane Mode" page -->
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">airplane-mode</property>
+ <property name="child">
+ <object class="GtkBox">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkImage">
+ <property name="icon_name">airplane-mode-symbolic</property>
+ <property name="pixel_size">256</property>
+ <property name="margin-bottom">18</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="wrap">True</property>
+ <property name="label" translatable="yes">Airplane Mode On</property>
+ <attributes>
+ <attribute name="weight" value="bold" />
+ <attribute name="scale" value="1.2" />
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="wrap">True</property>
+ <property name="label" translatable="yes">Turn off to use Wi-Fi</property>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <!-- Wi-Fi connections and devices -->
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">wifi-connections</property>
+ <property name="child">
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+
+ <child>
+ <object class="GtkBox" id="hotspot_box">
+ <property name="orientation">vertical</property>
+
+ <!-- Hotspot QR code -->
+ <child>
+ <object class="GtkPicture" id="wifi_qr_image">
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="width-request">180</property>
+ <property name="height-request">180</property>
+ <style>
+ <class name="frame"/>
+ <class name="qr-image"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel">
+ <property name="margin-top">12</property>
+ <property name="label" translatable="yes">Wi-Fi Hotspot Active</property>
+ <attributes>
+ <attribute name="weight" value="bold" />
+ <attribute name="scale" value="1.8" />
+ </attributes>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Mobile devices can scan the QR code to connect.</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkButton">
+ <property name="halign">center</property>
+ <property name="margin-top">12</property>
+ <property name="label" translatable="yes">Turn Off Hotspot…</property>
+ <signal name="clicked" handler="hotspot_stop_clicked_cb" swapped="yes"/>
+ <style>
+ <class name="destructive-action"/>
+ </style>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <!-- Visible Networks label & spinner -->
+ <child>
+ <object class="GtkBox">
+ <property name="hexpand">True</property>
+ <property name="halign">start</property>
+ <property name="spacing">6</property>
+ <property name="margin_bottom">12</property>
+ <child>
+ <object class="GtkLabel" id="list_label">
+ <property name="label" translatable="yes">Visible Networks</property>
+ <property name="xalign">0.0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSpinner" id="spinner">
+ <property name="hexpand">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- Stack with a listbox for each Wi-Fi device -->
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="transition_type">crossfade</property>
+ <signal name="notify::visible-child-name" handler="on_stack_visible_child_changed_cb" object="CcWifiPanel" swapped="no" />
+ </object>
+ </child>
+
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <!-- "NetworkManager Not Running" page -->
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">nm-not-running</property>
+ <property name="child">
+ <object class="GtkCenterBox">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="orientation">vertical</property>
+ <property name="margin-top">18</property>
+ <property name="margin-bottom">18</property>
+ <property name="margin-start">18</property>
+ <property name="margin-end">18</property>
+ <child type="center">
+ <object class="GtkImage">
+ <property name="icon_name">face-sad-symbolic</property>
+ <property name="pixel_size">128</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ </object>
+ </child>
+ <child type="end">
+ <object class="GtkLabel">
+ <property name="wrap">True</property>
+ <property name="label" translatable="yes">NetworkManager needs to be running</property>
+ </object>
+ </child>
+ <child type="end">
+ <object class="GtkLabel">
+ <property name="wrap">True</property>
+ <property name="label" translatable="yes">Oops, something has gone wrong. Please contact your software vendor.</property>
+ <attributes>
+ <attribute name="scale" value="1.42" />
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/connection-editor/8021x-security-page.ui b/panels/network/connection-editor/8021x-security-page.ui
new file mode 100644
index 0000000..5be96b3
--- /dev/null
+++ b/panels/network/connection-editor/8021x-security-page.ui
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CEPage8021xSecurity" parent="GtkGrid">
+ <property name="margin_start">50</property>
+ <property name="margin_end">50</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">10</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="security_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">802.1x _Security</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">enable_8021x_switch</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="enable_8021x_switch">
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="box">
+ <property name="orientation">vertical</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/connection-editor/ce-ip-address-entry.c b/panels/network/connection-editor/ce-ip-address-entry.c
new file mode 100644
index 0000000..586ea5d
--- /dev/null
+++ b/panels/network/connection-editor/ce-ip-address-entry.c
@@ -0,0 +1,99 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2020 Canonical Ltd.
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <NetworkManager.h>
+
+#include "ce-ip-address-entry.h"
+
+struct _CEIPAddressEntry
+{
+ GtkEntry parent_instance;
+
+ int family;
+};
+
+static void ce_ip_address_entry_editable_init (GtkEditableInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (CEIPAddressEntry, ce_ip_address_entry, GTK_TYPE_ENTRY,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE,
+ ce_ip_address_entry_editable_init))
+
+static void
+ce_ip_address_entry_changed (GtkEditable *editable)
+{
+ CEIPAddressEntry *self = CE_IP_ADDRESS_ENTRY (editable);
+ GtkStyleContext *context;
+
+ context = gtk_widget_get_style_context (GTK_WIDGET (self));
+ if (ce_ip_address_entry_is_valid (self))
+ gtk_style_context_remove_class (context, "error");
+ else
+ gtk_style_context_add_class (context, "error");
+}
+
+static void
+ce_ip_address_entry_init (CEIPAddressEntry *self)
+{
+}
+
+static void
+ce_ip_address_entry_editable_init (GtkEditableInterface *iface)
+{
+ iface->changed = ce_ip_address_entry_changed;
+}
+
+static void
+ce_ip_address_entry_class_init (CEIPAddressEntryClass *klass)
+{
+}
+
+CEIPAddressEntry *
+ce_ip_address_entry_new (int family)
+{
+ CEIPAddressEntry *self;
+
+ self = CE_IP_ADDRESS_ENTRY (g_object_new (ce_ip_address_entry_get_type (), NULL));
+ self->family = family;
+
+ return self;
+}
+
+gboolean
+ce_ip_address_entry_is_empty (CEIPAddressEntry *self)
+{
+ const gchar *text;
+
+ g_return_val_if_fail (CE_IS_IP_ADDRESS_ENTRY (self), FALSE);
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self));
+ return text[0] == '\0';
+}
+
+gboolean
+ce_ip_address_entry_is_valid (CEIPAddressEntry *self)
+{
+ const gchar *text;
+
+ g_return_val_if_fail (CE_IS_IP_ADDRESS_ENTRY (self), FALSE);
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self));
+ return text[0] == '\0' || nm_utils_ipaddr_valid (self->family, text);
+}
diff --git a/panels/network/connection-editor/ce-ip-address-entry.h b/panels/network/connection-editor/ce-ip-address-entry.h
new file mode 100644
index 0000000..e89a7fb
--- /dev/null
+++ b/panels/network/connection-editor/ce-ip-address-entry.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2020 Canonical Ltd.
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (CEIPAddressEntry, ce_ip_address_entry, CE, IP_ADDRESS_ENTRY, GtkEntry)
+
+CEIPAddressEntry *ce_ip_address_entry_new (int family);
+
+gboolean ce_ip_address_entry_is_empty (CEIPAddressEntry *entry);
+
+gboolean ce_ip_address_entry_is_valid (CEIPAddressEntry *entry);
+
+G_END_DECLS
diff --git a/panels/network/connection-editor/ce-netmask-entry.c b/panels/network/connection-editor/ce-netmask-entry.c
new file mode 100644
index 0000000..2fccf0f
--- /dev/null
+++ b/panels/network/connection-editor/ce-netmask-entry.c
@@ -0,0 +1,137 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2020 Canonical Ltd.
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <arpa/inet.h>
+#include <NetworkManager.h>
+
+#include "ce-netmask-entry.h"
+
+struct _CENetmaskEntry
+{
+ GtkEntry parent_instance;
+};
+
+static void ce_netmask_entry_editable_init (GtkEditableInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (CENetmaskEntry, ce_netmask_entry, GTK_TYPE_ENTRY,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE,
+ ce_netmask_entry_editable_init))
+
+static gboolean
+parse_netmask (const char *str, guint32 *prefix)
+{
+ struct in_addr tmp_addr;
+ glong tmp_prefix;
+
+ /* Is it a prefix? */
+ errno = 0;
+ if (!strchr (str, '.'))
+ {
+ tmp_prefix = strtol (str, NULL, 10);
+ if (!errno && tmp_prefix >= 0 && tmp_prefix <= 32)
+ {
+ if (prefix != NULL)
+ *prefix = tmp_prefix;
+ return TRUE;
+ }
+ }
+
+ /* Is it a netmask? */
+ if (inet_pton (AF_INET, str, &tmp_addr) > 0)
+ {
+ if (prefix != NULL)
+ *prefix = nm_utils_ip4_netmask_to_prefix (tmp_addr.s_addr);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+ce_netmask_entry_changed (GtkEditable *editable)
+{
+ CENetmaskEntry *self = CE_NETMASK_ENTRY (editable);
+ GtkStyleContext *context;
+
+ context = gtk_widget_get_style_context (GTK_WIDGET (self));
+ if (ce_netmask_entry_is_valid (self))
+ gtk_style_context_remove_class (context, "error");
+ else
+ gtk_style_context_add_class (context, "error");
+}
+
+static void
+ce_netmask_entry_init (CENetmaskEntry *self)
+{
+}
+
+static void
+ce_netmask_entry_editable_init (GtkEditableInterface *iface)
+{
+ iface->changed = ce_netmask_entry_changed;
+}
+
+static void
+ce_netmask_entry_class_init (CENetmaskEntryClass *klass)
+{
+}
+
+CENetmaskEntry *
+ce_netmask_entry_new (void)
+{
+ return CE_NETMASK_ENTRY (g_object_new (ce_netmask_entry_get_type (), NULL));
+}
+
+gboolean
+ce_netmask_entry_is_empty (CENetmaskEntry *self)
+{
+ const gchar *text;
+
+ g_return_val_if_fail (CE_IS_NETMASK_ENTRY (self), FALSE);
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self));
+ return text[0] == '\0';
+}
+
+gboolean
+ce_netmask_entry_is_valid (CENetmaskEntry *self)
+{
+ const gchar *text;
+
+ g_return_val_if_fail (CE_IS_NETMASK_ENTRY (self), FALSE);
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self));
+ return text[0] == '\0' || parse_netmask (text, NULL);
+}
+
+guint32
+ce_netmask_entry_get_prefix (CENetmaskEntry *self)
+{
+ const gchar *text;
+ guint32 prefix = 0;
+
+ g_return_val_if_fail (CE_IS_NETMASK_ENTRY (self), 0);
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self));
+ parse_netmask (text, &prefix);
+
+ return prefix;
+}
diff --git a/panels/network/connection-editor/ce-netmask-entry.h b/panels/network/connection-editor/ce-netmask-entry.h
new file mode 100644
index 0000000..ff6337e
--- /dev/null
+++ b/panels/network/connection-editor/ce-netmask-entry.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2020 Canonical Ltd.
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (CENetmaskEntry, ce_netmask_entry, CE, NETMASK_ENTRY, GtkEntry)
+
+CENetmaskEntry *ce_netmask_entry_new (void);
+
+gboolean ce_netmask_entry_is_empty (CENetmaskEntry *entry);
+
+gboolean ce_netmask_entry_is_valid (CENetmaskEntry *entry);
+
+guint32 ce_netmask_entry_get_prefix (CENetmaskEntry *entry);
+
+G_END_DECLS
diff --git a/panels/network/connection-editor/ce-page-8021x-security.c b/panels/network/connection-editor/ce-page-8021x-security.c
new file mode 100644
index 0000000..90732fa
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-8021x-security.c
@@ -0,0 +1,202 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Connection editor -- Connection editor for NetworkManager
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2008 - 2012 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <NetworkManager.h>
+#include <string.h>
+
+#include "ws-wpa-eap.h"
+#include "wireless-security.h"
+#include "ce-page.h"
+#include "ce-page-ethernet.h"
+#include "ce-page-8021x-security.h"
+
+struct _CEPage8021xSecurity {
+ GtkGrid parent;
+
+ GtkBox *box;
+ GtkSwitch *enable_8021x_switch;
+ GtkLabel *security_label;
+
+ NMConnection *connection;
+ WirelessSecurityWPAEAP *security;
+ GtkSizeGroup *group;
+ gboolean initial_have_8021x;
+};
+
+static void ce_page_iface_init (CEPageInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (CEPage8021xSecurity, ce_page_8021x_security, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (ce_page_get_type (), ce_page_iface_init))
+
+static void
+enable_toggled (CEPage8021xSecurity *self)
+{
+ gtk_widget_set_sensitive (GTK_WIDGET (self->security), gtk_switch_get_active (self->enable_8021x_switch));
+ ce_page_changed (CE_PAGE (self));
+}
+
+static void
+security_item_changed_cb (CEPage8021xSecurity *self)
+{
+ ce_page_changed (CE_PAGE (self));
+}
+
+static void
+finish_setup (CEPage8021xSecurity *self, gpointer unused, GError *error, gpointer user_data)
+{
+ if (error)
+ return;
+
+ self->group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
+ self->security = ws_wpa_eap_new (self->connection);
+ if (!self->security) {
+ g_warning ("Could not load 802.1x user interface.");
+ return;
+ }
+
+ g_signal_connect_object (WIRELESS_SECURITY (self->security), "changed", G_CALLBACK (security_item_changed_cb), self, G_CONNECT_SWAPPED);
+ if (gtk_widget_get_parent (GTK_WIDGET (self->security)))
+ gtk_box_remove (self->box, GTK_WIDGET (self->security));
+
+ gtk_switch_set_active (self->enable_8021x_switch, self->initial_have_8021x);
+ g_signal_connect_object (self->enable_8021x_switch, "notify::active", G_CALLBACK (enable_toggled), self, G_CONNECT_SWAPPED);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->security), self->initial_have_8021x);
+
+ gtk_size_group_add_widget (self->group, GTK_WIDGET (self->security_label));
+ wireless_security_add_to_size_group (WIRELESS_SECURITY (self->security), self->group);
+
+ gtk_box_append (self->box, GTK_WIDGET (self->security));
+
+}
+
+static const gchar *
+ce_page_8021x_security_get_security_setting (CEPage *page)
+{
+ CEPage8021xSecurity *self = CE_PAGE_8021X_SECURITY (page);
+
+ if (self->initial_have_8021x)
+ return NM_SETTING_802_1X_SETTING_NAME;
+
+ return NULL;
+}
+
+static const gchar *
+ce_page_8021x_security_get_title (CEPage *page)
+{
+ return _("Security");
+}
+
+static gboolean
+ce_page_8021x_security_validate (CEPage *cepage, NMConnection *connection, GError **error)
+{
+ CEPage8021xSecurity *self = CE_PAGE_8021X_SECURITY (cepage);
+ gboolean valid = TRUE;
+
+ if (gtk_switch_get_active (self->enable_8021x_switch)) {
+ NMSetting *s_8021x;
+
+ /* FIXME: get failed property and error out of wireless security objects */
+ valid = wireless_security_validate (WIRELESS_SECURITY (self->security), error);
+ if (valid) {
+ g_autoptr(NMConnection) tmp_connection = NULL;
+
+ /* Here's a nice hack to work around the fact that ws_802_1x_fill_connection needs wireless setting. */
+ tmp_connection = nm_simple_connection_new_clone (connection);
+ nm_connection_add_setting (tmp_connection, nm_setting_wireless_new ());
+
+ ws_wpa_eap_fill_connection (self->security, tmp_connection);
+
+ /* NOTE: It is important we create a copy of the settings, as the
+ * secrets might be cleared otherwise.
+ */
+ s_8021x = nm_connection_get_setting (tmp_connection, NM_TYPE_SETTING_802_1X);
+ nm_connection_add_setting (connection, nm_setting_duplicate (NM_SETTING (s_8021x)));
+ }
+ } else {
+ nm_connection_remove_setting (connection, NM_TYPE_SETTING_802_1X);
+ valid = TRUE;
+ }
+
+ return valid;
+}
+
+static void
+ce_page_8021x_security_init (CEPage8021xSecurity *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+ce_page_8021x_security_dispose (GObject *object)
+{
+ CEPage8021xSecurity *self = CE_PAGE_8021X_SECURITY (object);
+
+ g_clear_object (&self->connection);
+ g_clear_pointer ((GtkWidget **) &self->security, gtk_widget_unparent);
+ g_clear_object (&self->group);
+
+ G_OBJECT_CLASS (ce_page_8021x_security_parent_class)->dispose (object);
+}
+
+static void
+ce_page_8021x_security_class_init (CEPage8021xSecurityClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = ce_page_8021x_security_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/8021x-security-page.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CEPage8021xSecurity, box);
+ gtk_widget_class_bind_template_child (widget_class, CEPage8021xSecurity, enable_8021x_switch);
+ gtk_widget_class_bind_template_child (widget_class, CEPage8021xSecurity, security_label);
+}
+
+static void
+ce_page_iface_init (CEPageInterface *iface)
+{
+ iface->get_security_setting = ce_page_8021x_security_get_security_setting;
+ iface->get_title = ce_page_8021x_security_get_title;
+ iface->validate = ce_page_8021x_security_validate;
+}
+
+CEPage8021xSecurity *
+ce_page_8021x_security_new (NMConnection *connection)
+{
+ CEPage8021xSecurity *self;
+
+ self = CE_PAGE_8021X_SECURITY (g_object_new (ce_page_8021x_security_get_type (), NULL));
+
+ self->connection = g_object_ref (connection);
+
+ if (nm_connection_get_setting_802_1x (connection))
+ self->initial_have_8021x = TRUE;
+
+ g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);
+
+ return self;
+}
diff --git a/panels/network/connection-editor/ce-page-8021x-security.h b/panels/network/connection-editor/ce-page-8021x-security.h
new file mode 100644
index 0000000..e783587
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-8021x-security.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Connection editor -- Connection editor for NetworkManager
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2008 - 2012 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (CEPage8021xSecurity, ce_page_8021x_security, CE, PAGE_8021X_SECURITY, GtkGrid)
+
+CEPage8021xSecurity *ce_page_8021x_security_new (NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/connection-editor/ce-page-details.c b/panels/network/connection-editor/ce-page-details.c
new file mode 100644
index 0000000..e0f43ed
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-details.c
@@ -0,0 +1,571 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include <NetworkManager.h>
+
+#include "ce-page.h"
+#include "ce-page-details.h"
+
+#include "../panel-common.h"
+
+struct _CEPageDetails
+{
+ GtkGrid parent;
+
+ GtkCheckButton *all_user_check;
+ GtkCheckButton *auto_connect_check;
+ GtkLabel *dns4_heading_label;
+ GtkLabel *dns4_label;
+ GtkLabel *dns6_heading_label;
+ GtkLabel *dns6_label;
+ GtkButton *forget_button;
+ GtkLabel *freq_heading_label;
+ GtkLabel *freq_label;
+ GtkLabel *ipv4_heading_label;
+ GtkLabel *ipv4_label;
+ GtkLabel *ipv6_heading_label;
+ GtkLabel *ipv6_label;
+ GtkLabel *last_used_heading_label;
+ GtkLabel *last_used_label;
+ GtkLabel *mac_heading_label;
+ GtkLabel *mac_label;
+ GtkCheckButton *restrict_data_check;
+ GtkBox *restrict_data_check_container;
+ GtkLabel *route_heading_label;
+ GtkLabel *route_label;
+ GtkLabel *security_heading_label;
+ GtkLabel *security_label;
+ GtkLabel *speed_heading_label;
+ GtkLabel *speed_label;
+ GtkLabel *strength_heading_label;
+ GtkLabel *strength_label;
+
+ NMConnection *connection;
+ NMDevice *device;
+ NMAccessPoint *ap;
+ NetConnectionEditor *editor;
+};
+
+static void ce_page_iface_init (CEPageInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (CEPageDetails, ce_page_details, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (ce_page_get_type (), ce_page_iface_init))
+
+static void
+forget_cb (CEPageDetails *self)
+{
+ net_connection_editor_forget (self->editor);
+}
+
+static gchar *
+get_ap_security_string (NMAccessPoint *ap)
+{
+ NM80211ApSecurityFlags wpa_flags, rsn_flags;
+ NM80211ApFlags flags;
+ GString *str;
+
+ flags = nm_access_point_get_flags (ap);
+ wpa_flags = nm_access_point_get_wpa_flags (ap);
+ rsn_flags = nm_access_point_get_rsn_flags (ap);
+
+ str = g_string_new ("");
+ if ((flags & NM_802_11_AP_FLAGS_PRIVACY) &&
+ (wpa_flags == NM_802_11_AP_SEC_NONE) &&
+ (rsn_flags == NM_802_11_AP_SEC_NONE)) {
+ /* TRANSLATORS: this WEP WiFi security */
+ g_string_append_printf (str, "%s, ", _("WEP"));
+ }
+ if (wpa_flags != NM_802_11_AP_SEC_NONE) {
+ /* TRANSLATORS: this WPA WiFi security */
+ g_string_append_printf (str, "%s, ", _("WPA"));
+ }
+ if (rsn_flags != NM_802_11_AP_SEC_NONE) {
+#if NM_CHECK_VERSION(1,20,6)
+ if (rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_SAE) {
+ /* TRANSLATORS: this WPA3 WiFi security */
+ g_string_append_printf (str, "%s, ", _("WPA3"));
+ }
+#if NM_CHECK_VERSION(1,24,0)
+ else if (rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_OWE) {
+ /* TRANSLATORS: this Enhanced Open WiFi security */
+ g_string_append_printf (str, "%s, ", _("Enhanced Open"));
+ }
+#endif
+#if NM_CHECK_VERSION(1,26,0)
+ else if (rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_OWE_TM) {
+ /* Connected to open OWE-TM network. */
+ }
+#endif
+ else
+#endif
+ {
+ /* TRANSLATORS: this WPA WiFi security */
+ g_string_append_printf (str, "%s, ", _("WPA2"));
+ }
+ }
+ if ((wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) ||
+ (rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) {
+ /* TRANSLATORS: this Enterprise WiFi security */
+ g_string_append_printf (str, "%s, ", _("Enterprise"));
+ }
+ if (str->len > 0)
+ g_string_set_size (str, str->len - 2);
+ else {
+ g_string_append (str, C_("Wifi security", "None"));
+ }
+ return g_string_free (str, FALSE);
+}
+
+static void
+update_last_used (CEPageDetails *self, NMConnection *connection)
+{
+ g_autofree gchar *last_used = NULL;
+ g_autoptr(GDateTime) now = NULL;
+ g_autoptr(GDateTime) then = NULL;
+ gint days;
+ GTimeSpan diff;
+ guint64 timestamp;
+ NMSettingConnection *s_con;
+
+ s_con = nm_connection_get_setting_connection (connection);
+ if (s_con == NULL)
+ goto out;
+ timestamp = nm_setting_connection_get_timestamp (s_con);
+ if (timestamp == 0) {
+ last_used = g_strdup (_("Never"));
+ goto out;
+ }
+
+ /* calculate the amount of time that has elapsed */
+ now = g_date_time_new_now_utc ();
+ then = g_date_time_new_from_unix_utc (timestamp);
+
+ diff = g_date_time_difference (now, then);
+ days = diff / G_TIME_SPAN_DAY;
+ if (days == 0)
+ last_used = g_strdup (_("Today"));
+ else if (days == 1)
+ last_used = g_strdup (_("Yesterday"));
+ else
+ last_used = g_strdup_printf (ngettext ("%i day ago", "%i days ago", days), days);
+out:
+ gtk_label_set_label (self->last_used_label, last_used);
+ gtk_widget_set_visible (GTK_WIDGET (self->last_used_heading_label), last_used != NULL);
+ gtk_widget_set_visible (GTK_WIDGET (self->last_used_label), last_used != NULL);
+}
+
+static void
+all_user_changed (CEPageDetails *self)
+{
+ gboolean all_users;
+ NMSettingConnection *sc;
+
+ sc = nm_connection_get_setting_connection (self->connection);
+ all_users = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->all_user_check));
+
+ g_object_set (sc, "permissions", NULL, NULL);
+ if (!all_users)
+ nm_setting_connection_add_permission (sc, "user", g_get_user_name (), NULL);
+}
+
+static void
+restrict_data_changed (CEPageDetails *self)
+{
+ NMSettingConnection *s_con;
+ NMMetered metered;
+
+ s_con = nm_connection_get_setting_connection (self->connection);
+
+ if (gtk_check_button_get_active (GTK_CHECK_BUTTON (self->restrict_data_check)))
+ metered = NM_METERED_YES;
+ else
+ metered = NM_METERED_NO;
+
+ g_object_set (s_con, "metered", metered, NULL);
+}
+
+static void
+update_restrict_data (CEPageDetails *self)
+{
+ NMSettingConnection *s_con;
+ NMMetered metered;
+ const gchar *type;
+
+ s_con = nm_connection_get_setting_connection (self->connection);
+
+ if (s_con == NULL)
+ return;
+
+ /* Disable for VPN; NetworkManager does not implement that yet (see
+ * bug https://bugzilla.gnome.org/show_bug.cgi?id=792618) */
+ type = nm_setting_connection_get_connection_type (s_con);
+ if (g_str_equal (type, NM_SETTING_VPN_SETTING_NAME))
+ return;
+
+ metered = nm_setting_connection_get_metered (s_con);
+
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->restrict_data_check),
+ metered == NM_METERED_YES || metered == NM_METERED_GUESS_YES);
+ gtk_widget_show (GTK_WIDGET (self->restrict_data_check_container));
+
+ g_signal_connect_object (self->restrict_data_check, "notify::active", G_CALLBACK (restrict_data_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->restrict_data_check, "notify::active", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+}
+
+static void
+connect_details_page (CEPageDetails *self)
+{
+ NMSettingConnection *sc;
+ guint speed;
+ NMDeviceWifiCapabilities wifi_caps;
+ guint frequency;
+ guint strength;
+ NMDeviceState state;
+ NMAccessPoint *active_ap;
+ g_autofree gchar *speed_label = NULL;
+ const gchar *type;
+ const gchar *hw_address = NULL;
+ g_autofree gchar *security_string = NULL;
+ g_autofree gchar *freq_string = NULL;
+ const gchar *strength_label;
+ gboolean device_is_active;
+ NMIPConfig *ipv4_config = NULL, *ipv6_config = NULL;
+ gboolean have_ipv4_address = FALSE, have_ipv6_address = FALSE;
+ gboolean have_dns4 = FALSE, have_dns6 = FALSE;
+ const gchar *route4_text = NULL, *route6_text = NULL;
+
+ sc = nm_connection_get_setting_connection (self->connection);
+ type = nm_setting_connection_get_connection_type (sc);
+
+ if (NM_IS_DEVICE_WIFI (self->device))
+ active_ap = nm_device_wifi_get_active_access_point (NM_DEVICE_WIFI (self->device));
+ else
+ active_ap = NULL;
+ frequency = active_ap ? nm_access_point_get_frequency (active_ap) : 0;
+
+ state = self->device ? nm_device_get_state (self->device) : NM_DEVICE_STATE_DISCONNECTED;
+
+ device_is_active = FALSE;
+ speed = 0;
+ wifi_caps = 0;
+ if (active_ap && self->ap == active_ap && state != NM_DEVICE_STATE_UNAVAILABLE) {
+ device_is_active = TRUE;
+ if (NM_IS_DEVICE_WIFI (self->device)) {
+ speed = nm_device_wifi_get_bitrate (NM_DEVICE_WIFI (self->device)) / 1000;
+ wifi_caps = nm_device_wifi_get_capabilities (NM_DEVICE_WIFI (self->device));
+ }
+ } else if (self->device) {
+ NMActiveConnection *ac;
+ const gchar *p1, *p2;
+
+ ac = nm_device_get_active_connection (self->device);
+ p1 = ac ? nm_active_connection_get_uuid (ac) : NULL;
+ p2 = nm_connection_get_uuid (self->connection);
+ if (g_strcmp0 (p1, p2) == 0) {
+ device_is_active = TRUE;
+ if (NM_IS_DEVICE_WIFI (self->device)) {
+ speed = nm_device_wifi_get_bitrate (NM_DEVICE_WIFI (self->device)) / 1000;
+ wifi_caps = nm_device_wifi_get_capabilities (NM_DEVICE_WIFI (self->device));
+ } else if (NM_IS_DEVICE_ETHERNET (self->device))
+ speed = nm_device_ethernet_get_speed (NM_DEVICE_ETHERNET (self->device));
+ }
+ }
+
+ if (speed > 0 && frequency > 0)
+ speed_label = g_strdup_printf (_("%d Mb/s (%1.1f GHz)"), speed, (float) (frequency) / 1000.0);
+ else if (speed > 0)
+ speed_label = g_strdup_printf (_("%d Mb/s"), speed);
+ gtk_label_set_label (self->speed_label, speed_label);
+ gtk_widget_set_visible (GTK_WIDGET (self->speed_heading_label), speed_label != NULL);
+ gtk_widget_set_visible (GTK_WIDGET (self->speed_label), speed_label != NULL);
+
+ if (self->device)
+ hw_address = nm_device_get_hw_address (self->device);
+
+ gtk_label_set_label (self->mac_label, hw_address);
+ gtk_widget_set_visible (GTK_WIDGET (self->mac_heading_label), hw_address != NULL);
+ gtk_widget_set_visible (GTK_WIDGET (self->mac_label), hw_address != NULL);
+
+ if (wifi_caps & NM_WIFI_DEVICE_CAP_FREQ_VALID) {
+ if (wifi_caps & NM_WIFI_DEVICE_CAP_FREQ_2GHZ &&
+ wifi_caps & NM_WIFI_DEVICE_CAP_FREQ_5GHZ)
+ freq_string = g_strdup (_("2.4 GHz / 5 GHz"));
+ else if (wifi_caps & NM_WIFI_DEVICE_CAP_FREQ_2GHZ)
+ freq_string = g_strdup (_("2.4 GHz"));
+ else if (wifi_caps & NM_WIFI_DEVICE_CAP_FREQ_5GHZ)
+ freq_string = g_strdup (_("5 GHz"));
+ }
+
+ gtk_label_set_label (self->freq_label, freq_string);
+ gtk_widget_set_visible (GTK_WIDGET (self->freq_heading_label), freq_string != NULL);
+ gtk_widget_set_visible (GTK_WIDGET (self->freq_label), freq_string != NULL);
+
+ if (device_is_active && active_ap)
+ security_string = get_ap_security_string (active_ap);
+ gtk_label_set_label (self->security_label, security_string);
+ gtk_widget_set_visible (GTK_WIDGET (self->security_heading_label), security_string != NULL);
+ gtk_widget_set_visible (GTK_WIDGET (self->security_label), security_string != NULL);
+
+ strength = 0;
+ if (self->ap != NULL)
+ strength = nm_access_point_get_strength (self->ap);
+
+ if (strength <= 0)
+ strength_label = NULL;
+ else if (strength < 20)
+ strength_label = C_("Signal strength", "None");
+ else if (strength < 40)
+ strength_label = C_("Signal strength", "Weak");
+ else if (strength < 50)
+ strength_label = C_("Signal strength", "Ok");
+ else if (strength < 80)
+ strength_label = C_("Signal strength", "Good");
+ else
+ strength_label = C_("Signal strength", "Excellent");
+ gtk_label_set_label (self->strength_label, strength_label);
+ gtk_widget_set_visible (GTK_WIDGET (self->strength_heading_label), strength_label != NULL);
+ gtk_widget_set_visible (GTK_WIDGET (self->strength_label), strength_label != NULL);
+
+ if (device_is_active && self->device != NULL) {
+ ipv4_config = nm_device_get_ip4_config (self->device);
+ ipv6_config = nm_device_get_ip6_config (self->device);
+ }
+
+ if (ipv4_config != NULL) {
+ GPtrArray *addresses;
+ const gchar *ipv4_text = NULL;
+ g_autofree gchar *ip4_dns = NULL;
+
+ addresses = nm_ip_config_get_addresses (ipv4_config);
+ if (addresses->len > 0)
+ ipv4_text = nm_ip_address_get_address (g_ptr_array_index (addresses, 0));
+ gtk_label_set_label (self->ipv4_label, ipv4_text);
+ gtk_widget_set_visible (GTK_WIDGET (self->ipv4_heading_label), ipv4_text != NULL);
+ gtk_widget_set_visible (GTK_WIDGET (self->ipv4_label), ipv4_text != NULL);
+ have_ipv4_address = ipv4_text != NULL;
+
+ ip4_dns = g_strjoinv (" ", (char **) nm_ip_config_get_nameservers (ipv4_config));
+ if (!*ip4_dns)
+ ip4_dns = NULL;
+ gtk_label_set_label (self->dns4_label, ip4_dns);
+ gtk_widget_set_visible (GTK_WIDGET (self->dns4_heading_label), ip4_dns != NULL);
+ gtk_widget_set_visible (GTK_WIDGET (self->dns4_label), ip4_dns != NULL);
+ have_dns4 = ip4_dns != NULL;
+
+ route4_text = nm_ip_config_get_gateway (ipv4_config);
+ } else {
+ gtk_widget_hide (GTK_WIDGET (self->ipv4_heading_label));
+ gtk_widget_hide (GTK_WIDGET (self->ipv4_label));
+ gtk_widget_hide (GTK_WIDGET (self->dns4_heading_label));
+ gtk_widget_hide (GTK_WIDGET (self->dns4_label));
+ }
+
+ if (ipv6_config != NULL) {
+ g_autofree gchar *ipv6_text = NULL;
+ g_autofree gchar *ip6_dns = NULL;
+
+ ipv6_text = net_device_get_ip6_addresses (ipv6_config);
+ gtk_label_set_label (self->ipv6_label, ipv6_text);
+ gtk_widget_set_visible (GTK_WIDGET (self->ipv6_heading_label), ipv6_text != NULL);
+ gtk_widget_set_valign (GTK_WIDGET (self->ipv6_heading_label), GTK_ALIGN_START);
+ gtk_widget_set_visible (GTK_WIDGET (self->ipv6_label), ipv6_text != NULL);
+ have_ipv6_address = ipv6_text != NULL;
+
+ ip6_dns = g_strjoinv (" ", (char **) nm_ip_config_get_nameservers (ipv6_config));
+ if (!*ip6_dns)
+ ip6_dns = NULL;
+ gtk_label_set_label (self->dns6_label, ip6_dns);
+ gtk_widget_set_visible (GTK_WIDGET (self->dns6_heading_label), ip6_dns != NULL);
+ gtk_widget_set_visible (GTK_WIDGET (self->dns6_label), ip6_dns != NULL);
+ have_dns6 = ip6_dns != NULL;
+
+ route6_text = nm_ip_config_get_gateway (ipv6_config);
+ } else {
+ gtk_widget_hide (GTK_WIDGET (self->ipv6_heading_label));
+ gtk_widget_hide (GTK_WIDGET (self->ipv6_label));
+ gtk_widget_hide (GTK_WIDGET (self->dns6_heading_label));
+ gtk_widget_hide (GTK_WIDGET (self->dns6_label));
+ }
+
+ if (have_ipv4_address && have_ipv6_address) {
+ gtk_label_set_label (self->ipv4_heading_label, _("IPv4 Address"));
+ gtk_label_set_label (self->ipv6_heading_label, _("IPv6 Address"));
+ } else {
+ gtk_label_set_label (self->ipv4_heading_label, _("IP Address"));
+ gtk_label_set_label (self->ipv6_heading_label, _("IP Address"));
+ }
+
+ if (have_dns4 && have_dns6) {
+ gtk_label_set_label (self->dns4_heading_label, _("DNS4"));
+ gtk_label_set_label (self->dns6_heading_label, _("DNS6"));
+ } else {
+ gtk_label_set_label (self->dns4_heading_label, _("DNS"));
+ gtk_label_set_label (self->dns6_heading_label, _("DNS"));
+ }
+
+ if (route4_text != NULL || route6_text != NULL) {
+ g_autofree const gchar *routes_text = NULL;
+
+ if (route4_text == NULL) {
+ routes_text = g_strdup (route6_text);
+ } else if (route6_text == NULL) {
+ routes_text = g_strdup (route4_text);
+ } else {
+ routes_text = g_strjoin ("\n", route4_text, route6_text, NULL);
+ }
+ gtk_label_set_label (self->route_label, routes_text);
+ gtk_widget_set_visible (GTK_WIDGET (self->route_heading_label), routes_text != NULL);
+ gtk_widget_set_valign (GTK_WIDGET (self->route_heading_label), GTK_ALIGN_START);
+ gtk_widget_set_visible (GTK_WIDGET (self->route_label), routes_text != NULL);
+ } else {
+ gtk_widget_hide (GTK_WIDGET (self->route_heading_label));
+ gtk_widget_hide (GTK_WIDGET (self->route_label));
+ }
+
+ if (!device_is_active && self->connection)
+ update_last_used (self, self->connection);
+ else {
+ gtk_widget_set_visible (GTK_WIDGET (self->last_used_heading_label), FALSE);
+ gtk_widget_set_visible (GTK_WIDGET (self->last_used_label), FALSE);
+ }
+
+ /* Auto connect check */
+ if (g_str_equal (type, NM_SETTING_VPN_SETTING_NAME)) {
+ gtk_widget_hide (GTK_WIDGET (self->auto_connect_check));
+ } else {
+ g_object_bind_property (sc, "autoconnect",
+ self->auto_connect_check, "active",
+ G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+ g_signal_connect_object (self->auto_connect_check, "toggled", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+ }
+
+ /* All users check */
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->all_user_check),
+ nm_setting_connection_get_num_permissions (sc) == 0);
+ g_signal_connect_object (self->all_user_check, "toggled", G_CALLBACK (all_user_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->all_user_check, "toggled", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+
+ /* Restrict Data check */
+ update_restrict_data (self);
+
+ /* Forget button */
+ g_signal_connect_object (self->forget_button, "clicked", G_CALLBACK (forget_cb), self, G_CONNECT_SWAPPED);
+
+ if (g_str_equal (type, NM_SETTING_WIRELESS_SETTING_NAME))
+ gtk_button_set_label (self->forget_button, _("Forget Connection"));
+ else if (g_str_equal (type, NM_SETTING_WIRED_SETTING_NAME))
+ gtk_button_set_label (self->forget_button, _("Remove Connection Profile"));
+ else if (g_str_equal (type, NM_SETTING_VPN_SETTING_NAME))
+ gtk_button_set_label (self->forget_button, _("Remove VPN"));
+ else
+ gtk_widget_hide (GTK_WIDGET (self->forget_button));
+}
+
+static void
+ce_page_details_dispose (GObject *object)
+{
+ CEPageDetails *self = CE_PAGE_DETAILS (object);
+
+ g_clear_object (&self->connection);
+
+ G_OBJECT_CLASS (ce_page_details_parent_class)->dispose (object);
+}
+
+static const gchar *
+ce_page_details_get_title (CEPage *page)
+{
+ return _("Details");
+}
+
+static void
+ce_page_details_init (CEPageDetails *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+ce_page_details_class_init (CEPageDetailsClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = ce_page_details_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/details-page.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, all_user_check);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, auto_connect_check);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, dns4_heading_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, dns4_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, dns6_heading_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, dns6_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, forget_button);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, freq_heading_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, freq_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, ipv4_heading_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, ipv4_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, ipv6_heading_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, ipv6_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, last_used_heading_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, last_used_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, mac_heading_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, mac_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, restrict_data_check);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, restrict_data_check_container);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, route_heading_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, route_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, security_heading_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, security_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, speed_heading_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, speed_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, strength_heading_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageDetails, strength_label);
+}
+
+static void
+ce_page_iface_init (CEPageInterface *iface)
+{
+ iface->get_title = ce_page_details_get_title;
+}
+
+CEPageDetails *
+ce_page_details_new (NMConnection *connection,
+ NMDevice *device,
+ NMAccessPoint *ap,
+ NetConnectionEditor *editor)
+{
+ CEPageDetails *self;
+
+ self = CE_PAGE_DETAILS (g_object_new (ce_page_details_get_type (), NULL));
+
+ self->connection = g_object_ref (connection);
+ self->editor = editor;
+ self->device = device;
+ self->ap = ap;
+
+ connect_details_page (self);
+
+ return self;
+}
diff --git a/panels/network/connection-editor/ce-page-details.h b/panels/network/connection-editor/ce-page-details.h
new file mode 100644
index 0000000..4fd660c
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-details.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+#include "net-connection-editor.h"
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (CEPageDetails, ce_page_details, CE, PAGE_DETAILS, GtkGrid)
+
+CEPageDetails *ce_page_details_new (NMConnection *connection,
+ NMDevice *device,
+ NMAccessPoint *ap,
+ NetConnectionEditor *editor);
+
+G_END_DECLS
diff --git a/panels/network/connection-editor/ce-page-ethernet.c b/panels/network/connection-editor/ce-page-ethernet.c
new file mode 100644
index 0000000..79c1b7d
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-ethernet.c
@@ -0,0 +1,224 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <net/if_arp.h>
+#include <NetworkManager.h>
+
+#include "ce-page.h"
+#include "ce-page-ethernet.h"
+#include "ui-helpers.h"
+
+struct _CEPageEthernet
+{
+ GtkGrid parent;
+
+ GtkComboBoxText *cloned_mac_combo;
+ GtkComboBoxText *mac_combo;
+ GtkSpinButton *mtu_spin;
+ GtkWidget *mtu_label;
+ GtkEntry *name_entry;
+
+ NMClient *client;
+ NMSettingConnection *setting_connection;
+ NMSettingWired *setting_wired;
+};
+
+static void ce_page_iface_init (CEPageInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (CEPageEthernet, ce_page_ethernet, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (ce_page_get_type (), ce_page_iface_init))
+
+static void
+mtu_changed (CEPageEthernet *self)
+{
+ if (gtk_spin_button_get_value_as_int (self->mtu_spin) == 0)
+ gtk_widget_hide (self->mtu_label);
+ else
+ gtk_widget_show (self->mtu_label);
+}
+
+static void
+mtu_output_cb (CEPageEthernet *self)
+{
+ gint defvalue;
+ gint val;
+ g_autofree gchar *buf = NULL;
+
+ val = gtk_spin_button_get_value_as_int (self->mtu_spin);
+ defvalue = ce_get_property_default (NM_SETTING (self->setting_wired), NM_SETTING_WIRED_MTU);
+ if (val == defvalue)
+ buf = g_strdup (_("automatic"));
+ else
+ buf = g_strdup_printf ("%d", val);
+
+ if (strcmp (buf, gtk_editable_get_text (GTK_EDITABLE (self->mtu_spin))))
+ gtk_editable_set_text (GTK_EDITABLE (self->mtu_spin), buf);
+}
+
+static void
+connect_ethernet_page (CEPageEthernet *self)
+{
+ NMSettingWired *setting = self->setting_wired;
+ char **mac_list;
+ const char *s_mac_str;
+ const gchar *name;
+ const gchar *cloned_mac;
+
+ name = nm_setting_connection_get_id (self->setting_connection);
+ gtk_editable_set_text (GTK_EDITABLE (self->name_entry), name);
+
+ /* Device MAC address */
+ mac_list = ce_page_get_mac_list (self->client, NM_TYPE_DEVICE_ETHERNET,
+ NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS);
+ s_mac_str = nm_setting_wired_get_mac_address (setting);
+ ce_page_setup_mac_combo (self->mac_combo, s_mac_str, mac_list);
+ g_strfreev (mac_list);
+ g_signal_connect_object (self->mac_combo, "changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+
+ /* Cloned MAC address */
+ cloned_mac = nm_setting_wired_get_cloned_mac_address (setting);
+ ce_page_setup_cloned_mac_combo (self->cloned_mac_combo, cloned_mac);
+ g_signal_connect_object (self->cloned_mac_combo, "changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+
+ /* MTU */
+ g_signal_connect_object (self->mtu_spin, "output", G_CALLBACK (mtu_output_cb), self, G_CONNECT_SWAPPED);
+ gtk_spin_button_set_value (self->mtu_spin, (gdouble) nm_setting_wired_get_mtu (setting));
+ g_signal_connect_object (self->mtu_spin, "value-changed", G_CALLBACK (mtu_changed), self, G_CONNECT_SWAPPED);
+ mtu_changed (self);
+
+ g_signal_connect_object (self->name_entry, "changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->mtu_spin, "value-changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+}
+
+static void
+ui_to_setting (CEPageEthernet *self)
+{
+ g_autofree gchar *device_mac = NULL;
+ g_autofree gchar *cloned_mac = NULL;
+ const gchar *text;
+ GtkWidget *entry;
+
+ entry = gtk_combo_box_get_child (GTK_COMBO_BOX (self->mac_combo));
+ if (entry) {
+ text = gtk_editable_get_text (GTK_EDITABLE (entry));
+ device_mac = ce_page_trim_address (text);
+ }
+
+ cloned_mac = ce_page_cloned_mac_get (self->cloned_mac_combo);
+
+ g_object_set (self->setting_wired,
+ NM_SETTING_WIRED_MAC_ADDRESS, device_mac,
+ NM_SETTING_WIRED_CLONED_MAC_ADDRESS, cloned_mac,
+ NM_SETTING_WIRED_MTU, (guint32) gtk_spin_button_get_value_as_int (self->mtu_spin),
+ NULL);
+
+ g_object_set (self->setting_connection,
+ NM_SETTING_CONNECTION_ID, gtk_editable_get_text (GTK_EDITABLE (self->name_entry)),
+ NULL);
+}
+
+static const gchar *
+ce_page_ethernet_get_title (CEPage *page)
+{
+ return _("Identity");
+}
+
+static gboolean
+ce_page_ethernet_validate (CEPage *page,
+ NMConnection *connection,
+ GError **error)
+{
+ CEPageEthernet *self = CE_PAGE_ETHERNET (page);
+ GtkWidget *entry;
+ gboolean ret = TRUE;
+
+ entry = gtk_combo_box_get_child (GTK_COMBO_BOX (self->mac_combo));
+ if (entry) {
+ if (!ce_page_address_is_valid (gtk_editable_get_text (GTK_EDITABLE (entry)))) {
+ widget_set_error (entry);
+ ret = FALSE;
+ } else {
+ widget_unset_error (entry);
+ }
+ }
+
+ if (!ce_page_cloned_mac_combo_valid (self->cloned_mac_combo)) {
+ widget_set_error (gtk_combo_box_get_child (GTK_COMBO_BOX (self->cloned_mac_combo)));
+ ret = FALSE;
+ } else {
+ widget_unset_error (gtk_combo_box_get_child (GTK_COMBO_BOX (self->cloned_mac_combo)));
+ }
+
+ if (!ret)
+ return ret;
+
+ ui_to_setting (self);
+
+ return nm_setting_verify (NM_SETTING (self->setting_connection), NULL, error) &&
+ nm_setting_verify (NM_SETTING (self->setting_wired), NULL, error);
+}
+
+static void
+ce_page_ethernet_init (CEPageEthernet *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+ce_page_ethernet_class_init (CEPageEthernetClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/ethernet-page.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CEPageEthernet, cloned_mac_combo);
+ gtk_widget_class_bind_template_child (widget_class, CEPageEthernet, mac_combo);
+ gtk_widget_class_bind_template_child (widget_class, CEPageEthernet, mtu_spin);
+ gtk_widget_class_bind_template_child (widget_class, CEPageEthernet, mtu_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageEthernet, name_entry);
+}
+
+static void
+ce_page_iface_init (CEPageInterface *iface)
+{
+ iface->get_title = ce_page_ethernet_get_title;
+ iface->validate = ce_page_ethernet_validate;
+}
+
+CEPageEthernet *
+ce_page_ethernet_new (NMConnection *connection,
+ NMClient *client)
+{
+ CEPageEthernet *self;
+
+ self = CE_PAGE_ETHERNET (g_object_new (ce_page_ethernet_get_type (), NULL));
+
+ self->client = client;
+ self->setting_connection = nm_connection_get_setting_connection (connection);
+ self->setting_wired = nm_connection_get_setting_wired (connection);
+
+ connect_ethernet_page (self);
+
+ return self;
+}
diff --git a/panels/network/connection-editor/ce-page-ethernet.h b/panels/network/connection-editor/ce-page-ethernet.h
new file mode 100644
index 0000000..5fce19f
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-ethernet.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (CEPageEthernet, ce_page_ethernet, CE, PAGE_ETHERNET, GtkGrid)
+
+CEPageEthernet *ce_page_ethernet_new (NMConnection *connection,
+ NMClient *client);
+
+G_END_DECLS
diff --git a/panels/network/connection-editor/ce-page-ip4.c b/panels/network/connection-editor/ce-page-ip4.c
new file mode 100644
index 0000000..c3f0864
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-ip4.c
@@ -0,0 +1,846 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <glib/gi18n.h>
+#include <NetworkManager.h>
+
+#include "ce-ip-address-entry.h"
+#include "ce-netmask-entry.h"
+#include "ce-page.h"
+#include "ce-page-ip4.h"
+#include "ui-helpers.h"
+
+static void ensure_empty_address_row (CEPageIP4 *self);
+static void ensure_empty_routes_row (CEPageIP4 *self);
+
+struct _CEPageIP4
+{
+ AdwBin parent;
+
+ GtkLabel *address_address_label;
+ GtkBox *address_box;
+ GtkLabel *address_gateway_label;
+ GtkLabel *address_netmask_label;
+ GtkSizeGroup *address_sizegroup;
+ GtkSwitch *auto_dns_switch;
+ GtkSwitch *auto_routes_switch;
+ GtkCheckButton *automatic_radio;
+ GtkBox *content_box;
+ GtkCheckButton *disabled_radio;
+ GtkEntry *dns_entry;
+ GtkCheckButton *local_radio;
+ GtkGrid *main_box;
+ GtkCheckButton *manual_radio;
+ GtkCheckButton *never_default_check;
+ GtkLabel *routes_address_label;
+ GtkBox *routes_box;
+ GtkLabel *routes_gateway_label;
+ GtkLabel *routes_metric_label;
+ GtkSizeGroup *routes_metric_sizegroup;
+ GtkLabel *routes_netmask_label;
+ GtkSizeGroup *routes_sizegroup;
+ GtkCheckButton *shared_radio;
+
+ NMSettingIPConfig *setting;
+
+ GtkWidget *address_list;
+ GtkWidget *routes_list;
+};
+
+static void ce_page_iface_init (CEPageInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (CEPageIP4, ce_page_ip4, ADW_TYPE_BIN,
+ G_IMPLEMENT_INTERFACE (ce_page_get_type (), ce_page_iface_init))
+
+enum {
+ METHOD_COL_NAME,
+ METHOD_COL_METHOD
+};
+
+enum {
+ IP4_METHOD_AUTO,
+ IP4_METHOD_MANUAL,
+ IP4_METHOD_LINK_LOCAL,
+ IP4_METHOD_SHARED,
+ IP4_METHOD_DISABLED
+};
+
+static void
+method_changed (CEPageIP4 *self)
+{
+ gboolean addr_enabled;
+ gboolean dns_enabled;
+ gboolean routes_enabled;
+
+ if (gtk_check_button_get_active (GTK_CHECK_BUTTON (self->disabled_radio)) ||
+ gtk_check_button_get_active (GTK_CHECK_BUTTON (self->shared_radio))) {
+ addr_enabled = FALSE;
+ dns_enabled = FALSE;
+ routes_enabled = FALSE;
+ } else {
+ addr_enabled = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->manual_radio));
+ dns_enabled = !gtk_check_button_get_active (GTK_CHECK_BUTTON (self->local_radio));
+ routes_enabled = !gtk_check_button_get_active (GTK_CHECK_BUTTON (self->local_radio));
+ }
+
+ gtk_widget_set_visible (GTK_WIDGET (self->address_box), addr_enabled);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->dns_entry), dns_enabled);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->routes_list), routes_enabled);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->never_default_check), routes_enabled);
+
+ ce_page_changed (CE_PAGE (self));
+}
+
+static void
+update_row_sensitivity (CEPageIP4 *self, GtkWidget *list)
+{
+ GtkWidget *child;
+ gint rows = 0, i = 0;
+
+ for (child = gtk_widget_get_first_child (GTK_WIDGET (list));
+ child;
+ child = gtk_widget_get_next_sibling (child)) {
+ GtkWidget *button;
+
+ button = GTK_WIDGET (g_object_get_data (G_OBJECT (child), "delete-button"));
+ if (button != NULL)
+ rows++;
+ }
+ for (child = gtk_widget_get_first_child (GTK_WIDGET (list));
+ child;
+ child = gtk_widget_get_next_sibling (child)) {
+ GtkWidget *button;
+
+ button = GTK_WIDGET (g_object_get_data (G_OBJECT (child), "delete-button"));
+ if (button != NULL)
+ gtk_widget_set_sensitive (button, rows > 1 && ++i < rows);
+ }
+}
+
+static void
+update_row_gateway_sensitivity (CEPageIP4 *self)
+{
+ GtkWidget *child;
+ gint rows = 0;
+
+ for (child = gtk_widget_get_first_child (self->address_list);
+ child;
+ child = gtk_widget_get_next_sibling (child)) {
+ GtkWidget *entry;
+
+ entry = GTK_WIDGET (g_object_get_data (G_OBJECT (child), "gateway"));
+
+ gtk_widget_set_sensitive (entry, (rows == 0));
+
+ rows++;
+ }
+}
+
+static void
+remove_row (CEPageIP4 *self, GtkButton *button)
+{
+ GtkWidget *list;
+ GtkWidget *row;
+ GtkWidget *row_box;
+
+ row_box = gtk_widget_get_parent (GTK_WIDGET (button));
+ row = gtk_widget_get_parent (row_box);
+ list = gtk_widget_get_parent (row);
+
+ gtk_list_box_remove (GTK_LIST_BOX (list), row);
+
+ ce_page_changed (CE_PAGE (self));
+
+ update_row_sensitivity (self, list);
+ if (list == self->address_list)
+ update_row_gateway_sensitivity (self);
+}
+
+static gboolean
+validate_row (GtkWidget *row)
+{
+ GtkWidget *child;
+ GtkWidget *box;
+ gboolean valid;
+
+ valid = FALSE;
+ box = gtk_list_box_row_get_child (GTK_LIST_BOX_ROW (row));
+
+ for (child = gtk_widget_get_first_child (box);
+ child;
+ child = gtk_widget_get_next_sibling (child)) {
+ if (!GTK_IS_ENTRY (child))
+ continue;
+
+ valid = valid || gtk_entry_get_text_length (GTK_ENTRY (child)) > 0;
+ }
+
+ return valid;
+}
+
+static void
+add_address_row (CEPageIP4 *self,
+ const gchar *address,
+ const gchar *network,
+ const gchar *gateway)
+{
+ GtkWidget *row;
+ GtkWidget *row_box;
+ GtkWidget *widget;
+ GtkWidget *delete_button;
+
+ row = gtk_list_box_row_new ();
+ gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), FALSE);
+
+ row_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_widget_add_css_class (row_box, "linked");
+
+ widget = GTK_WIDGET (ce_ip_address_entry_new (AF_INET));
+ g_signal_connect_object (widget, "changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (widget, "activate", G_CALLBACK (ensure_empty_address_row), self, G_CONNECT_SWAPPED);
+ g_object_set_data (G_OBJECT (row), "address", widget);
+ gtk_editable_set_text (GTK_EDITABLE (widget), address);
+ gtk_editable_set_width_chars (GTK_EDITABLE (widget), 16);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_accessible_update_relation (GTK_ACCESSIBLE (widget),
+ GTK_ACCESSIBLE_RELATION_LABELLED_BY, self->address_address_label, NULL,
+ -1);
+ gtk_box_append (GTK_BOX (row_box), widget);
+
+ widget = GTK_WIDGET (ce_netmask_entry_new ());
+ g_signal_connect_object (widget, "changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (widget, "activate", G_CALLBACK (ensure_empty_address_row), self, G_CONNECT_SWAPPED);
+ g_object_set_data (G_OBJECT (row), "netmask", widget);
+ gtk_editable_set_text (GTK_EDITABLE (widget), network);
+ gtk_editable_set_width_chars (GTK_EDITABLE (widget), 16);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_accessible_update_relation (GTK_ACCESSIBLE (widget),
+ GTK_ACCESSIBLE_RELATION_LABELLED_BY, self->address_netmask_label, NULL,
+ -1);
+ gtk_box_append (GTK_BOX (row_box), widget);
+
+ widget = GTK_WIDGET (ce_ip_address_entry_new (AF_INET));
+ g_signal_connect_object (widget, "changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (widget, "activate", G_CALLBACK (ensure_empty_address_row), self, G_CONNECT_SWAPPED);
+ g_object_set_data (G_OBJECT (row), "gateway", widget);
+ gtk_editable_set_text (GTK_EDITABLE (widget), gateway ? gateway : "");
+ gtk_editable_set_width_chars (GTK_EDITABLE (widget), 16);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_accessible_update_relation (GTK_ACCESSIBLE (widget),
+ GTK_ACCESSIBLE_RELATION_LABELLED_BY, self->address_gateway_label, NULL,
+ -1);
+ gtk_box_append (GTK_BOX (row_box), widget);
+
+ delete_button = gtk_button_new_from_icon_name ("edit-delete-symbolic");
+ gtk_widget_set_sensitive (delete_button, FALSE);
+ g_signal_connect_object (delete_button, "clicked", G_CALLBACK (remove_row), self, G_CONNECT_SWAPPED);
+ gtk_accessible_update_property (GTK_ACCESSIBLE (delete_button),
+ GTK_ACCESSIBLE_PROPERTY_LABEL, _("Delete Address"),
+ -1);
+ gtk_box_append (GTK_BOX (row_box), delete_button);
+ g_object_set_data (G_OBJECT (row), "delete-button", delete_button);
+
+ gtk_size_group_add_widget (self->address_sizegroup, delete_button);
+
+ gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), row_box);
+ gtk_list_box_append (GTK_LIST_BOX (self->address_list), row);
+
+ update_row_gateway_sensitivity (self);
+ update_row_sensitivity (self, self->address_list);
+}
+
+static void
+ensure_empty_address_row (CEPageIP4 *self)
+{
+ GtkWidget *child = gtk_widget_get_last_child (self->address_list);
+
+ /* Add the last, stub row if needed*/
+ if (!child || validate_row (child))
+ add_address_row (self, "", "", "");
+}
+
+static void
+add_address_box (CEPageIP4 *self)
+{
+ GtkWidget *list;
+ gint i;
+
+ self->address_list = list = gtk_list_box_new ();
+ gtk_list_box_set_selection_mode (GTK_LIST_BOX (list), GTK_SELECTION_NONE);
+ gtk_box_append (self->address_box, list);
+
+ for (i = 0; i < nm_setting_ip_config_get_num_addresses (self->setting); i++) {
+ NMIPAddress *addr;
+ struct in_addr tmp_addr;
+ gchar network[INET_ADDRSTRLEN + 1];
+
+ addr = nm_setting_ip_config_get_address (self->setting, i);
+ if (!addr)
+ continue;
+
+ tmp_addr.s_addr = nm_utils_ip4_prefix_to_netmask (nm_ip_address_get_prefix (addr));
+ (void) inet_ntop (AF_INET, &tmp_addr, &network[0], sizeof (network));
+
+ add_address_row (self,
+ nm_ip_address_get_address (addr),
+ network,
+ i == 0 ? nm_setting_ip_config_get_gateway (self->setting) : "");
+ }
+ if (nm_setting_ip_config_get_num_addresses (self->setting) == 0)
+ ensure_empty_address_row (self);
+}
+
+static void
+add_dns_section (CEPageIP4 *self)
+{
+ GString *string;
+ gint i;
+
+ gtk_switch_set_active (self->auto_dns_switch, !nm_setting_ip_config_get_ignore_auto_dns (self->setting));
+ g_signal_connect_object (self->auto_dns_switch, "notify::active", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+
+ string = g_string_new ("");
+
+ for (i = 0; i < nm_setting_ip_config_get_num_dns (self->setting); i++) {
+ const char *address;
+
+ address = nm_setting_ip_config_get_dns (self->setting, i);
+
+ if (i > 0)
+ g_string_append (string, ", ");
+
+ g_string_append (string, address);
+ }
+
+ gtk_editable_set_text (GTK_EDITABLE (self->dns_entry), string->str);
+
+ g_signal_connect_object (self->dns_entry, "notify::text", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+
+ g_string_free (string, TRUE);
+}
+
+static void
+add_route_row (CEPageIP4 *self,
+ const gchar *address,
+ const gchar *netmask,
+ const gchar *gateway,
+ gint metric)
+{
+ GtkWidget *row;
+ GtkWidget *row_box;
+ GtkWidget *widget;
+ GtkWidget *delete_button;
+
+ row = gtk_list_box_row_new ();
+ gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), FALSE);
+
+ row_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_widget_add_css_class (row_box, "linked");
+
+ widget = GTK_WIDGET (ce_ip_address_entry_new (AF_INET));
+ g_signal_connect_object (widget, "changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (widget, "activate", G_CALLBACK (ensure_empty_routes_row), self, G_CONNECT_SWAPPED);
+ g_object_set_data (G_OBJECT (row), "address", widget);
+ gtk_editable_set_text (GTK_EDITABLE (widget), address);
+ gtk_editable_set_width_chars (GTK_EDITABLE (widget), 16);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_accessible_update_relation (GTK_ACCESSIBLE (widget),
+ GTK_ACCESSIBLE_RELATION_LABELLED_BY, self->routes_address_label, NULL,
+ -1);
+ gtk_box_append (GTK_BOX (row_box), widget);
+
+ widget = GTK_WIDGET (ce_netmask_entry_new ());
+ g_signal_connect_object (widget, "changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (widget, "activate", G_CALLBACK (ensure_empty_routes_row), self, G_CONNECT_SWAPPED);
+ g_object_set_data (G_OBJECT (row), "netmask", widget);
+ gtk_editable_set_text (GTK_EDITABLE (widget), netmask);
+ gtk_editable_set_width_chars (GTK_EDITABLE (widget), 16);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_accessible_update_relation (GTK_ACCESSIBLE (widget),
+ GTK_ACCESSIBLE_RELATION_LABELLED_BY, self->routes_netmask_label, NULL,
+ -1);
+ gtk_box_append (GTK_BOX (row_box), widget);
+
+ widget = GTK_WIDGET (ce_ip_address_entry_new (AF_INET));
+ g_signal_connect_object (widget, "changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (widget, "activate", G_CALLBACK (ensure_empty_routes_row), self, G_CONNECT_SWAPPED);
+ g_object_set_data (G_OBJECT (row), "gateway", widget);
+ gtk_editable_set_text (GTK_EDITABLE (widget), gateway ? gateway : "");
+ gtk_editable_set_width_chars (GTK_EDITABLE (widget), 16);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_accessible_update_relation (GTK_ACCESSIBLE (widget),
+ GTK_ACCESSIBLE_RELATION_LABELLED_BY, self->routes_gateway_label, NULL,
+ -1);
+ gtk_box_append (GTK_BOX (row_box), widget);
+
+ widget = gtk_entry_new ();
+ g_signal_connect_object (widget, "changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (widget, "activate", G_CALLBACK (ensure_empty_routes_row), self, G_CONNECT_SWAPPED);
+ g_object_set_data (G_OBJECT (row), "metric", widget);
+ if (metric >= 0) {
+ g_autofree gchar *s = g_strdup_printf ("%d", metric);
+ gtk_editable_set_text (GTK_EDITABLE (widget), s);
+ }
+ gtk_editable_set_width_chars (GTK_EDITABLE (widget), 5);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_accessible_update_relation (GTK_ACCESSIBLE (widget),
+ GTK_ACCESSIBLE_RELATION_LABELLED_BY, self->routes_metric_label, NULL,
+ -1);
+ gtk_box_append (GTK_BOX (row_box), widget);
+
+ gtk_size_group_add_widget (self->routes_metric_sizegroup, widget);
+
+ delete_button = gtk_button_new_from_icon_name ("edit-delete-symbolic");
+ gtk_widget_set_sensitive (delete_button, FALSE);
+ g_signal_connect_object (delete_button, "clicked", G_CALLBACK (remove_row), self, G_CONNECT_SWAPPED);
+ gtk_accessible_update_property (GTK_ACCESSIBLE (delete_button),
+ GTK_ACCESSIBLE_PROPERTY_LABEL, _("Delete Route"),
+ -1);
+ gtk_widget_set_halign (delete_button, GTK_ALIGN_CENTER);
+ gtk_widget_set_valign (delete_button, GTK_ALIGN_CENTER);
+ gtk_box_append (GTK_BOX (row_box), delete_button);
+ g_object_set_data (G_OBJECT (row), "delete-button", delete_button);
+
+ gtk_size_group_add_widget (self->routes_sizegroup, delete_button);
+
+ gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), row_box);
+ gtk_list_box_append (GTK_LIST_BOX (self->routes_list), row);
+
+ update_row_sensitivity (self, self->routes_list);
+}
+
+static void
+ensure_empty_routes_row (CEPageIP4 *self)
+{
+ GtkWidget *child = gtk_widget_get_last_child (self->routes_list);
+
+ /* Add the last, stub row if needed*/
+ if (!child || validate_row (child))
+ add_route_row (self, "", "", "", -1);
+}
+
+static void
+add_routes_box (CEPageIP4 *self)
+{
+ GtkWidget *list;
+ gint i;
+
+ self->routes_list = list = gtk_list_box_new ();
+ gtk_list_box_set_selection_mode (GTK_LIST_BOX (list), GTK_SELECTION_NONE);
+ gtk_box_append (GTK_BOX (self->routes_box), list);
+ gtk_switch_set_active (self->auto_routes_switch, !nm_setting_ip_config_get_ignore_auto_routes (self->setting));
+ g_signal_connect_object (self->auto_routes_switch, "notify::active", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+
+ for (i = 0; i < nm_setting_ip_config_get_num_routes (self->setting); i++) {
+ NMIPRoute *route;
+ struct in_addr tmp_addr;
+ gchar netmask[INET_ADDRSTRLEN + 1];
+
+ route = nm_setting_ip_config_get_route (self->setting, i);
+ if (!route)
+ continue;
+
+ tmp_addr.s_addr = nm_utils_ip4_prefix_to_netmask (nm_ip_route_get_prefix (route));
+ (void) inet_ntop (AF_INET, &tmp_addr, &netmask[0], sizeof (netmask));
+
+ add_route_row (self,
+ nm_ip_route_get_dest (route),
+ netmask,
+ nm_ip_route_get_next_hop (route),
+ nm_ip_route_get_metric (route));
+ }
+ if (nm_setting_ip_config_get_num_routes (self->setting) == 0)
+ ensure_empty_routes_row (self);
+}
+
+static void
+connect_ip4_page (CEPageIP4 *self)
+{
+ const gchar *str_method;
+ guint method;
+
+ add_address_box (self);
+ add_dns_section (self);
+ add_routes_box (self);
+
+ str_method = nm_setting_ip_config_get_method (self->setting);
+ g_signal_connect_object (self->disabled_radio, "notify::active", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+ g_object_bind_property (self->disabled_radio, "active",
+ self->content_box, "sensitive",
+ G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN);
+
+ g_signal_connect_object (self->shared_radio, "notify::active", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+ g_object_bind_property (self->shared_radio, "active",
+ self->content_box, "sensitive",
+ G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN);
+
+ method = IP4_METHOD_AUTO;
+ if (g_strcmp0 (str_method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) == 0) {
+ method = IP4_METHOD_LINK_LOCAL;
+ } else if (g_strcmp0 (str_method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0) {
+ method = IP4_METHOD_MANUAL;
+ } else if (g_strcmp0 (str_method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0) {
+ method = IP4_METHOD_SHARED;
+ } else if (g_strcmp0 (str_method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0) {
+ method = IP4_METHOD_DISABLED;
+ }
+
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->never_default_check),
+ nm_setting_ip_config_get_never_default (self->setting));
+ g_signal_connect_object (self->never_default_check, "toggled", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self->automatic_radio, "toggled", G_CALLBACK (method_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->local_radio, "toggled", G_CALLBACK (method_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->manual_radio, "toggled", G_CALLBACK (method_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->disabled_radio, "toggled", G_CALLBACK (method_changed), self, G_CONNECT_SWAPPED);
+
+ switch (method) {
+ case IP4_METHOD_AUTO:
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->automatic_radio), TRUE);
+ break;
+ case IP4_METHOD_LINK_LOCAL:
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->local_radio), TRUE);
+ break;
+ case IP4_METHOD_MANUAL:
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->manual_radio), TRUE);
+ break;
+ case IP4_METHOD_SHARED:
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->shared_radio), TRUE);
+ break;
+ case IP4_METHOD_DISABLED:
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->disabled_radio), TRUE);
+ break;
+ default:
+ break;
+ }
+
+ method_changed (self);
+}
+
+static gboolean
+ui_to_setting (CEPageIP4 *self)
+{
+ const gchar *method;
+ gboolean ignore_auto_dns;
+ gboolean ignore_auto_routes;
+ gboolean never_default;
+ GPtrArray *addresses = NULL;
+ GPtrArray *dns_servers = NULL;
+ GPtrArray *routes = NULL;
+ GtkWidget *child;
+ GStrv dns_addresses = NULL;
+ gboolean ret = TRUE;
+ const char *default_gateway = NULL;
+ gboolean add_addresses = FALSE;
+ gboolean add_routes = FALSE;
+ gchar *dns_text = NULL;
+ guint i;
+
+ if (gtk_check_button_get_active (GTK_CHECK_BUTTON (self->disabled_radio)))
+ method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
+ else if (gtk_check_button_get_active (GTK_CHECK_BUTTON (self->automatic_radio)))
+ method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
+ else if (gtk_check_button_get_active (GTK_CHECK_BUTTON (self->local_radio)))
+ method = NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL;
+ else if (gtk_check_button_get_active (GTK_CHECK_BUTTON (self->manual_radio)))
+ method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL;
+ else if (gtk_check_button_get_active (GTK_CHECK_BUTTON (self->shared_radio)))
+ method = NM_SETTING_IP4_CONFIG_METHOD_SHARED;
+
+ addresses = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_address_unref);
+ add_addresses = g_str_equal (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL);
+
+ for (child = gtk_widget_get_first_child (self->address_list);
+ add_addresses && child;
+ child = gtk_widget_get_next_sibling (child)) {
+ GtkWidget *row = child;
+ CEIPAddressEntry *address_entry;
+ CENetmaskEntry *netmask_entry;
+ CEIPAddressEntry *gateway_entry;
+ NMIPAddress *addr;
+
+ address_entry = CE_IP_ADDRESS_ENTRY (g_object_get_data (G_OBJECT (row), "address"));
+ if (!address_entry)
+ continue;
+
+ netmask_entry = CE_NETMASK_ENTRY (g_object_get_data (G_OBJECT (row), "netmask"));
+ gateway_entry = CE_IP_ADDRESS_ENTRY (g_object_get_data (G_OBJECT (row), "gateway"));
+
+ if (ce_ip_address_entry_is_empty (address_entry) && ce_netmask_entry_is_empty (netmask_entry) && ce_ip_address_entry_is_empty (gateway_entry)) {
+ /* ignore empty rows */
+ continue;
+ }
+
+ if (!ce_ip_address_entry_is_valid (address_entry))
+ ret = FALSE;
+
+ if (!ce_netmask_entry_is_valid (netmask_entry))
+ ret = FALSE;
+
+ if (!ce_ip_address_entry_is_valid (gateway_entry)) {
+ ret = FALSE;
+ } else {
+ if (!ce_ip_address_entry_is_empty (gateway_entry)) {
+ g_assert (default_gateway == NULL);
+ default_gateway = gtk_editable_get_text (GTK_EDITABLE (gateway_entry));
+ }
+ }
+
+ if (!ret)
+ continue;
+
+ addr = nm_ip_address_new (AF_INET, gtk_editable_get_text (GTK_EDITABLE (address_entry)), ce_netmask_entry_get_prefix (netmask_entry), NULL);
+ if (addr)
+ g_ptr_array_add (addresses, addr);
+
+ if (!gtk_widget_get_next_sibling (row))
+ ensure_empty_address_row (self);
+ }
+
+ if (addresses->len == 0) {
+ g_ptr_array_free (addresses, TRUE);
+ addresses = NULL;
+ }
+
+ dns_servers = g_ptr_array_new_with_free_func (g_free);
+ dns_text = g_strstrip (g_strdup (gtk_editable_get_text (GTK_EDITABLE (self->dns_entry))));
+ if (g_str_equal (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) ||
+ g_str_equal (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL))
+ dns_addresses = g_strsplit_set (dns_text, ", ", -1);
+ else
+ dns_addresses = NULL;
+
+ for (i = 0; dns_addresses && dns_addresses[i]; i++) {
+ const gchar *text;
+
+ text = dns_addresses[i];
+
+ if (!text || !*text)
+ continue;
+
+ if (!nm_utils_ipaddr_valid (AF_INET, text)) {
+ g_ptr_array_remove_range (dns_servers, 0, dns_servers->len);
+ widget_set_error (GTK_WIDGET (self->dns_entry));
+ ret = FALSE;
+ break;
+ } else {
+ widget_unset_error (GTK_WIDGET (self->dns_entry));
+ g_ptr_array_add (dns_servers, g_strdup (text));
+ }
+ }
+ g_clear_pointer (&dns_addresses, g_strfreev);
+
+ if (dns_servers->len == 0) {
+ g_ptr_array_free (dns_servers, TRUE);
+ dns_servers = NULL;
+ } else {
+ g_ptr_array_add (dns_servers, NULL);
+ }
+
+ routes = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_route_unref);
+ add_routes = g_str_equal (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) ||
+ g_str_equal (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL);
+
+ for (child = gtk_widget_get_first_child (self->routes_list);
+ add_routes && child;
+ child = gtk_widget_get_next_sibling (child)) {
+ GtkWidget *row = child;
+ CEIPAddressEntry *address_entry;
+ CENetmaskEntry *netmask_entry;
+ CEIPAddressEntry *gateway_entry;
+ const gchar *text_metric;
+ gint64 metric;
+ NMIPRoute *route;
+
+ address_entry = CE_IP_ADDRESS_ENTRY (g_object_get_data (G_OBJECT (row), "address"));
+ if (!address_entry)
+ continue;
+
+ netmask_entry = CE_NETMASK_ENTRY (g_object_get_data (G_OBJECT (row), "netmask"));
+ gateway_entry = CE_IP_ADDRESS_ENTRY (g_object_get_data (G_OBJECT (row), "gateway"));
+ text_metric = gtk_editable_get_text (GTK_EDITABLE (g_object_get_data (G_OBJECT (row), "metric")));
+
+ if (ce_ip_address_entry_is_empty (address_entry) && ce_netmask_entry_is_empty (netmask_entry) && ce_ip_address_entry_is_empty (gateway_entry) && !*text_metric) {
+ /* ignore empty rows */
+ continue;
+ }
+
+ if (!ce_ip_address_entry_is_valid (address_entry))
+ ret = FALSE;
+
+ if (!ce_netmask_entry_is_valid (netmask_entry))
+ ret = FALSE;
+
+ if (!ce_ip_address_entry_is_valid (gateway_entry))
+ ret = FALSE;
+
+ metric = -1;
+ if (*text_metric) {
+ errno = 0;
+ metric = g_ascii_strtoull (text_metric, NULL, 10);
+ if (errno || metric < 0 || metric > G_MAXUINT32) {
+ widget_set_error (GTK_WIDGET (g_object_get_data (G_OBJECT (row), "metric")));
+ ret = FALSE;
+ } else {
+ widget_unset_error (GTK_WIDGET (g_object_get_data (G_OBJECT (row), "metric")));
+ }
+ } else {
+ widget_unset_error (GTK_WIDGET (g_object_get_data (G_OBJECT (row), "metric")));
+ }
+
+ if (!ret)
+ continue;
+
+ route = nm_ip_route_new (AF_INET,
+ gtk_editable_get_text (GTK_EDITABLE (address_entry)),
+ ce_netmask_entry_get_prefix (netmask_entry),
+ gtk_editable_get_text (GTK_EDITABLE (gateway_entry)),
+ metric, NULL);
+ if (route)
+ g_ptr_array_add (routes, route);
+
+ if (!gtk_widget_get_next_sibling (row))
+ ensure_empty_routes_row (self);
+ }
+
+ if (routes->len == 0) {
+ g_ptr_array_free (routes, TRUE);
+ routes = NULL;
+ }
+
+ if (!ret)
+ goto out;
+
+ ignore_auto_dns = !gtk_switch_get_active (self->auto_dns_switch);
+ ignore_auto_routes = !gtk_switch_get_active (self->auto_routes_switch);
+ never_default = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->never_default_check));
+
+ g_object_set (self->setting,
+ NM_SETTING_IP_CONFIG_METHOD, method,
+ NM_SETTING_IP_CONFIG_ADDRESSES, addresses,
+ NM_SETTING_IP_CONFIG_GATEWAY, default_gateway,
+ NM_SETTING_IP_CONFIG_DNS, dns_servers ? dns_servers->pdata : NULL,
+ NM_SETTING_IP_CONFIG_ROUTES, routes,
+ NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, ignore_auto_dns,
+ NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, ignore_auto_routes,
+ NM_SETTING_IP_CONFIG_NEVER_DEFAULT, never_default,
+ NULL);
+
+out:
+ if (addresses)
+ g_ptr_array_free (addresses, TRUE);
+
+ if (dns_servers)
+ g_ptr_array_free (dns_servers, TRUE);
+
+ if (routes)
+ g_ptr_array_free (routes, TRUE);
+
+ g_clear_pointer (&dns_text, g_free);
+
+ return ret;
+}
+
+static const gchar *
+ce_page_ip4_get_title (CEPage *page)
+{
+ return _("IPv4");
+}
+
+static gboolean
+ce_page_ip4_validate (CEPage *self,
+ NMConnection *connection,
+ GError **error)
+{
+ if (!ui_to_setting (CE_PAGE_IP4 (self)))
+ return FALSE;
+
+ return nm_setting_verify (NM_SETTING (CE_PAGE_IP4 (self)->setting), NULL, error);
+}
+
+static void
+ce_page_ip4_init (CEPageIP4 *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+ce_page_ip4_class_init (CEPageIP4Class *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/ip4-page.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP4, address_box);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP4, address_sizegroup);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP4, auto_dns_switch);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP4, auto_routes_switch);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP4, automatic_radio);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP4, content_box);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP4, disabled_radio);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP4, dns_entry);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP4, local_radio);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP4, main_box);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP4, manual_radio);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP4, never_default_check);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP4, address_address_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP4, address_netmask_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP4, address_gateway_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP4, routes_box);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP4, routes_address_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP4, routes_netmask_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP4, routes_gateway_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP4, routes_metric_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP4, routes_metric_sizegroup);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP4, routes_sizegroup);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP4, shared_radio);
+}
+
+static void
+ce_page_iface_init (CEPageInterface *iface)
+{
+ iface->get_title = ce_page_ip4_get_title;
+ iface->validate = ce_page_ip4_validate;
+}
+
+CEPageIP4 *
+ce_page_ip4_new (NMConnection *connection,
+ NMClient *client)
+{
+ CEPageIP4 *self;
+
+ self = CE_PAGE_IP4 (g_object_new (ce_page_ip4_get_type (), NULL));
+
+ self->setting = nm_connection_get_setting_ip4_config (connection);
+ if (!self->setting) {
+ self->setting = NM_SETTING_IP_CONFIG (nm_setting_ip4_config_new ());
+ nm_connection_add_setting (connection, NM_SETTING (self->setting));
+ }
+
+ connect_ip4_page (self);
+
+ return self;
+}
diff --git a/panels/network/connection-editor/ce-page-ip4.h b/panels/network/connection-editor/ce-page-ip4.h
new file mode 100644
index 0000000..3e6545f
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-ip4.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <adwaita.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (CEPageIP4, ce_page_ip4, CE, PAGE_IP4, AdwBin)
+
+CEPageIP4 *ce_page_ip4_new (NMConnection *connection,
+ NMClient *client);
+
+G_END_DECLS
diff --git a/panels/network/connection-editor/ce-page-ip6.c b/panels/network/connection-editor/ce-page-ip6.c
new file mode 100644
index 0000000..09b9eb6
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-ip6.c
@@ -0,0 +1,817 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <glib/gi18n.h>
+#include <NetworkManager.h>
+
+#include "ce-ip-address-entry.h"
+#include "ce-page.h"
+#include "ce-page-ip6.h"
+#include "ui-helpers.h"
+
+static void ensure_empty_address_row (CEPageIP6 *self);
+static void ensure_empty_routes_row (CEPageIP6 *self);
+
+
+struct _CEPageIP6
+{
+ AdwBin parent;
+
+ GtkBox *address_box;
+ GtkLabel *address_address_label;
+ GtkLabel *address_prefix_label;
+ GtkLabel *address_gateway_label;
+ GtkSizeGroup *address_sizegroup;
+ GtkSwitch *auto_dns_switch;
+ GtkSwitch *auto_routes_switch;
+ GtkCheckButton *automatic_radio;
+ GtkBox *content_box;
+ GtkCheckButton *dhcp_radio;
+ GtkCheckButton *disabled_radio;
+ GtkEntry *dns_entry;
+ GtkCheckButton *local_radio;
+ GtkGrid *main_box;
+ GtkCheckButton *manual_radio;
+ GtkCheckButton *never_default_check;
+ GtkBox *routes_box;
+ GtkLabel *routes_address_label;
+ GtkLabel *routes_prefix_label;
+ GtkLabel *routes_gateway_label;
+ GtkLabel *routes_metric_label;
+ GtkSizeGroup *routes_metric_sizegroup;
+ GtkSizeGroup *routes_sizegroup;
+ GtkCheckButton *shared_radio;
+
+ NMSettingIPConfig *setting;
+
+ GtkWidget *address_list;
+ GtkWidget *routes_list;
+};
+
+static void ce_page_iface_init (CEPageInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (CEPageIP6, ce_page_ip6, ADW_TYPE_BIN,
+ G_IMPLEMENT_INTERFACE (ce_page_get_type (), ce_page_iface_init))
+
+enum {
+ METHOD_COL_NAME,
+ METHOD_COL_METHOD
+};
+
+enum {
+ IP6_METHOD_AUTO,
+ IP6_METHOD_DHCP,
+ IP6_METHOD_MANUAL,
+ IP6_METHOD_LINK_LOCAL,
+ IP6_METHOD_SHARED,
+ IP6_METHOD_DISABLED
+};
+
+static void
+method_changed (CEPageIP6 *self)
+{
+ gboolean addr_enabled;
+ gboolean dns_enabled;
+ gboolean routes_enabled;
+
+ if (gtk_check_button_get_active (self->disabled_radio) ||
+ gtk_check_button_get_active (self->shared_radio)) {
+ addr_enabled = FALSE;
+ dns_enabled = FALSE;
+ routes_enabled = FALSE;
+ } else {
+ addr_enabled = gtk_check_button_get_active (self->manual_radio);
+ dns_enabled = !gtk_check_button_get_active (self->local_radio);
+ routes_enabled = !gtk_check_button_get_active (self->local_radio);
+ }
+
+ gtk_widget_set_visible (GTK_WIDGET (self->address_box), addr_enabled);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->dns_entry), dns_enabled);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->routes_list), routes_enabled);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->never_default_check), routes_enabled);
+
+ ce_page_changed (CE_PAGE (self));
+}
+
+static void
+update_row_sensitivity (CEPageIP6 *self, GtkWidget *list)
+{
+ GtkWidget *child;
+ gint rows = 0, i = 0;
+
+ for (child = gtk_widget_get_first_child (GTK_WIDGET (list));
+ child;
+ child = gtk_widget_get_next_sibling (child)) {
+ GtkWidget *button;
+
+ button = GTK_WIDGET (g_object_get_data (G_OBJECT (child), "delete-button"));
+ if (button != NULL)
+ rows++;
+ }
+ for (child = gtk_widget_get_first_child (GTK_WIDGET (list));
+ child;
+ child = gtk_widget_get_next_sibling (child)) {
+ GtkWidget *button;
+
+ button = GTK_WIDGET (g_object_get_data (G_OBJECT (child), "delete-button"));
+ if (button != NULL)
+ gtk_widget_set_sensitive (button, rows > 1 && ++i < rows);
+ }
+}
+
+static void
+remove_row (CEPageIP6 *self, GtkButton *button)
+{
+ GtkWidget *row;
+ GtkWidget *row_box;
+ GtkWidget *list;
+
+ row_box = gtk_widget_get_parent (GTK_WIDGET (button));
+ row = gtk_widget_get_parent (row_box);
+ list = gtk_widget_get_parent (row);
+
+ gtk_list_box_remove (GTK_LIST_BOX (list), row);
+
+ ce_page_changed (CE_PAGE (self));
+
+ update_row_sensitivity (self, list);
+}
+
+static gboolean
+validate_row (GtkWidget *row)
+{
+ GtkWidget *child;
+ GtkWidget *box;
+ gboolean valid;
+
+ valid = FALSE;
+ box = gtk_list_box_row_get_child (GTK_LIST_BOX_ROW (row));
+
+ for (child = gtk_widget_get_first_child (box);
+ child;
+ child = gtk_widget_get_next_sibling (child)) {
+ if (!GTK_IS_ENTRY (child))
+ continue;
+
+ valid = valid || gtk_entry_get_text_length (GTK_ENTRY (child)) > 0;
+ }
+
+ return valid;
+}
+
+static void
+add_address_row (CEPageIP6 *self,
+ const gchar *address,
+ const gchar *network,
+ const gchar *gateway)
+{
+ GtkWidget *row;
+ GtkWidget *row_box;
+ GtkWidget *widget;
+ GtkWidget *delete_button;
+
+ row = gtk_list_box_row_new ();
+ gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), FALSE);
+
+ row_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_widget_add_css_class (row_box, "linked");
+
+ widget = GTK_WIDGET (ce_ip_address_entry_new (AF_INET6));
+ g_signal_connect_object (widget, "changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (widget, "activate", G_CALLBACK (ensure_empty_address_row), self, G_CONNECT_SWAPPED);
+ g_object_set_data (G_OBJECT (row), "address", widget);
+ gtk_editable_set_text (GTK_EDITABLE (widget), address);
+ gtk_editable_set_width_chars (GTK_EDITABLE (widget), 16);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_accessible_update_relation (GTK_ACCESSIBLE (widget),
+ GTK_ACCESSIBLE_RELATION_LABELLED_BY, self->address_address_label, NULL,
+ -1);
+ gtk_box_append (GTK_BOX (row_box), widget);
+
+ widget = gtk_entry_new ();
+ g_signal_connect_object (widget, "changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (widget, "activate", G_CALLBACK (ensure_empty_address_row), self, G_CONNECT_SWAPPED);
+ g_object_set_data (G_OBJECT (row), "prefix", widget);
+ gtk_editable_set_text (GTK_EDITABLE (widget), network);
+ gtk_editable_set_width_chars (GTK_EDITABLE (widget), 16);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_accessible_update_relation (GTK_ACCESSIBLE (widget),
+ GTK_ACCESSIBLE_RELATION_LABELLED_BY, self->address_prefix_label, NULL,
+ -1);
+ gtk_box_append (GTK_BOX (row_box), widget);
+
+ widget = GTK_WIDGET (ce_ip_address_entry_new (AF_INET6));
+ g_signal_connect_object (widget, "changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (widget, "activate", G_CALLBACK (ensure_empty_address_row), self, G_CONNECT_SWAPPED);
+ g_object_set_data (G_OBJECT (row), "gateway", widget);
+ gtk_editable_set_text (GTK_EDITABLE (widget), gateway ? gateway : "");
+ gtk_editable_set_width_chars (GTK_EDITABLE (widget), 16);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_accessible_update_relation (GTK_ACCESSIBLE (widget),
+ GTK_ACCESSIBLE_RELATION_LABELLED_BY, self->address_gateway_label, NULL,
+ -1);
+ gtk_box_append (GTK_BOX (row_box), widget);
+
+ delete_button = gtk_button_new_from_icon_name ("edit-delete-symbolic");
+ gtk_widget_set_sensitive (delete_button, FALSE);
+ g_signal_connect_object (delete_button, "clicked", G_CALLBACK (remove_row), self, G_CONNECT_SWAPPED);
+ gtk_accessible_update_property (GTK_ACCESSIBLE (delete_button),
+ GTK_ACCESSIBLE_PROPERTY_LABEL, _("Delete Address"),
+ -1);
+ gtk_box_append (GTK_BOX (row_box), delete_button);
+ g_object_set_data (G_OBJECT (row), "delete-button", delete_button);
+
+ gtk_size_group_add_widget (self->address_sizegroup, delete_button);
+
+ gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), row_box);
+ gtk_list_box_append (GTK_LIST_BOX (self->address_list), row);
+
+ update_row_sensitivity (self, self->address_list);
+}
+
+static void
+ensure_empty_address_row (CEPageIP6 *self)
+{
+ GtkWidget *child = gtk_widget_get_last_child (self->address_list);
+
+ /* Add the last, stub row if needed*/
+ if (!child || validate_row (child))
+ add_address_row (self, "", "", "");
+}
+
+static void
+add_address_box (CEPageIP6 *self)
+{
+ GtkWidget *list;
+ gint i;
+
+ self->address_list = list = gtk_list_box_new ();
+ gtk_list_box_set_selection_mode (GTK_LIST_BOX (list), GTK_SELECTION_NONE);
+ gtk_box_append (self->address_box, list);
+
+ for (i = 0; i < nm_setting_ip_config_get_num_addresses (self->setting); i++) {
+ NMIPAddress *addr;
+ g_autofree gchar *netmask = NULL;
+
+ addr = nm_setting_ip_config_get_address (self->setting, i);
+ netmask = g_strdup_printf ("%u", nm_ip_address_get_prefix (addr));
+ add_address_row (self, nm_ip_address_get_address (addr), netmask,
+ i == 0 ? nm_setting_ip_config_get_gateway (self->setting) : NULL);
+ }
+ if (nm_setting_ip_config_get_num_addresses (self->setting) == 0)
+ ensure_empty_address_row (self);
+}
+
+static void
+add_dns_section (CEPageIP6 *self)
+{
+ GString *string;
+ gint i;
+
+ gtk_switch_set_active (self->auto_dns_switch, !nm_setting_ip_config_get_ignore_auto_dns (self->setting));
+ g_signal_connect_object (self->auto_dns_switch, "notify::active", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+
+ string = g_string_new ("");
+
+ for (i = 0; i < nm_setting_ip_config_get_num_dns (self->setting); i++) {
+ const char *address;
+
+ address = nm_setting_ip_config_get_dns (self->setting, i);
+
+ if (i > 0)
+ g_string_append (string, ", ");
+
+ g_string_append (string, address);
+
+ }
+
+ gtk_editable_set_text (GTK_EDITABLE (self->dns_entry), string->str);
+
+ g_signal_connect_object (self->dns_entry, "notify::text", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+
+ g_string_free (string, TRUE);
+}
+
+static void
+add_route_row (CEPageIP6 *self,
+ const gchar *address,
+ const gchar *prefix,
+ const gchar *gateway,
+ const gchar *metric)
+{
+ GtkWidget *row;
+ GtkWidget *row_box;
+ GtkWidget *widget;
+ GtkWidget *delete_button;
+
+ row = gtk_list_box_row_new ();
+ gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), FALSE);
+
+ row_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_widget_add_css_class (row_box, "linked");
+
+ widget = GTK_WIDGET (ce_ip_address_entry_new (AF_INET6));
+ g_signal_connect_object (widget, "changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (widget, "activate", G_CALLBACK (ensure_empty_routes_row), self, G_CONNECT_SWAPPED);
+ g_object_set_data (G_OBJECT (row), "address", widget);
+ gtk_editable_set_text (GTK_EDITABLE (widget), address);
+ gtk_editable_set_width_chars (GTK_EDITABLE (widget), 16);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_accessible_update_relation (GTK_ACCESSIBLE (widget),
+ GTK_ACCESSIBLE_RELATION_LABELLED_BY, self->routes_address_label, NULL,
+ -1);
+ gtk_box_append (GTK_BOX (row_box), widget);
+
+ widget = gtk_entry_new ();
+ g_signal_connect_object (widget, "changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (widget, "activate", G_CALLBACK (ensure_empty_routes_row), self, G_CONNECT_SWAPPED);
+ g_object_set_data (G_OBJECT (row), "prefix", widget);
+ gtk_editable_set_text (GTK_EDITABLE (widget), prefix ? prefix : "");
+ gtk_editable_set_width_chars (GTK_EDITABLE (widget), 16);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_accessible_update_relation (GTK_ACCESSIBLE (widget),
+ GTK_ACCESSIBLE_RELATION_LABELLED_BY, self->routes_prefix_label, NULL,
+ -1);
+ gtk_box_append (GTK_BOX (row_box), widget);
+
+ widget = GTK_WIDGET (ce_ip_address_entry_new (AF_INET6));
+ g_signal_connect_object (widget, "changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (widget, "activate", G_CALLBACK (ensure_empty_routes_row), self, G_CONNECT_SWAPPED);
+ g_object_set_data (G_OBJECT (row), "gateway", widget);
+ gtk_editable_set_text (GTK_EDITABLE (widget), gateway);
+ gtk_editable_set_width_chars (GTK_EDITABLE (widget), 16);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_accessible_update_relation (GTK_ACCESSIBLE (widget),
+ GTK_ACCESSIBLE_RELATION_LABELLED_BY, self->routes_gateway_label, NULL,
+ -1);
+ gtk_box_append (GTK_BOX (row_box), widget);
+
+ widget = gtk_entry_new ();
+ g_signal_connect_object (widget, "changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (widget, "activate", G_CALLBACK (ensure_empty_routes_row), self, G_CONNECT_SWAPPED);
+ g_object_set_data (G_OBJECT (row), "metric", widget);
+ gtk_editable_set_text (GTK_EDITABLE (widget), metric ? metric : "");
+ gtk_editable_set_width_chars (GTK_EDITABLE (widget), 5);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_accessible_update_relation (GTK_ACCESSIBLE (widget),
+ GTK_ACCESSIBLE_RELATION_LABELLED_BY, self->routes_prefix_label, NULL,
+ -1);
+ gtk_box_append (GTK_BOX (row_box), widget);
+
+ gtk_size_group_add_widget (self->routes_metric_sizegroup, widget);
+
+ delete_button = gtk_button_new_from_icon_name ("edit-delete-symbolic");
+ g_signal_connect_object (delete_button, "clicked", G_CALLBACK (remove_row), self, G_CONNECT_SWAPPED);
+ gtk_accessible_update_property (GTK_ACCESSIBLE (delete_button),
+ GTK_ACCESSIBLE_PROPERTY_LABEL, _("Delete Route"),
+ -1);
+ gtk_widget_set_halign (delete_button, GTK_ALIGN_CENTER);
+ gtk_widget_set_valign (delete_button, GTK_ALIGN_CENTER);
+ gtk_box_append (GTK_BOX (row_box), delete_button);
+ g_object_set_data (G_OBJECT (row), "delete-button", delete_button);
+
+ gtk_size_group_add_widget (self->routes_sizegroup, delete_button);
+
+ gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), row_box);
+ gtk_list_box_append (GTK_LIST_BOX (self->routes_list), row);
+
+ update_row_sensitivity (self, self->routes_list);
+}
+
+static void
+ensure_empty_routes_row (CEPageIP6 *self)
+{
+ GtkWidget *child = gtk_widget_get_last_child (self->routes_list);
+
+ /* Add the last, stub row if needed*/
+ if (!child || validate_row (child))
+ add_route_row (self, "", NULL, "", NULL);
+}
+
+static void
+add_empty_route_row (CEPageIP6 *self)
+{
+ add_route_row (self, "", NULL, "", NULL);
+}
+
+static void
+add_routes_box (CEPageIP6 *self)
+{
+ GtkWidget *list;
+ gint i;
+
+ self->routes_list = list = gtk_list_box_new ();
+ gtk_list_box_set_selection_mode (GTK_LIST_BOX (list), GTK_SELECTION_NONE);
+ gtk_box_append (self->routes_box, list);
+ gtk_switch_set_active (self->auto_routes_switch, !nm_setting_ip_config_get_ignore_auto_routes (self->setting));
+ g_signal_connect_object (self->auto_routes_switch, "notify::active", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+
+ for (i = 0; i < nm_setting_ip_config_get_num_routes (self->setting); i++) {
+ NMIPRoute *route;
+ g_autofree gchar *prefix = NULL;
+ g_autofree gchar *metric = NULL;
+
+ route = nm_setting_ip_config_get_route (self->setting, i);
+ prefix = g_strdup_printf ("%u", nm_ip_route_get_prefix (route));
+ metric = g_strdup_printf ("%" G_GINT64_FORMAT, nm_ip_route_get_metric (route));
+ add_route_row (self, nm_ip_route_get_dest (route),
+ prefix,
+ nm_ip_route_get_next_hop (route),
+ metric);
+ }
+ if (nm_setting_ip_config_get_num_routes (self->setting) == 0)
+ add_empty_route_row (self);
+}
+
+static void
+connect_ip6_page (CEPageIP6 *self)
+{
+ const gchar *str_method;
+ guint method;
+
+ add_address_box (self);
+ add_dns_section (self);
+ add_routes_box (self);
+
+ str_method = nm_setting_ip_config_get_method (self->setting);
+ g_signal_connect_object (self->disabled_radio, "notify::active", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+ g_object_bind_property (self->disabled_radio, "active",
+ self->content_box, "sensitive",
+ G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN);
+
+ g_signal_connect_object (self->shared_radio, "notify::active", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+ g_object_bind_property (self->shared_radio, "active",
+ self->content_box, "sensitive",
+ G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN);
+
+ method = IP6_METHOD_AUTO;
+ if (g_strcmp0 (str_method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0) {
+ method = IP6_METHOD_DHCP;
+ } else if (g_strcmp0 (str_method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0) {
+ method = IP6_METHOD_LINK_LOCAL;
+ } else if (g_strcmp0 (str_method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL) == 0) {
+ method = IP6_METHOD_MANUAL;
+ } else if (g_strcmp0 (str_method, NM_SETTING_IP6_CONFIG_METHOD_SHARED) == 0) {
+ method = IP6_METHOD_SHARED;
+ } else if (g_strcmp0 (str_method, NM_SETTING_IP6_CONFIG_METHOD_DISABLED) == 0 ||
+ g_strcmp0 (str_method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0) {
+ method = IP6_METHOD_DISABLED;
+ }
+
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->never_default_check),
+ nm_setting_ip_config_get_never_default (self->setting));
+ g_signal_connect_object (self->never_default_check, "toggled", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self->automatic_radio, "toggled", G_CALLBACK (method_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->dhcp_radio, "toggled", G_CALLBACK (method_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->local_radio, "toggled", G_CALLBACK (method_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->manual_radio, "toggled", G_CALLBACK (method_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->disabled_radio, "toggled", G_CALLBACK (method_changed), self, G_CONNECT_SWAPPED);
+
+ switch (method) {
+ case IP6_METHOD_AUTO:
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->automatic_radio), TRUE);
+ break;
+ case IP6_METHOD_DHCP:
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->dhcp_radio), TRUE);
+ break;
+ case IP6_METHOD_LINK_LOCAL:
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->local_radio), TRUE);
+ break;
+ case IP6_METHOD_MANUAL:
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->manual_radio), TRUE);
+ break;
+ case IP6_METHOD_SHARED:
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->shared_radio), TRUE);
+ break;
+ case IP6_METHOD_DISABLED:
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->disabled_radio), TRUE);
+ break;
+ default:
+ break;
+ }
+
+ method_changed (self);
+}
+
+static gboolean
+ui_to_setting (CEPageIP6 *self)
+{
+ GtkWidget *child;
+ const gchar *method;
+ gboolean ignore_auto_dns;
+ gboolean ignore_auto_routes;
+ gboolean never_default;
+ gboolean add_addresses = FALSE;
+ gboolean add_routes = FALSE;
+ gboolean ret = TRUE;
+ GStrv dns_addresses = NULL;
+ gchar *dns_text = NULL;
+ guint i;
+
+ if (gtk_check_button_get_active (self->disabled_radio))
+ method = NM_SETTING_IP6_CONFIG_METHOD_DISABLED;
+ else if (gtk_check_button_get_active (self->manual_radio))
+ method = NM_SETTING_IP6_CONFIG_METHOD_MANUAL;
+ else if (gtk_check_button_get_active (self->local_radio))
+ method = NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL;
+ else if (gtk_check_button_get_active (self->dhcp_radio))
+ method = NM_SETTING_IP6_CONFIG_METHOD_DHCP;
+ else if (gtk_check_button_get_active (self->automatic_radio))
+ method = NM_SETTING_IP6_CONFIG_METHOD_AUTO;
+ else if (gtk_check_button_get_active (self->shared_radio))
+ method = NM_SETTING_IP6_CONFIG_METHOD_SHARED;
+
+ nm_setting_ip_config_clear_addresses (self->setting);
+ if (g_str_equal (method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
+ add_addresses = TRUE;
+ } else {
+ g_object_set (G_OBJECT (self->setting),
+ NM_SETTING_IP_CONFIG_GATEWAY, NULL,
+ NULL);
+ }
+
+ for (child = gtk_widget_get_first_child (self->address_list);
+ add_addresses && child;
+ child = gtk_widget_get_next_sibling (child)) {
+ GtkWidget *row = child;
+ CEIPAddressEntry *address_entry;
+ CEIPAddressEntry *gateway_entry;
+ const gchar *text_prefix;
+ guint32 prefix;
+ gchar *end;
+ NMIPAddress *addr;
+
+ address_entry = CE_IP_ADDRESS_ENTRY (g_object_get_data (G_OBJECT (row), "address"));
+ if (!address_entry)
+ continue;
+
+ text_prefix = gtk_editable_get_text (GTK_EDITABLE (g_object_get_data (G_OBJECT (row), "prefix")));
+ gateway_entry = CE_IP_ADDRESS_ENTRY (g_object_get_data (G_OBJECT (row), "gateway"));
+
+ if (ce_ip_address_entry_is_empty (address_entry) && !*text_prefix && ce_ip_address_entry_is_empty (gateway_entry)) {
+ /* ignore empty rows */
+ widget_unset_error (g_object_get_data (G_OBJECT (row), "prefix"));
+ continue;
+ }
+
+ if (!ce_ip_address_entry_is_valid (address_entry))
+ ret = FALSE;
+
+ prefix = strtoul (text_prefix, &end, 10);
+ if (!end || *end || prefix == 0 || prefix > 128) {
+ widget_set_error (g_object_get_data (G_OBJECT (row), "prefix"));
+ ret = FALSE;
+ } else {
+ widget_unset_error (g_object_get_data (G_OBJECT (row), "prefix"));
+ }
+
+ if (!ce_ip_address_entry_is_valid (gateway_entry))
+ ret = FALSE;
+
+ if (!ret)
+ continue;
+
+ addr = nm_ip_address_new (AF_INET6, gtk_editable_get_text (GTK_EDITABLE (address_entry)), prefix, NULL);
+ if (!ce_ip_address_entry_is_empty (gateway_entry))
+ g_object_set (G_OBJECT (self->setting),
+ NM_SETTING_IP_CONFIG_GATEWAY, gtk_editable_get_text (GTK_EDITABLE (gateway_entry)),
+ NULL);
+ nm_setting_ip_config_add_address (self->setting, addr);
+
+ if (!gtk_widget_get_next_sibling (row))
+ ensure_empty_address_row (self);
+ }
+
+ nm_setting_ip_config_clear_dns (self->setting);
+ dns_text = g_strstrip (g_strdup (gtk_editable_get_text (GTK_EDITABLE (self->dns_entry))));
+
+ if (g_str_equal (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) ||
+ g_str_equal (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) ||
+ g_str_equal (method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL))
+ dns_addresses = g_strsplit_set (dns_text, ", ", -1);
+ else
+ dns_addresses = NULL;
+
+ for (i = 0; dns_addresses && dns_addresses[i]; i++) {
+ const gchar *text;
+ struct in6_addr tmp_addr;
+
+ text = dns_addresses[i];
+
+ if (!text || !*text)
+ continue;
+
+ if (inet_pton (AF_INET6, text, &tmp_addr) <= 0) {
+ g_clear_pointer (&dns_addresses, g_strfreev);
+ widget_set_error (GTK_WIDGET (self->dns_entry));
+ ret = FALSE;
+ break;
+ } else {
+ widget_unset_error (GTK_WIDGET (self->dns_entry));
+ nm_setting_ip_config_add_dns (self->setting, text);
+ }
+ }
+
+ nm_setting_ip_config_clear_routes (self->setting);
+ add_routes = g_str_equal (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) ||
+ g_str_equal (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) ||
+ g_str_equal (method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL);
+
+ for (child = gtk_widget_get_first_child (self->routes_list);
+ add_routes && child;
+ child = gtk_widget_get_next_sibling (child)) {
+ GtkWidget *row = child;
+ CEIPAddressEntry *address_entry;
+ CEIPAddressEntry *gateway_entry;
+ const gchar *text_prefix;
+ const gchar *text_metric;
+ guint32 prefix;
+ gint64 metric;
+ gchar *end;
+ NMIPRoute *route;
+
+ address_entry = CE_IP_ADDRESS_ENTRY (g_object_get_data (G_OBJECT (row), "address"));
+ if (!address_entry)
+ continue;
+
+ text_prefix = gtk_editable_get_text (GTK_EDITABLE (g_object_get_data (G_OBJECT (row), "prefix")));
+ gateway_entry = CE_IP_ADDRESS_ENTRY (g_object_get_data (G_OBJECT (row), "gateway"));
+ text_metric = gtk_editable_get_text (GTK_EDITABLE (g_object_get_data (G_OBJECT (row), "metric")));
+
+ if (ce_ip_address_entry_is_empty (address_entry) && !*text_prefix && ce_ip_address_entry_is_empty (gateway_entry) && !*text_metric) {
+ /* ignore empty rows */
+ widget_unset_error (g_object_get_data (G_OBJECT (row), "prefix"));
+ widget_unset_error (g_object_get_data (G_OBJECT (row), "metric"));
+ continue;
+ }
+
+ if (!ce_ip_address_entry_is_valid (address_entry))
+ ret = FALSE;
+
+ prefix = strtoul (text_prefix, &end, 10);
+ if (!end || *end || prefix == 0 || prefix > 128) {
+ widget_set_error (g_object_get_data (G_OBJECT (row), "prefix"));
+ ret = FALSE;
+ } else {
+ widget_unset_error (g_object_get_data (G_OBJECT (row), "prefix"));
+ }
+
+ if (!ce_ip_address_entry_is_valid (gateway_entry))
+ ret = FALSE;
+
+ metric = -1;
+ if (*text_metric) {
+ errno = 0;
+ metric = g_ascii_strtoull (text_metric, NULL, 10);
+ if (errno) {
+ widget_set_error (g_object_get_data (G_OBJECT (row), "metric"));
+ ret = FALSE;
+ } else {
+ widget_unset_error (g_object_get_data (G_OBJECT (row), "metric"));
+ }
+ } else {
+ widget_unset_error (g_object_get_data (G_OBJECT (row), "metric"));
+ }
+
+ if (!ret)
+ continue;
+
+ route = nm_ip_route_new (AF_INET6,
+ gtk_editable_get_text (GTK_EDITABLE (address_entry)),
+ prefix,
+ gtk_editable_get_text (GTK_EDITABLE (gateway_entry)),
+ metric,
+ NULL);
+ nm_setting_ip_config_add_route (self->setting, route);
+ nm_ip_route_unref (route);
+
+ if (!gtk_widget_get_next_sibling (row))
+ ensure_empty_routes_row (self);
+ }
+
+ if (!ret)
+ goto out;
+
+ ignore_auto_dns = !gtk_switch_get_active (self->auto_dns_switch);
+ ignore_auto_routes = !gtk_switch_get_active (self->auto_routes_switch);
+ never_default = gtk_check_button_get_active (self->never_default_check);
+
+ g_object_set (self->setting,
+ NM_SETTING_IP_CONFIG_METHOD, method,
+ NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, ignore_auto_dns,
+ NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, ignore_auto_routes,
+ NM_SETTING_IP_CONFIG_NEVER_DEFAULT, never_default,
+ NULL);
+
+out:
+ g_clear_pointer (&dns_addresses, g_strfreev);
+ g_clear_pointer (&dns_text, g_free);
+
+ return ret;
+}
+
+static const gchar *
+ce_page_ip6_get_title (CEPage *page)
+{
+ return _("IPv6");
+}
+
+static gboolean
+ce_page_ip6_validate (CEPage *self,
+ NMConnection *connection,
+ GError **error)
+{
+ if (!ui_to_setting (CE_PAGE_IP6 (self)))
+ return FALSE;
+
+ return nm_setting_verify (NM_SETTING (CE_PAGE_IP6 (self)->setting), NULL, error);
+}
+
+static void
+ce_page_ip6_init (CEPageIP6 *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+ce_page_ip6_class_init (CEPageIP6Class *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/ip6-page.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP6, address_box);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP6, address_address_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP6, address_prefix_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP6, address_gateway_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP6, address_sizegroup);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP6, auto_dns_switch);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP6, auto_routes_switch);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP6, automatic_radio);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP6, content_box);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP6, dhcp_radio);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP6, disabled_radio);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP6, dns_entry);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP6, local_radio);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP6, main_box);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP6, manual_radio);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP6, never_default_check);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP6, routes_box);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP6, routes_address_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP6, routes_prefix_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP6, routes_gateway_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP6, routes_metric_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP6, routes_metric_sizegroup);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP6, routes_sizegroup);
+ gtk_widget_class_bind_template_child (widget_class, CEPageIP6, shared_radio);
+}
+
+static void
+ce_page_iface_init (CEPageInterface *iface)
+{
+ iface->get_title = ce_page_ip6_get_title;
+ iface->validate = ce_page_ip6_validate;
+}
+
+CEPageIP6 *
+ce_page_ip6_new (NMConnection *connection,
+ NMClient *client)
+{
+ CEPageIP6 *self;
+
+ self = CE_PAGE_IP6 (g_object_new (ce_page_ip6_get_type (), NULL));
+
+ self->setting = nm_connection_get_setting_ip6_config (connection);
+ if (!self->setting) {
+ self->setting = NM_SETTING_IP_CONFIG (nm_setting_ip6_config_new ());
+ nm_connection_add_setting (connection, NM_SETTING (self->setting));
+ }
+
+ connect_ip6_page (self);
+
+ return self;
+}
diff --git a/panels/network/connection-editor/ce-page-ip6.h b/panels/network/connection-editor/ce-page-ip6.h
new file mode 100644
index 0000000..c2c7d1b
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-ip6.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <adwaita.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (CEPageIP6, ce_page_ip6, CE, PAGE_IP6, AdwBin)
+
+CEPageIP6 *ce_page_ip6_new (NMConnection *connection,
+ NMClient *client);
+
+G_END_DECLS
diff --git a/panels/network/connection-editor/ce-page-security.c b/panels/network/connection-editor/ce-page-security.c
new file mode 100644
index 0000000..c7cd7d9
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-security.c
@@ -0,0 +1,553 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include <NetworkManager.h>
+
+#include "ce-page.h"
+#include "ce-page-security.h"
+#include "wireless-security.h"
+#include "ws-dynamic-wep.h"
+#include "ws-leap.h"
+#include "ws-sae.h"
+#include "ws-wep-key.h"
+#include "ws-wpa-eap.h"
+#include "ws-wpa-psk.h"
+
+struct _CEPageSecurity
+{
+ GtkGrid parent;
+
+ GtkBox *box;
+ GtkComboBox *security_combo;
+ GtkLabel *security_label;
+
+ NMConnection *connection;
+ const gchar *security_setting;
+ GtkSizeGroup *group;
+ gboolean adhoc;
+};
+
+static void ce_page_iface_init (CEPageInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (CEPageSecurity, ce_page_security, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (ce_page_get_type (), ce_page_iface_init))
+
+enum {
+ S_NAME_COLUMN,
+ S_SEC_COLUMN,
+ S_ADHOC_VALID_COLUMN
+};
+
+static gboolean
+find_proto (NMSettingWirelessSecurity *sec, const char *item)
+{
+ guint32 i;
+
+ for (i = 0; i < nm_setting_wireless_security_get_num_protos (sec); i++) {
+ if (!strcmp (item, nm_setting_wireless_security_get_proto (sec, i)))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static NMUtilsSecurityType
+get_default_type_for_security (NMSettingWirelessSecurity *sec)
+{
+ const char *key_mgmt, *auth_alg;
+
+ g_return_val_if_fail (sec != NULL, NMU_SEC_NONE);
+
+ key_mgmt = nm_setting_wireless_security_get_key_mgmt (sec);
+ auth_alg = nm_setting_wireless_security_get_auth_alg (sec);
+
+ /* No IEEE 802.1x */
+ if (!strcmp (key_mgmt, "none"))
+ return NMU_SEC_STATIC_WEP;
+
+ if (!strcmp (key_mgmt, "ieee8021x")) {
+ if (auth_alg && !strcmp (auth_alg, "leap"))
+ return NMU_SEC_LEAP;
+ return NMU_SEC_DYNAMIC_WEP;
+ }
+
+#if NM_CHECK_VERSION(1,24,0)
+ if (!strcmp (key_mgmt, "owe")) {
+ return NMU_SEC_OWE;
+ }
+#endif
+
+#if NM_CHECK_VERSION(1,20,6)
+ if (!strcmp (key_mgmt, "sae")) {
+ return NMU_SEC_SAE;
+ }
+#endif
+
+ if ( !strcmp (key_mgmt, "wpa-none")
+ || !strcmp (key_mgmt, "wpa-psk")) {
+ if (find_proto (sec, "rsn"))
+ return NMU_SEC_WPA2_PSK;
+ else if (find_proto (sec, "wpa"))
+ return NMU_SEC_WPA_PSK;
+ else
+ return NMU_SEC_WPA_PSK;
+ }
+
+ if (!strcmp (key_mgmt, "wpa-eap")) {
+ if (find_proto (sec, "rsn"))
+ return NMU_SEC_WPA2_ENTERPRISE;
+ else if (find_proto (sec, "wpa"))
+ return NMU_SEC_WPA_ENTERPRISE;
+ else
+ return NMU_SEC_WPA_ENTERPRISE;
+ }
+
+ return NMU_SEC_INVALID;
+}
+
+static WirelessSecurity *
+security_combo_get_active (CEPageSecurity *self)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ WirelessSecurity *sec = NULL;
+
+ model = gtk_combo_box_get_model (self->security_combo);
+ if (!gtk_combo_box_get_active_iter (self->security_combo, &iter))
+ return NULL;
+ gtk_tree_model_get (model, &iter, S_SEC_COLUMN, &sec, -1);
+
+ return sec;
+}
+
+static void
+wsec_size_group_clear (GtkSizeGroup *group)
+{
+ GSList *children;
+ GSList *iter;
+
+ g_return_if_fail (group != NULL);
+
+ children = gtk_size_group_get_widgets (group);
+ for (iter = children; iter; iter = g_slist_next (iter))
+ gtk_size_group_remove_widget (group, GTK_WIDGET (iter->data));
+}
+
+static void
+security_combo_changed (CEPageSecurity *self)
+{
+ g_autoptr(WirelessSecurity) sec = NULL;
+ GtkWidget *child;
+
+ wsec_size_group_clear (self->group);
+
+ while ((child = gtk_widget_get_first_child (GTK_WIDGET (self->box))) != NULL)
+ gtk_box_remove (self->box, child);
+
+ sec = security_combo_get_active (self);
+ if (sec) {
+ if (gtk_widget_get_parent (GTK_WIDGET (sec)))
+ gtk_box_remove (self->box, GTK_WIDGET (sec));
+
+ gtk_size_group_add_widget (self->group, GTK_WIDGET (self->security_label));
+ wireless_security_add_to_size_group (sec, self->group);
+
+ gtk_box_append (self->box, g_object_ref (GTK_WIDGET (sec)));
+ }
+
+ ce_page_changed (CE_PAGE (self));
+}
+
+static void
+security_item_changed_cb (CEPageSecurity *self)
+{
+ ce_page_changed (CE_PAGE (self));
+}
+
+static void
+add_security_item (CEPageSecurity *self,
+ WirelessSecurity *sec,
+ GtkListStore *model,
+ GtkTreeIter *iter,
+ const char *text,
+ gboolean adhoc_valid)
+{
+ g_signal_connect_object (sec, "changed", G_CALLBACK (security_item_changed_cb), self, G_CONNECT_SWAPPED);
+ gtk_list_store_append (model, iter);
+ gtk_list_store_set (model, iter,
+ S_NAME_COLUMN, text,
+ S_SEC_COLUMN, sec,
+ S_ADHOC_VALID_COLUMN, adhoc_valid,
+ -1);
+ g_object_unref (sec);
+}
+
+static void
+set_sensitive (GtkCellLayout *cell_layout,
+ GtkCellRenderer *cell,
+ GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ gboolean *adhoc = data;
+ gboolean sensitive = TRUE, adhoc_valid = TRUE;
+
+ gtk_tree_model_get (tree_model, iter, S_ADHOC_VALID_COLUMN, &adhoc_valid, -1);
+ if (*adhoc && !adhoc_valid)
+ sensitive = FALSE;
+
+ g_object_set (cell, "sensitive", sensitive, NULL);
+}
+
+static void
+finish_setup (CEPageSecurity *self)
+{
+ NMSettingWireless *sw;
+ NMSettingWirelessSecurity *sws;
+ gboolean is_adhoc = FALSE;
+ g_autoptr(GtkListStore) sec_model = NULL;
+ GtkTreeIter iter;
+ const gchar *mode;
+ guint32 dev_caps = 0;
+ NMUtilsSecurityType default_type = NMU_SEC_NONE;
+ int active = -1;
+ int item = 0;
+ GtkCellRenderer *renderer;
+
+ sw = nm_connection_get_setting_wireless (self->connection);
+ g_assert (sw);
+
+ self->group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
+ dev_caps = NM_WIFI_DEVICE_CAP_CIPHER_WEP40
+ | NM_WIFI_DEVICE_CAP_CIPHER_WEP104
+ | NM_WIFI_DEVICE_CAP_CIPHER_TKIP
+ | NM_WIFI_DEVICE_CAP_CIPHER_CCMP
+ | NM_WIFI_DEVICE_CAP_WPA
+ | NM_WIFI_DEVICE_CAP_RSN;
+
+ mode = nm_setting_wireless_get_mode (sw);
+ if (mode && !strcmp (mode, "adhoc"))
+ is_adhoc = TRUE;
+ self->adhoc = is_adhoc;
+
+ sws = nm_connection_get_setting_wireless_security (self->connection);
+ if (sws)
+ default_type = get_default_type_for_security (sws);
+
+ sec_model = gtk_list_store_new (3, G_TYPE_STRING, wireless_security_get_type (), G_TYPE_BOOLEAN);
+
+ if (nm_utils_security_valid (NMU_SEC_NONE, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
+ gtk_list_store_insert_with_values (sec_model, &iter, -1,
+ S_NAME_COLUMN, C_("Wi-Fi/Ethernet security", "None"),
+ S_ADHOC_VALID_COLUMN, TRUE,
+ -1);
+ if (default_type == NMU_SEC_NONE)
+ active = item;
+ item++;
+ }
+
+#if NM_CHECK_VERSION(1,24,0)
+ if (nm_utils_security_valid (NMU_SEC_OWE, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
+ gtk_list_store_insert_with_values (sec_model, &iter, -1,
+ S_NAME_COLUMN, _("Enhanced Open"),
+ S_ADHOC_VALID_COLUMN, FALSE,
+ -1);
+ if (active < 0 && default_type == NMU_SEC_OWE)
+ active = item;
+ item++;
+ }
+#endif
+
+ if (nm_utils_security_valid (NMU_SEC_STATIC_WEP, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
+ WirelessSecurityWEPKey *ws_wep;
+ NMWepKeyType wep_type = NM_WEP_KEY_TYPE_KEY;
+
+ if (default_type == NMU_SEC_STATIC_WEP) {
+ sws = nm_connection_get_setting_wireless_security (self->connection);
+ if (sws)
+ wep_type = nm_setting_wireless_security_get_wep_key_type (sws);
+ if (wep_type == NM_WEP_KEY_TYPE_UNKNOWN)
+ wep_type = NM_WEP_KEY_TYPE_KEY;
+ }
+
+ ws_wep = ws_wep_key_new (self->connection, NM_WEP_KEY_TYPE_KEY);
+ if (ws_wep) {
+ add_security_item (self, WIRELESS_SECURITY (ws_wep), sec_model,
+ &iter, _("WEP 40/128-bit Key (Hex or ASCII)"),
+ TRUE);
+ if ((active < 0) && (default_type == NMU_SEC_STATIC_WEP) && (wep_type == NM_WEP_KEY_TYPE_KEY))
+ active = item;
+ item++;
+ }
+
+ ws_wep = ws_wep_key_new (self->connection, NM_WEP_KEY_TYPE_PASSPHRASE);
+ if (ws_wep) {
+ add_security_item (self, WIRELESS_SECURITY (ws_wep), sec_model,
+ &iter, _("WEP 128-bit Passphrase"), TRUE);
+ if ((active < 0) && (default_type == NMU_SEC_STATIC_WEP) && (wep_type == NM_WEP_KEY_TYPE_PASSPHRASE))
+ active = item;
+ item++;
+ }
+ }
+
+ if (nm_utils_security_valid (NMU_SEC_LEAP, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
+ WirelessSecurityLEAP *ws_leap;
+
+ ws_leap = ws_leap_new (self->connection);
+ if (ws_leap) {
+ add_security_item (self, WIRELESS_SECURITY (ws_leap), sec_model,
+ &iter, _("LEAP"), FALSE);
+ if ((active < 0) && (default_type == NMU_SEC_LEAP))
+ active = item;
+ item++;
+ }
+ }
+
+ if (nm_utils_security_valid (NMU_SEC_DYNAMIC_WEP, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
+ WirelessSecurityDynamicWEP *ws_dynamic_wep;
+
+ ws_dynamic_wep = ws_dynamic_wep_new (self->connection);
+ if (ws_dynamic_wep) {
+ add_security_item (self, WIRELESS_SECURITY (ws_dynamic_wep), sec_model,
+ &iter, _("Dynamic WEP (802.1x)"), FALSE);
+ if ((active < 0) && (default_type == NMU_SEC_DYNAMIC_WEP))
+ active = item;
+ item++;
+ }
+ }
+
+ if (nm_utils_security_valid (NMU_SEC_WPA_PSK, dev_caps, FALSE, is_adhoc, 0, 0, 0) ||
+ nm_utils_security_valid (NMU_SEC_WPA2_PSK, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
+ WirelessSecurityWPAPSK *ws_wpa_psk;
+
+ ws_wpa_psk = ws_wpa_psk_new (self->connection);
+ if (ws_wpa_psk) {
+ add_security_item (self, WIRELESS_SECURITY (ws_wpa_psk), sec_model,
+ &iter, _("WPA & WPA2 Personal"), FALSE);
+ if ((active < 0) && ((default_type == NMU_SEC_WPA_PSK) || (default_type == NMU_SEC_WPA2_PSK)))
+ active = item;
+ item++;
+ }
+ }
+
+ if (nm_utils_security_valid (NMU_SEC_WPA_ENTERPRISE, dev_caps, FALSE, is_adhoc, 0, 0, 0) ||
+ nm_utils_security_valid (NMU_SEC_WPA2_ENTERPRISE, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
+ WirelessSecurityWPAEAP *ws_wpa_eap;
+
+ ws_wpa_eap = ws_wpa_eap_new (self->connection);
+ if (ws_wpa_eap) {
+ add_security_item (self, WIRELESS_SECURITY (ws_wpa_eap), sec_model,
+ &iter, _("WPA & WPA2 Enterprise"), FALSE);
+ if ((active < 0) && ((default_type == NMU_SEC_WPA_ENTERPRISE) || (default_type == NMU_SEC_WPA2_ENTERPRISE)))
+ active = item;
+ item++;
+ }
+ }
+
+#if NM_CHECK_VERSION(1,20,6)
+ if (nm_utils_security_valid (NMU_SEC_SAE, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
+ WirelessSecuritySAE *ws_sae;
+
+ ws_sae = ws_sae_new (self->connection);
+ if (ws_sae) {
+ add_security_item (self, WIRELESS_SECURITY (ws_sae), sec_model,
+ &iter, _("WPA3 Personal"), FALSE);
+ if ((active < 0) && ((default_type == NMU_SEC_SAE)))
+ active = item;
+ item++;
+ }
+ }
+#endif
+
+ gtk_combo_box_set_model (self->security_combo, GTK_TREE_MODEL (sec_model));
+ gtk_cell_layout_clear (GTK_CELL_LAYOUT (self->security_combo));
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (self->security_combo), renderer, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (self->security_combo), renderer, "text", S_NAME_COLUMN, NULL);
+ gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (self->security_combo), renderer, set_sensitive, &self->adhoc, NULL);
+
+ gtk_combo_box_set_active (self->security_combo, active < 0 ? 0 : (guint32) active);
+
+ security_combo_changed (self);
+ g_signal_connect_object (self->security_combo, "changed",
+ G_CALLBACK (security_combo_changed), self, G_CONNECT_SWAPPED);
+}
+
+static void
+ce_page_security_dispose (GObject *object)
+{
+ CEPageSecurity *self = CE_PAGE_SECURITY (object);
+
+ g_clear_object (&self->connection);
+ g_clear_object (&self->group);
+
+ G_OBJECT_CLASS (ce_page_security_parent_class)->dispose (object);
+}
+
+static const gchar *
+ce_page_security_get_security_setting (CEPage *page)
+{
+ return CE_PAGE_SECURITY (page)->security_setting;
+}
+
+static const gchar *
+ce_page_security_get_title (CEPage *page)
+{
+ return _("Security");
+}
+
+static gboolean
+ce_page_security_validate (CEPage *page,
+ NMConnection *connection,
+ GError **error)
+{
+ CEPageSecurity *self = CE_PAGE_SECURITY (page);
+ NMSettingWireless *sw;
+ g_autoptr(WirelessSecurity) sec = NULL;
+ gboolean valid = FALSE;
+ const char *mode;
+
+ sw = nm_connection_get_setting_wireless (connection);
+
+ mode = nm_setting_wireless_get_mode (sw);
+ if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_ADHOC) == 0)
+ CE_PAGE_SECURITY (self)->adhoc = TRUE;
+ else
+ CE_PAGE_SECURITY (self)->adhoc = FALSE;
+
+ sec = security_combo_get_active (CE_PAGE_SECURITY (self));
+ if (sec) {
+ GBytes *ssid = nm_setting_wireless_get_ssid (sw);
+
+ if (ssid) {
+ /* FIXME: get failed property and error out of wifi security objects */
+ valid = wireless_security_validate (sec, error);
+ if (valid)
+ wireless_security_fill_connection (sec, connection);
+ } else {
+ g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_SETTING, "Missing SSID");
+ valid = FALSE;
+ }
+
+ if (self->adhoc) {
+ if (!wireless_security_adhoc_compatible (sec)) {
+ if (valid)
+ g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING, "Security not compatible with Ad-Hoc mode");
+ valid = FALSE;
+ }
+ }
+ } else {
+
+ if (gtk_combo_box_get_active ((CE_PAGE_SECURITY (self))->security_combo) == 0) {
+ /* No security, unencrypted */
+ nm_connection_remove_setting (connection, NM_TYPE_SETTING_WIRELESS_SECURITY);
+ nm_connection_remove_setting (connection, NM_TYPE_SETTING_802_1X);
+ valid = TRUE;
+ } else {
+ /* owe case:
+ * fill the connection manually until libnma implements OWE wireless security
+ */
+ NMSetting *sws;
+
+ sws = nm_setting_wireless_security_new ();
+ g_object_set (sws, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "owe", NULL);
+ nm_connection_add_setting (connection, sws);
+ nm_connection_remove_setting (connection, NM_TYPE_SETTING_802_1X);
+ valid = TRUE;
+ }
+
+ }
+
+ return valid;
+}
+
+static void
+ce_page_security_init (CEPageSecurity *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+ce_page_security_class_init (CEPageSecurityClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = ce_page_security_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/security-page.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CEPageSecurity, box);
+ gtk_widget_class_bind_template_child (widget_class, CEPageSecurity, security_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageSecurity, security_combo);
+}
+
+static void
+ce_page_iface_init (CEPageInterface *iface)
+{
+ iface->get_security_setting = ce_page_security_get_security_setting;
+ iface->get_title = ce_page_security_get_title;
+ iface->validate = ce_page_security_validate;
+}
+
+CEPageSecurity *
+ce_page_security_new (NMConnection *connection)
+{
+ CEPageSecurity *self;
+ NMUtilsSecurityType default_type = NMU_SEC_NONE;
+ NMSettingWirelessSecurity *sws;
+
+ self = CE_PAGE_SECURITY (g_object_new (ce_page_security_get_type (), NULL));
+
+ self->connection = g_object_ref (connection);
+
+ sws = nm_connection_get_setting_wireless_security (connection);
+ if (sws)
+ default_type = get_default_type_for_security (sws);
+
+ if (default_type == NMU_SEC_STATIC_WEP ||
+ default_type == NMU_SEC_LEAP ||
+ default_type == NMU_SEC_WPA_PSK ||
+#if NM_CHECK_VERSION(1,20,6)
+ default_type == NMU_SEC_SAE ||
+#endif
+#if NM_CHECK_VERSION(1,24,0)
+ default_type == NMU_SEC_OWE ||
+#endif
+ default_type == NMU_SEC_WPA2_PSK) {
+ self->security_setting = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME;
+ }
+
+ if (default_type == NMU_SEC_DYNAMIC_WEP ||
+ default_type == NMU_SEC_WPA_ENTERPRISE ||
+ default_type == NMU_SEC_WPA2_ENTERPRISE) {
+ self->security_setting = NM_SETTING_802_1X_SETTING_NAME;
+ }
+
+ g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);
+
+ return self;
+}
diff --git a/panels/network/connection-editor/ce-page-security.h b/panels/network/connection-editor/ce-page-security.h
new file mode 100644
index 0000000..e7c84e5
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-security.h
@@ -0,0 +1,33 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (CEPageSecurity, ce_page_security, CE, PAGE_SECURITY, GtkGrid)
+
+CEPageSecurity *ce_page_security_new (NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/connection-editor/ce-page-vpn.c b/panels/network/connection-editor/ce-page-vpn.c
new file mode 100644
index 0000000..36afde5
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-vpn.c
@@ -0,0 +1,227 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2013 Red Hat, Inc
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include <NetworkManager.h>
+
+#include "ce-page.h"
+#include "ce-page-vpn.h"
+#include "vpn-helpers.h"
+
+struct _CEPageVpn
+{
+ GtkBox parent;
+
+ GtkLabel *failure_label;
+ GtkEntry *name_entry;
+
+ NMConnection *connection;
+ NMSettingConnection *setting_connection;
+ NMSettingVpn *setting_vpn;
+
+ NMVpnEditorPlugin *plugin;
+ NMVpnEditor *editor;
+};
+
+static void ce_page_iface_init (CEPageInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (CEPageVpn, ce_page_vpn, GTK_TYPE_BOX,
+ G_IMPLEMENT_INTERFACE (ce_page_get_type (), ce_page_iface_init))
+
+/* Hack to make the plugin-provided editor widget fit in better with
+ * the control center by changing
+ *
+ * Foo: [__________]
+ * Bar baz: [__________]
+ *
+ * to
+ *
+ * Foo [__________]
+ * Bar baz [__________]
+ */
+static void
+vpn_gnome3ify_editor (GtkWidget *widget)
+{
+ if (GTK_IS_LABEL (widget)) {
+ const char *text;
+ gfloat xalign;
+ g_autofree gchar *newtext = NULL;
+ int len;
+
+ xalign = gtk_label_get_xalign (GTK_LABEL (widget));
+ if (xalign != 0.0)
+ return;
+ text = gtk_label_get_text (GTK_LABEL (widget));
+ len = strlen (text);
+ if (len < 2 || text[len - 1] != ':')
+ return;
+
+ newtext = g_strndup (text, len - 1);
+ gtk_label_set_text (GTK_LABEL (widget), newtext);
+ gtk_label_set_xalign (GTK_LABEL (widget), 1.0);
+ } else if (GTK_IS_WIDGET (widget)) {
+ GtkWidget *child;
+
+ for (child = gtk_widget_get_first_child (widget);
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ vpn_gnome3ify_editor (child);
+ }
+}
+
+static void
+load_vpn_plugin (CEPageVpn *self)
+{
+ GtkWidget *ui_widget;
+
+ self->editor = nm_vpn_editor_plugin_get_editor (self->plugin,
+ self->connection,
+ NULL);
+ ui_widget = NULL;
+ if (self->editor)
+ ui_widget = GTK_WIDGET (nm_vpn_editor_get_widget (self->editor));
+
+ if (!ui_widget) {
+ g_clear_object (&self->editor);
+ self->plugin = NULL;
+ return;
+ }
+ vpn_gnome3ify_editor (ui_widget);
+
+ gtk_box_remove (GTK_BOX (self), GTK_WIDGET (self->failure_label));
+ gtk_box_append (GTK_BOX (self), ui_widget);
+
+ g_signal_connect_object (self->editor, "changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+}
+
+static void
+connect_vpn_page (CEPageVpn *self)
+{
+ const gchar *name;
+
+ name = nm_setting_connection_get_id (self->setting_connection);
+ gtk_editable_set_text (GTK_EDITABLE (self->name_entry), name);
+ g_signal_connect_object (self->name_entry, "changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+}
+
+static void
+ce_page_vpn_dispose (GObject *object)
+{
+ CEPageVpn *self = CE_PAGE_VPN (object);
+
+ g_clear_object (&self->connection);
+ g_clear_object (&self->editor);
+
+ G_OBJECT_CLASS (ce_page_vpn_parent_class)->dispose (object);
+}
+
+static const gchar *
+ce_page_vpn_get_security_setting (CEPage *page)
+{
+ return NM_SETTING_VPN_SETTING_NAME;
+}
+
+static const gchar *
+ce_page_vpn_get_title (CEPage *page)
+{
+ return _("Identity");
+}
+
+static gboolean
+ce_page_vpn_validate (CEPage *page,
+ NMConnection *connection,
+ GError **error)
+{
+ CEPageVpn *self = CE_PAGE_VPN (page);
+
+ g_object_set (self->setting_connection,
+ NM_SETTING_CONNECTION_ID, gtk_editable_get_text (GTK_EDITABLE (self->name_entry)),
+ NULL);
+
+ if (!nm_setting_verify (NM_SETTING (self->setting_connection), NULL, error))
+ return FALSE;
+
+ if (!self->editor)
+ return TRUE;
+
+ return nm_vpn_editor_update_connection (self->editor, connection, error);
+}
+
+static void
+ce_page_vpn_init (CEPageVpn *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+ce_page_vpn_class_init (CEPageVpnClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+
+ object_class->dispose = ce_page_vpn_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/vpn-page.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CEPageVpn, failure_label);
+ gtk_widget_class_bind_template_child (widget_class, CEPageVpn, name_entry);
+}
+
+static void
+ce_page_iface_init (CEPageInterface *iface)
+{
+ iface->get_security_setting = ce_page_vpn_get_security_setting;
+ iface->get_title = ce_page_vpn_get_title;
+ iface->validate = ce_page_vpn_validate;
+}
+
+static void
+finish_setup (CEPageVpn *self, gpointer unused, GError *error, gpointer user_data)
+{
+ const char *vpn_type;
+
+ self->setting_connection = nm_connection_get_setting_connection (self->connection);
+ self->setting_vpn = nm_connection_get_setting_vpn (self->connection);
+ vpn_type = nm_setting_vpn_get_service_type (self->setting_vpn);
+
+ self->plugin = vpn_get_plugin_by_service (vpn_type);
+ if (self->plugin)
+ load_vpn_plugin (self);
+
+ connect_vpn_page (self);
+}
+
+CEPageVpn *
+ce_page_vpn_new (NMConnection *connection)
+{
+ CEPageVpn *self;
+
+ self = CE_PAGE_VPN (g_object_new (ce_page_vpn_get_type (), NULL));
+
+ self->connection = g_object_ref (connection);
+
+ g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);
+
+ return self;
+}
diff --git a/panels/network/connection-editor/ce-page-vpn.h b/panels/network/connection-editor/ce-page-vpn.h
new file mode 100644
index 0000000..f194080
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-vpn.h
@@ -0,0 +1,33 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (CEPageVpn, ce_page_vpn, CE, PAGE_VPN, GtkBox)
+
+CEPageVpn *ce_page_vpn_new (NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/connection-editor/ce-page-wifi.c b/panels/network/connection-editor/ce-page-wifi.c
new file mode 100644
index 0000000..5a66292
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-wifi.c
@@ -0,0 +1,212 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <NetworkManager.h>
+#include <net/if_arp.h>
+
+#include "ce-page.h"
+#include "ce-page-wifi.h"
+#include "ui-helpers.h"
+
+struct _CEPageWifi
+{
+ GtkGrid parent;
+
+ GtkComboBoxText *bssid_combo;
+ GtkComboBoxText *cloned_mac_combo;
+ GtkComboBoxText *mac_combo;
+ GtkEntry *ssid_entry;
+
+ NMClient *client;
+ NMSettingWireless *setting;
+};
+
+static void ce_page_iface_init (CEPageInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (CEPageWifi, ce_page_wifi, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (ce_page_get_type (), ce_page_iface_init))
+
+static void
+connect_wifi_page (CEPageWifi *self)
+{
+ GBytes *ssid;
+ g_autofree gchar *utf8_ssid = NULL;
+ GPtrArray *bssid_array;
+ gchar **bssid_list;
+ const char *s_bssid_str;
+ gchar **mac_list;
+ const gchar *s_mac_str;
+ const gchar *cloned_mac;
+ gint i;
+
+ ssid = nm_setting_wireless_get_ssid (self->setting);
+ if (ssid)
+ utf8_ssid = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid));
+ else
+ utf8_ssid = g_strdup ("");
+ gtk_editable_set_text (GTK_EDITABLE (self->ssid_entry), utf8_ssid);
+
+ g_signal_connect_object (self->ssid_entry, "changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+
+ bssid_array = g_ptr_array_new ();
+ for (i = 0; i < nm_setting_wireless_get_num_seen_bssids (self->setting); i++) {
+ g_ptr_array_add (bssid_array, g_strdup (nm_setting_wireless_get_seen_bssid (self->setting, i)));
+ }
+ g_ptr_array_add (bssid_array, NULL);
+ bssid_list = (gchar **) g_ptr_array_free (bssid_array, FALSE);
+ s_bssid_str = nm_setting_wireless_get_bssid (self->setting);
+ ce_page_setup_mac_combo (self->bssid_combo, s_bssid_str, bssid_list);
+ g_strfreev (bssid_list);
+ g_signal_connect_object (self->bssid_combo, "changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+
+ mac_list = ce_page_get_mac_list (self->client, NM_TYPE_DEVICE_WIFI,
+ NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS);
+ s_mac_str = nm_setting_wireless_get_mac_address (self->setting);
+ ce_page_setup_mac_combo (self->mac_combo, s_mac_str, mac_list);
+ g_strfreev (mac_list);
+ g_signal_connect_object (self->mac_combo, "changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+
+ cloned_mac = nm_setting_wireless_get_cloned_mac_address (self->setting);
+ ce_page_setup_cloned_mac_combo (self->cloned_mac_combo, cloned_mac);
+ g_signal_connect_object (self->cloned_mac_combo, "changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED);
+}
+
+static void
+ui_to_setting (CEPageWifi *self)
+{
+ g_autoptr(GBytes) ssid = NULL;
+ const gchar *utf8_ssid, *bssid;
+ GtkWidget *entry;
+ g_autofree gchar *device_mac = NULL;
+ g_autofree gchar *cloned_mac = NULL;
+
+ utf8_ssid = gtk_editable_get_text (GTK_EDITABLE (self->ssid_entry));
+ if (!utf8_ssid || !*utf8_ssid)
+ ssid = NULL;
+ else {
+ ssid = g_bytes_new_static (utf8_ssid, strlen (utf8_ssid));
+ }
+ entry = gtk_combo_box_get_child (GTK_COMBO_BOX (self->bssid_combo));
+ bssid = gtk_editable_get_text (GTK_EDITABLE (entry));
+ if (*bssid == '\0')
+ bssid = NULL;
+ entry = gtk_combo_box_get_child (GTK_COMBO_BOX (self->mac_combo));
+ device_mac = ce_page_trim_address (gtk_editable_get_text (GTK_EDITABLE (entry)));
+ cloned_mac = ce_page_cloned_mac_get (self->cloned_mac_combo);
+
+ g_object_set (self->setting,
+ NM_SETTING_WIRELESS_SSID, ssid,
+ NM_SETTING_WIRELESS_BSSID, bssid,
+ NM_SETTING_WIRELESS_MAC_ADDRESS, device_mac,
+ NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, cloned_mac,
+ NULL);
+}
+
+static const gchar *
+ce_page_wifi_get_title (CEPage *page)
+{
+ return _("Identity");
+}
+
+static gboolean
+ce_page_wifi_class_validate (CEPage *parent,
+ NMConnection *connection,
+ GError **error)
+{
+ CEPageWifi *self = (CEPageWifi *) parent;
+ GtkWidget *entry;
+ gboolean ret = TRUE;
+
+ entry = gtk_combo_box_get_child (GTK_COMBO_BOX (self->bssid_combo));
+ if (!ce_page_address_is_valid (gtk_editable_get_text (GTK_EDITABLE (entry)))) {
+ widget_set_error (entry);
+ ret = FALSE;
+ } else {
+ widget_unset_error (entry);
+ }
+
+ entry = gtk_combo_box_get_child (GTK_COMBO_BOX (self->mac_combo));
+ if (!ce_page_address_is_valid (gtk_editable_get_text (GTK_EDITABLE (entry)))) {
+ widget_set_error (entry);
+ ret = FALSE;
+ } else {
+ widget_unset_error (entry);
+ }
+
+ if (!ce_page_cloned_mac_combo_valid (self->cloned_mac_combo)) {
+ widget_set_error (gtk_combo_box_get_child (GTK_COMBO_BOX (self->cloned_mac_combo)));
+ ret = FALSE;
+ } else {
+ widget_unset_error (gtk_combo_box_get_child (GTK_COMBO_BOX (self->cloned_mac_combo)));
+ }
+
+ if (!ret)
+ return ret;
+
+ ui_to_setting (CE_PAGE_WIFI (self));
+
+ return ret;
+}
+
+static void
+ce_page_wifi_init (CEPageWifi *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+ce_page_wifi_class_init (CEPageWifiClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/wifi-page.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CEPageWifi, bssid_combo);
+ gtk_widget_class_bind_template_child (widget_class, CEPageWifi, cloned_mac_combo);
+ gtk_widget_class_bind_template_child (widget_class, CEPageWifi, mac_combo);
+ gtk_widget_class_bind_template_child (widget_class, CEPageWifi, ssid_entry);
+}
+
+static void
+ce_page_iface_init (CEPageInterface *iface)
+{
+ iface->get_title = ce_page_wifi_get_title;
+ iface->validate = ce_page_wifi_class_validate;
+}
+
+CEPageWifi *
+ce_page_wifi_new (NMConnection *connection,
+ NMClient *client)
+{
+ CEPageWifi *self;
+
+ self = CE_PAGE_WIFI (g_object_new (ce_page_wifi_get_type (), NULL));
+
+ self->client = client;
+ self->setting = nm_connection_get_setting_wireless (connection);
+
+ connect_wifi_page (self);
+
+ return self;
+}
diff --git a/panels/network/connection-editor/ce-page-wifi.h b/panels/network/connection-editor/ce-page-wifi.h
new file mode 100644
index 0000000..8beabad
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-wifi.h
@@ -0,0 +1,32 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_DECLARE_FINAL_TYPE (CEPageWifi, ce_page_wifi, CE, PAGE_WIFI, GtkGrid)
+
+CEPageWifi *ce_page_wifi_new (NMConnection *connection,
+ NMClient *client);
+
+G_END_DECLS
diff --git a/panels/network/connection-editor/ce-page.c b/panels/network/connection-editor/ce-page.c
new file mode 100644
index 0000000..b6f0779
--- /dev/null
+++ b/panels/network/connection-editor/ce-page.c
@@ -0,0 +1,417 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <net/if_arp.h>
+#include <netinet/ether.h>
+
+#include <NetworkManager.h>
+
+#include <glib/gi18n.h>
+
+#include "ce-page.h"
+
+
+G_DEFINE_INTERFACE (CEPage, ce_page, G_TYPE_OBJECT)
+
+enum {
+ CHANGED,
+ INITIALIZED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+gboolean
+ce_page_validate (CEPage *self, NMConnection *connection, GError **error)
+{
+ g_return_val_if_fail (CE_IS_PAGE (self), FALSE);
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
+
+ if (CE_PAGE_GET_IFACE (self)->validate)
+ return CE_PAGE_GET_IFACE (self)->validate (self, connection, error);
+
+ return TRUE;
+}
+
+const char *
+ce_page_get_title (CEPage *self)
+{
+ g_return_val_if_fail (CE_IS_PAGE (self), NULL);
+
+ return CE_PAGE_GET_IFACE (self)->get_title (self);
+}
+
+void
+ce_page_changed (CEPage *self)
+{
+ g_return_if_fail (CE_IS_PAGE (self));
+
+ g_signal_emit (self, signals[CHANGED], 0);
+}
+
+static void
+ce_page_default_init (CEPageInterface *iface)
+{
+ signals[CHANGED] =
+ g_signal_new ("changed",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_FIRST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[INITIALIZED] =
+ g_signal_new ("initialized",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_FIRST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
+}
+
+static void
+emit_initialized (CEPage *self,
+ GError *error)
+{
+ g_signal_emit (self, signals[INITIALIZED], 0, error);
+ g_clear_error (&error);
+}
+
+void
+ce_page_complete_init (CEPage *self,
+ NMConnection *connection,
+ const gchar *setting_name,
+ GVariant *secrets,
+ GError *error)
+{
+ g_autoptr(GError) update_error = NULL;
+ g_autoptr(GVariant) setting_dict = NULL;
+ gboolean ignore_error = FALSE;
+
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (CE_IS_PAGE (self));
+
+ if (error) {
+ ignore_error = g_error_matches (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_SETTING_NOT_FOUND) ||
+ g_error_matches (error, NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_NO_SECRETS);
+ }
+
+ /* Ignore missing settings errors */
+ if (error && !ignore_error) {
+ emit_initialized (self, error);
+ return;
+ } else if (!setting_name || !secrets || g_variant_n_children (secrets) == 0) {
+ /* Success, no secrets */
+ emit_initialized (self, NULL);
+ return;
+ }
+
+ g_assert (setting_name);
+ g_assert (secrets);
+
+ setting_dict = g_variant_lookup_value (secrets, setting_name, NM_VARIANT_TYPE_SETTING);
+ if (!setting_dict) {
+ /* Success, no secrets */
+ emit_initialized (self, NULL);
+ return;
+ }
+
+ /* Update the connection with the new secrets */
+ if (!nm_connection_update_secrets (connection,
+ setting_name,
+ secrets,
+ &update_error))
+ g_warning ("Couldn't update secrets: %s", update_error->message);
+
+ emit_initialized (self, NULL);
+}
+
+gchar **
+ce_page_get_mac_list (NMClient *client,
+ GType device_type,
+ const gchar *mac_property)
+{
+ const GPtrArray *devices;
+ GPtrArray *macs;
+ int i;
+
+ macs = g_ptr_array_new ();
+ devices = nm_client_get_devices (client);
+ for (i = 0; devices && (i < devices->len); i++) {
+ NMDevice *dev = g_ptr_array_index (devices, i);
+ const char *iface;
+ g_autofree gchar *mac = NULL;
+ g_autofree gchar *item = NULL;
+
+ if (!G_TYPE_CHECK_INSTANCE_TYPE (dev, device_type))
+ continue;
+
+ g_object_get (G_OBJECT (dev), mac_property, &mac, NULL);
+ iface = nm_device_get_iface (NM_DEVICE (dev));
+ item = g_strdup_printf ("%s (%s)", mac, iface);
+ g_ptr_array_add (macs, g_steal_pointer (&item));
+ }
+
+ g_ptr_array_add (macs, NULL);
+ return (char **)g_ptr_array_free (macs, FALSE);
+}
+
+void
+ce_page_setup_mac_combo (GtkComboBoxText *combo,
+ const gchar *current_mac,
+ gchar **mac_list)
+{
+ gchar **m, *active_mac = NULL;
+ gint current_mac_len;
+ GtkWidget *entry;
+
+ if (current_mac)
+ current_mac_len = strlen (current_mac);
+ else
+ current_mac_len = -1;
+
+ for (m= mac_list; m && *m; m++) {
+ gtk_combo_box_text_append_text (combo, *m);
+ if (current_mac &&
+ g_ascii_strncasecmp (*m, current_mac, current_mac_len) == 0
+ && ((*m)[current_mac_len] == '\0' || (*m)[current_mac_len] == ' '))
+ active_mac = *m;
+ }
+
+ if (current_mac) {
+ if (!active_mac) {
+ gtk_combo_box_text_prepend_text (combo, current_mac);
+ }
+
+ entry = gtk_combo_box_get_child (GTK_COMBO_BOX (combo));
+ if (entry)
+ gtk_editable_set_text (GTK_EDITABLE (entry), active_mac ? active_mac : current_mac);
+ }
+}
+
+gchar *
+ce_page_trim_address (const gchar *addr)
+{
+ char *space;
+
+ if (!addr || *addr == '\0')
+ return NULL;
+
+ space = strchr (addr, ' ');
+ if (space != NULL)
+ return g_strndup (addr, space - addr);
+ return g_strdup (addr);
+}
+
+void
+ce_page_setup_cloned_mac_combo (GtkComboBoxText *combo, const char *current)
+{
+ GtkWidget *entry;
+ static const char *entries[][2] = { { "preserve", N_("Preserve") },
+ { "permanent", N_("Permanent") },
+ { "random", N_("Random") },
+ { "stable", N_("Stable") } };
+ int i, active = -1;
+
+ gtk_widget_set_tooltip_text (GTK_WIDGET (combo),
+ _("The MAC address entered here will be used as hardware address for "
+ "the network device this connection is activated on. This feature is "
+ "known as MAC cloning or spoofing. Example: 00:11:22:33:44:55"));
+
+ gtk_combo_box_text_remove_all (combo);
+
+ for (i = 0; i < G_N_ELEMENTS (entries); i++) {
+ gtk_combo_box_text_append (combo, entries[i][0], _(entries[i][1]));
+ if (g_strcmp0 (current, entries[i][0]) == 0)
+ active = i;
+ }
+
+ if (active != -1) {
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo), active);
+ } else if (current && current[0]) {
+ entry = gtk_combo_box_get_child (GTK_COMBO_BOX (combo));
+ g_assert (entry);
+ gtk_editable_set_text (GTK_EDITABLE (entry), current);
+ }
+}
+
+char *
+ce_page_cloned_mac_get (GtkComboBoxText *combo)
+{
+ g_autofree gchar *active_text = NULL;
+ const char *id;
+
+ id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (combo));
+ if (id)
+ return g_strdup (id);
+
+ active_text = gtk_combo_box_text_get_active_text (combo);
+
+ if (active_text[0] == '\0')
+ return NULL;
+
+ return g_steal_pointer (&active_text);
+}
+
+gboolean
+ce_page_address_is_valid (const gchar *addr)
+{
+ guint8 invalid_addr[4][ETH_ALEN] = {
+ {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x44, 0x44, 0x44, 0x44, 0x44, 0x44},
+ {0x00, 0x30, 0xb4, 0x00, 0x00, 0x00}, /* prism54 dummy MAC */
+ };
+ guint8 addr_bin[ETH_ALEN];
+ g_autofree gchar *trimmed_addr = NULL;
+ guint i;
+
+ if (!addr || *addr == '\0')
+ return TRUE;
+
+ trimmed_addr = ce_page_trim_address (addr);
+
+ if (!nm_utils_hwaddr_valid (trimmed_addr, -1))
+ return FALSE;
+
+ if (!nm_utils_hwaddr_aton (trimmed_addr, addr_bin, ETH_ALEN))
+ return FALSE;
+
+ /* Check for multicast address */
+ if ((((guint8 *) addr_bin)[0]) & 0x01)
+ return FALSE;
+
+ for (i = 0; i < G_N_ELEMENTS (invalid_addr); i++) {
+ if (nm_utils_hwaddr_matches (addr_bin, ETH_ALEN, invalid_addr[i], ETH_ALEN))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+ce_page_cloned_mac_combo_valid (GtkComboBoxText *combo)
+{
+ g_autofree gchar *active_text = NULL;
+
+ if (gtk_combo_box_get_active (GTK_COMBO_BOX (combo)) != -1)
+ return TRUE;
+
+ active_text = gtk_combo_box_text_get_active_text (combo);
+
+ return active_text[0] == '\0' || ce_page_address_is_valid (active_text);
+}
+
+const gchar *
+ce_page_get_security_setting (CEPage *self)
+{
+ if (CE_PAGE_GET_IFACE (self)->get_security_setting)
+ return CE_PAGE_GET_IFACE (self)->get_security_setting (self);
+
+ return NULL;
+}
+
+gint
+ce_get_property_default (NMSetting *setting, const gchar *property_name)
+{
+ GParamSpec *spec;
+ GValue value = { 0, };
+
+ spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), property_name);
+ g_return_val_if_fail (spec != NULL, -1);
+
+ g_value_init (&value, spec->value_type);
+ g_param_value_set_default (spec, &value);
+
+ if (G_VALUE_HOLDS_CHAR (&value))
+ return (int) g_value_get_schar (&value);
+ else if (G_VALUE_HOLDS_INT (&value))
+ return g_value_get_int (&value);
+ else if (G_VALUE_HOLDS_INT64 (&value))
+ return (int) g_value_get_int64 (&value);
+ else if (G_VALUE_HOLDS_LONG (&value))
+ return (int) g_value_get_long (&value);
+ else if (G_VALUE_HOLDS_UINT (&value))
+ return (int) g_value_get_uint (&value);
+ else if (G_VALUE_HOLDS_UINT64 (&value))
+ return (int) g_value_get_uint64 (&value);
+ else if (G_VALUE_HOLDS_ULONG (&value))
+ return (int) g_value_get_ulong (&value);
+ else if (G_VALUE_HOLDS_UCHAR (&value))
+ return (int) g_value_get_uchar (&value);
+ g_return_val_if_fail (FALSE, 0);
+ return 0;
+}
+
+gchar *
+ce_page_get_next_available_name (const GPtrArray *connections,
+ NameFormat format,
+ const gchar *type_name)
+{
+ GSList *names = NULL, *l;
+ gchar *cname = NULL;
+ gint i = 0;
+ guint con_idx;
+
+ for (con_idx = 0; con_idx < connections->len; con_idx++) {
+ NMConnection *connection = g_ptr_array_index (connections, con_idx);
+ const gchar *id;
+
+ id = nm_connection_get_id (connection);
+ g_assert (id);
+ names = g_slist_append (names, (gpointer) id);
+ }
+
+ /* Find the next available unique connection name */
+ while (!cname && (i++ < 10000)) {
+ g_autofree gchar *temp = NULL;
+ gboolean found = FALSE;
+
+ switch (format) {
+ case NAME_FORMAT_TYPE:
+ temp = g_strdup_printf ("%s %d", type_name, i);
+ break;
+ case NAME_FORMAT_PROFILE:
+ temp = g_strdup_printf (_("Profile %d"), i);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ for (l = names; l; l = l->next) {
+ if (!strcmp (l->data, temp)) {
+ found = TRUE;
+ break;
+ }
+ }
+ if (!found)
+ cname = g_steal_pointer (&temp);
+ }
+ g_slist_free (names);
+
+ return cname;
+}
diff --git a/panels/network/connection-editor/ce-page.h b/panels/network/connection-editor/ce-page.h
new file mode 100644
index 0000000..a180afb
--- /dev/null
+++ b/panels/network/connection-editor/ce-page.h
@@ -0,0 +1,79 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <glib-object.h>
+
+#include <NetworkManager.h>
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_INTERFACE (CEPage, ce_page, CE, PAGE, GObject)
+
+struct _CEPageInterface
+{
+ GTypeInterface g_iface;
+
+ gboolean (*validate) (CEPage *page, NMConnection *connection, GError **error);
+ const gchar *(*get_title) (CEPage *page);
+ const gchar *(*get_security_setting) (CEPage *page);
+};
+
+const gchar *ce_page_get_title (CEPage *page);
+const gchar *ce_page_get_security_setting (CEPage *page);
+gboolean ce_page_validate (CEPage *page,
+ NMConnection *connection,
+ GError **error);
+void ce_page_changed (CEPage *page);
+void ce_page_complete_init (CEPage *page,
+ NMConnection *connection,
+ const gchar *setting_name,
+ GVariant *variant,
+ GError *error);
+
+gchar **ce_page_get_mac_list (NMClient *client,
+ GType device_type,
+ const gchar *mac_property);
+void ce_page_setup_mac_combo (GtkComboBoxText *combo,
+ const gchar *current_mac,
+ gchar **mac_list);
+void ce_page_setup_cloned_mac_combo (GtkComboBoxText *combo,
+ const char *current);
+gint ce_get_property_default (NMSetting *setting,
+ const gchar *property_name);
+gboolean ce_page_address_is_valid (const gchar *addr);
+gchar *ce_page_trim_address (const gchar *addr);
+char *ce_page_cloned_mac_get (GtkComboBoxText *combo);
+gboolean ce_page_cloned_mac_combo_valid (GtkComboBoxText *combo);
+
+typedef enum {
+ NAME_FORMAT_TYPE,
+ NAME_FORMAT_PROFILE
+} NameFormat;
+
+gchar * ce_page_get_next_available_name (const GPtrArray *connections,
+ NameFormat format,
+ const gchar *type_name);
+
+G_END_DECLS
diff --git a/panels/network/connection-editor/connection-editor.gresource.xml b/panels/network/connection-editor/connection-editor.gresource.xml
new file mode 100644
index 0000000..3d06f5a
--- /dev/null
+++ b/panels/network/connection-editor/connection-editor.gresource.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/network">
+ <file preprocess="xml-stripblanks">8021x-security-page.ui</file>
+ <file preprocess="xml-stripblanks">connection-editor.ui</file>
+ <file preprocess="xml-stripblanks">details-page.ui</file>
+ <file preprocess="xml-stripblanks">ethernet-page.ui</file>
+ <file preprocess="xml-stripblanks">ip4-page.ui</file>
+ <file preprocess="xml-stripblanks">ip6-page.ui</file>
+ <file preprocess="xml-stripblanks">security-page.ui</file>
+ <file preprocess="xml-stripblanks">vpn-page.ui</file>
+ <file preprocess="xml-stripblanks">wifi-page.ui</file>
+ </gresource>
+</gresources>
diff --git a/panels/network/connection-editor/connection-editor.ui b/panels/network/connection-editor/connection-editor.ui
new file mode 100644
index 0000000..18031e8
--- /dev/null
+++ b/panels/network/connection-editor/connection-editor.ui
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="NetConnectionEditor" parent="GtkDialog">
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="default_width">500</property>
+ <property name="default_height">600</property>
+ <!-- This doesn't seem to work for a template, so it is also hardcoded. -->
+ <property name="use_header_bar">1</property>
+ <signal name="close-request" handler="close_request_cb" swapped="yes"/>
+ <child type="action">
+ <object class="GtkButton" id="cancel_button">
+ <property name="label" translatable="yes">_Cancel</property>
+ <property name="use_underline">True</property>
+ <signal name="clicked" handler="cancel_clicked_cb" object="NetConnectionEditor" swapped="yes"/>
+ </object>
+ </child>
+ <child type="action">
+ <object class="GtkButton" id="apply_button">
+ <property name="label" translatable="yes">_Apply</property>
+ <property name="use_underline">True</property>
+ <signal name="clicked" handler="apply_clicked_cb" object="NetConnectionEditor" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">0</property>
+ <child>
+ <object class="GtkStack" id="toplevel_stack">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <child>
+ <object class="GtkSpinner" id="spinner">
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="spinning">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkNotebook" id="notebook">
+ <property name="show_border">False</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="add_connection_box">
+ <property name="vexpand">True</property>
+ <child>
+ <object class="GtkBox">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="AdwBin" id="add_connection_frame">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="width_request">300</property>
+ <property name="valign">start</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="cancel">cancel_button</action-widget>
+ <action-widget response="apply" default="true">apply_button</action-widget>
+ </action-widgets>
+ </template>
+</interface>
diff --git a/panels/network/connection-editor/details-page.ui b/panels/network/connection-editor/details-page.ui
new file mode 100644
index 0000000..c8e4595
--- /dev/null
+++ b/panels/network/connection-editor/details-page.ui
@@ -0,0 +1,458 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CEPageDetails" parent="GtkGrid">
+ <property name="margin_start">24</property>
+ <property name="margin_end">24</property>
+ <property name="margin_top">24</property>
+ <property name="margin_bottom">24</property>
+ <property name="row_spacing">12</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="strength_heading_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Signal Strength</property>
+ <property name="mnemonic_widget">strength_label</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="strength_label">
+ <property name="hexpand">True</property>
+ <property name="xalign">0</property>
+ <property name="label">Weak</property>
+ <property name="selectable">True</property>
+ <property name="max-width-chars">50</property>
+ <property name="ellipsize">end</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="speed_heading_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Link speed</property>
+ <property name="mnemonic_widget">speed_label</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="speed_label">
+ <property name="xalign">0</property>
+ <property name="label">1Mb/sec</property>
+ <property name="selectable">True</property>
+ <property name="hexpand">True</property>
+ <property name="max-width-chars">50</property>
+ <property name="ellipsize">end</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="security_heading_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Security</property>
+ <property name="mnemonic_widget">security_label</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="ipv4_heading_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">IPv4 Address</property>
+ <property name="mnemonic_widget">ipv4_label</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="ipv6_heading_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">IPv6 Address</property>
+ <property name="mnemonic_widget">ipv6_label</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">4</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="mac_heading_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Hardware Address</property>
+ <property name="mnemonic_widget">mac_label</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">5</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="freq_heading_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Supported Frequencies</property>
+ <property name="mnemonic_widget">freq_label</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">6</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="route_heading_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Default Route</property>
+ <property name="mnemonic_widget">route_label</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">7</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="dns4_heading_label">
+ <property name="xalign">1</property>
+ <property name="yalign">0</property>
+ <property name="label" translatable="yes">DNS</property>
+ <property name="mnemonic_widget">dns4_label</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">8</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="dns6_heading_label">
+ <property name="xalign">1</property>
+ <property name="yalign">0</property>
+ <property name="label" translatable="yes">DNS</property>
+ <property name="mnemonic_widget">dns6_label</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">9</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="last_used_heading_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Last Used</property>
+ <property name="mnemonic_widget">last_used_label</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">10</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="security_label">
+ <property name="xalign">0</property>
+ <property name="label">WPA</property>
+ <property name="selectable">True</property>
+ <property name="hexpand">True</property>
+ <property name="max-width-chars">50</property>
+ <property name="ellipsize">end</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="ipv4_label">
+ <property name="xalign">0</property>
+ <property name="label">127.0.0.1</property>
+ <property name="selectable">True</property>
+ <property name="hexpand">True</property>
+ <property name="max-width-chars">50</property>
+ <property name="ellipsize">end</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="ipv6_label">
+ <property name="xalign">0</property>
+ <property name="label">::1</property>
+ <property name="selectable">True</property>
+ <property name="hexpand">True</property>
+ <property name="max-width-chars">50</property>
+ <property name="ellipsize">end</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">4</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="mac_label">
+ <property name="xalign">0</property>
+ <property name="label">AA:BB:CC:DD:55:66:77:88</property>
+ <property name="selectable">True</property>
+ <property name="hexpand">True</property>
+ <property name="max-width-chars">50</property>
+ <property name="ellipsize">end</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">5</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="freq_label">
+ <property name="xalign">0</property>
+ <property name="label">2.4 GHz / 5 GHz</property>
+ <property name="selectable">True</property>
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">6</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="route_label">
+ <property name="xalign">0</property>
+ <property name="label">127.0.0.1</property>
+ <property name="selectable">True</property>
+ <property name="hexpand">True</property>
+ <property name="max-width-chars">50</property>
+ <property name="ellipsize">end</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">7</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="dns4_label">
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="label">127.0.0.1</property>
+ <property name="wrap">True</property>
+ <property name="selectable">True</property>
+ <property name="hexpand">True</property>
+ <property name="max-width-chars">50</property>
+ <property name="ellipsize">end</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">8</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="dns6_label">
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="label">::1</property>
+ <property name="wrap">True</property>
+ <property name="selectable">True</property>
+ <property name="hexpand">True</property>
+ <property name="max-width-chars">50</property>
+ <property name="ellipsize">end</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">9</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="last_used_label">
+ <property name="xalign">0</property>
+ <property name="label">today</property>
+ <property name="selectable">True</property>
+ <property name="hexpand">True</property>
+ <property name="max-width-chars">50</property>
+ <property name="ellipsize">end</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">10</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="auto_connect_check">
+ <property name="label" translatable="yes">Connect _automatically</property>
+ <property name="valign">end</property>
+ <property name="use_underline">True</property>
+ <property name="margin_top">12</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">11</property>
+ <property name="column-span">2</property>
+ <property name="row-span">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="all_user_check">
+ <property name="label" translatable="yes">Make available to _other users</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">12</property>
+ <property name="column-span">2</property>
+ <property name="row-span">1</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- "Restrict Data Usage" section -->
+ <child>
+ <object class="GtkBox" id="restrict_data_check_container">
+ <layout>
+ <property name="column">0</property>
+ <property name="row">13</property>
+ <property name="column-span">2</property>
+ <property name="row-span">1</property>
+ </layout>
+ <child>
+ <object class="GtkCheckButton" id="restrict_data_check">
+ <property name="margin_bottom">12</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Metered connection: has data limits or can incur charges</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">restrict_data_check</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Software updates and other large downloads will not be started automatically.</property>
+ <property name="wrap">True</property>
+ <property name="max_width_chars">60</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ <attributes>
+ <attribute name="scale" value="0.8" />
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkButton" id="forget_button">
+ <property name="use_underline">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="halign">end</property>
+ <property name="valign">end</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">14</property>
+ <property name="column-span">2</property>
+ <property name="row-span">1</property>
+ </layout>
+ <style>
+ <class name="destructive-action" />
+ </style>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/connection-editor/ethernet-page.ui b/panels/network/connection-editor/ethernet-page.ui
new file mode 100644
index 0000000..ad4f2cb
--- /dev/null
+++ b/panels/network/connection-editor/ethernet-page.ui
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkAdjustment" id="mtu_adjustment">
+ <property name="upper">10000</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <template class="CEPageEthernet" parent="GtkGrid">
+ <property name="margin_start">50</property>
+ <property name="margin_end">50</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">10</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Name</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">name_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="name_entry">
+ <property name="invisible_char">●</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_MAC Address</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">mac_combo</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="mac_combo">
+ <property name="has_entry">True</property>
+ <property name="entry_text_column">0</property>
+ <property name="id_column">1</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="cloned_mac_combo">
+ <property name="has_entry">True</property>
+ <property name="hexpand">True</property>
+ <property name="active_id">0</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ <child internal-child="entry">
+ <object class="GtkEntry">
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">M_TU</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">mtu_spin</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="valign">center</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Cloned Address</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">cloned_mac_combo</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="mtu_label">
+ <property name="label" translatable="yes">bytes</property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="mtu_spin">
+ <property name="adjustment">mtu_adjustment</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/connection-editor/ip4-page.ui b/panels/network/connection-editor/ip4-page.ui
new file mode 100644
index 0000000..a2210ea
--- /dev/null
+++ b/panels/network/connection-editor/ip4-page.ui
@@ -0,0 +1,339 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CEPageIP4" parent="AdwBin">
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="hscrollbar_policy">never</property>
+ <child>
+ <object class="GtkViewport">
+ <child>
+ <object class="GtkGrid" id="main_box">
+ <property name="margin_start">24</property>
+ <property name="margin_end">24</property>
+ <property name="margin_top">24</property>
+ <property name="margin_bottom">24</property>
+ <property name="orientation">vertical</property>
+ <property name="row-spacing">6</property>
+ <property name="column-spacing">6</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">IPv_4 Method</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">disabled_radio</property>
+ <property name="xalign">0.0</property>
+ <layout>
+ <property name="row">0</property>
+ <property name="column">0</property>
+ </layout>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="automatic_radio">
+ <property name="label" translatable="yes">Automatic (DHCP)</property>
+ <layout>
+ <property name="row">0</property>
+ <property name="column">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="local_radio">
+ <property name="label" translatable="yes">Link-Local Only</property>
+ <property name="group">automatic_radio</property>
+ <layout>
+ <property name="row">0</property>
+ <property name="column">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="manual_radio">
+ <property name="label" translatable="yes">Manual</property>
+ <property name="group">automatic_radio</property>
+ <layout>
+ <property name="row">1</property>
+ <property name="column">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="disabled_radio">
+ <property name="label" translatable="yes">Disable</property>
+ <property name="group">automatic_radio</property>
+ <layout>
+ <property name="row">1</property>
+ <property name="column">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="shared_radio">
+ <property name="label" translatable="yes">Shared to other computers</property>
+ <property name="group">automatic_radio</property>
+ <layout>
+ <property name="row">2</property>
+ <property name="column">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="content_box">
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <layout>
+ <property name="row">3</property>
+ <property name="column">0</property>
+ <property name="column-span">3</property>
+ </layout>
+ <child>
+ <object class="GtkBox" id="address_box">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Addresses</property>
+ <property name="margin_top">24</property>
+ <property name="margin_bottom">8</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <child>
+ <object class="GtkLabel" id="address_address_label">
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Address</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ <attributes>
+ <attribute name="scale" value="0.8"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="address_netmask_label">
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Netmask</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ <attributes>
+ <attribute name="scale" value="0.8"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="address_gateway_label">
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Gateway</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ <attributes>
+ <attribute name="scale" value="0.8"/>
+ </attributes>
+ </object>
+ </child>
+
+ <!-- This invisible box is used to add some width in the
+ end of the header row, assuming the space used by the
+ delete button in the rows -->
+ <child>
+ <object class="GtkBox" id="address_stub_box">
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="margin_top">24</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="dns4_label">
+ <property name="hexpand">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">DNS</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="hexpand">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Automatic</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="auto_dns_switch">
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Automatic DNS</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="dns_entry">
+ <accessibility>
+ <property name="label" translatable="yes">DNS server address(es)</property>
+ <relation name="described-by">dns_multiple_help</relation>
+ </accessibility>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="dns_multiple_help">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Separate IP addresses with commas</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ <attributes>
+ <attribute name="scale" value="0.8"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="margin_top">24</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Routes</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="hexpand">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Automatic</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="auto_routes_switch">
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Automatic Routes</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="routes_box">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <child>
+ <object class="GtkLabel" id="routes_address_label">
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Address</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ <attributes>
+ <attribute name="scale" value="0.8"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="routes_netmask_label">
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Netmask</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ <attributes>
+ <attribute name="scale" value="0.8"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="routes_gateway_label">
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Gateway</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ <attributes>
+ <attribute name="scale" value="0.8"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="routes_metric_label">
+ <property name="label" translatable="yes" comments="Translators: Please see https://en.wikipedia.org/wiki/Metrics_(networking)">Metric</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ <attributes>
+ <attribute name="scale" value="0.8"/>
+ </attributes>
+ </object>
+ </child>
+
+ <!-- This invisible box is used to add some width in the
+ end of the header row, assuming the space used by the
+ delete button in the rows -->
+ <child>
+ <object class="GtkBox" id="routes_stub_box">
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="never_default_check">
+ <property name="label" translatable="yes">Use this connection _only for resources on its network</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GtkSizeGroup" id="routes_metric_sizegroup">
+ <property name="mode">horizontal</property>
+ <widgets>
+ <widget name="routes_metric_label" />
+ </widgets>
+ </object>
+ <object class="GtkSizeGroup" id="routes_sizegroup">
+ <property name="mode">horizontal</property>
+ <widgets>
+ <widget name="routes_stub_box" />
+ </widgets>
+ </object>
+ <object class="GtkSizeGroup" id="address_sizegroup">
+ <property name="mode">horizontal</property>
+ <widgets>
+ <widget name="address_stub_box" />
+ </widgets>
+ </object>
+</interface>
diff --git a/panels/network/connection-editor/ip6-page.ui b/panels/network/connection-editor/ip6-page.ui
new file mode 100644
index 0000000..c22fb0f
--- /dev/null
+++ b/panels/network/connection-editor/ip6-page.ui
@@ -0,0 +1,349 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CEPageIP6" parent="AdwBin">column
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="hscrollbar_policy">never</property>
+ <child>
+ <object class="GtkViewport">
+ <child>
+ <object class="GtkGrid" id="main_box">
+ <property name="margin_start">24</property>
+ <property name="margin_end">24</property>
+ <property name="margin_top">24</property>
+ <property name="margin_bottom">24</property>
+ <property name="orientation">vertical</property>
+ <property name="row-spacing">6</property>
+ <property name="column-spacing">6</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">IPv_6 Method</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">disabled_radio</property>
+ <property name="xalign">0.0</property>
+ <layout>
+ <property name="row">0</property>
+ <property name="column">0</property>
+ </layout>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="automatic_radio">
+ <property name="label" translatable="yes">Automatic</property>
+ <layout>
+ <property name="row">0</property>
+ <property name="column">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="dhcp_radio">
+ <property name="label" translatable="yes">Automatic, DHCP only</property>
+ <property name="group">automatic_radio</property>
+ <layout>
+ <property name="row">0</property>
+ <property name="column">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="local_radio">
+ <property name="label" translatable="yes">Link-Local Only</property>
+ <property name="group">automatic_radio</property>
+ <layout>
+ <property name="row">1</property>
+ <property name="column">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="manual_radio">
+ <property name="label" translatable="yes">Manual</property>
+ <property name="group">automatic_radio</property>
+ <layout>
+ <property name="row">1</property>
+ <property name="column">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="disabled_radio">
+ <property name="label" translatable="yes">Disable</property>
+ <property name="group">automatic_radio</property>
+ <layout>
+ <property name="row">2</property>
+ <property name="column">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="shared_radio">
+ <property name="label" translatable="yes">Shared to other computers</property>
+ <property name="group">automatic_radio</property>
+ <layout>
+ <property name="row">2</property>
+ <property name="column">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="content_box">
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <layout>
+ <property name="row">3</property>
+ <property name="column">0</property>
+ <property name="column-span">3</property>
+ </layout>
+ <child>
+ <object class="GtkBox" id="address_box">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Addresses</property>
+ <property name="margin_top">24</property>
+ <property name="margin_bottom">8</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <child>
+ <object class="GtkLabel" id="address_address_label">
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Address</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ <attributes>
+ <attribute name="scale" value="0.8"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="address_prefix_label">
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Prefix</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ <attributes>
+ <attribute name="scale" value="0.8"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="address_gateway_label">
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Gateway</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ <attributes>
+ <attribute name="scale" value="0.8"/>
+ </attributes>
+ </object>
+ </child>
+
+ <!-- This invisible box is used to add some width in the
+ end of the header row, assuming the space used by the
+ delete button in the rows -->
+ <child>
+ <object class="GtkBox" id="address_stub_box">
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="margin_top">24</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="dns6_label">
+ <property name="hexpand">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">DNS</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="hexpand">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Automatic</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="auto_dns_switch">
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Automatic DNS</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="dns_entry">
+ <accessibility>
+ <property name="label" translatable="yes">DNS server address(es)</property>
+ <relation name="described-by">dns_multiple_help</relation>
+ </accessibility>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="dns_multiple_help">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Separate IP addresses with commas</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ <attributes>
+ <attribute name="scale" value="0.8"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="margin_top">24</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Routes</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="hexpand">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Automatic</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="auto_routes_switch">
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Automatic Routes</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="routes_box">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <child>
+ <object class="GtkLabel" id="routes_address_label">
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Address</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ <attributes>
+ <attribute name="scale" value="0.8"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="routes_prefix_label">
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Prefix</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ <attributes>
+ <attribute name="scale" value="0.8"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="routes_gateway_label">
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Gateway</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ <attributes>
+ <attribute name="scale" value="0.8"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="routes_metric_label">
+ <property name="label" translatable="yes" comments="Translators: Please see https://en.wikipedia.org/wiki/Metrics_(networking)">Metric</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ <attributes>
+ <attribute name="scale" value="0.8"/>
+ </attributes>
+ </object>
+ </child>
+
+ <!-- This invisible box is used to add some width in the
+ end of the header row, assuming the space used by the
+ delete button in the rows -->
+ <child>
+ <object class="GtkBox" id="routes_stub_box">
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="never_default_check">
+ <property name="label" translatable="yes">Use this connection _only for resources on its network</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GtkSizeGroup" id="routes_metric_sizegroup">
+ <property name="mode">horizontal</property>
+ <widgets>
+ <widget name="routes_metric_label" />
+ </widgets>
+ </object>
+ <object class="GtkSizeGroup" id="routes_sizegroup">
+ <property name="mode">horizontal</property>
+ <widgets>
+ <widget name="routes_stub_box" />
+ </widgets>
+ </object>
+ <object class="GtkSizeGroup" id="address_sizegroup">
+ <property name="mode">horizontal</property>
+ <widgets>
+ <widget name="address_stub_box" />
+ </widgets>
+ </object>
+</interface>
diff --git a/panels/network/connection-editor/meson.build b/panels/network/connection-editor/meson.build
new file mode 100644
index 0000000..fd4ddf9
--- /dev/null
+++ b/panels/network/connection-editor/meson.build
@@ -0,0 +1,48 @@
+name = 'connection-editor'
+
+sources = files(
+ 'ce-ip-address-entry.c',
+ 'ce-netmask-entry.c',
+ 'ce-page-8021x-security.c',
+ 'ce-page-details.c',
+ 'ce-page-ethernet.c',
+ 'ce-page-ip4.c',
+ 'ce-page-ip6.c',
+ 'ce-page-security.c',
+ 'ce-page-vpn.c',
+ 'ce-page-wifi.c',
+ 'ce-page.c',
+ 'net-connection-editor.c',
+ 'vpn-helpers.c'
+)
+
+resource_data = files(
+ '8021x-security-page.ui',
+ 'connection-editor.ui',
+ 'details-page.ui',
+ 'ethernet-page.ui',
+ 'ip4-page.ui',
+ 'ip6-page.ui',
+ 'security-page.ui',
+ 'vpn-page.ui',
+ 'wifi-page.ui'
+)
+
+c_name = 'net-' + name
+
+sources += gnome.compile_resources(
+ c_name + '-resources',
+ name + '.gresource.xml',
+ c_name: c_name.underscorify(),
+ dependencies: resource_data,
+ export: true
+)
+
+libconnection_editor = static_library(
+ name,
+ sources: sources,
+ include_directories: [top_inc, common_inc, network_inc, wireless_security_inc],
+ dependencies: deps,
+ c_args: cflags,
+ link_with: libwireless_security
+)
diff --git a/panels/network/connection-editor/net-connection-editor.c b/panels/network/connection-editor/net-connection-editor.c
new file mode 100644
index 0000000..9de938c
--- /dev/null
+++ b/panels/network/connection-editor/net-connection-editor.c
@@ -0,0 +1,830 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <glib/gi18n.h>
+
+#include <NetworkManager.h>
+
+#include "net-connection-editor.h"
+#include "net-connection-editor-resources.h"
+#include "ce-page.h"
+#include "ce-page-details.h"
+#include "ce-page-wifi.h"
+#include "ce-page-ip4.h"
+#include "ce-page-ip6.h"
+#include "ce-page-security.h"
+#include "ce-page-ethernet.h"
+#include "ce-page-8021x-security.h"
+#include "ce-page-vpn.h"
+#include "vpn-helpers.h"
+#include "eap-method.h"
+
+enum {
+ DONE,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+struct _NetConnectionEditor
+{
+ GtkDialog parent;
+
+ GtkBox *add_connection_box;
+ AdwBin *add_connection_frame;
+ GtkButton *apply_button;
+ GtkButton *cancel_button;
+ GtkNotebook *notebook;
+ GtkStack *toplevel_stack;
+
+ NMClient *client;
+ NMDevice *device;
+
+ NMConnection *connection;
+ NMConnection *orig_connection;
+ gboolean is_new_connection;
+ gboolean is_changed;
+ NMAccessPoint *ap;
+
+ GSList *initializing_pages;
+
+ NMClientPermissionResult can_modify;
+
+ gboolean title_set;
+};
+
+G_DEFINE_TYPE (NetConnectionEditor, net_connection_editor, GTK_TYPE_DIALOG)
+
+static void page_changed (NetConnectionEditor *self);
+
+static void
+cancel_editing (NetConnectionEditor *self)
+{
+ g_signal_emit (self, signals[DONE], 0, FALSE);
+ gtk_window_destroy (GTK_WINDOW (self));
+}
+
+static void
+close_request_cb (NetConnectionEditor *self)
+{
+ cancel_editing (self);
+}
+
+static void
+cancel_clicked_cb (NetConnectionEditor *self)
+{
+ cancel_editing (self);
+}
+
+static void
+update_connection (NetConnectionEditor *self)
+{
+ g_autoptr(GVariant) settings = NULL;
+
+ settings = nm_connection_to_dbus (self->connection, NM_CONNECTION_SERIALIZE_ALL);
+ nm_connection_replace_settings (self->orig_connection, settings, NULL);
+}
+
+static void
+update_complete (NetConnectionEditor *self,
+ gboolean success)
+{
+ gtk_widget_hide (GTK_WIDGET (self));
+ g_signal_emit (self, signals[DONE], 0, success);
+}
+
+static void
+updated_connection_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ NetConnectionEditor *self;
+ g_autoptr(GError) error = NULL;
+ gboolean success = TRUE;
+
+ if (!nm_remote_connection_commit_changes_finish (NM_REMOTE_CONNECTION (source_object),
+ res, &error)) {
+ g_warning ("Failed to commit changes: %s", error->message);
+ success = FALSE;
+ //return; FIXME return if cancelled
+ }
+
+ nm_connection_clear_secrets (NM_CONNECTION (source_object));
+
+ self = user_data;
+ update_complete (self, success);
+}
+
+static void
+added_connection_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ NetConnectionEditor *self;
+ g_autoptr(GError) error = NULL;
+ gboolean success = TRUE;
+
+ if (!nm_client_add_connection_finish (NM_CLIENT (source_object), res, &error)) {
+ g_warning ("Failed to add connection: %s", error->message);
+ success = FALSE;
+ /* Leave the editor open */
+ // return; FIXME return if cancelled
+ }
+
+ self = user_data;
+ update_complete (self, success);
+}
+
+static void
+apply_clicked_cb (NetConnectionEditor *self)
+{
+ update_connection (self);
+
+ eap_method_ca_cert_ignore_save (self->connection);
+
+ if (self->is_new_connection) {
+ nm_client_add_connection_async (self->client,
+ self->orig_connection,
+ TRUE,
+ NULL,
+ added_connection_cb,
+ self);
+ } else {
+ nm_remote_connection_commit_changes_async (NM_REMOTE_CONNECTION (self->orig_connection),
+ TRUE,
+ NULL,
+ updated_connection_cb, self);
+ }
+}
+
+static void
+net_connection_editor_init (NetConnectionEditor *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+net_connection_editor_finalize (GObject *object)
+{
+ NetConnectionEditor *self = NET_CONNECTION_EDITOR (object);
+
+ g_clear_object (&self->connection);
+ g_clear_object (&self->orig_connection);
+ g_clear_object (&self->device);
+ g_clear_object (&self->client);
+ g_clear_object (&self->ap);
+
+ G_OBJECT_CLASS (net_connection_editor_parent_class)->finalize (object);
+}
+
+static void
+net_connection_editor_class_init (NetConnectionEditorClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+
+ g_resources_register (net_connection_editor_get_resource ());
+
+ object_class->finalize = net_connection_editor_finalize;
+
+ signals[DONE] = g_signal_new ("done",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ 0,
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/connection-editor.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, NetConnectionEditor, add_connection_box);
+ gtk_widget_class_bind_template_child (widget_class, NetConnectionEditor, add_connection_frame);
+ gtk_widget_class_bind_template_child (widget_class, NetConnectionEditor, apply_button);
+ gtk_widget_class_bind_template_child (widget_class, NetConnectionEditor, cancel_button);
+ gtk_widget_class_bind_template_child (widget_class, NetConnectionEditor, notebook);
+ gtk_widget_class_bind_template_child (widget_class, NetConnectionEditor, toplevel_stack);
+
+ gtk_widget_class_bind_template_callback (widget_class, cancel_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, close_request_cb);
+ gtk_widget_class_bind_template_callback (widget_class, apply_clicked_cb);
+}
+
+static void
+net_connection_editor_error_dialog (NetConnectionEditor *self,
+ const char *primary_text,
+ const char *secondary_text)
+{
+ GtkWidget *dialog;
+ GtkWindow *parent;
+
+ if (gtk_widget_is_visible (GTK_WIDGET (self)))
+ parent = GTK_WINDOW (self);
+ else
+ parent = gtk_window_get_transient_for (GTK_WINDOW (self));
+
+ dialog = gtk_message_dialog_new (parent,
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ "%s", primary_text);
+
+ if (secondary_text) {
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s", secondary_text);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+static void
+net_connection_editor_do_fallback (NetConnectionEditor *self, const gchar *type)
+{
+ g_autofree gchar *cmdline = NULL;
+ g_autoptr(GError) error = NULL;
+
+ if (self->is_new_connection) {
+ cmdline = g_strdup_printf ("nm-connection-editor --type='%s' --create", type);
+ } else {
+ cmdline = g_strdup_printf ("nm-connection-editor --edit='%s'",
+ nm_connection_get_uuid (self->connection));
+ }
+
+ g_spawn_command_line_async (cmdline, &error);
+
+ if (error)
+ net_connection_editor_error_dialog (self,
+ _("Unable to open connection editor"),
+ error->message);
+
+ g_signal_emit (self, signals[DONE], 0, FALSE);
+}
+
+static void
+net_connection_editor_update_title (NetConnectionEditor *self)
+{
+ g_autofree gchar *id = NULL;
+
+ if (self->title_set)
+ return;
+
+ if (self->is_new_connection) {
+ if (self->device) {
+ id = g_strdup (_("New Profile"));
+ } else {
+ /* Leave it set to "Add New Connection" */
+ return;
+ }
+ } else {
+ NMSettingWireless *sw;
+ sw = nm_connection_get_setting_wireless (self->connection);
+ if (sw) {
+ GBytes *ssid;
+ ssid = nm_setting_wireless_get_ssid (sw);
+ id = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid));
+ } else {
+ id = g_strdup (nm_connection_get_id (self->connection));
+ }
+ }
+ gtk_window_set_title (GTK_WINDOW (self), id);
+}
+
+static gboolean
+editor_is_initialized (NetConnectionEditor *self)
+{
+ return self->initializing_pages == NULL;
+}
+
+static void
+update_sensitivity (NetConnectionEditor *self)
+{
+ NMSettingConnection *sc;
+ gboolean sensitive;
+ gint i;
+
+ if (!editor_is_initialized (self))
+ return;
+
+ sc = nm_connection_get_setting_connection (self->connection);
+
+ if (nm_setting_connection_get_read_only (sc)) {
+ sensitive = FALSE;
+ } else {
+ sensitive = self->can_modify;
+ }
+
+ for (i = 0; i < gtk_notebook_get_n_pages (self->notebook); i++) {
+ GtkWidget *page = gtk_notebook_get_nth_page (self->notebook, i);
+ gtk_widget_set_sensitive (page, sensitive);
+ }
+}
+
+static void
+validate (NetConnectionEditor *self)
+{
+ gboolean valid = FALSE;
+ g_autofree gchar *apply_tooltip = NULL;
+ gint i;
+
+ if (!editor_is_initialized (self))
+ goto done;
+
+ valid = TRUE;
+ for (i = 0; i < gtk_notebook_get_n_pages (self->notebook); i++) {
+ CEPage *page = CE_PAGE (gtk_notebook_get_nth_page (self->notebook, i));
+ g_autoptr(GError) error = NULL;
+
+ if (!ce_page_validate (page, self->connection, &error)) {
+ valid = FALSE;
+ if (error) {
+ apply_tooltip = g_strdup_printf (_("Invalid setting %s: %s"), ce_page_get_title (page), error->message);
+ g_debug ("%s", apply_tooltip);
+ } else {
+ apply_tooltip = g_strdup_printf (_("Invalid setting %s"), ce_page_get_title (page));
+ g_debug ("%s", apply_tooltip);
+ }
+ }
+ }
+
+ update_sensitivity (self);
+done:
+ if (apply_tooltip != NULL)
+ gtk_widget_set_tooltip_text(GTK_WIDGET (self->apply_button), apply_tooltip);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->apply_button), valid && self->is_changed);
+}
+
+static void
+page_changed (NetConnectionEditor *self)
+{
+ if (editor_is_initialized (self))
+ self->is_changed = TRUE;
+ validate (self);
+}
+
+static gboolean
+idle_validate (gpointer user_data)
+{
+ validate (NET_CONNECTION_EDITOR (user_data));
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+recheck_initialization (NetConnectionEditor *self)
+{
+ if (!editor_is_initialized (self))
+ return;
+
+ gtk_stack_set_visible_child (self->toplevel_stack, GTK_WIDGET (self->notebook));
+ gtk_notebook_set_current_page (self->notebook, 0);
+
+ g_idle_add (idle_validate, self);
+}
+
+static void
+page_initialized (NetConnectionEditor *self, GError *error, CEPage *page)
+{
+ GtkWidget *label;
+ gint position;
+ gint i;
+
+ position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (page), "position"));
+ g_object_set_data (G_OBJECT (page), "position", GINT_TO_POINTER (position));
+ for (i = 0; i < gtk_notebook_get_n_pages (self->notebook); i++) {
+ GtkWidget *page = gtk_notebook_get_nth_page (self->notebook, i);
+ gint pos = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (page), "position"));
+ if (pos > position)
+ break;
+ }
+
+ label = gtk_label_new (ce_page_get_title (page));
+
+ gtk_notebook_insert_page (self->notebook, GTK_WIDGET (page), label, i);
+
+ self->initializing_pages = g_slist_remove (self->initializing_pages, page);
+
+ recheck_initialization (self);
+}
+
+typedef struct {
+ NetConnectionEditor *editor;
+ CEPage *page;
+ const gchar *setting_name;
+} GetSecretsInfo;
+
+static void
+get_secrets_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ NMRemoteConnection *connection;
+ g_autofree GetSecretsInfo *info = user_data;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) variant = NULL;
+
+ connection = NM_REMOTE_CONNECTION (source_object);
+ variant = nm_remote_connection_get_secrets_finish (connection, res, &error);
+
+ if (!variant && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
+ ce_page_complete_init (info->page, info->editor->connection, info->setting_name, variant, g_steal_pointer (&error));
+}
+
+static void
+get_secrets_for_page (NetConnectionEditor *self,
+ CEPage *page,
+ const gchar *setting_name)
+{
+ GetSecretsInfo *info;
+
+ info = g_new0 (GetSecretsInfo, 1);
+ info->editor = self;
+ info->page = page;
+ info->setting_name = setting_name;
+
+ nm_remote_connection_get_secrets_async (NM_REMOTE_CONNECTION (self->orig_connection),
+ setting_name,
+ NULL, //FIXME
+ get_secrets_cb,
+ info);
+}
+
+static void
+add_page (NetConnectionEditor *self, CEPage *page)
+{
+ gint position;
+
+ position = g_slist_length (self->initializing_pages);
+ g_object_set_data (G_OBJECT (page), "position", GINT_TO_POINTER (position));
+
+ self->initializing_pages = g_slist_append (self->initializing_pages, page);
+
+ g_signal_connect_object (page, "changed", G_CALLBACK (page_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (page, "initialized", G_CALLBACK (page_initialized), self, G_CONNECT_SWAPPED);
+}
+
+static void
+net_connection_editor_set_connection (NetConnectionEditor *self,
+ NMConnection *connection)
+{
+ GSList *pages, *l;
+ NMSettingConnection *sc;
+ const gchar *type;
+ gboolean is_wired;
+ gboolean is_wifi;
+ gboolean is_vpn;
+
+ self->is_new_connection = !nm_client_get_connection_by_uuid (self->client,
+ nm_connection_get_uuid (connection));
+
+ if (self->is_new_connection) {
+ gtk_button_set_label (self->apply_button, _("_Add"));
+ self->is_changed = TRUE;
+ }
+
+ self->connection = nm_simple_connection_new_clone (connection);
+ self->orig_connection = g_object_ref (connection);
+
+ net_connection_editor_update_title (self);
+
+ eap_method_ca_cert_ignore_load (self->connection);
+
+ sc = nm_connection_get_setting_connection (connection);
+ type = nm_setting_connection_get_connection_type (sc);
+
+ is_wired = g_str_equal (type, NM_SETTING_WIRED_SETTING_NAME);
+ is_wifi = g_str_equal (type, NM_SETTING_WIRELESS_SETTING_NAME);
+ is_vpn = g_str_equal (type, NM_SETTING_VPN_SETTING_NAME);
+
+ if (!self->is_new_connection)
+ add_page (self, CE_PAGE (ce_page_details_new (self->connection, self->device, self->ap, self)));
+
+ if (is_wifi)
+ add_page (self, CE_PAGE (ce_page_wifi_new (self->connection, self->client)));
+ else if (is_wired)
+ add_page (self, CE_PAGE (ce_page_ethernet_new (self->connection, self->client)));
+ else if (is_vpn)
+ add_page (self, CE_PAGE (ce_page_vpn_new (self->connection)));
+ else {
+ /* Unsupported type */
+ net_connection_editor_do_fallback (self, type);
+ return;
+ }
+
+ add_page (self, CE_PAGE (ce_page_ip4_new (self->connection, self->client)));
+ add_page (self, CE_PAGE (ce_page_ip6_new (self->connection, self->client)));
+
+ if (is_wifi)
+ add_page (self, CE_PAGE (ce_page_security_new (self->connection)));
+ else if (is_wired)
+ add_page (self, CE_PAGE (ce_page_8021x_security_new (self->connection)));
+
+ pages = g_slist_copy (self->initializing_pages);
+ for (l = pages; l; l = l->next) {
+ CEPage *page = l->data;
+ const gchar *security_setting;
+
+ security_setting = ce_page_get_security_setting (page);
+ if (!security_setting || self->is_new_connection) {
+ ce_page_complete_init (page, NULL, NULL, NULL, NULL);
+ } else {
+ get_secrets_for_page (self, page, security_setting);
+ }
+ }
+ g_slist_free (pages);
+}
+
+static NMConnection *
+complete_vpn_connection (NetConnectionEditor *self, NMConnection *connection)
+{
+ NMSettingConnection *s_con;
+ NMSetting *s_type;
+
+ if (!connection)
+ connection = nm_simple_connection_new ();
+
+ s_con = nm_connection_get_setting_connection (connection);
+ if (!s_con) {
+ s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
+ nm_connection_add_setting (connection, NM_SETTING (s_con));
+ }
+
+ if (!nm_setting_connection_get_uuid (s_con)) {
+ g_autofree gchar *uuid = nm_utils_uuid_generate ();
+ g_object_set (s_con,
+ NM_SETTING_CONNECTION_UUID, uuid,
+ NULL);
+ }
+
+ if (!nm_setting_connection_get_id (s_con)) {
+ const GPtrArray *connections;
+ g_autofree gchar *id = NULL;
+
+ connections = nm_client_get_connections (self->client);
+ id = ce_page_get_next_available_name (connections, NAME_FORMAT_TYPE, _("VPN"));
+ g_object_set (s_con,
+ NM_SETTING_CONNECTION_ID, id,
+ NULL);
+ }
+
+ s_type = nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN);
+ if (!s_type) {
+ s_type = g_object_new (NM_TYPE_SETTING_VPN, NULL);
+ nm_connection_add_setting (connection, s_type);
+ }
+
+ if (!nm_setting_connection_get_connection_type (s_con)) {
+ g_object_set (s_con,
+ NM_SETTING_CONNECTION_TYPE, nm_setting_get_name (s_type),
+ NULL);
+ }
+
+ return connection;
+}
+
+static void
+finish_add_connection (NetConnectionEditor *self, NMConnection *connection)
+{
+ adw_bin_set_child (self->add_connection_frame, NULL);
+ gtk_stack_set_visible_child (self->toplevel_stack, GTK_WIDGET (self->notebook));
+ gtk_widget_show (GTK_WIDGET (self->apply_button));
+
+ if (connection)
+ net_connection_editor_set_connection (self, connection);
+}
+
+static void
+vpn_import_complete (NMConnection *connection, gpointer user_data)
+{
+ NetConnectionEditor *self = user_data;
+
+ if (!connection) {
+ /* The import code shows its own error dialogs. */
+ g_signal_emit (self, signals[DONE], 0, FALSE);
+ return;
+ }
+
+ complete_vpn_connection (self, connection);
+ finish_add_connection (self, connection);
+}
+
+static void
+vpn_type_activated (NetConnectionEditor *self, GtkWidget *row)
+{
+ const char *service_name = g_object_get_data (G_OBJECT (row), "service_name");
+ NMConnection *connection;
+ NMSettingVpn *s_vpn;
+ NMSettingConnection *s_con;
+
+ if (!strcmp (service_name, "import")) {
+ vpn_import (GTK_WINDOW (self), vpn_import_complete, self);
+ return;
+ }
+
+ connection = complete_vpn_connection (self, NULL);
+ s_vpn = nm_connection_get_setting_vpn (connection);
+ g_object_set (s_vpn, NM_SETTING_VPN_SERVICE_TYPE, service_name, NULL);
+
+ /* Mark the connection as private to this user, and non-autoconnect */
+ s_con = nm_connection_get_setting_connection (connection);
+ g_object_set (s_con, NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, NULL);
+ nm_setting_connection_add_permission (s_con, "user", g_get_user_name (), NULL);
+
+ finish_add_connection (self, connection);
+}
+
+static void
+select_vpn_type (NetConnectionEditor *self, GtkListBox *list)
+{
+ GSList *vpn_plugins, *iter;
+ GtkWidget *row, *row_box;
+ GtkWidget *name_label, *desc_label;
+ GtkWidget *child;
+
+ /* Get the available VPN types */
+ vpn_plugins = vpn_get_plugins ();
+
+ /* Remove the previous menu contents */
+ while ((child = gtk_widget_get_first_child (GTK_WIDGET (list))) != NULL)
+ gtk_list_box_remove (list, child);
+
+ /* Add the VPN types */
+ for (iter = vpn_plugins; iter; iter = iter->next) {
+ NMVpnEditorPlugin *plugin = nm_vpn_plugin_info_get_editor_plugin (iter->data);
+ g_autofree gchar *name = NULL;
+ g_autofree gchar *desc = NULL;
+ g_autofree gchar *desc_markup = NULL;
+ g_autofree gchar *service_name = NULL;
+
+ g_object_get (plugin,
+ NM_VPN_EDITOR_PLUGIN_NAME, &name,
+ NM_VPN_EDITOR_PLUGIN_DESCRIPTION, &desc,
+ NM_VPN_EDITOR_PLUGIN_SERVICE, &service_name,
+ NULL);
+ desc_markup = g_markup_printf_escaped ("<span size='smaller'>%s</span>", desc);
+
+ row = gtk_list_box_row_new ();
+
+ row_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+ gtk_widget_set_margin_start (row_box, 12);
+ gtk_widget_set_margin_end (row_box, 12);
+ gtk_widget_set_margin_top (row_box, 12);
+ gtk_widget_set_margin_bottom (row_box, 12);
+
+ name_label = gtk_label_new (name);
+ gtk_widget_set_halign (name_label, GTK_ALIGN_START);
+ gtk_box_append (GTK_BOX (row_box), name_label);
+
+ desc_label = gtk_label_new (NULL);
+ gtk_label_set_markup (GTK_LABEL (desc_label), desc_markup);
+ gtk_label_set_wrap (GTK_LABEL (desc_label), TRUE);
+ gtk_widget_set_halign (desc_label, GTK_ALIGN_START);
+ gtk_widget_add_css_class (desc_label, "dim-label");
+ gtk_box_append (GTK_BOX (row_box), desc_label);
+
+ gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), row_box);
+ g_object_set_data_full (G_OBJECT (row), "service_name", g_steal_pointer (&service_name), g_free);
+ gtk_list_box_append (list, row);
+ }
+
+ /* Import */
+ row = gtk_list_box_row_new ();
+
+ row_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+ gtk_widget_set_margin_start (row_box, 12);
+ gtk_widget_set_margin_end (row_box, 12);
+ gtk_widget_set_margin_top (row_box, 12);
+ gtk_widget_set_margin_bottom (row_box, 12);
+
+ name_label = gtk_label_new (_("Import from file…"));
+ gtk_widget_set_halign (name_label, GTK_ALIGN_START);
+ gtk_box_append (GTK_BOX (row_box), name_label);
+
+ gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), row_box);
+ g_object_set_data (G_OBJECT (row), "service_name", "import");
+ gtk_list_box_append (list, row);
+
+ g_signal_connect_object (list, "row-activated",
+ G_CALLBACK (vpn_type_activated), self, G_CONNECT_SWAPPED);
+}
+
+static void
+net_connection_editor_add_connection (NetConnectionEditor *self)
+{
+ GtkListBox *list;
+
+ list = GTK_LIST_BOX (gtk_list_box_new ());
+ gtk_list_box_set_selection_mode (list, GTK_SELECTION_NONE);
+
+ select_vpn_type (self, list);
+
+ adw_bin_set_child (self->add_connection_frame, GTK_WIDGET (list));
+
+ gtk_stack_set_visible_child (self->toplevel_stack, GTK_WIDGET (self->add_connection_box));
+ gtk_widget_hide (GTK_WIDGET (self->apply_button));
+ gtk_window_set_title (GTK_WINDOW (self), _("Add VPN"));
+}
+
+static void
+permission_changed (NetConnectionEditor *self,
+ NMClientPermission permission,
+ NMClientPermissionResult result)
+{
+ if (permission != NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM)
+ return;
+
+ if (result == NM_CLIENT_PERMISSION_RESULT_YES || result == NM_CLIENT_PERMISSION_RESULT_AUTH)
+ self->can_modify = TRUE;
+ else
+ self->can_modify = FALSE;
+
+ validate (self);
+}
+
+NetConnectionEditor *
+net_connection_editor_new (NMConnection *connection,
+ NMDevice *device,
+ NMAccessPoint *ap,
+ NMClient *client)
+{
+ NetConnectionEditor *self;
+
+ self = g_object_new (net_connection_editor_get_type (),
+ /* This doesn't seem to work for a template, so it is also hardcoded. */
+ "use-header-bar", 1,
+ NULL);
+
+ if (ap)
+ self->ap = g_object_ref (ap);
+ if (device)
+ self->device = g_object_ref (device);
+ self->client = g_object_ref (client);
+
+ self->can_modify = nm_client_get_permission_result (client, NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM);
+ g_signal_connect_object (self->client, "permission-changed",
+ G_CALLBACK (permission_changed), self, G_CONNECT_SWAPPED);
+
+ if (connection)
+ net_connection_editor_set_connection (self, connection);
+ else
+ net_connection_editor_add_connection (self);
+
+ return self;
+}
+
+static void
+forgotten_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ NMRemoteConnection *connection = NM_REMOTE_CONNECTION (source_object);
+ NetConnectionEditor *self = user_data;
+ g_autoptr(GError) error = NULL;
+
+ if (!nm_remote_connection_delete_finish (connection, res, &error)) {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to delete connection %s: %s",
+ nm_connection_get_id (NM_CONNECTION (connection)),
+ error->message);
+ return;
+ }
+
+ cancel_editing (self);
+}
+
+void
+net_connection_editor_forget (NetConnectionEditor *self)
+{
+ nm_remote_connection_delete_async (NM_REMOTE_CONNECTION (self->orig_connection),
+ NULL, forgotten_cb, self);
+}
+
+void
+net_connection_editor_set_title (NetConnectionEditor *self,
+ const gchar *title)
+{
+ gtk_window_set_title (GTK_WINDOW (self), title);
+ self->title_set = TRUE;
+}
diff --git a/panels/network/connection-editor/net-connection-editor.h b/panels/network/connection-editor/net-connection-editor.h
new file mode 100644
index 0000000..cbd197f
--- /dev/null
+++ b/panels/network/connection-editor/net-connection-editor.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (NetConnectionEditor, net_connection_editor, NET, CONNECTION_EDITOR, GtkDialog)
+
+NetConnectionEditor *net_connection_editor_new (NMConnection *connection,
+ NMDevice *device,
+ NMAccessPoint *ap,
+ NMClient *client);
+void net_connection_editor_set_title (NetConnectionEditor *editor,
+ const gchar *title);
+void net_connection_editor_forget (NetConnectionEditor *editor);
+
+G_END_DECLS
+
diff --git a/panels/network/connection-editor/security-page.ui b/panels/network/connection-editor/security-page.ui
new file mode 100644
index 0000000..9a1c0de
--- /dev/null
+++ b/panels/network/connection-editor/security-page.ui
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CEPageSecurity" parent="GtkGrid">
+ <property name="margin_start">50</property>
+ <property name="margin_end">50</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">10</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="security_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">S_ecurity</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">security_combo</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="security_combo">
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="box">
+ <property name="orientation">vertical</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ <property name="column-span">2</property>
+ </layout>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/connection-editor/vpn-helpers.c b/panels/network/connection-editor/vpn-helpers.c
new file mode 100644
index 0000000..e0358a9
--- /dev/null
+++ b/panels/network/connection-editor/vpn-helpers.c
@@ -0,0 +1,358 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Connection editor -- Connection editor for NetworkManager
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib.h>
+#include <gmodule.h>
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <NetworkManager.h>
+
+#include "vpn-helpers.h"
+
+NMVpnEditorPlugin *
+vpn_get_plugin_by_service (const char *service)
+{
+ NMVpnPluginInfo *plugin_info;
+
+ g_return_val_if_fail (service != NULL, NULL);
+
+ plugin_info = nm_vpn_plugin_info_list_find_by_service (vpn_get_plugins (), service);
+ if (plugin_info)
+ return nm_vpn_plugin_info_get_editor_plugin (plugin_info);
+ return NULL;
+}
+
+static gint
+_sort_vpn_plugins (NMVpnPluginInfo *aa, NMVpnPluginInfo *bb)
+{
+ return strcmp (nm_vpn_plugin_info_get_name (aa), nm_vpn_plugin_info_get_name (bb));
+}
+
+GSList *
+vpn_get_plugins (void)
+{
+ static GSList *plugins = NULL;
+ GSList *p;
+
+ p = nm_vpn_plugin_info_list_load ();
+ plugins = NULL;
+ while (p) {
+ g_autoptr(NMVpnPluginInfo) plugin_info = NM_VPN_PLUGIN_INFO (p->data);
+ g_autoptr(GError) error = NULL;
+
+ /* load the editor plugin, and preserve only those NMVpnPluginInfo that can
+ * successfully load the plugin. */
+ if (nm_vpn_plugin_info_load_editor_plugin (plugin_info, &error))
+ plugins = g_slist_prepend (plugins, g_steal_pointer (&plugin_info));
+ else {
+ if ( !nm_vpn_plugin_info_get_plugin (plugin_info)
+ && nm_vpn_plugin_info_lookup_property (plugin_info, NM_VPN_PLUGIN_INFO_KF_GROUP_GNOME, "properties")) {
+ g_message ("vpn: (%s,%s) cannot load legacy-only plugin",
+ nm_vpn_plugin_info_get_name (plugin_info),
+ nm_vpn_plugin_info_get_filename (plugin_info));
+ } else if (g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) {
+ g_message ("vpn: (%s,%s) file \"%s\" not found. Did you install the client package?",
+ nm_vpn_plugin_info_get_name (plugin_info),
+ nm_vpn_plugin_info_get_filename (plugin_info),
+ nm_vpn_plugin_info_get_plugin (plugin_info));
+ } else {
+ g_warning ("vpn: (%s,%s) could not load plugin: %s",
+ nm_vpn_plugin_info_get_name (plugin_info),
+ nm_vpn_plugin_info_get_filename (plugin_info),
+ error->message);
+ }
+ }
+ p = g_slist_delete_link (p, p);
+ }
+
+ /* sort the list of plugins alphabetically. */
+ plugins = g_slist_sort (plugins, (GCompareFunc) _sort_vpn_plugins);
+ return plugins;
+}
+
+
+typedef struct {
+ GMainLoop *mainloop;
+ gint response;
+} RunData;
+
+static void
+on_dialog_close_request_cb (GtkDialog *dialog,
+ gint response,
+ RunData *data)
+{
+ data->response = GTK_RESPONSE_CLOSE;
+ g_main_loop_quit (data->mainloop);
+}
+
+static void
+on_dialog_response_cb (GtkDialog *dialog,
+ gint response,
+ RunData *data)
+{
+ data->response = response;
+ g_main_loop_quit (data->mainloop);
+}
+
+static int
+run_dialog (GtkDialog *dialog)
+{
+ g_autoptr(GMainLoop) mainloop = NULL;
+ RunData run_data;
+ gulong response_id;
+ gulong close_id;
+
+ mainloop = g_main_loop_new (NULL, FALSE);
+ run_data = (RunData) {
+ .response = GTK_RESPONSE_CLOSE,
+ .mainloop = mainloop,
+ };
+
+ close_id = g_signal_connect (dialog, "close-request", G_CALLBACK (on_dialog_close_request_cb), &run_data);
+ response_id = g_signal_connect_swapped (dialog, "response", G_CALLBACK (on_dialog_response_cb), &run_data);
+
+ gtk_window_present (GTK_WINDOW (dialog));
+ g_main_loop_run (mainloop);
+
+ g_clear_signal_handler (&close_id, dialog);
+ g_clear_signal_handler (&response_id, dialog);
+
+ return run_data.response;
+}
+
+typedef struct {
+ VpnImportCallback callback;
+ gpointer user_data;
+} ActionInfo;
+
+static void
+import_vpn_from_file_cb (GtkWidget *dialog, gint response, gpointer user_data)
+{
+ g_autofree gchar *filename = NULL;
+ g_autoptr(GFile) file = NULL;
+ ActionInfo *info = (ActionInfo *) user_data;
+ NMConnection *connection = NULL;
+ g_autoptr(GError) error = NULL;
+ GSList *iter;
+
+ if (response != GTK_RESPONSE_ACCEPT)
+ goto out;
+
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+ if (!file) {
+ g_warning ("%s: didn't get a filename back from the chooser!", __func__);
+ goto out;
+ }
+
+ filename = g_file_get_path (file);
+ for (iter = vpn_get_plugins (); !connection && iter; iter = iter->next) {
+ NMVpnEditorPlugin *plugin;
+
+ plugin = nm_vpn_plugin_info_get_editor_plugin (iter->data);
+ g_clear_error (&error);
+ connection = nm_vpn_editor_plugin_import (plugin, filename, &error);
+ }
+
+ if (!connection) {
+ GtkWidget *err_dialog;
+ g_autofree gchar *bname = g_path_get_basename (filename);
+
+ err_dialog = gtk_message_dialog_new (GTK_WINDOW (dialog),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ _("Cannot import VPN connection"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (err_dialog),
+ _("The file “%s” could not be read or does not contain recognized VPN connection information\n\nError: %s."),
+ bname, error ? error->message : "unknown error");
+ run_dialog (GTK_DIALOG (err_dialog));
+ }
+
+out:
+ gtk_window_destroy (GTK_WINDOW (dialog));
+
+ info->callback (connection, info->user_data);
+ g_free (info);
+}
+
+static gboolean
+destroy_import_chooser (GtkWidget *dialog, gpointer user_data)
+{
+ ActionInfo *info = (ActionInfo *) user_data;
+
+ info->callback (NULL, info->user_data);
+ g_free (info);
+
+ return FALSE;
+}
+
+void
+vpn_import (GtkWindow *parent, VpnImportCallback callback, gpointer user_data)
+{
+ g_autoptr(GFile) home_folder = NULL;
+ GtkWidget *dialog;
+ ActionInfo *info;
+
+ dialog = gtk_file_chooser_dialog_new (_("Select file to import"),
+ parent,
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Open"), GTK_RESPONSE_ACCEPT,
+ NULL);
+ gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+ home_folder = g_file_new_for_path (g_get_home_dir ());
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), home_folder, NULL);
+
+ info = g_malloc0 (sizeof (ActionInfo));
+ info->callback = callback;
+ info->user_data = user_data;
+
+ g_signal_connect (G_OBJECT (dialog), "close-request", G_CALLBACK (destroy_import_chooser), info);
+ g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (import_vpn_from_file_cb), info);
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+static void
+export_vpn_to_file_cb (GtkWidget *dialog, gint response, gpointer user_data)
+{
+ g_autoptr(NMConnection) connection = NM_CONNECTION (user_data);
+ g_autoptr(GFile) file = NULL;
+ char *filename = NULL;
+ g_autoptr(GError) error = NULL;
+ NMVpnEditorPlugin *plugin;
+ NMSettingConnection *s_con = NULL;
+ NMSettingVpn *s_vpn = NULL;
+ const char *service_type;
+ const char *id = NULL;
+ gboolean success = FALSE;
+
+ if (response != GTK_RESPONSE_ACCEPT)
+ goto out;
+
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+ if (!file) {
+ g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED, "no filename");
+ goto done;
+ }
+
+ filename = g_file_get_path (file);
+ if (g_file_test (filename, G_FILE_TEST_EXISTS)) {
+ int replace_response;
+ GtkWidget *replace_dialog;
+ g_autofree gchar *bname = NULL;
+
+ bname = g_path_get_basename (filename);
+ replace_dialog = gtk_message_dialog_new (NULL,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_CANCEL,
+ _("A file named “%s” already exists."),
+ bname);
+ gtk_dialog_add_buttons (GTK_DIALOG (replace_dialog), _("_Replace"), GTK_RESPONSE_OK, NULL);
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (replace_dialog),
+ _("Do you want to replace %s with the VPN connection you are saving?"), bname);
+ replace_response = run_dialog (GTK_DIALOG (replace_dialog));
+ gtk_window_destroy (GTK_WINDOW (replace_dialog));
+ if (replace_response != GTK_RESPONSE_OK)
+ goto out;
+ }
+
+ s_con = nm_connection_get_setting_connection (connection);
+ id = s_con ? nm_setting_connection_get_id (s_con) : NULL;
+ if (!id) {
+ g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED, "connection setting invalid");
+ goto done;
+ }
+
+ s_vpn = nm_connection_get_setting_vpn (connection);
+ service_type = s_vpn ? nm_setting_vpn_get_service_type (s_vpn) : NULL;
+
+ if (!service_type) {
+ g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED, "VPN setting invalid");
+ goto done;
+ }
+
+ plugin = vpn_get_plugin_by_service (service_type);
+ if (plugin)
+ success = nm_vpn_editor_plugin_export (plugin, filename, connection, &error);
+
+done:
+ if (!success) {
+ GtkWidget *err_dialog;
+ g_autofree gchar *bname = filename ? g_path_get_basename (filename) : g_strdup ("(none)");
+
+ err_dialog = gtk_message_dialog_new (NULL,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ _("Cannot export VPN connection"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (err_dialog),
+ _("The VPN connection “%s” could not be exported to %s.\n\nError: %s."),
+ id ? id : "(unknown)", bname, error ? error->message : "unknown error");
+ run_dialog (GTK_DIALOG (err_dialog));
+ }
+
+out:
+ gtk_window_destroy (GTK_WINDOW (dialog));
+}
+
+void
+vpn_export (NMConnection *connection)
+{
+ g_autoptr(GFile) home_folder = NULL;
+ GtkWidget *dialog;
+ NMVpnEditorPlugin *plugin;
+ NMSettingVpn *s_vpn = NULL;
+ const char *service_type;
+
+ s_vpn = nm_connection_get_setting_vpn (connection);
+ service_type = s_vpn ? nm_setting_vpn_get_service_type (s_vpn) : NULL;
+
+ if (!service_type) {
+ g_warning ("%s: invalid VPN connection!", __func__);
+ return;
+ }
+
+ dialog = gtk_file_chooser_dialog_new (_("Export VPN connection"),
+ NULL,
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Save"), GTK_RESPONSE_ACCEPT,
+ NULL);
+ home_folder = g_file_new_for_path (g_get_home_dir ());
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), home_folder, NULL);
+
+ plugin = vpn_get_plugin_by_service (service_type);
+ if (plugin) {
+ g_autofree gchar *suggested = NULL;
+
+ suggested = nm_vpn_editor_plugin_get_suggested_filename (plugin, connection);
+ if (suggested)
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), suggested);
+ }
+
+ g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (export_vpn_to_file_cb), g_object_ref (connection));
+ gtk_window_present (GTK_WINDOW (dialog));
+}
diff --git a/panels/network/connection-editor/vpn-helpers.h b/panels/network/connection-editor/vpn-helpers.h
new file mode 100644
index 0000000..578f68c
--- /dev/null
+++ b/panels/network/connection-editor/vpn-helpers.h
@@ -0,0 +1,39 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Connection editor -- Connection editor for NetworkManager
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ */
+
+#ifndef _VPN_HELPERS_H_
+#define _VPN_HELPERS_H_
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+GSList *vpn_get_plugins (void);
+
+NMVpnEditorPlugin *vpn_get_plugin_by_service (const char *service);
+
+typedef void (*VpnImportCallback) (NMConnection *connection, gpointer user_data);
+void vpn_import (GtkWindow *parent, VpnImportCallback callback, gpointer user_data);
+
+void vpn_export (NMConnection *connection);
+
+#endif /* _VPN_HELPERS_H_ */
diff --git a/panels/network/connection-editor/vpn-page.ui b/panels/network/connection-editor/vpn-page.ui
new file mode 100644
index 0000000..98f801b
--- /dev/null
+++ b/panels/network/connection-editor/vpn-page.ui
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CEPageVpn" parent="GtkBox">
+ <property name="margin_start">50</property>
+ <property name="margin_end">50</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Name</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">name_entry</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="name_entry">
+ <property name="hexpand">True</property>
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="failure_label">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">(Error: unable to load VPN connection editor)</property>
+ <attributes>
+ <attribute name="style" value="italic"/>
+ </attributes>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/connection-editor/wifi-page.ui b/panels/network/connection-editor/wifi-page.ui
new file mode 100644
index 0000000..6662b8f
--- /dev/null
+++ b/panels/network/connection-editor/wifi-page.ui
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CEPageWifi" parent="GtkGrid">
+ <property name="margin_start">50</property>
+ <property name="margin_end">50</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">10</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_SSID</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">ssid_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_BSSID</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">bssid_combo</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="ssid_entry">
+ <property name="hexpand">True</property>
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_MAC Address</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">mac_combo</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="cloned_mac_combo">
+ <property name="has_entry">True</property>
+ <property name="hexpand">True</property>
+ <property name="active_id">0</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ </layout>
+ <child internal-child="entry">
+ <object class="GtkEntry">
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">_Cloned Address</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">cloned_mac_combo</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="bssid_combo">
+ <property name="has_entry">True</property>
+ <property name="entry_text_column">0</property>
+ <property name="id_column">1</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="mac_combo">
+ <property name="has_entry">True</property>
+ <property name="entry_text_column">0</property>
+ <property name="id_column">1</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/gnome-network-panel.desktop.in.in b/panels/network/gnome-network-panel.desktop.in.in
new file mode 100644
index 0000000..d9ab05c
--- /dev/null
+++ b/panels/network/gnome-network-panel.desktop.in.in
@@ -0,0 +1,18 @@
+[Desktop Entry]
+Name=Network
+Comment=Control how you connect to the Internet
+Exec=gnome-control-center network
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-network-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;HardwareSettings;X-GNOME-Settings-Panel;X-GNOME-ConnectivitySettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=network
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: Search terms to find the Network panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=Network;IP;LAN;Proxy;WAN;Broadband;Modem;Bluetooth;vpn;DNS;
diff --git a/panels/network/gnome-wifi-panel.desktop.in.in b/panels/network/gnome-wifi-panel.desktop.in.in
new file mode 100644
index 0000000..8104ede
--- /dev/null
+++ b/panels/network/gnome-wifi-panel.desktop.in.in
@@ -0,0 +1,18 @@
+[Desktop Entry]
+Name=Wi-Fi
+Comment=Control how you connect to Wi-Fi networks
+Exec=gnome-control-center wifi
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=network-wireless
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;HardwareSettings;X-GNOME-Settings-Panel;X-GNOME-ConnectivitySettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=network
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: Search terms to find the Wi-Fi panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=Network;Wireless;Wi-Fi;Wifi;IP;LAN;Broadband;DNS;Hotspot;
diff --git a/panels/network/icons/meson.build b/panels/network/icons/meson.build
new file mode 100644
index 0000000..0501dfe
--- /dev/null
+++ b/panels/network/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-network-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/network/icons/scalable/org.gnome.Settings-network-symbolic.svg b/panels/network/icons/scalable/org.gnome.Settings-network-symbolic.svg
new file mode 100644
index 0000000..a6ef9ce
--- /dev/null
+++ b/panels/network/icons/scalable/org.gnome.Settings-network-symbolic.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <g fill="#2e3436">
+ <path d="m 3.75 0.00390625 c -0.953125 0.00390625 -1.75 0.80078175 -1.75 1.74999975 v 5.496094 c 0 0.953125 0.796875 1.75 1.75 1.75 h 0.75 s 0.5 0.007812 0.5 0.507812 c 0 0.492188 -0.5 0.492188 -0.5 0.492188 h -0.5 v 1.992188 h 8 v -2 h -0.5 s -0.5 0.007812 -0.5 -0.492188 s 0.5 -0.507812 0.5 -0.507812 h 0.75 c 0.953125 0 1.75 -0.796876 1.75 -1.75 v -5.492188 c 0 -0.953125 -0.796875 -1.75 -1.75 -1.75 z m 0.25 1.99999975 l 8 -0.003906 v 4.992188 l -8 0.007812 z m 0 0"/>
+ <path d="m 6.96875 10.003906 l 0.03125 3.996094 h -5.5 c -0.277344 0 -0.5 0.222656 -0.5 0.5 v 1 c 0 0.277344 0.222656 0.5 0.5 0.5 h 13 c 0.277344 0 0.5 -0.222656 0.5 -0.5 v -1 c 0 -0.277344 -0.222656 -0.5 -0.5 -0.5 h -5.5 v -4 z m 0 0" fill-rule="evenodd"/>
+ </g>
+</svg>
diff --git a/panels/network/lock-small-symbolic.svg b/panels/network/lock-small-symbolic.svg
new file mode 100644
index 0000000..5d2e2a2
--- /dev/null
+++ b/panels/network/lock-small-symbolic.svg
@@ -0,0 +1 @@
+<svg width="10" height="10" xmlns="http://www.w3.org/2000/svg"><path style="fill:#36343e;" d="M5 0C3.355 0 2 1.355 2 3v2H1v5h8V5H8V3c0-1.645-1.355-3-3-3zm0 2c.571 0 1 .429 1 1v2H4V3c0-.571.429-1 1-1z"/></svg>
diff --git a/panels/network/meson.build b/panels/network/meson.build
new file mode 100644
index 0000000..e6340ce
--- /dev/null
+++ b/panels/network/meson.build
@@ -0,0 +1,85 @@
+deps = common_deps + network_manager_deps + [
+ polkit_gobject_dep,
+ dependency('gmodule-2.0')
+]
+
+network_inc = include_directories('.')
+
+subdir('wireless-security')
+subdir('connection-editor')
+subdir('icons')
+
+panel_names = [
+ cappletname,
+ 'wifi'
+]
+
+panels_list += panel_names
+
+foreach name: panel_names
+ desktop = 'gnome-' + name + '-panel.desktop'
+
+ desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+ )
+
+ i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+ )
+endforeach
+
+sources = files(
+ 'cc-qr-code.c',
+ 'cc-network-panel.c',
+ 'cc-wifi-connection-row.c',
+ 'cc-wifi-connection-list.c',
+ 'cc-wifi-panel.c',
+ 'cc-wifi-hotspot-dialog.c',
+ 'net-device-bluetooth.c',
+ 'net-device-ethernet.c',
+ 'net-device-mobile.c',
+ 'net-device-wifi.c',
+ 'net-proxy.c',
+ 'net-vpn.c',
+ 'network-dialogs.c',
+ 'panel-common.c',
+ 'ui-helpers.c'
+)
+
+resource_data = files(
+ 'cc-network-panel.ui',
+ 'cc-wifi-connection-row.ui',
+ 'cc-wifi-panel.ui',
+ 'cc-wifi-hotspot-dialog.ui',
+ 'network-bluetooth.ui',
+ 'network-ethernet.ui',
+ 'network-mobile.ui',
+ 'network-proxy.ui',
+ 'network-vpn.ui',
+ 'network-wifi.ui',
+)
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname,
+ dependencies: resource_data,
+ export: true
+)
+
+network_panel_lib = static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [top_inc, common_inc],
+ dependencies: deps,
+ c_args: cflags,
+ link_with: libconnection_editor
+)
+panels_libs += network_panel_lib
diff --git a/panels/network/net-device-bluetooth.c b/panels/network/net-device-bluetooth.c
new file mode 100644
index 0000000..303f4a8
--- /dev/null
+++ b/panels/network/net-device-bluetooth.c
@@ -0,0 +1,201 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2011-2012 Richard Hughes <richard@hughsie.com>
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <glib/gi18n.h>
+
+#include <NetworkManager.h>
+
+#include "panel-common.h"
+
+#include "net-device-bluetooth.h"
+
+struct _NetDeviceBluetooth
+{
+ AdwActionRow parent;
+
+ GtkSwitch *device_off_switch;
+ GtkButton *options_button;
+
+ NMClient *client;
+ NMDevice *device;
+ gboolean updating_device;
+};
+
+G_DEFINE_TYPE (NetDeviceBluetooth, net_device_bluetooth, ADW_TYPE_ACTION_ROW)
+
+static void
+update_off_switch_from_device_state (GtkSwitch *sw,
+ NMDeviceState state,
+ NetDeviceBluetooth *self)
+{
+ self->updating_device = TRUE;
+ switch (state) {
+ case NM_DEVICE_STATE_UNMANAGED:
+ case NM_DEVICE_STATE_UNAVAILABLE:
+ case NM_DEVICE_STATE_DISCONNECTED:
+ case NM_DEVICE_STATE_DEACTIVATING:
+ case NM_DEVICE_STATE_FAILED:
+ gtk_switch_set_active (sw, FALSE);
+ break;
+ default:
+ gtk_switch_set_active (sw, TRUE);
+ break;
+ }
+ self->updating_device = FALSE;
+}
+
+static void
+nm_device_bluetooth_refresh_ui (NetDeviceBluetooth *self)
+{
+ NMDeviceState state;
+ g_autofree gchar *path = NULL;
+
+ /* set up the device on/off switch */
+ state = nm_device_get_state (self->device);
+ gtk_widget_set_visible (GTK_WIDGET (self->device_off_switch),
+ state != NM_DEVICE_STATE_UNAVAILABLE
+ && state != NM_DEVICE_STATE_UNMANAGED);
+ update_off_switch_from_device_state (self->device_off_switch, state, self);
+
+ /* set up the Options button */
+ path = g_find_program_in_path ("nm-connection-editor");
+ gtk_widget_set_visible (GTK_WIDGET (self->options_button), state != NM_DEVICE_STATE_UNMANAGED && path != NULL);
+}
+
+static void
+device_off_switch_changed_cb (NetDeviceBluetooth *self)
+{
+ const GPtrArray *acs;
+ gboolean active;
+ gint i;
+ NMActiveConnection *a;
+ NMConnection *connection;
+
+ if (self->updating_device)
+ return;
+
+ connection = net_device_get_find_connection (self->client, self->device);
+ if (connection == NULL)
+ return;
+
+ active = gtk_switch_get_active (self->device_off_switch);
+ if (active) {
+ nm_client_activate_connection_async (self->client,
+ connection,
+ self->device,
+ NULL, NULL, NULL, NULL);
+ } else {
+ const gchar *uuid;
+
+ uuid = nm_connection_get_uuid (connection);
+ acs = nm_client_get_active_connections (self->client);
+ for (i = 0; acs && i < acs->len; i++) {
+ a = (NMActiveConnection*)acs->pdata[i];
+ if (strcmp (nm_active_connection_get_uuid (a), uuid) == 0) {
+ nm_client_deactivate_connection_async (self->client, a, NULL, NULL, NULL);
+ break;
+ }
+ }
+ }
+}
+
+static void
+options_button_clicked_cb (NetDeviceBluetooth *self)
+{
+ const gchar *uuid;
+ g_autofree gchar *cmdline = NULL;
+ g_autoptr(GError) error = NULL;
+ NMConnection *connection;
+
+ connection = net_device_get_find_connection (self->client, self->device);
+ uuid = nm_connection_get_uuid (connection);
+ cmdline = g_strdup_printf ("nm-connection-editor --edit %s", uuid);
+ g_debug ("Launching '%s'\n", cmdline);
+ if (!g_spawn_command_line_async (cmdline, &error))
+ g_warning ("Failed to launch nm-connection-editor: %s", error->message);
+}
+
+static void
+net_device_bluetooth_finalize (GObject *object)
+{
+ NetDeviceBluetooth *self = NET_DEVICE_BLUETOOTH (object);
+
+ g_clear_object (&self->client);
+ g_clear_object (&self->device);
+
+ G_OBJECT_CLASS (net_device_bluetooth_parent_class)->finalize (object);
+}
+
+static void
+net_device_bluetooth_class_init (NetDeviceBluetoothClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = net_device_bluetooth_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/network-bluetooth.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceBluetooth, device_off_switch);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceBluetooth, options_button);
+
+ gtk_widget_class_bind_template_callback (widget_class, device_off_switch_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, options_button_clicked_cb);
+
+}
+
+static void
+net_device_bluetooth_init (NetDeviceBluetooth *self)
+{
+ g_autofree gchar *path = NULL;
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ path = g_find_program_in_path ("nm-connection-editor");
+ gtk_widget_set_visible (GTK_WIDGET (self->options_button), path != NULL);
+}
+
+NetDeviceBluetooth *
+net_device_bluetooth_new (NMClient *client, NMDevice *device)
+{
+ NetDeviceBluetooth *self;
+
+ self = g_object_new (net_device_bluetooth_get_type (), NULL);
+ self->client = g_object_ref (client);
+ self->device = g_object_ref (device);
+
+ g_signal_connect_object (device, "state-changed", G_CALLBACK (nm_device_bluetooth_refresh_ui), self, G_CONNECT_SWAPPED);
+
+ nm_device_bluetooth_refresh_ui (self);
+
+ return self;
+}
+
+NMDevice *
+net_device_bluetooth_get_device (NetDeviceBluetooth *self)
+{
+ g_return_val_if_fail (NET_IS_DEVICE_BLUETOOTH (self), NULL);
+ return self->device;
+}
diff --git a/panels/network/net-device-bluetooth.h b/panels/network/net-device-bluetooth.h
new file mode 100644
index 0000000..b0ce5ae
--- /dev/null
+++ b/panels/network/net-device-bluetooth.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2011-2012 Richard Hughes <richard@hughsie.com>
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <adwaita.h>
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (NetDeviceBluetooth, net_device_bluetooth, NET, DEVICE_BLUETOOTH, AdwActionRow)
+
+NetDeviceBluetooth *net_device_bluetooth_new (NMClient *client,
+ NMDevice *device);
+
+NMDevice *net_device_bluetooth_get_device (NetDeviceBluetooth *device);
+
+G_END_DECLS
diff --git a/panels/network/net-device-ethernet.c b/panels/network/net-device-ethernet.c
new file mode 100644
index 0000000..a230498
--- /dev/null
+++ b/panels/network/net-device-ethernet.c
@@ -0,0 +1,540 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2011-2012 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <glib/gi18n.h>
+#include <NetworkManager.h>
+
+#include "panel-common.h"
+
+#include "connection-editor/net-connection-editor.h"
+#include "connection-editor/ce-page.h"
+
+#include "net-device-ethernet.h"
+
+struct _NetDeviceEthernet
+{
+ AdwPreferencesGroup parent;
+
+ GtkListBox *connection_list;
+ GtkStack *connection_stack;
+ GtkButton *details_button;
+ GtkListBox *details_listbox;
+ AdwActionRow *details_row;
+ GtkSwitch *device_off_switch;
+
+ NMClient *client;
+ NMDevice *device;
+ gboolean updating_device;
+ GHashTable *connections;
+};
+
+G_DEFINE_TYPE (NetDeviceEthernet, net_device_ethernet, ADW_TYPE_PREFERENCES_GROUP)
+
+static void
+add_details_row (GtkWidget *details, gint top, const gchar *heading, const gchar *value)
+{
+ GtkWidget *heading_label;
+ GtkWidget *value_label;
+
+ heading_label = gtk_label_new (heading);
+ gtk_style_context_add_class (gtk_widget_get_style_context (heading_label), "dim-label");
+ gtk_widget_set_halign (heading_label, GTK_ALIGN_END);
+ gtk_widget_set_valign (heading_label, GTK_ALIGN_START);
+ gtk_widget_set_hexpand (heading_label, TRUE);
+
+ gtk_grid_attach (GTK_GRID (details), heading_label, 0, top, 1, 1);
+
+ value_label = gtk_label_new (value);
+ gtk_widget_set_halign (value_label, GTK_ALIGN_START);
+ gtk_widget_set_hexpand (value_label, TRUE);
+ gtk_label_set_selectable (GTK_LABEL (value_label), TRUE);
+
+ gtk_label_set_mnemonic_widget (GTK_LABEL (heading_label), value_label);
+
+ gtk_grid_attach (GTK_GRID (details), value_label, 1, top, 1, 1);
+}
+
+static gchar *
+get_last_used_string (NMConnection *connection)
+{
+ g_autoptr(GDateTime) now = NULL;
+ g_autoptr(GDateTime) then = NULL;
+ gint days;
+ GTimeSpan diff;
+ guint64 timestamp;
+ NMSettingConnection *s_con;
+
+ s_con = nm_connection_get_setting_connection (connection);
+ if (s_con == NULL)
+ return NULL;
+ timestamp = nm_setting_connection_get_timestamp (s_con);
+ if (timestamp == 0)
+ return g_strdup (_("never"));
+
+ /* calculate the amount of time that has elapsed */
+ now = g_date_time_new_now_utc ();
+ then = g_date_time_new_from_unix_utc (timestamp);
+ diff = g_date_time_difference (now, then);
+ days = diff / G_TIME_SPAN_DAY;
+ if (days == 0)
+ return g_strdup (_("today"));
+ else if (days == 1)
+ return g_strdup (_("yesterday"));
+ else
+ return g_strdup_printf (ngettext ("%i day ago", "%i days ago", days), days);
+}
+
+static void
+add_details (GtkWidget *details, NMDevice *device, NMConnection *connection)
+{
+ NMIPConfig *ip4_config = NULL;
+ NMIPConfig *ip6_config = NULL;
+ const gchar *ip4_address = NULL;
+ const gchar *ip4_route = NULL;
+ g_autofree gchar *ip4_dns = NULL;
+ g_autofree gchar *ip6_addresses = NULL;
+ const gchar *ip6_route = NULL;
+ g_autofree gchar *ip6_dns = NULL;
+ gint i = 0;
+
+ ip4_config = nm_device_get_ip4_config (device);
+ if (ip4_config) {
+ GPtrArray *addresses;
+
+ addresses = nm_ip_config_get_addresses (ip4_config);
+ if (addresses->len > 0)
+ ip4_address = nm_ip_address_get_address (g_ptr_array_index (addresses, 0));
+
+ ip4_route = nm_ip_config_get_gateway (ip4_config);
+ ip4_dns = g_strjoinv (" ", (char **) nm_ip_config_get_nameservers (ip4_config));
+ if (!*ip4_dns)
+ ip4_dns = NULL;
+ }
+ ip6_config = nm_device_get_ip6_config (device);
+ if (ip6_config) {
+ ip6_addresses = net_device_get_ip6_addresses (ip6_config);
+ ip6_route = nm_ip_config_get_gateway (ip6_config);
+ ip6_dns = g_strjoinv (" ", (char **) nm_ip_config_get_nameservers (ip6_config));
+ if (!*ip6_dns)
+ ip6_dns = NULL;
+ }
+
+ if (ip4_address && ip6_addresses) {
+ add_details_row (details, i++, _("IPv4 Address"), ip4_address);
+ gtk_widget_set_valign (details, GTK_ALIGN_START);
+ add_details_row (details, i++, _("IPv6 Address"), ip6_addresses);
+ gtk_widget_set_valign (details, GTK_ALIGN_START);
+ } else if (ip4_address) {
+ add_details_row (details, i++, _("IP Address"), ip4_address);
+ } else if (ip6_addresses) {
+ add_details_row (details, i++, _("IP Address"), ip6_addresses);
+ }
+
+ add_details_row (details, i++, _("Hardware Address"), nm_device_get_hw_address (device));
+
+ if (ip4_route && ip6_route) {
+ g_autofree gchar *ip_routes = g_strjoin ("\n", ip4_route, ip6_route, NULL);
+ add_details_row (details, i++, _("Default Route"), ip_routes);
+ } else if (ip4_route) {
+ add_details_row (details, i++, _("Default Route"), ip4_route);
+ } else if (ip6_route) {
+ add_details_row (details, i++, _("Default Route"), ip6_route);
+ }
+
+ if (ip4_dns && ip6_dns) {
+ add_details_row (details, i++, _("DNS4"), ip4_dns);
+ add_details_row (details, i++, _("DNS6"), ip6_dns);
+ } else if (ip4_dns) {
+ add_details_row (details, i++, _("DNS"), ip4_dns);
+ } else if (ip6_dns) {
+ add_details_row (details, i++, _("DNS"), ip6_dns);
+ }
+
+ if (nm_device_get_state (device) != NM_DEVICE_STATE_ACTIVATED) {
+ g_autofree gchar *last_used = NULL;
+ last_used = get_last_used_string (connection);
+ add_details_row (details, i++, _("Last used"), last_used);
+ }
+}
+
+static void populate_ui (NetDeviceEthernet *self);
+
+static gboolean
+device_state_to_off_switch (NMDeviceState state)
+{
+ switch (state) {
+ case NM_DEVICE_STATE_UNMANAGED:
+ case NM_DEVICE_STATE_UNAVAILABLE:
+ case NM_DEVICE_STATE_DISCONNECTED:
+ case NM_DEVICE_STATE_DEACTIVATING:
+ case NM_DEVICE_STATE_FAILED:
+ return FALSE;
+ default:
+ return TRUE;
+ }
+}
+
+static void
+device_ethernet_refresh_ui (NetDeviceEthernet *self)
+{
+ NMDeviceState state;
+ g_autofree gchar *speed_text = NULL;
+ g_autofree gchar *status = NULL;
+
+ state = nm_device_get_state (self->device);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->device_off_switch),
+ state != NM_DEVICE_STATE_UNAVAILABLE
+ && state != NM_DEVICE_STATE_UNMANAGED);
+ self->updating_device = TRUE;
+ gtk_switch_set_active (self->device_off_switch, device_state_to_off_switch (state));
+ self->updating_device = FALSE;
+
+ if (state != NM_DEVICE_STATE_UNAVAILABLE) {
+ guint speed = nm_device_ethernet_get_speed (NM_DEVICE_ETHERNET (self->device));
+ if (speed > 0) {
+ /* Translators: network device speed */
+ speed_text = g_strdup_printf (_("%d Mb/s"), speed);
+ }
+ }
+ status = panel_device_status_to_localized_string (self->device, speed_text);
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self->details_row), status);
+
+ populate_ui (self);
+}
+
+static void
+editor_done (NetDeviceEthernet *self)
+{
+ device_ethernet_refresh_ui (self);
+}
+
+static void
+show_details (NetDeviceEthernet *self, GtkButton *button, const gchar *title)
+{
+ GtkWidget *row;
+ NMConnection *connection;
+ NetConnectionEditor *editor;
+
+ row = g_object_get_data (G_OBJECT (button), "row");
+ connection = NM_CONNECTION (g_object_get_data (G_OBJECT (row), "connection"));
+
+ editor = net_connection_editor_new (connection, self->device, NULL, self->client);
+ gtk_window_set_transient_for (GTK_WINDOW (editor), GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (self))));
+ if (title)
+ net_connection_editor_set_title (editor, title);
+ g_signal_connect_object (editor, "done", G_CALLBACK (editor_done), self, G_CONNECT_SWAPPED);
+ gtk_window_present (GTK_WINDOW (editor));
+}
+
+static void
+show_details_for_row (NetDeviceEthernet *self, GtkButton *button)
+{
+ show_details (self, button, NULL);
+}
+
+static void
+details_button_clicked_cb (NetDeviceEthernet *self)
+{
+ /* Translators: This is used as the title of the connection
+ * details window for ethernet, if there is only a single
+ * profile. It is also used to display ethernet in the
+ * device list.
+ */
+ show_details (self, self->details_button, _("Wired"));
+}
+
+static void
+add_row (NetDeviceEthernet *self, NMConnection *connection)
+{
+ GtkWidget *row;
+ GtkWidget *widget;
+ GtkWidget *box;
+ GtkWidget *details;
+ NMActiveConnection *aconn;
+ gboolean active;
+
+ active = FALSE;
+
+ aconn = nm_device_get_active_connection (self->device);
+ if (aconn) {
+ const gchar *uuid1, *uuid2;
+ uuid1 = nm_active_connection_get_uuid (aconn);
+ uuid2 = nm_connection_get_uuid (connection);
+ active = g_strcmp0 (uuid1, uuid2) == 0;
+ }
+
+ row = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_box_append (GTK_BOX (row), box);
+ widget = gtk_label_new (nm_connection_get_id (connection));
+ gtk_widget_set_margin_start (widget, 12);
+ gtk_widget_set_margin_end (widget, 12);
+ gtk_widget_set_margin_top (widget, 8);
+ gtk_widget_set_margin_bottom (widget, 8);
+ gtk_box_append (GTK_BOX (box), widget);
+
+ if (active) {
+ widget = gtk_image_new_from_icon_name ("object-select-symbolic");
+ gtk_widget_set_halign (widget, GTK_ALIGN_CENTER);
+ gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
+ gtk_box_append (GTK_BOX (box), widget);
+
+ details = gtk_grid_new ();
+ gtk_grid_set_row_spacing (GTK_GRID (details), 10);
+ gtk_grid_set_column_spacing (GTK_GRID (details), 10);
+
+ gtk_box_append (GTK_BOX (row), details);
+
+ add_details (details, self->device, connection);
+ }
+
+ /* filler */
+ widget = gtk_label_new ("");
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_box_append (GTK_BOX (box), widget);
+
+ widget = gtk_button_new_from_icon_name ("emblem-system-symbolic");
+ gtk_widget_set_margin_start (widget, 12);
+ gtk_widget_set_margin_end (widget, 12);
+ gtk_widget_set_margin_top (widget, 8);
+ gtk_widget_set_margin_bottom (widget, 8);
+ gtk_widget_set_halign (widget, GTK_ALIGN_CENTER);
+ gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
+ gtk_accessible_update_property (GTK_ACCESSIBLE (widget),
+ GTK_ACCESSIBLE_PROPERTY_LABEL, _("Options…"),
+ -1);
+ gtk_box_append (GTK_BOX (box), widget);
+ g_object_set_data (G_OBJECT (widget), "edit", widget);
+ g_object_set_data (G_OBJECT (widget), "row", row);
+ g_signal_connect_object (widget, "clicked", G_CALLBACK (show_details_for_row), self, G_CONNECT_SWAPPED);
+
+ g_object_set_data (G_OBJECT (row), "connection", connection);
+
+ gtk_list_box_append (self->connection_list, row);
+}
+
+static void
+connection_removed (NetDeviceEthernet *self, NMRemoteConnection *connection)
+{
+ if (g_hash_table_remove (self->connections, connection))
+ device_ethernet_refresh_ui (self);
+}
+
+static void
+populate_ui (NetDeviceEthernet *self)
+{
+ GSList *connections, *l;
+ NMConnection *connection;
+ GtkWidget *child;
+ gint n_connections;
+
+ while ((child = gtk_widget_get_first_child (GTK_WIDGET (self->connection_list))) != NULL)
+ gtk_list_box_remove (self->connection_list, child);
+
+ connections = net_device_get_valid_connections (self->client, self->device);
+ for (l = connections; l; l = l->next) {
+ NMConnection *connection = l->data;
+ if (!g_hash_table_contains (self->connections, connection)) {
+ g_hash_table_add (self->connections, connection);
+ }
+ }
+ n_connections = g_slist_length (connections);
+
+ if (n_connections > 1) {
+ for (l = connections; l; l = l->next) {
+ NMConnection *connection = l->data;
+ add_row (self, connection);
+ }
+ gtk_stack_set_visible_child (self->connection_stack,
+ GTK_WIDGET (self->connection_list));
+ } else if (n_connections == 1) {
+ connection = connections->data;
+ gtk_stack_set_visible_child (self->connection_stack,
+ GTK_WIDGET (self->details_listbox));
+ g_object_set_data (G_OBJECT (self->details_button), "row", self->details_button);
+ g_object_set_data (G_OBJECT (self->details_button), "connection", connection);
+
+ }
+
+ gtk_widget_set_visible (GTK_WIDGET (self->connection_stack), n_connections >= 1);
+
+ g_slist_free (connections);
+}
+
+static void
+client_connection_added_cb (NetDeviceEthernet *self)
+{
+ device_ethernet_refresh_ui (self);
+}
+
+static void
+add_profile_button_clicked_cb (NetDeviceEthernet *self)
+{
+ NMConnection *connection;
+ NMSettingConnection *sc;
+ g_autofree gchar *uuid = NULL;
+ g_autofree gchar *id = NULL;
+ NetConnectionEditor *editor;
+ const GPtrArray *connections;
+ const char *iface;
+
+ connection = nm_simple_connection_new ();
+ sc = NM_SETTING_CONNECTION (nm_setting_connection_new ());
+ nm_connection_add_setting (connection, NM_SETTING (sc));
+
+ uuid = nm_utils_uuid_generate ();
+
+ connections = nm_client_get_connections (self->client);
+ id = ce_page_get_next_available_name (connections, NAME_FORMAT_PROFILE, NULL);
+
+ g_object_set (sc,
+ NM_SETTING_CONNECTION_UUID, uuid,
+ NM_SETTING_CONNECTION_ID, id,
+ NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
+ NM_SETTING_CONNECTION_AUTOCONNECT, TRUE,
+ NULL);
+
+ iface = nm_device_get_iface (self->device);
+ g_object_set (sc,
+ NM_SETTING_CONNECTION_INTERFACE_NAME, iface,
+ NULL);
+
+ nm_connection_add_setting (connection, nm_setting_wired_new ());
+
+ editor = net_connection_editor_new (connection, self->device, NULL, self->client);
+ gtk_window_set_transient_for (GTK_WINDOW (editor), GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (self))));
+ g_signal_connect_object (editor, "done", G_CALLBACK (editor_done), self, G_CONNECT_SWAPPED);
+ gtk_window_present (GTK_WINDOW (editor));
+}
+
+static void
+device_off_switch_changed_cb (NetDeviceEthernet *self)
+{
+ NMConnection *connection;
+
+ if (self->updating_device)
+ return;
+
+ if (gtk_switch_get_active (self->device_off_switch)) {
+ connection = net_device_get_find_connection (self->client, self->device);
+ if (connection != NULL) {
+ nm_client_activate_connection_async (self->client,
+ connection,
+ self->device,
+ NULL, NULL, NULL, NULL);
+ }
+ } else {
+ nm_device_disconnect_async (self->device, NULL, NULL, NULL);
+ }
+}
+
+static void
+connection_list_row_activated_cb (NetDeviceEthernet *self, GtkListBoxRow *row)
+{
+ NMConnection *connection;
+ GtkWidget *child;
+
+ if (!NM_IS_DEVICE_ETHERNET (self->device) ||
+ !nm_device_ethernet_get_carrier (NM_DEVICE_ETHERNET (self->device)))
+ return;
+
+ child = gtk_list_box_row_get_child (GTK_LIST_BOX_ROW (row));
+ connection = NM_CONNECTION (g_object_get_data (G_OBJECT (child), "connection"));
+
+ nm_client_activate_connection_async (self->client,
+ connection,
+ self->device,
+ NULL, NULL, NULL, NULL);
+}
+
+static void
+device_ethernet_finalize (GObject *object)
+{
+ NetDeviceEthernet *self = NET_DEVICE_ETHERNET (object);
+
+ g_clear_object (&self->client);
+ g_clear_object (&self->device);
+ g_hash_table_destroy (self->connections);
+
+ G_OBJECT_CLASS (net_device_ethernet_parent_class)->finalize (object);
+}
+
+static void
+net_device_ethernet_class_init (NetDeviceEthernetClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = device_ethernet_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/network-ethernet.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceEthernet, connection_list);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceEthernet, connection_stack);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceEthernet, details_button);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceEthernet, details_listbox);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceEthernet, details_row);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceEthernet, device_off_switch);
+
+ gtk_widget_class_bind_template_callback (widget_class, connection_list_row_activated_cb);
+ gtk_widget_class_bind_template_callback (widget_class, device_off_switch_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, details_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, add_profile_button_clicked_cb);
+}
+
+static void
+net_device_ethernet_init (NetDeviceEthernet *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->connections = g_hash_table_new (NULL, NULL);
+}
+
+NetDeviceEthernet *
+net_device_ethernet_new (NMClient *client, NMDevice *device)
+{
+ NetDeviceEthernet *self;
+
+ self = g_object_new (net_device_ethernet_get_type (), NULL);
+ self->client = g_object_ref (client);
+ self->device = g_object_ref (device);
+
+ g_signal_connect_object (client, NM_CLIENT_CONNECTION_ADDED,
+ G_CALLBACK (client_connection_added_cb), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (client, NM_CLIENT_CONNECTION_REMOVED,
+ G_CALLBACK (connection_removed), self, G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (device, "state-changed", G_CALLBACK (device_ethernet_refresh_ui), self, G_CONNECT_SWAPPED);
+
+ device_ethernet_refresh_ui (self);
+
+ return self;
+}
+
+NMDevice *
+net_device_ethernet_get_device (NetDeviceEthernet *self)
+{
+ g_return_val_if_fail (NET_IS_DEVICE_ETHERNET (self), NULL);
+ return self->device;
+}
diff --git a/panels/network/net-device-ethernet.h b/panels/network/net-device-ethernet.h
new file mode 100644
index 0000000..8a6acb8
--- /dev/null
+++ b/panels/network/net-device-ethernet.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <adwaita.h>
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (NetDeviceEthernet, net_device_ethernet, NET, DEVICE_ETHERNET, AdwPreferencesGroup)
+
+NetDeviceEthernet *net_device_ethernet_new (NMClient *client,
+ NMDevice *device);
+
+NMDevice *net_device_ethernet_get_device (NetDeviceEthernet *device);
+
+G_END_DECLS
diff --git a/panels/network/net-device-mobile.c b/panels/network/net-device-mobile.c
new file mode 100644
index 0000000..2c4012c
--- /dev/null
+++ b/panels/network/net-device-mobile.c
@@ -0,0 +1,912 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2011-2012 Richard Hughes <richard@hughsie.com>
+ * Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <glib/gi18n.h>
+
+#include <NetworkManager.h>
+#include <libmm-glib.h>
+#include <nma-mobile-providers.h>
+
+#include "panel-common.h"
+#include "network-dialogs.h"
+#include "net-device-mobile.h"
+
+static void nm_device_mobile_refresh_ui (NetDeviceMobile *self);
+
+struct _NetDeviceMobile
+{
+ GtkBox parent;
+
+ GtkLabel *device_label;
+ GtkSwitch *device_off_switch;
+ GtkLabel *dns4_heading_label;
+ GtkLabel *dns4_label;
+ GtkLabel *dns6_heading_label;
+ GtkLabel *dns6_label;
+ GtkLabel *imei_heading_label;
+ GtkLabel *imei_label;
+ GtkLabel *ipv4_heading_label;
+ GtkLabel *ipv4_label;
+ GtkLabel *ipv6_heading_label;
+ GtkLabel *ipv6_label;
+ GtkListStore *mobile_connections_list_store;
+ GtkComboBox *network_combo;
+ GtkLabel *network_label;
+ GtkButton *options_button;
+ GtkLabel *provider_heading_label;
+ GtkLabel *provider_label;
+ GtkLabel *route_heading_label;
+ GtkLabel *route_label;
+ GtkLabel *status_label;
+
+ NMClient *client;
+ NMDevice *device;
+ GDBusObject *modem;
+ GCancellable *cancellable;
+
+ gboolean updating_device;
+
+ /* Old MM < 0.7 support */
+ GDBusProxy *gsm_proxy;
+ GDBusProxy *cdma_proxy;
+
+ /* New MM >= 0.7 support */
+ MMObject *mm_object;
+
+ NMAMobileProvidersDatabase *mpd;
+};
+
+enum {
+ COLUMN_ID,
+ COLUMN_TITLE,
+ COLUMN_LAST
+};
+
+G_DEFINE_TYPE (NetDeviceMobile, net_device_mobile, GTK_TYPE_BOX)
+
+static void
+connection_activate_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+
+ if (!nm_client_activate_connection_finish (NM_CLIENT (source_object), res, &error)) {
+ /* failed to activate */
+ nm_device_mobile_refresh_ui (user_data);
+ }
+}
+
+static void
+network_combo_changed_cb (NetDeviceMobile *self)
+{
+ gboolean ret;
+ g_autofree gchar *object_path = NULL;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ NMConnection *connection;
+
+ if (self->updating_device)
+ return;
+
+ ret = gtk_combo_box_get_active_iter (self->network_combo, &iter);
+ if (!ret)
+ return;
+
+ /* get entry */
+ model = gtk_combo_box_get_model (self->network_combo);
+ gtk_tree_model_get (model, &iter,
+ COLUMN_ID, &object_path,
+ -1);
+ if (g_strcmp0 (object_path, NULL) == 0) {
+ GtkNative *native = gtk_widget_get_native (GTK_WIDGET (self));
+ cc_network_panel_connect_to_3g_network (GTK_WIDGET (native), self->client, self->device);
+ return;
+ }
+
+ /* activate the connection */
+ g_debug ("try to switch to connection %s", object_path);
+ connection = (NMConnection*) nm_client_get_connection_by_path (self->client, object_path);
+ if (connection != NULL) {
+ nm_device_disconnect_async (self->device, NULL, NULL, NULL);
+ nm_client_activate_connection_async (self->client,
+ connection,
+ self->device, NULL, NULL,
+ connection_activate_cb,
+ self);
+ return;
+ }
+}
+
+static void
+mobilebb_enabled_toggled (NetDeviceMobile *self)
+{
+ gboolean enabled = FALSE;
+
+ if (nm_client_wwan_get_enabled (self->client)) {
+ NMDeviceState state;
+
+ state = nm_device_get_state (self->device);
+ if (state == NM_DEVICE_STATE_UNKNOWN ||
+ state == NM_DEVICE_STATE_UNMANAGED ||
+ state == NM_DEVICE_STATE_UNAVAILABLE ||
+ state == NM_DEVICE_STATE_DISCONNECTED ||
+ state == NM_DEVICE_STATE_DEACTIVATING ||
+ state == NM_DEVICE_STATE_FAILED) {
+ enabled = FALSE;
+ } else {
+ enabled = TRUE;
+ }
+ }
+
+ self->updating_device = TRUE;
+ gtk_switch_set_active (self->device_off_switch, enabled);
+ self->updating_device = FALSE;
+}
+
+static void
+device_add_device_connections (NetDeviceMobile *self,
+ NMDevice *nm_device,
+ GtkListStore *liststore,
+ GtkComboBox *combobox)
+{
+ GSList *list, *l;
+ GtkTreeIter treeiter;
+ NMActiveConnection *active_connection;
+ NMConnection *connection;
+
+ /* get the list of available connections for this device */
+ list = net_device_get_valid_connections (self->client, nm_device);
+ gtk_list_store_clear (liststore);
+ active_connection = nm_device_get_active_connection (nm_device);
+ for (l = list; l; l = g_slist_next (l)) {
+ connection = NM_CONNECTION (l->data);
+ gtk_list_store_append (liststore, &treeiter);
+ gtk_list_store_set (liststore,
+ &treeiter,
+ COLUMN_ID, nm_connection_get_uuid (connection),
+ COLUMN_TITLE, nm_connection_get_id (connection),
+ -1);
+
+ /* is this already activated? */
+ if (active_connection != NULL &&
+ g_strcmp0 (nm_connection_get_uuid (connection),
+ nm_active_connection_get_uuid (active_connection)) == 0) {
+ self->updating_device = TRUE;
+ gtk_combo_box_set_active_iter (combobox, &treeiter);
+ self->updating_device = FALSE;
+ }
+ }
+
+ /* add new connection entry */
+ gtk_list_store_append (liststore, &treeiter);
+ gtk_list_store_set (liststore,
+ &treeiter,
+ COLUMN_ID, NULL,
+ COLUMN_TITLE, _("Add new connection"),
+ -1);
+
+ g_slist_free (list);
+}
+
+static void
+device_mobile_refresh_equipment_id (NetDeviceMobile *self)
+{
+ const gchar *equipment_id = NULL;
+
+ if (self->mm_object != NULL) {
+ MMModem *modem;
+
+ /* Modem interface should always be present */
+ modem = mm_object_peek_modem (self->mm_object);
+ equipment_id = mm_modem_get_equipment_identifier (modem);
+
+ /* Set equipment ID */
+ if (equipment_id != NULL) {
+ g_debug ("[%s] Equipment ID set to '%s'",
+ mm_object_get_path (self->mm_object),
+ equipment_id);
+ }
+ } else {
+ /* Assume old MM handling */
+ equipment_id = g_object_get_data (G_OBJECT (self),
+ "ControlCenter::EquipmentIdentifier");
+ }
+
+ gtk_label_set_label (self->imei_label, equipment_id);
+ gtk_widget_set_visible (GTK_WIDGET (self->imei_heading_label), equipment_id != NULL);
+ gtk_widget_set_visible (GTK_WIDGET (self->imei_label), equipment_id != NULL);
+}
+
+static gchar *
+device_mobile_find_provider (NetDeviceMobile *self,
+ const gchar *mccmnc,
+ guint32 sid)
+{
+ NMAMobileProvider *provider;
+ GString *name = NULL;
+
+ if (self->mpd == NULL) {
+ g_autoptr(GError) error = NULL;
+
+ /* Use defaults */
+ self->mpd = nma_mobile_providers_database_new_sync (NULL, NULL, NULL, &error);
+ if (self->mpd == NULL) {
+ g_debug ("Couldn't load mobile providers database: %s",
+ error ? error->message : "");
+ return NULL;
+ }
+ }
+
+ if (mccmnc != NULL) {
+ provider = nma_mobile_providers_database_lookup_3gpp_mcc_mnc (self->mpd, mccmnc);
+ if (provider != NULL)
+ name = g_string_new (nma_mobile_provider_get_name (provider));
+ }
+
+ if (sid != 0) {
+ provider = nma_mobile_providers_database_lookup_cdma_sid (self->mpd, sid);
+ if (provider != NULL) {
+ if (name == NULL)
+ name = g_string_new (nma_mobile_provider_get_name (provider));
+ else
+ g_string_append_printf (name, ", %s", nma_mobile_provider_get_name (provider));
+ }
+ }
+
+ return (name != NULL ? g_string_free (name, FALSE) : NULL);
+}
+
+static void
+device_mobile_refresh_operator_name (NetDeviceMobile *self)
+{
+ g_autofree gchar *operator_name = NULL;
+
+ if (self->mm_object != NULL) {
+ MMModem3gpp *modem_3gpp;
+ MMModemCdma *modem_cdma;
+
+ modem_3gpp = mm_object_peek_modem_3gpp (self->mm_object);
+ modem_cdma = mm_object_peek_modem_cdma (self->mm_object);
+
+ if (modem_3gpp != NULL) {
+ const gchar *operator_name_unsafe;
+
+ operator_name_unsafe = mm_modem_3gpp_get_operator_name (modem_3gpp);
+ if (operator_name_unsafe != NULL && operator_name_unsafe[0] != '\0')
+ operator_name = g_strescape (operator_name_unsafe, NULL);
+ }
+
+ /* If not directly given in the 3GPP interface, try to guess from
+ * MCCMNC/SID */
+ if (operator_name == NULL) {
+ const gchar *mccmnc = NULL;
+ guint32 sid = 0;
+
+ if (modem_3gpp != NULL)
+ mccmnc = mm_modem_3gpp_get_operator_code (modem_3gpp);
+ if (modem_cdma != NULL)
+ sid = mm_modem_cdma_get_sid (modem_cdma);
+ operator_name = device_mobile_find_provider (self, mccmnc, sid);
+ }
+
+ /* Set operator name */
+ if (operator_name != NULL) {
+ g_debug ("[%s] Operator name set to '%s'",
+ mm_object_get_path (self->mm_object),
+ operator_name);
+ }
+
+ } else {
+ const gchar *gsm;
+ const gchar *cdma;
+
+ /* Assume old MM handling */
+ gsm = g_object_get_data (G_OBJECT (self),
+ "ControlCenter::OperatorNameGsm");
+ cdma = g_object_get_data (G_OBJECT (self),
+ "ControlCenter::OperatorNameCdma");
+
+ if (gsm != NULL && cdma != NULL)
+ operator_name = g_strdup_printf ("%s, %s", gsm, cdma);
+ else if (gsm != NULL)
+ operator_name = g_strdup (gsm);
+ else if (cdma != NULL)
+ operator_name = g_strdup (cdma);
+ }
+
+ gtk_label_set_label (self->provider_label, operator_name);
+ gtk_widget_set_visible (GTK_WIDGET (self->provider_heading_label), operator_name != NULL);
+ gtk_widget_set_visible (GTK_WIDGET (self->provider_label), operator_name != NULL);
+}
+
+static void
+nm_device_mobile_refresh_ui (NetDeviceMobile *self)
+{
+ gboolean is_connected;
+ NMDeviceModemCapabilities caps;
+ g_autofree gchar *status = NULL;
+ NMIPConfig *ipv4_config = NULL, *ipv6_config = NULL;
+ gboolean have_ipv4_address = FALSE, have_ipv6_address = FALSE;
+ gboolean have_dns4 = FALSE, have_dns6 = FALSE;
+ const gchar *route4_text = NULL, *route6_text = NULL;
+
+ /* set up the device on/off switch */
+ gtk_widget_show (GTK_WIDGET (self->device_off_switch));
+ mobilebb_enabled_toggled (self);
+
+ /* set device state, with status */
+ status = panel_device_status_to_localized_string (self->device, NULL);
+ gtk_label_set_label (self->status_label, status);
+
+ /* sensitive for other connection types if the device is currently connected */
+ is_connected = net_device_get_find_connection (self->client, self->device) != NULL;
+ gtk_widget_set_sensitive (GTK_WIDGET (self->options_button), is_connected);
+
+ caps = nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (self->device));
+ if ((caps & NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS) ||
+ (caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO) ||
+ (caps & NM_DEVICE_MODEM_CAPABILITY_LTE)) {
+ device_mobile_refresh_operator_name (self);
+ device_mobile_refresh_equipment_id (self);
+ }
+
+ /* add possible connections to device */
+ device_add_device_connections (self,
+ self->device,
+ self->mobile_connections_list_store,
+ self->network_combo);
+
+ ipv4_config = nm_device_get_ip4_config (self->device);
+ if (ipv4_config != NULL) {
+ GPtrArray *addresses;
+ const gchar *ipv4_text = NULL;
+ g_autofree gchar *ip4_dns = NULL;
+
+ addresses = nm_ip_config_get_addresses (ipv4_config);
+ if (addresses->len > 0)
+ ipv4_text = nm_ip_address_get_address (g_ptr_array_index (addresses, 0));
+ gtk_label_set_label (self->ipv4_label, ipv4_text);
+ gtk_widget_set_visible (GTK_WIDGET (self->ipv4_heading_label), ipv4_text != NULL);
+ gtk_widget_set_visible (GTK_WIDGET (self->ipv4_label), ipv4_text != NULL);
+ have_ipv4_address = ipv4_text != NULL;
+
+ ip4_dns = g_strjoinv (" ", (char **) nm_ip_config_get_nameservers (ipv4_config));
+ if (!*ip4_dns)
+ ip4_dns = NULL;
+ gtk_label_set_label (self->dns4_label, ip4_dns);
+ gtk_widget_set_visible (GTK_WIDGET (self->dns4_heading_label), ip4_dns != NULL);
+ gtk_widget_set_visible (GTK_WIDGET (self->dns4_label), ip4_dns != NULL);
+ have_dns4 = ip4_dns != NULL;
+
+ route4_text = nm_ip_config_get_gateway (ipv4_config);
+ } else {
+ gtk_widget_hide (GTK_WIDGET (self->ipv4_heading_label));
+ gtk_widget_hide (GTK_WIDGET (self->ipv4_label));
+ gtk_widget_hide (GTK_WIDGET (self->dns4_heading_label));
+ gtk_widget_hide (GTK_WIDGET (self->dns4_label));
+ }
+
+ ipv6_config = nm_device_get_ip6_config (self->device);
+ if (ipv6_config != NULL) {
+ g_autofree gchar *ipv6_text = NULL;
+ g_autofree gchar *ip6_dns = NULL;
+
+ ipv6_text = net_device_get_ip6_addresses (ipv6_config);
+ gtk_label_set_label (self->ipv6_label, ipv6_text);
+ gtk_widget_set_visible (GTK_WIDGET (self->ipv6_heading_label), ipv6_text != NULL);
+ gtk_widget_set_valign (GTK_WIDGET (self->ipv6_heading_label), GTK_ALIGN_START);
+ gtk_widget_set_visible (GTK_WIDGET (self->ipv6_label), ipv6_text != NULL);
+ have_ipv6_address = ipv6_text != NULL;
+
+ ip6_dns = g_strjoinv (" ", (char **) nm_ip_config_get_nameservers (ipv6_config));
+ if (!*ip6_dns)
+ ip6_dns = NULL;
+ gtk_label_set_label (self->dns6_label, ip6_dns);
+ gtk_widget_set_visible (GTK_WIDGET (self->dns6_heading_label), ip6_dns != NULL);
+ gtk_widget_set_visible (GTK_WIDGET (self->dns6_label), ip6_dns != NULL);
+ have_dns6 = ip6_dns != NULL;
+
+ route6_text = nm_ip_config_get_gateway (ipv6_config);
+ } else {
+ gtk_widget_hide (GTK_WIDGET (self->ipv6_heading_label));
+ gtk_widget_hide (GTK_WIDGET (self->ipv6_label));
+ gtk_widget_hide (GTK_WIDGET (self->dns6_heading_label));
+ gtk_widget_hide (GTK_WIDGET (self->dns6_label));
+ }
+
+ if (have_ipv4_address && have_ipv6_address) {
+ gtk_label_set_label (self->ipv4_heading_label, _("IPv4 Address"));
+ gtk_label_set_label (self->ipv6_heading_label, _("IPv6 Address"));
+ }
+ else {
+ gtk_label_set_label (self->ipv4_heading_label, _("IP Address"));
+ gtk_label_set_label (self->ipv6_heading_label, _("IP Address"));
+ }
+
+ if (have_dns4 && have_dns6) {
+ gtk_label_set_label (self->dns4_heading_label, _("DNS4"));
+ gtk_label_set_label (self->dns6_heading_label, _("DNS6"));
+ } else {
+ gtk_label_set_label (self->dns4_heading_label, _("DNS"));
+ gtk_label_set_label (self->dns6_heading_label, _("DNS"));
+ }
+
+ if (route4_text != NULL || route6_text != NULL) {
+ g_autofree const gchar *routes_text = NULL;
+
+ if (route4_text == NULL) {
+ routes_text = g_strdup (route6_text);
+ } else if (route6_text == NULL) {
+ routes_text = g_strdup (route4_text);
+ } else {
+ routes_text = g_strjoin ("\n", route4_text, route6_text, NULL);
+ }
+ gtk_label_set_label (self->route_label, routes_text);
+ gtk_widget_set_visible (GTK_WIDGET (self->route_heading_label), routes_text != NULL);
+ gtk_widget_set_valign (GTK_WIDGET (self->route_heading_label), GTK_ALIGN_START);
+ gtk_widget_set_visible (GTK_WIDGET (self->route_label), routes_text != NULL);
+ } else {
+ gtk_widget_hide (GTK_WIDGET (self->route_heading_label));
+ gtk_widget_hide (GTK_WIDGET (self->route_label));
+ }
+}
+
+static void
+device_off_switch_changed_cb (NetDeviceMobile *self)
+{
+ const GPtrArray *acs;
+ gboolean active;
+ gint i;
+ NMActiveConnection *a;
+ NMConnection *connection;
+
+ if (self->updating_device)
+ return;
+
+ connection = net_device_get_find_connection (self->client, self->device);
+ if (connection == NULL)
+ return;
+
+ active = gtk_switch_get_active (self->device_off_switch);
+ if (active) {
+ nm_client_activate_connection_async (self->client,
+ connection,
+ self->device,
+ NULL, NULL, NULL, NULL);
+ } else {
+ const gchar *uuid;
+
+ uuid = nm_connection_get_uuid (connection);
+ acs = nm_client_get_active_connections (self->client);
+ for (i = 0; acs && i < acs->len; i++) {
+ a = (NMActiveConnection*)acs->pdata[i];
+ if (strcmp (nm_active_connection_get_uuid (a), uuid) == 0) {
+ nm_client_deactivate_connection_async (self->client, a, NULL, NULL, NULL);
+ break;
+ }
+ }
+ }
+}
+
+static void
+options_button_clicked_cb (NetDeviceMobile *self)
+{
+ const gchar *uuid;
+ g_autofree gchar *cmdline = NULL;
+ g_autoptr(GError) error = NULL;
+ NMConnection *connection;
+
+ connection = net_device_get_find_connection (self->client, self->device);
+ uuid = nm_connection_get_uuid (connection);
+ cmdline = g_strdup_printf ("nm-connection-editor --edit %s", uuid);
+ g_debug ("Launching '%s'\n", cmdline);
+ if (!g_spawn_command_line_async (cmdline, &error))
+ g_warning ("Failed to launch nm-connection-editor: %s", error->message);
+}
+
+static void
+device_mobile_device_got_modem_manager_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) result = NULL;
+ g_autoptr(GDBusProxy) proxy = NULL;
+ NetDeviceMobile *self = (NetDeviceMobile *)user_data;
+
+ proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+ if (!proxy) {
+ g_warning ("Error creating ModemManager proxy: %s",
+ error->message);
+ return;
+ }
+
+ /* get the IMEI */
+ result = g_dbus_proxy_get_cached_property (proxy,
+ "EquipmentIdentifier");
+
+ /* save */
+ if (result)
+ g_object_set_data_full (G_OBJECT (self),
+ "ControlCenter::EquipmentIdentifier",
+ g_variant_dup_string (result, NULL),
+ g_free);
+
+ device_mobile_refresh_equipment_id (self);
+}
+
+static void
+device_mobile_save_operator_name (NetDeviceMobile *self,
+ const gchar *field,
+ const gchar *operator_name)
+{
+ gchar *operator_name_safe = NULL;
+
+ if (operator_name != NULL && operator_name[0] != '\0')
+ operator_name_safe = g_strescape (operator_name, NULL);
+
+ /* save */
+ g_object_set_data_full (G_OBJECT (self),
+ field,
+ operator_name_safe,
+ g_free);
+ /* refresh */
+ device_mobile_refresh_operator_name (self);
+}
+
+static void
+device_mobile_get_registration_info_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autofree gchar *operator_code = NULL;
+ g_autoptr(GError) error = NULL;
+ guint registration_status;
+ g_autoptr(GVariant) result = NULL;
+ g_autofree gchar *operator_name = NULL;
+ NetDeviceMobile *self = (NetDeviceMobile *)user_data;
+
+ result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error);
+ if (result == NULL) {
+ g_warning ("Error getting registration info: %s\n",
+ error->message);
+ return;
+ }
+
+ /* get values */
+ g_variant_get (result, "((uss))",
+ &registration_status,
+ &operator_code,
+ &operator_name);
+
+ /* If none give, try to guess it */
+ if (operator_name == NULL || operator_name[0] == '\0') {
+ g_free (operator_name);
+ operator_name = device_mobile_find_provider (self, operator_code, 0);
+ }
+
+ /* save and refresh */
+ device_mobile_save_operator_name (self,
+ "ControlCenter::OperatorNameGsm",
+ operator_name);
+}
+
+static void
+device_mobile_gsm_signal_cb (NetDeviceMobile *self,
+ const gchar *sender_name,
+ const gchar *signal_name,
+ GVariant *parameters)
+{
+ guint registration_status = 0;
+ g_autofree gchar *operator_code = NULL;
+ g_autofree gchar *operator_name = NULL;
+
+ if (!g_str_equal (signal_name, "RegistrationInfo"))
+ return;
+
+ g_variant_get (parameters,
+ "(uss)",
+ &registration_status,
+ &operator_code,
+ &operator_name);
+
+ /* If none given, try to guess it */
+ if (operator_name == NULL || operator_name[0] == '\0') {
+ g_free (operator_name);
+ operator_name = device_mobile_find_provider (self, operator_code, 0);
+ }
+
+ /* save and refresh */
+ device_mobile_save_operator_name (self,
+ "ControlCenter::OperatorNameGsm",
+ operator_name);
+}
+
+static void
+device_mobile_device_got_modem_manager_gsm_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+ NetDeviceMobile *self = (NetDeviceMobile *)user_data;
+
+ self->gsm_proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+ if (self->gsm_proxy == NULL) {
+ g_warning ("Error creating ModemManager GSM proxy: %s\n",
+ error->message);
+ return;
+ }
+
+ /* Setup value updates */
+ g_signal_connect_object (self->gsm_proxy,
+ "g-signal",
+ G_CALLBACK (device_mobile_gsm_signal_cb),
+ self,
+ G_CONNECT_SWAPPED);
+
+ /* Load initial value */
+ g_dbus_proxy_call (self->gsm_proxy,
+ "GetRegistrationInfo",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ device_mobile_get_registration_info_cb,
+ self);
+}
+
+static void
+device_mobile_get_serving_system_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ NetDeviceMobile *self = (NetDeviceMobile *)user_data;
+ g_autoptr(GVariant) result = NULL;
+ g_autoptr(GError) error = NULL;
+
+ guint32 band_class;
+ g_autofree gchar *band = NULL;
+ guint32 sid;
+ gchar *operator_name;
+
+ result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error);
+ if (result == NULL) {
+ g_warning ("Error getting serving system: %s\n",
+ error->message);
+ return;
+ }
+
+ /* get values */
+ g_variant_get (result, "((usu))",
+ &band_class,
+ &band,
+ &sid);
+
+ operator_name = device_mobile_find_provider (self, NULL, sid);
+
+ /* save and refresh */
+ device_mobile_save_operator_name (self,
+ "ControlCenter::OperatorNameCdma",
+ operator_name);
+}
+
+static void
+device_mobile_device_got_modem_manager_cdma_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+ NetDeviceMobile *self = (NetDeviceMobile *)user_data;
+
+ self->cdma_proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+ if (self->cdma_proxy == NULL) {
+ g_warning ("Error creating ModemManager CDMA proxy: %s\n",
+ error->message);
+ return;
+ }
+
+ /* Load initial value */
+ g_dbus_proxy_call (self->cdma_proxy,
+ "GetServingSystem",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ device_mobile_get_serving_system_cb,
+ self);
+}
+
+static void
+operator_name_updated (NetDeviceMobile *self)
+{
+ device_mobile_refresh_operator_name (self);
+}
+
+static void
+net_device_mobile_dispose (GObject *object)
+{
+ NetDeviceMobile *self = NET_DEVICE_MOBILE (object);
+
+ g_cancellable_cancel (self->cancellable);
+
+ g_clear_object (&self->client);
+ g_clear_object (&self->device);
+ g_clear_object (&self->modem);
+ g_clear_object (&self->cancellable);
+ g_clear_object (&self->gsm_proxy);
+ g_clear_object (&self->cdma_proxy);
+ g_clear_object (&self->mm_object);
+ g_clear_object (&self->mpd);
+
+ G_OBJECT_CLASS (net_device_mobile_parent_class)->dispose (object);
+}
+
+static void
+net_device_mobile_class_init (NetDeviceMobileClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = net_device_mobile_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/network-mobile.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, device_label);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, device_off_switch);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, dns4_heading_label);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, dns4_label);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, dns6_heading_label);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, dns6_label);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, imei_heading_label);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, imei_label);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, ipv4_heading_label);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, ipv4_label);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, ipv6_heading_label);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, ipv6_label);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, mobile_connections_list_store);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, network_combo);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, network_label);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, options_button);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, provider_heading_label);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, provider_label);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, route_heading_label);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, route_label);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, status_label);
+
+ gtk_widget_class_bind_template_callback (widget_class, device_off_switch_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, network_combo_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, options_button_clicked_cb);
+}
+
+static void
+net_device_mobile_init (NetDeviceMobile *self)
+{
+ g_autofree gchar *path = NULL;
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->cancellable = g_cancellable_new ();
+
+ path = g_find_program_in_path ("nm-connection-editor");
+ gtk_widget_set_visible (GTK_WIDGET (self->options_button), path != NULL);
+}
+
+NetDeviceMobile *
+net_device_mobile_new (NMClient *client, NMDevice *device, GDBusObject *modem)
+{
+ NetDeviceMobile *self;
+ NMDeviceModemCapabilities caps;
+
+ self = g_object_new (net_device_mobile_get_type (), NULL);
+ self->client = g_object_ref (client);
+ self->device = g_object_ref (device);
+
+ g_signal_connect_object (device, "state-changed", G_CALLBACK (nm_device_mobile_refresh_ui), self, G_CONNECT_SWAPPED);
+
+ if (modem != NULL) {
+ MMModem3gpp *modem_3gpp;
+
+ self->modem = g_object_ref (modem);
+
+ /* Load equipment ID initially */
+ device_mobile_refresh_equipment_id (self);
+
+ /* Follow changes in operator name and load initial values */
+ modem_3gpp = mm_object_peek_modem_3gpp (self->mm_object);
+ if (modem_3gpp != NULL) {
+ g_signal_connect_object (modem_3gpp,
+ "notify::operator-name",
+ G_CALLBACK (operator_name_updated),
+ self,
+ G_CONNECT_SWAPPED);
+ device_mobile_refresh_operator_name (self);
+ }
+ }
+
+ caps = nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (device));
+
+ /* Only load proxies if we have broadband modems of the OLD ModemManager interface */
+ if (g_str_has_prefix (nm_device_get_udi (device), "/org/freedesktop/ModemManager/") &&
+ ((caps & NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS) ||
+ (caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO) ||
+ (caps & NM_DEVICE_MODEM_CAPABILITY_LTE))) {
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.freedesktop.ModemManager",
+ nm_device_get_udi (device),
+ "org.freedesktop.ModemManager.Modem",
+ self->cancellable,
+ device_mobile_device_got_modem_manager_cb,
+ self);
+
+ if ((caps & NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS) ||
+ (caps & NM_DEVICE_MODEM_CAPABILITY_LTE)) {
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.freedesktop.ModemManager",
+ nm_device_get_udi (device),
+ "org.freedesktop.ModemManager.Modem.Gsm.Network",
+ self->cancellable,
+ device_mobile_device_got_modem_manager_gsm_cb,
+ self);
+ }
+
+ if (caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO) {
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.freedesktop.ModemManager",
+ nm_device_get_udi (device),
+ "org.freedesktop.ModemManager.Modem.Cdma",
+ self->cancellable,
+ device_mobile_device_got_modem_manager_cdma_cb,
+ self);
+ }
+ }
+
+ g_signal_connect_object (client, "notify::wwan-enabled",
+ G_CALLBACK (mobilebb_enabled_toggled),
+ self, G_CONNECT_SWAPPED);
+ nm_device_mobile_refresh_ui (self);
+
+ return self;
+}
+
+NMDevice *
+net_device_mobile_get_device (NetDeviceMobile *self)
+{
+ g_return_val_if_fail (NET_IS_DEVICE_MOBILE (self), NULL);
+ return self->device;
+}
+
+void
+net_device_mobile_set_title (NetDeviceMobile *self, const gchar *title)
+{
+ g_return_if_fail (NET_IS_DEVICE_MOBILE (self));
+ gtk_label_set_label (self->device_label, title);
+}
diff --git a/panels/network/net-device-mobile.h b/panels/network/net-device-mobile.h
new file mode 100644
index 0000000..7574d3f
--- /dev/null
+++ b/panels/network/net-device-mobile.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2011-2012 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (NetDeviceMobile, net_device_mobile, NET, DEVICE_MOBILE, GtkBox)
+
+NetDeviceMobile *net_device_mobile_new (NMClient *client,
+ NMDevice *device,
+ GDBusObject *modem);
+
+NMDevice *net_device_mobile_get_device (NetDeviceMobile *device);
+
+void net_device_mobile_set_title (NetDeviceMobile *device,
+ const gchar *title);
+
+G_END_DECLS
diff --git a/panels/network/net-device-wifi.c b/panels/network/net-device-wifi.c
new file mode 100644
index 0000000..28160b4
--- /dev/null
+++ b/panels/network/net-device-wifi.c
@@ -0,0 +1,1303 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2011-2012 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <glib/gi18n.h>
+
+#include <netinet/ether.h>
+
+#include <NetworkManager.h>
+#include <polkit/polkit.h>
+
+#include "cc-wifi-hotspot-dialog.h"
+#include "hostname-helper.h"
+#include "network-dialogs.h"
+#include "panel-common.h"
+#include "cc-list-row.h"
+
+#include "connection-editor/net-connection-editor.h"
+#include "net-device-wifi.h"
+
+#include "cc-wifi-connection-list.h"
+#include "cc-wifi-connection-row.h"
+
+#define PERIODIC_WIFI_SCAN_TIMEOUT 15
+
+static void nm_device_wifi_refresh_ui (NetDeviceWifi *self);
+static void show_wifi_list (NetDeviceWifi *self);
+static void show_hotspot_ui (NetDeviceWifi *self);
+
+
+struct _NetDeviceWifi
+{
+ AdwBin parent;
+
+ GtkBox *center_box;
+ GtkListBoxRow *connect_hidden_row;
+ GtkSwitch *device_off_switch;
+ GtkBox *header_box;
+ GtkPopover *header_button_popover;
+ GtkBox *hotspot_box;
+ CcListRow *hotspot_name_row;
+ CcListRow *hotspot_security_row;
+ CcListRow *hotspot_password_row;
+ GtkBox *listbox_box;
+ GtkStack *stack;
+ GtkListBoxRow *start_hotspot_row;
+ GtkLabel *status_label;
+ GtkLabel *title_label;
+
+ CcPanel *panel;
+ NMClient *client;
+ NMDevice *device;
+ gboolean updating_device;
+ gchar *selected_ssid_title;
+ gchar *selected_connection_id;
+ gchar *selected_ap_id;
+ CcWifiHotspotDialog *hotspot_dialog;
+
+ gint64 last_scan;
+ gboolean scanning;
+
+ guint monitor_scanning_id;
+ guint scan_id;
+ GCancellable *cancellable;
+};
+
+enum {
+ PROP_0,
+ PROP_SCANNING,
+ PROP_LAST,
+};
+
+G_DEFINE_TYPE (NetDeviceWifi, net_device_wifi, ADW_TYPE_BIN)
+
+static void
+disable_scan_timeout (NetDeviceWifi *self)
+{
+ g_debug ("Disabling periodic Wi-Fi scan");
+ if (self->monitor_scanning_id > 0) {
+ g_source_remove (self->monitor_scanning_id);
+ self->monitor_scanning_id = 0;
+ }
+ if (self->scan_id > 0) {
+ g_source_remove (self->scan_id);
+ self->scan_id = 0;
+ }
+}
+
+static void
+wireless_enabled_toggled (NetDeviceWifi *self)
+{
+ gboolean enabled;
+
+ enabled = nm_client_wireless_get_enabled (self->client);
+
+ self->updating_device = TRUE;
+ gtk_switch_set_active (self->device_off_switch, enabled);
+ if (!enabled)
+ disable_scan_timeout (self);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->connect_hidden_row), enabled);
+ self->updating_device = FALSE;
+}
+
+static NMConnection *
+find_connection_for_device (NetDeviceWifi *self,
+ NMDevice *device)
+{
+ return net_device_get_find_connection (self->client, device);
+}
+
+static gboolean
+connection_is_shared (NMConnection *c)
+{
+ NMSettingIPConfig *s_ip4;
+
+ s_ip4 = nm_connection_get_setting_ip4_config (c);
+ if (g_strcmp0 (nm_setting_ip_config_get_method (s_ip4),
+ NM_SETTING_IP4_CONFIG_METHOD_SHARED) != 0) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+device_is_hotspot (NetDeviceWifi *self)
+{
+ NMConnection *c;
+
+ if (nm_device_get_active_connection (self->device) == NULL)
+ return FALSE;
+
+ c = find_connection_for_device (self, self->device);
+ if (c == NULL)
+ return FALSE;
+
+ return connection_is_shared (c);
+}
+
+static GBytes *
+device_get_hotspot_ssid (NetDeviceWifi *self,
+ NMDevice *device)
+{
+ NMConnection *c;
+ NMSettingWireless *sw;
+
+ c = find_connection_for_device (self, device);
+ if (c == NULL)
+ return NULL;
+
+ sw = nm_connection_get_setting_wireless (c);
+ return nm_setting_wireless_get_ssid (sw);
+}
+
+static void
+get_secrets_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer data)
+{
+ NetDeviceWifi *self = data;
+ g_autoptr(GVariant) secrets = NULL;
+ g_autoptr(GError) error = NULL;
+
+ secrets = nm_remote_connection_get_secrets_finish (NM_REMOTE_CONNECTION (source_object), res, &error);
+ if (!secrets) {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Could not get secrets: %s", error->message);
+ return;
+ }
+
+ nm_connection_update_secrets (NM_CONNECTION (source_object),
+ NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+ secrets, NULL);
+
+ nm_device_wifi_refresh_ui (self);
+}
+
+static void
+device_get_hotspot_security_details (NetDeviceWifi *self,
+ NMDevice *device,
+ gchar **secret,
+ gchar **security)
+{
+ NMConnection *c;
+ NMSettingWirelessSecurity *sws;
+ const gchar *key_mgmt;
+ const gchar *tmp_secret;
+ const gchar *tmp_security;
+
+ c = find_connection_for_device (self, device);
+ if (c == NULL)
+ return;
+
+ sws = nm_connection_get_setting_wireless_security (c);
+ if (sws == NULL)
+ return;
+
+ tmp_secret = NULL;
+ tmp_security = C_("Wifi security", "None");
+
+ /* Key management values:
+ * "none" = WEP
+ * "wpa-none" = WPAv1 Ad-Hoc mode (not supported in NM >= 0.9.4)
+ * "wpa-psk" = WPAv2 Ad-Hoc mode (eg IBSS RSN) and AP-mode WPA v1 and v2
+ */
+ key_mgmt = nm_setting_wireless_security_get_key_mgmt (sws);
+ if (strcmp (key_mgmt, "none") == 0) {
+ tmp_secret = nm_setting_wireless_security_get_wep_key (sws, 0);
+ tmp_security = _("WEP");
+ }
+ else if (strcmp (key_mgmt, "wpa-none") == 0 ||
+ strcmp (key_mgmt, "wpa-psk") == 0) {
+ tmp_secret = nm_setting_wireless_security_get_psk (sws);
+ tmp_security = _("WPA");
+ } else {
+ g_warning ("unhandled security key-mgmt: %s", key_mgmt);
+ }
+
+ /* If we don't have secrets, request them from NM and bail.
+ * We'll refresh the UI when secrets arrive.
+ */
+ if (tmp_secret == NULL) {
+ nm_remote_connection_get_secrets_async ((NMRemoteConnection*)c,
+ NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+ self->cancellable,
+ get_secrets_cb,
+ self);
+ return;
+ }
+
+ if (secret)
+ *secret = g_strdup (tmp_secret);
+ if (security)
+ *security = g_strdup (tmp_security);
+}
+
+static void
+nm_device_wifi_refresh_hotspot (NetDeviceWifi *self)
+{
+ GBytes *ssid;
+ g_autofree gchar *hotspot_secret = NULL;
+ g_autofree gchar *hotspot_security = NULL;
+ g_autofree gchar *hotspot_ssid = NULL;
+
+ /* refresh hotspot ui */
+ ssid = device_get_hotspot_ssid (self, self->device);
+ if (ssid)
+ hotspot_ssid = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid));
+ device_get_hotspot_security_details (self,
+ self->device,
+ &hotspot_secret,
+ &hotspot_security);
+
+ g_debug ("Refreshing hotspot labels to name: '%s', security key: '%s', security: '%s'",
+ hotspot_ssid, hotspot_secret, hotspot_security);
+
+ cc_list_row_set_secondary_label (self->hotspot_name_row, hotspot_ssid);
+ gtk_widget_set_visible (GTK_WIDGET (self->hotspot_name_row), hotspot_ssid != NULL);
+
+ cc_list_row_set_secondary_label (self->hotspot_password_row, hotspot_secret);
+ gtk_widget_set_visible (GTK_WIDGET (self->hotspot_password_row), hotspot_secret != NULL);
+
+ cc_list_row_set_secondary_label (self->hotspot_security_row, hotspot_security);
+ gtk_widget_set_visible (GTK_WIDGET (self->hotspot_security_row), hotspot_security != NULL);
+}
+
+static void
+set_scanning (NetDeviceWifi *self,
+ gboolean scanning,
+ gint64 last_scan)
+{
+ gboolean scanning_changed = self->scanning != scanning;
+
+ self->scanning = scanning;
+ self->last_scan = last_scan;
+
+ if (scanning_changed)
+ g_object_notify (G_OBJECT (self), "scanning");
+}
+
+static gboolean
+update_scanning (gpointer user_data)
+{
+ NetDeviceWifi *self = user_data;
+ gint64 last_scan;
+
+ last_scan = nm_device_wifi_get_last_scan (NM_DEVICE_WIFI (self->device));
+
+ /* The last_scan property is updated after the device finished scanning,
+ * so notify about it and stop monitoring for changes.
+ */
+ if (self->last_scan != last_scan) {
+ set_scanning (self, FALSE, last_scan);
+ self->monitor_scanning_id = 0;
+ return G_SOURCE_REMOVE;
+ }
+
+ return G_SOURCE_CONTINUE;
+}
+
+static gboolean
+request_scan (gpointer user_data)
+{
+ NetDeviceWifi *self = user_data;
+
+ g_debug ("Periodic Wi-Fi scan requested");
+
+ set_scanning (self, TRUE,
+ nm_device_wifi_get_last_scan (NM_DEVICE_WIFI (self->device)));
+
+ if (self->monitor_scanning_id == 0) {
+ self->monitor_scanning_id = g_timeout_add (1500, update_scanning,
+ self);
+ }
+
+ nm_device_wifi_request_scan_async (NM_DEVICE_WIFI (self->device),
+ self->cancellable, NULL, NULL);
+
+ return G_SOURCE_CONTINUE;
+}
+
+static void
+nm_device_wifi_refresh_ui (NetDeviceWifi *self)
+{
+ g_autofree gchar *status = NULL;
+
+ if (device_is_hotspot (self)) {
+ nm_device_wifi_refresh_hotspot (self);
+ show_hotspot_ui (self);
+ disable_scan_timeout (self);
+ return;
+ }
+
+ if (self->scan_id == 0 &&
+ nm_client_wireless_get_enabled (self->client)) {
+ self->scan_id = g_timeout_add_seconds (PERIODIC_WIFI_SCAN_TIMEOUT,
+ request_scan, self);
+ request_scan (self);
+ }
+
+ /* keep this in sync with the signal handler setup in cc_network_panel_init */
+ wireless_enabled_toggled (self);
+
+ status = panel_device_status_to_localized_string (self->device, NULL);
+ gtk_label_set_label (self->status_label, status);
+
+ /* update list of APs */
+ show_wifi_list (self);
+}
+
+static void
+device_off_switch_changed_cb (NetDeviceWifi *self)
+{
+ gboolean active;
+
+ if (self->updating_device)
+ return;
+
+ active = gtk_switch_get_active (self->device_off_switch);
+ nm_client_dbus_set_property (self->client,
+ NM_DBUS_PATH,
+ NM_DBUS_INTERFACE,
+ "WirelessEnabled",
+ g_variant_new_boolean (active),
+ -1,
+ NULL, NULL, NULL);
+ if (!active)
+ disable_scan_timeout (self);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->connect_hidden_row), active);
+}
+
+static void
+connect_hidden (NetDeviceWifi *self)
+{
+ GtkNative *native = gtk_widget_get_native (GTK_WIDGET (self));
+ cc_network_panel_connect_to_hidden_network (GTK_WIDGET (native), self->client);
+ gtk_popover_popdown (self->header_button_popover);
+}
+
+static void
+connection_add_activate_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ NMActiveConnection *conn;
+ g_autoptr(GError) error = NULL;
+
+ conn = nm_client_add_and_activate_connection_finish (NM_CLIENT (source_object), res, &error);
+ if (!conn) {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ nm_device_wifi_refresh_ui (user_data);
+ /* failed to activate */
+ g_warning ("Failed to add and activate connection '%d': %s",
+ error->code,
+ error->message);
+ }
+ return;
+ }
+}
+
+static void
+connection_activate_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+
+ if (!nm_client_activate_connection_finish (NM_CLIENT (source_object), res, &error)) {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ nm_device_wifi_refresh_ui (user_data);
+ /* failed to activate */
+ g_debug ("Failed to add and activate connection '%d': %s",
+ error->code,
+ error->message);
+ }
+ return;
+ }
+}
+
+static gboolean
+is_8021x (NMDevice *device,
+ const char *ap_object_path)
+{
+ NM80211ApSecurityFlags wpa_flags, rsn_flags;
+ NMAccessPoint *ap;
+
+ ap = nm_device_wifi_get_access_point_by_path (NM_DEVICE_WIFI (device),
+ ap_object_path);
+ if (!ap)
+ return FALSE;
+
+ rsn_flags = nm_access_point_get_rsn_flags (ap);
+ if (rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)
+ return TRUE;
+
+ wpa_flags = nm_access_point_get_wpa_flags (ap);
+ if (wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)
+ return TRUE;
+ return FALSE;
+}
+
+static void
+wireless_try_to_connect (NetDeviceWifi *self,
+ GBytes *ssid,
+ const gchar *ap_object_path)
+{
+ const gchar *ssid_target;
+
+ if (self->updating_device)
+ return;
+
+ if (ap_object_path == NULL || ap_object_path[0] == 0)
+ return;
+
+ ssid_target = nm_utils_escape_ssid ((gpointer) g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid));
+ g_debug ("try to connect to WIFI network %s [%s]",
+ ssid_target, ap_object_path);
+
+ /* activate the connection */
+ if (!is_8021x (self->device, ap_object_path)) {
+ g_autoptr(GPermission) permission = NULL;
+ gboolean allowed_to_share = FALSE;
+ g_autoptr(NMConnection) partial = NULL;
+
+ permission = polkit_permission_new_sync ("org.freedesktop.NetworkManager.settings.modify.system",
+ NULL, NULL, NULL);
+ if (permission)
+ allowed_to_share = g_permission_get_allowed (permission);
+
+ if (!allowed_to_share) {
+ NMSettingConnection *s_con;
+
+ s_con = (NMSettingConnection *)nm_setting_connection_new ();
+ nm_setting_connection_add_permission (s_con, "user", g_get_user_name (), NULL);
+ partial = nm_simple_connection_new ();
+ nm_connection_add_setting (partial, NM_SETTING (s_con));
+ }
+
+ g_debug ("no existing connection found for %s, creating and activating one", ssid_target);
+ nm_client_add_and_activate_connection_async (self->client,
+ partial,
+ self->device,
+ ap_object_path,
+ self->cancellable,
+ connection_add_activate_cb,
+ self);
+ } else {
+ g_autoptr(GVariantBuilder) builder = NULL;
+ GVariant *parameters;
+
+ g_debug ("no existing connection found for %s, creating", ssid_target);
+ builder = g_variant_builder_new (G_VARIANT_TYPE ("av"));
+ g_variant_builder_add (builder, "v", g_variant_new_string ("connect-8021x-wifi"));
+ g_variant_builder_add (builder, "v", g_variant_new_string (nm_object_get_path (NM_OBJECT (self->device))));
+ g_variant_builder_add (builder, "v", g_variant_new_string (ap_object_path));
+ parameters = g_variant_new ("av", builder);
+
+ g_object_set (self->panel, "parameters", parameters, NULL);
+ }
+}
+
+static gchar *
+get_hostname (void)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+ g_autoptr(GVariant) res = NULL;
+ g_autoptr(GVariant) inner = NULL;
+ g_autoptr(GError) error = NULL;
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (bus == NULL) {
+ g_warning ("Failed to get system bus connection: %s", error->message);
+ return NULL;
+ }
+ res = g_dbus_connection_call_sync (bus,
+ "org.freedesktop.hostname1",
+ "/org/freedesktop/hostname1",
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ g_variant_new ("(ss)",
+ "org.freedesktop.hostname1",
+ "PrettyHostname"),
+ (GVariantType*)"(v)",
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if (res == NULL) {
+ g_warning ("Getting pretty hostname failed: %s", error->message);
+ return NULL;
+ }
+
+ g_variant_get (res, "(v)", &inner);
+ return g_variant_dup_string (inner, NULL);
+}
+
+static gboolean
+is_hotspot_connection (NMConnection *connection)
+{
+ NMSettingConnection *sc;
+ NMSettingWireless *sw;
+ NMSettingIPConfig *sip;
+ NMSetting *setting;
+
+ sc = nm_connection_get_setting_connection (connection);
+ if (g_strcmp0 (nm_setting_connection_get_connection_type (sc), "802-11-wireless") != 0) {
+ return FALSE;
+ }
+ sw = nm_connection_get_setting_wireless (connection);
+ if (g_strcmp0 (nm_setting_wireless_get_mode (sw), "adhoc") != 0 &&
+ g_strcmp0 (nm_setting_wireless_get_mode (sw), "ap") != 0) {
+ return FALSE;
+ }
+ setting = nm_connection_get_setting_by_name (connection, NM_SETTING_WIRELESS_SETTING_NAME);
+ if (!setting)
+ return FALSE;
+
+ sip = nm_connection_get_setting_ip4_config (connection);
+ if (g_strcmp0 (nm_setting_ip_config_get_method (sip), "shared") != 0) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+show_hotspot_ui (NetDeviceWifi *self)
+{
+ /* show hotspot tab */
+ gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->hotspot_box));
+}
+
+static void
+activate_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+
+ if (nm_client_activate_connection_finish (NM_CLIENT (source_object), res, &error) == NULL) {
+ g_warning ("Failed to add new connection: (%d) %s",
+ error->code,
+ error->message);
+ return;
+ }
+
+ /* show hotspot tab */
+ nm_device_wifi_refresh_ui (user_data);
+}
+
+static void
+activate_new_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ NMActiveConnection *conn;
+ g_autoptr(GError) error = NULL;
+
+ conn = nm_client_add_and_activate_connection_finish (NM_CLIENT (source_object),
+ res, &error);
+ if (!conn) {
+ g_warning ("Failed to add new connection: (%d) %s",
+ error->code,
+ error->message);
+ return;
+ }
+
+ /* show hotspot tab */
+ nm_device_wifi_refresh_ui (user_data);
+}
+
+static NMConnection *
+net_device_wifi_get_hotspot_connection (NetDeviceWifi *self)
+{
+ GSList *connections, *l;
+ NMConnection *c = NULL;
+
+ connections = net_device_get_valid_connections (self->client, self->device);
+ for (l = connections; l; l = l->next) {
+ NMConnection *tmp = l->data;
+ if (is_hotspot_connection (tmp)) {
+ c = tmp;
+ break;
+ }
+ }
+ g_slist_free (connections);
+
+ return c;
+}
+
+static void
+overwrite_ssid_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+ NMRemoteConnection *connection;
+ NMConnection *c;
+ NetDeviceWifi *self;
+
+ connection = NM_REMOTE_CONNECTION (source_object);
+
+ if (!nm_remote_connection_commit_changes_finish (connection, res, &error)) {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to save hotspot's settings to disk: %s",
+ error->message);
+ return;
+ }
+
+ self = user_data;
+ c = net_device_wifi_get_hotspot_connection (self);
+
+ g_debug ("activate existing hotspot connection\n");
+ nm_client_activate_connection_async (self->client,
+ c,
+ self->device,
+ NULL,
+ self->cancellable,
+ activate_cb,
+ self);
+}
+
+static void
+on_wifi_hotspot_dialog_respnse_cb (GtkDialog *dialog,
+ gint response,
+ NetDeviceWifi *self)
+{
+ if (response == GTK_RESPONSE_APPLY) {
+ NMConnection *connection;
+
+ connection = cc_wifi_hotspot_dialog_get_connection (self->hotspot_dialog);
+ if (NM_IS_REMOTE_CONNECTION (connection))
+ nm_remote_connection_commit_changes_async (NM_REMOTE_CONNECTION (connection),
+ TRUE,
+ self->cancellable,
+ overwrite_ssid_cb,
+ self);
+ else
+ nm_client_add_and_activate_connection_async (self->client,
+ connection,
+ self->device,
+ NULL,
+ self->cancellable,
+ activate_new_cb,
+ self);
+ }
+
+ gtk_widget_hide (GTK_WIDGET (self->hotspot_dialog));
+}
+
+static void
+start_hotspot (NetDeviceWifi *self)
+{
+ GtkNative *native;
+ NMConnection *c;
+ g_autofree gchar *hostname = NULL;
+ g_autofree gchar *ssid = NULL;
+
+ native = gtk_widget_get_native (GTK_WIDGET (self));
+
+ if (!self->hotspot_dialog)
+ self->hotspot_dialog = cc_wifi_hotspot_dialog_new (GTK_WINDOW (native));
+ cc_wifi_hotspot_dialog_set_device (self->hotspot_dialog, NM_DEVICE_WIFI (self->device));
+ hostname = get_hostname ();
+ ssid = pretty_hostname_to_ssid (hostname);
+ cc_wifi_hotspot_dialog_set_hostname (self->hotspot_dialog, ssid);
+ c = net_device_wifi_get_hotspot_connection (self);
+ if (c)
+ cc_wifi_hotspot_dialog_set_connection (self->hotspot_dialog, c);
+
+ g_signal_connect_after (self->hotspot_dialog, "response", G_CALLBACK (on_wifi_hotspot_dialog_respnse_cb), self);
+ gtk_window_present (GTK_WINDOW (self->hotspot_dialog));
+ gtk_popover_popdown (self->header_button_popover);
+}
+
+static void
+stop_shared_connection (NetDeviceWifi *self)
+{
+ const GPtrArray *connections;
+ const GPtrArray *devices;
+ gint i;
+ NMActiveConnection *c;
+ gboolean found = FALSE;
+
+ connections = nm_client_get_active_connections (self->client);
+ for (i = 0; connections && i < connections->len; i++) {
+ c = (NMActiveConnection *)connections->pdata[i];
+
+ devices = nm_active_connection_get_devices (c);
+ if (devices && devices->pdata[0] == self->device) {
+ nm_client_deactivate_connection_async (self->client, c, NULL, NULL, NULL);
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found) {
+ g_warning ("Could not stop hotspot connection as no connection attached to the device could be found.");
+ return;
+ }
+
+ nm_device_wifi_refresh_ui (self);
+}
+
+static void
+show_wifi_list (NetDeviceWifi *self)
+{
+ gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->listbox_box));
+}
+
+static void
+net_device_wifi_finalize (GObject *object)
+{
+ NetDeviceWifi *self = NET_DEVICE_WIFI (object);
+
+ g_cancellable_cancel (self->cancellable);
+ g_clear_object (&self->cancellable);
+ disable_scan_timeout (self);
+
+ g_clear_object (&self->client);
+ g_clear_object (&self->device);
+ g_clear_pointer (&self->selected_ssid_title, g_free);
+ g_clear_pointer (&self->selected_connection_id, g_free);
+ g_clear_pointer (&self->selected_ap_id, g_free);
+
+ G_OBJECT_CLASS (net_device_wifi_parent_class)->finalize (object);
+}
+
+static void
+net_device_wifi_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ NetDeviceWifi *self = NET_DEVICE_WIFI (object);
+
+ switch (prop_id) {
+ case PROP_SCANNING:
+ g_value_set_boolean (value, self->scanning);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+really_forgotten (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(CcWifiConnectionList) list = user_data;
+ g_autoptr(GError) error = NULL;
+
+ cc_wifi_connection_list_thaw (list);
+
+ if (!nm_remote_connection_delete_finish (NM_REMOTE_CONNECTION (source_object), res, &error))
+ g_warning ("failed to delete connection %s: %s",
+ nm_object_get_path (NM_OBJECT (source_object)),
+ error->message);
+}
+
+static void
+really_forget (GtkDialog *dialog, gint response, gpointer data)
+{
+ GtkWidget *forget = data;
+ CcWifiConnectionRow *row;
+ GList *rows;
+ GList *r;
+ NMRemoteConnection *connection;
+ NetDeviceWifi *self;
+
+ gtk_window_destroy (GTK_WINDOW (dialog));
+
+ if (response != GTK_RESPONSE_OK)
+ return;
+
+ self = NET_DEVICE_WIFI (g_object_get_data (G_OBJECT (forget), "net"));
+ rows = g_object_steal_data (G_OBJECT (forget), "rows");
+ for (r = rows; r; r = r->next) {
+ row = r->data;
+ connection = NM_REMOTE_CONNECTION (cc_wifi_connection_row_get_connection (row));
+ nm_remote_connection_delete_async (connection, self->cancellable, really_forgotten, g_object_ref (data));
+ gtk_widget_hide (GTK_WIDGET (row));
+ }
+ g_list_free (rows);
+}
+
+static void
+forget_selected (GtkButton *forget, CcWifiConnectionList *list)
+{
+ GtkNative *native;
+ GtkWidget *dialog;
+
+ native = gtk_widget_get_native (GTK_WIDGET (forget));
+ dialog = gtk_message_dialog_new (GTK_WINDOW (native),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_OTHER,
+ GTK_BUTTONS_NONE,
+ NULL);
+ gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog),
+ _("Network details for the selected networks, including passwords and any custom configuration will be lost."));
+
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Forget"), GTK_RESPONSE_OK,
+ NULL);
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (really_forget), list);
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+static void
+check_toggled (CcWifiConnectionRow *row, GParamSpec *pspec, CcWifiConnectionList *list)
+{
+ GtkWidget *forget;
+ gboolean active;
+ GList *rows;
+
+ active = cc_wifi_connection_row_get_checked (row);
+ rows = g_object_steal_data (G_OBJECT (list), "rows");
+
+ if (active) {
+ cc_wifi_connection_list_freeze (list);
+ rows = g_list_prepend (rows, row);
+ } else {
+ cc_wifi_connection_list_thaw (list);
+ rows = g_list_remove (rows, row);
+ }
+
+ g_object_set_data_full (G_OBJECT (list), "rows", rows, (GDestroyNotify)g_list_free);
+ forget = g_object_get_data (G_OBJECT (list), "forget");
+ gtk_widget_set_sensitive (forget, rows != NULL);
+}
+
+static gint
+history_sort (gconstpointer a, gconstpointer b, gpointer data)
+{
+ guint64 ta, tb;
+ NMConnection *ca, *cb;
+ NMSettingConnection *sc;
+
+ ca = cc_wifi_connection_row_get_connection (CC_WIFI_CONNECTION_ROW ((gpointer) a));
+ cb = cc_wifi_connection_row_get_connection (CC_WIFI_CONNECTION_ROW ((gpointer) b));
+
+ if (ca) {
+ sc = nm_connection_get_setting_connection (ca);
+ ta = nm_setting_connection_get_timestamp (sc);
+ } else {
+ ta = 0;
+ }
+
+ if (cb) {
+ sc = nm_connection_get_setting_connection (cb);
+ tb = nm_setting_connection_get_timestamp (sc);
+ } else {
+ tb = 0;
+ }
+
+ if (ta > tb) return -1;
+ if (tb > ta) return 1;
+
+ return 0;
+}
+
+static gint
+ap_sort (gconstpointer a, gconstpointer b, gpointer data)
+{
+ NetDeviceWifi *self = data;
+ CcWifiConnectionRow *a_row = CC_WIFI_CONNECTION_ROW ((gpointer) a);
+ CcWifiConnectionRow *b_row = CC_WIFI_CONNECTION_ROW ((gpointer) b);
+ NMActiveConnection *active_connection;
+ gboolean a_configured, b_configured;
+ NMAccessPoint *apa, *apb;
+ guint sa, sb;
+
+ /* Show the connected AP first */
+ active_connection = nm_device_get_active_connection (NM_DEVICE (self->device));
+ if (active_connection != NULL) {
+ NMConnection *connection = NM_CONNECTION (nm_active_connection_get_connection (active_connection));
+ if (connection == cc_wifi_connection_row_get_connection (a_row))
+ return -1;
+ else if (connection == cc_wifi_connection_row_get_connection (b_row))
+ return 1;
+ }
+
+ /* Show configured networks before non-configured */
+ a_configured = cc_wifi_connection_row_get_connection (a_row) != NULL;
+ b_configured = cc_wifi_connection_row_get_connection (b_row) != NULL;
+ if (a_configured != b_configured) {
+ if (a_configured) return -1;
+ if (b_configured) return 1;
+ }
+
+ /* Show higher strength networks above lower strength ones */
+
+ apa = cc_wifi_connection_row_best_access_point (a_row);
+ apb = cc_wifi_connection_row_best_access_point (b_row);
+
+ if (apa)
+ sa = nm_access_point_get_strength (apa);
+ else
+ sa = 0;
+
+ if (apb)
+ sb = nm_access_point_get_strength (apb);
+ else
+ sb = 0;
+
+ if (sa > sb) return -1;
+ if (sb > sa) return 1;
+
+ return 0;
+}
+
+static void
+show_details_for_row (NetDeviceWifi *self, CcWifiConnectionRow *row, CcWifiConnectionList *list)
+{
+ NMConnection *connection;
+ NMAccessPoint *ap;
+ NetConnectionEditor *editor;
+
+ connection = cc_wifi_connection_row_get_connection (row);
+ ap = cc_wifi_connection_row_best_access_point (row);
+
+ editor = net_connection_editor_new (connection, self->device, ap, self->client);
+ gtk_window_set_transient_for (GTK_WINDOW (editor), GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (row))));
+ gtk_window_present (GTK_WINDOW (editor));
+}
+
+static void
+on_connection_list_row_added_cb (NetDeviceWifi *self,
+ CcWifiConnectionRow *row,
+ CcWifiConnectionList *list)
+{
+ g_signal_connect (row, "notify::checked",
+ G_CALLBACK (check_toggled), list);
+}
+
+static void
+on_connection_list_row_removed_cb (NetDeviceWifi *self,
+ CcWifiConnectionRow *row,
+ CcWifiConnectionList *list)
+{
+ GList *rows = g_object_steal_data (G_OBJECT (list), "rows");
+ GList *item;
+ GtkWidget *forget;
+
+ item = g_list_find (rows, row);
+ if (item)
+ {
+ rows = g_list_remove (rows, row);
+ cc_wifi_connection_list_thaw (list);
+ }
+ g_object_set_data_full (G_OBJECT (list), "rows", rows, (GDestroyNotify)g_list_free);
+
+ forget = g_object_get_data (G_OBJECT (list), "forget");
+ gtk_widget_set_sensitive (forget, rows != NULL);
+}
+
+static void
+on_connection_list_row_activated_cb (NetDeviceWifi *self,
+ CcWifiConnectionRow *row,
+ CcWifiConnectionList *list)
+{
+ cc_wifi_connection_row_set_checked (row, !cc_wifi_connection_row_get_checked (row));
+}
+
+static void
+show_history (NetDeviceWifi *self)
+{
+ GtkNative *native;
+ GtkWidget *dialog;
+ GtkWidget *page;
+ GtkWidget *list_group;
+ GtkWidget *forget_group;
+ GtkListBox *listbox;
+ GtkWidget *list;
+ GtkWidget *forget;
+ GtkWidget *child;
+
+ dialog = adw_preferences_window_new ();
+ adw_preferences_window_set_search_enabled (ADW_PREFERENCES_WINDOW (dialog), FALSE);
+ adw_preferences_window_set_can_navigate_back (ADW_PREFERENCES_WINDOW (dialog), FALSE);
+ native = gtk_widget_get_native (GTK_WIDGET (self));
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (native));
+ gtk_window_set_title (GTK_WINDOW (dialog), _("Known Wi-Fi Networks"));
+ gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 500, 400);
+
+ page = adw_preferences_page_new ();
+ adw_preferences_window_add (ADW_PREFERENCES_WINDOW (dialog), ADW_PREFERENCES_PAGE (page));
+
+ list_group = adw_preferences_group_new ();
+ adw_preferences_page_add (ADW_PREFERENCES_PAGE (page), ADW_PREFERENCES_GROUP (list_group));
+
+ list = GTK_WIDGET (cc_wifi_connection_list_new (self->client,
+ NM_DEVICE_WIFI (self->device),
+ FALSE, FALSE, TRUE));
+ listbox = cc_wifi_connection_list_get_list_box (CC_WIFI_CONNECTION_LIST (list));
+ gtk_list_box_set_selection_mode (listbox, GTK_SELECTION_NONE);
+ gtk_list_box_set_sort_func (listbox, (GtkListBoxSortFunc)history_sort, NULL, NULL);
+ adw_preferences_group_add (ADW_PREFERENCES_GROUP (list_group), list);
+
+ /* translators: This is the label for the "Forget wireless network" functionality */
+ forget = gtk_button_new_with_mnemonic (C_("Wi-Fi Network", "_Forget"));
+ gtk_widget_set_sensitive (forget, FALSE);
+ gtk_style_context_add_class (gtk_widget_get_style_context (forget), "destructive-action");
+
+ g_signal_connect (forget, "clicked",
+ G_CALLBACK (forget_selected), list);
+ forget_group = adw_preferences_group_new ();
+ adw_preferences_group_add (ADW_PREFERENCES_GROUP (forget_group), forget);
+ adw_preferences_page_add (ADW_PREFERENCES_PAGE (page), ADW_PREFERENCES_GROUP (forget_group));
+
+ g_object_set_data (G_OBJECT (list), "forget", forget);
+ g_object_set_data (G_OBJECT (list), "net", self);
+
+ g_signal_connect_object (list, "add-row",
+ G_CALLBACK (on_connection_list_row_added_cb),
+ self,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (list, "remove-row",
+ G_CALLBACK (on_connection_list_row_removed_cb),
+ self,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (listbox, "row-activated",
+ G_CALLBACK (on_connection_list_row_activated_cb),
+ self,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (list, "configure",
+ G_CALLBACK (show_details_for_row),
+ self,
+ G_CONNECT_SWAPPED);
+
+ for (child = gtk_widget_get_first_child (GTK_WIDGET (listbox));
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ {
+ on_connection_list_row_added_cb (self,
+ CC_WIFI_CONNECTION_ROW (child),
+ CC_WIFI_CONNECTION_LIST (list));
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+ gtk_popover_popdown (self->header_button_popover);
+}
+
+static void
+on_popover_row_activated_cb (GtkListBox *list,
+ GtkListBoxRow *row,
+ gpointer user_data)
+{
+ NetDeviceWifi *self = user_data;
+
+ if (row == self->connect_hidden_row)
+ connect_hidden (self);
+ else if (row == self->start_hotspot_row)
+ start_hotspot (self);
+ else
+ show_history (self);
+}
+
+static void
+ap_activated (NetDeviceWifi *self, GtkListBoxRow *row)
+{
+ CcWifiConnectionRow *c_row;
+ NMConnection *connection;
+ NMAccessPoint *ap;
+
+ /* The mockups want a row to connecto hidden networks; this could
+ * be handeled here. */
+ if (!CC_IS_WIFI_CONNECTION_ROW (row))
+ return;
+
+ c_row = CC_WIFI_CONNECTION_ROW (row);
+
+ connection = cc_wifi_connection_row_get_connection (c_row);
+ ap = cc_wifi_connection_row_best_access_point (c_row);
+
+ if (ap != NULL) {
+ if (connection != NULL) {
+ nm_client_activate_connection_async (self->client,
+ connection,
+ self->device, NULL, self->cancellable,
+ connection_activate_cb, self);
+ } else {
+ GBytes *ssid;
+ const gchar *object_path;
+
+ ssid = nm_access_point_get_ssid (ap);
+ object_path = nm_object_get_path (NM_OBJECT (ap));
+ wireless_try_to_connect (self, ssid, object_path);
+ }
+ }
+}
+
+static void
+net_device_wifi_class_init (NetDeviceWifiClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = net_device_wifi_finalize;
+ object_class->get_property = net_device_wifi_get_property;
+
+ g_object_class_install_property (object_class,
+ PROP_SCANNING,
+ g_param_spec_boolean ("scanning",
+ "Scanning",
+ "Whether the device is scanning for access points",
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/network-wifi.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceWifi, center_box);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceWifi, connect_hidden_row);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceWifi, device_off_switch);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceWifi, header_box);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceWifi, header_button_popover);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceWifi, hotspot_box);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceWifi, hotspot_name_row);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceWifi, hotspot_security_row);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceWifi, hotspot_password_row);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceWifi, listbox_box);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceWifi, stack);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceWifi, start_hotspot_row);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceWifi, status_label);
+ gtk_widget_class_bind_template_child (widget_class, NetDeviceWifi, title_label);
+
+ gtk_widget_class_bind_template_callback (widget_class, device_off_switch_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_popover_row_activated_cb);
+}
+
+static void
+net_device_wifi_init (NetDeviceWifi *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->cancellable = g_cancellable_new ();
+}
+
+
+static void
+nm_client_on_permission_change (NetDeviceWifi *self) {
+ NMClientPermissionResult perm;
+ NMDeviceWifiCapabilities caps;
+
+ if (nm_client_get_permissions_state (self->client) != NM_TERNARY_TRUE) {
+ /* permissions aren't ready yet */
+ return;
+ }
+
+ /* only enable the button if the user can create a hotspot */
+ perm = nm_client_get_permission_result (self->client, NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN);
+ caps = nm_device_wifi_get_capabilities (NM_DEVICE_WIFI (self->device));
+ if (perm != NM_CLIENT_PERMISSION_RESULT_YES &&
+ perm != NM_CLIENT_PERMISSION_RESULT_AUTH) {
+ gtk_widget_set_tooltip_text (GTK_WIDGET (self->start_hotspot_row), _("System policy prohibits use as a Hotspot"));
+ gtk_widget_set_sensitive (GTK_WIDGET (self->start_hotspot_row), FALSE);
+ } else if (!(caps & (NM_WIFI_DEVICE_CAP_AP | NM_WIFI_DEVICE_CAP_ADHOC))) {
+ gtk_widget_set_tooltip_text (GTK_WIDGET (self->start_hotspot_row), _("Wireless device does not support Hotspot mode"));
+ gtk_widget_set_sensitive (GTK_WIDGET (self->start_hotspot_row), FALSE);
+ } else
+ gtk_widget_set_sensitive (GTK_WIDGET (self->start_hotspot_row), TRUE);
+
+}
+
+NetDeviceWifi *
+net_device_wifi_new (CcPanel *panel, NMClient *client, NMDevice *device)
+{
+ NetDeviceWifi *self;
+ GtkListBox *listbox;
+ GtkWidget *list;
+
+ self = g_object_new (net_device_wifi_get_type (), NULL);
+ self->panel = panel;
+ self->client = g_object_ref (client);
+ self->device = g_object_ref (device);
+
+ g_signal_connect_object (client, "notify::wireless-enabled",
+ G_CALLBACK (wireless_enabled_toggled), self, G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (device, "state-changed", G_CALLBACK (nm_device_wifi_refresh_ui), self, G_CONNECT_SWAPPED);
+
+ list = GTK_WIDGET (cc_wifi_connection_list_new (client, NM_DEVICE_WIFI (device), TRUE, TRUE, FALSE));
+ gtk_box_append (self->listbox_box, list);
+
+ listbox = cc_wifi_connection_list_get_list_box (CC_WIFI_CONNECTION_LIST (list));
+ gtk_list_box_set_sort_func (listbox, (GtkListBoxSortFunc)ap_sort, self, NULL);
+
+ g_signal_connect_object (listbox, "row-activated",
+ G_CALLBACK (ap_activated), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (list, "configure",
+ G_CALLBACK (show_details_for_row), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (client, "notify",
+ G_CALLBACK(nm_client_on_permission_change), self, G_CONNECT_SWAPPED);
+
+ nm_client_on_permission_change(self);
+
+ nm_device_wifi_refresh_ui (self);
+
+ return self;
+}
+
+NMDevice *
+net_device_wifi_get_device (NetDeviceWifi *self)
+{
+ g_return_val_if_fail (NET_IS_DEVICE_WIFI (self), NULL);
+ return self->device;
+}
+
+void
+net_device_wifi_set_title (NetDeviceWifi *self, const gchar *title)
+{
+ g_return_if_fail (NET_IS_DEVICE_WIFI (self));
+ gtk_label_set_label (self->title_label, title);
+}
+
+GtkWidget *
+net_device_wifi_get_header_widget (NetDeviceWifi *self)
+{
+ g_return_val_if_fail (NET_IS_DEVICE_WIFI (self), NULL);
+ return GTK_WIDGET (self->header_box);
+}
+
+GtkWidget *
+net_device_wifi_get_title_widget (NetDeviceWifi *self)
+{
+ g_return_val_if_fail (NET_IS_DEVICE_WIFI (self), NULL);
+ return GTK_WIDGET (self->center_box);
+}
+
+void
+net_device_wifi_turn_off_hotspot (NetDeviceWifi *self)
+{
+ g_return_if_fail (NET_IS_DEVICE_WIFI (self));
+
+ stop_shared_connection (self);
+}
+
diff --git a/panels/network/net-device-wifi.h b/panels/network/net-device-wifi.h
new file mode 100644
index 0000000..1d4ae7d
--- /dev/null
+++ b/panels/network/net-device-wifi.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2011-2012 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (NetDeviceWifi, net_device_wifi, NET, DEVICE_WIFI, AdwBin)
+
+NetDeviceWifi *net_device_wifi_new (CcPanel *panel,
+ NMClient *client,
+ NMDevice *device);
+
+NMDevice *net_device_wifi_get_device (NetDeviceWifi *device);
+
+void net_device_wifi_set_title (NetDeviceWifi *device,
+ const gchar *title);
+
+GtkWidget *net_device_wifi_get_header_widget (NetDeviceWifi *device);
+
+GtkWidget *net_device_wifi_get_title_widget (NetDeviceWifi *device);
+
+void net_device_wifi_turn_off_hotspot (NetDeviceWifi *self);
+
+G_END_DECLS
+
diff --git a/panels/network/net-proxy.c b/panels/network/net-proxy.c
new file mode 100644
index 0000000..fc6c744
--- /dev/null
+++ b/panels/network/net-proxy.c
@@ -0,0 +1,372 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2011-2012 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+#include "net-proxy.h"
+
+typedef enum
+{
+ MODE_DISABLED,
+ MODE_MANUAL,
+ MODE_AUTOMATIC
+} ProxyMode;
+
+struct _NetProxy
+{
+ AdwBin parent;
+
+ GtkCheckButton *automatic_radio;
+ GtkDialog *dialog;
+ GtkCheckButton *manual_radio;
+ GtkCheckButton *none_radio;
+ GtkEntry *proxy_ftp_entry;
+ GtkEntry *proxy_http_entry;
+ GtkEntry *proxy_https_entry;
+ GtkEntry *proxy_ignore_entry;
+ GtkAdjustment *proxy_port_ftp_adjustment;
+ GtkAdjustment *proxy_port_http_adjustment;
+ GtkAdjustment *proxy_port_https_adjustment;
+ GtkAdjustment *proxy_port_socks_adjustment;
+ GtkEntry *proxy_socks_entry;
+ GtkEntry *proxy_url_entry;
+ GtkLabel *proxy_warning_label;
+ GtkStack *stack;
+ GtkLabel *status_label;
+
+ GSettings *settings;
+};
+
+G_DEFINE_TYPE (NetProxy, net_proxy, ADW_TYPE_BIN)
+
+static const gchar *
+panel_get_string_for_value (ProxyMode mode)
+{
+ switch (mode) {
+ case MODE_DISABLED:
+ return _("Off");
+ case MODE_MANUAL:
+ return _("Manual");
+ case MODE_AUTOMATIC:
+ return _("Automatic");
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static inline void
+panel_update_status_label (NetProxy *self,
+ ProxyMode mode)
+{
+ gtk_label_set_label (self->status_label, panel_get_string_for_value (mode));
+}
+
+static void
+check_wpad_warning (NetProxy *self)
+{
+ g_autofree gchar *autoconfig_url = NULL;
+ GString *string = NULL;
+ gboolean ret = FALSE;
+ guint mode;
+
+ string = g_string_new ("");
+
+ /* check we're using 'Automatic' */
+ mode = g_settings_get_enum (self->settings, "mode");
+ if (mode != MODE_AUTOMATIC)
+ goto out;
+
+ /* see if the PAC is blank */
+ autoconfig_url = g_settings_get_string (self->settings,
+ "autoconfig-url");
+ ret = autoconfig_url == NULL ||
+ autoconfig_url[0] == '\0';
+ if (!ret)
+ goto out;
+
+ g_string_append (string, "<small>");
+
+ /* TRANSLATORS: this is when the use leaves the PAC textbox blank */
+ g_string_append (string, _("Web Proxy Autodiscovery is used when a Configuration URL is not provided."));
+
+ g_string_append (string, "\n");
+
+ /* TRANSLATORS: WPAD is bad: if you enable it on an untrusted
+ * network, then anyone else on that network can tell your
+ * machine that it should proxy all of your web traffic
+ * through them. */
+ g_string_append (string, _("This is not recommended for untrusted public networks."));
+ g_string_append (string, "</small>");
+out:
+ gtk_label_set_markup (self->proxy_warning_label, string->str);
+ gtk_widget_set_visible (GTK_WIDGET (self->proxy_warning_label), (string->len > 0));
+
+ g_string_free (string, TRUE);
+}
+
+static void
+settings_changed_cb (NetProxy *self)
+{
+ check_wpad_warning (self);
+}
+
+static void
+panel_proxy_mode_setup_widgets (NetProxy *self, ProxyMode value)
+{
+ /* hide or show the PAC text box */
+ switch (value) {
+ case MODE_DISABLED:
+ gtk_stack_set_visible_child_name (self->stack, "disabled");
+ break;
+ case MODE_MANUAL:
+ gtk_stack_set_visible_child_name (self->stack, "manual");
+ break;
+ case MODE_AUTOMATIC:
+ gtk_stack_set_visible_child_name (self->stack, "automatic");
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ /* perhaps show the wpad warning */
+ check_wpad_warning (self);
+}
+
+static void
+panel_proxy_mode_radio_changed_cb (NetProxy *self, GtkCheckButton *radio)
+{
+ ProxyMode value;
+
+ if (!gtk_check_button_get_active (GTK_CHECK_BUTTON (radio)))
+ return;
+
+ /* get selected radio */
+ if (radio == self->none_radio)
+ value = MODE_DISABLED;
+ else if (radio == self->manual_radio)
+ value = MODE_MANUAL;
+ else if (radio == self->automatic_radio)
+ value = MODE_AUTOMATIC;
+ else
+ g_assert_not_reached ();
+
+ /* set */
+ g_settings_set_enum (self->settings, "mode", value);
+
+ /* hide or show the correct widgets */
+ panel_proxy_mode_setup_widgets (self, value);
+
+ /* status label */
+ panel_update_status_label (self, value);
+}
+
+static void
+show_dialog_cb (NetProxy *self)
+{
+ gtk_window_set_transient_for (GTK_WINDOW (self->dialog), GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (self))));
+ gtk_window_present (GTK_WINDOW (self->dialog));
+}
+
+static void
+net_proxy_finalize (GObject *object)
+{
+ NetProxy *self = NET_PROXY (object);
+
+ g_clear_object (&self->settings);
+
+ G_OBJECT_CLASS (net_proxy_parent_class)->finalize (object);
+}
+
+static void
+net_proxy_class_init (NetProxyClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = net_proxy_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/network-proxy.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, NetProxy, automatic_radio);
+ gtk_widget_class_bind_template_child (widget_class, NetProxy, dialog);
+ gtk_widget_class_bind_template_child (widget_class, NetProxy, manual_radio);
+ gtk_widget_class_bind_template_child (widget_class, NetProxy, none_radio);
+ gtk_widget_class_bind_template_child (widget_class, NetProxy, proxy_ftp_entry);
+ gtk_widget_class_bind_template_child (widget_class, NetProxy, proxy_http_entry);
+ gtk_widget_class_bind_template_child (widget_class, NetProxy, proxy_https_entry);
+ gtk_widget_class_bind_template_child (widget_class, NetProxy, proxy_ignore_entry);
+ gtk_widget_class_bind_template_child (widget_class, NetProxy, proxy_port_ftp_adjustment);
+ gtk_widget_class_bind_template_child (widget_class, NetProxy, proxy_port_http_adjustment);
+ gtk_widget_class_bind_template_child (widget_class, NetProxy, proxy_port_https_adjustment);
+ gtk_widget_class_bind_template_child (widget_class, NetProxy, proxy_port_socks_adjustment);
+ gtk_widget_class_bind_template_child (widget_class, NetProxy, proxy_socks_entry);
+ gtk_widget_class_bind_template_child (widget_class, NetProxy, proxy_url_entry);
+ gtk_widget_class_bind_template_child (widget_class, NetProxy, proxy_warning_label);
+ gtk_widget_class_bind_template_child (widget_class, NetProxy, stack);
+ gtk_widget_class_bind_template_child (widget_class, NetProxy, status_label);
+
+ gtk_widget_class_bind_template_callback (widget_class, panel_proxy_mode_radio_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, show_dialog_cb);
+}
+
+static gboolean
+get_ignore_hosts (GValue *value,
+ GVariant *variant,
+ gpointer user_data)
+{
+ GVariantIter iter;
+ const gchar *s;
+ g_autofree gchar **av = NULL;
+ gchar **p;
+ gsize n;
+
+ n = g_variant_iter_init (&iter, variant);
+ p = av = g_new0 (gchar *, n + 1);
+
+ while (g_variant_iter_next (&iter, "&s", &s))
+ if (s[0] != '\0') {
+ *p = (gchar *) s;
+ ++p;
+ }
+
+ g_value_take_string (value, g_strjoinv (", ", av));
+
+ return TRUE;
+}
+
+static GVariant *
+set_ignore_hosts (const GValue *value,
+ const GVariantType *expected_type,
+ gpointer user_data)
+{
+ GVariantBuilder builder;
+ const gchar *sv;
+ gchar **av, **p;
+
+ sv = g_value_get_string (value);
+ av = g_strsplit_set (sv, ", ", 0);
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE_STRING_ARRAY);
+ for (p = av; *p; ++p) {
+ if (*p[0] != '\0')
+ g_variant_builder_add (&builder, "s", *p);
+ }
+
+ g_strfreev (av);
+
+ return g_variant_builder_end (&builder);
+}
+
+static void
+net_proxy_init (NetProxy *self)
+{
+ g_autoptr(GSettings) http_settings = NULL;
+ g_autoptr(GSettings) https_settings = NULL;
+ g_autoptr(GSettings) ftp_settings = NULL;
+ g_autoptr(GSettings) socks_settings = NULL;
+ ProxyMode value;
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->settings = g_settings_new ("org.gnome.system.proxy");
+ g_signal_connect_object (self->settings,
+ "changed",
+ G_CALLBACK (settings_changed_cb),
+ self,
+ G_CONNECT_SWAPPED);
+
+ /* actions */
+ value = g_settings_get_enum (self->settings, "mode");
+
+ /* bind the proxy values */
+ g_settings_bind (self->settings, "autoconfig-url",
+ self->proxy_url_entry, "text",
+ G_SETTINGS_BIND_DEFAULT);
+
+ /* bind the HTTP proxy values */
+ http_settings = g_settings_get_child (self->settings, "http");
+ g_settings_bind (http_settings, "host",
+ self->proxy_http_entry, "text",
+ G_SETTINGS_BIND_DEFAULT);
+ g_settings_bind (http_settings, "port",
+ self->proxy_port_http_adjustment, "value",
+ G_SETTINGS_BIND_DEFAULT);
+
+ /* bind the HTTPS proxy values */
+ https_settings = g_settings_get_child (self->settings, "https");
+ g_settings_bind (https_settings, "host",
+ self->proxy_https_entry, "text",
+ G_SETTINGS_BIND_DEFAULT);
+ g_settings_bind (https_settings, "port",
+ self->proxy_port_https_adjustment, "value",
+ G_SETTINGS_BIND_DEFAULT);
+
+ /* bind the FTP proxy values */
+ ftp_settings = g_settings_get_child (self->settings, "ftp");
+ g_settings_bind (ftp_settings, "host",
+ self->proxy_ftp_entry, "text",
+ G_SETTINGS_BIND_DEFAULT);
+ g_settings_bind (ftp_settings, "port",
+ self->proxy_port_ftp_adjustment, "value",
+ G_SETTINGS_BIND_DEFAULT);
+
+ /* bind the SOCKS proxy values */
+ socks_settings = g_settings_get_child (self->settings, "socks");
+ g_settings_bind (socks_settings, "host",
+ self->proxy_socks_entry, "text",
+ G_SETTINGS_BIND_DEFAULT);
+ g_settings_bind (socks_settings, "port",
+ self->proxy_port_socks_adjustment, "value",
+ G_SETTINGS_BIND_DEFAULT);
+
+ /* bind the proxy ignore hosts */
+ g_settings_bind_with_mapping (self->settings, "ignore-hosts",
+ self->proxy_ignore_entry, "text",
+ G_SETTINGS_BIND_DEFAULT, get_ignore_hosts, set_ignore_hosts,
+ NULL, NULL);
+
+ /* setup the radio before connecting to the :toggled signal */
+ switch (value) {
+ case MODE_DISABLED:
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->none_radio), TRUE);
+ break;
+ case MODE_MANUAL:
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->manual_radio), TRUE);
+ break;
+ case MODE_AUTOMATIC:
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->automatic_radio), TRUE);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ panel_proxy_mode_setup_widgets (self, value);
+ panel_update_status_label (self, value);
+}
+
+NetProxy *
+net_proxy_new (void)
+{
+ return g_object_new (net_proxy_get_type (), NULL);
+}
diff --git a/panels/network/net-proxy.h b/panels/network/net-proxy.h
new file mode 100644
index 0000000..5469c25
--- /dev/null
+++ b/panels/network/net-proxy.h
@@ -0,0 +1,32 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2011-2012 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <adwaita.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (NetProxy, net_proxy, NET, PROXY, AdwBin)
+
+NetProxy *net_proxy_new (void);
+
+G_END_DECLS
diff --git a/panels/network/net-vpn.c b/panels/network/net-vpn.c
new file mode 100644
index 0000000..74009d5
--- /dev/null
+++ b/panels/network/net-vpn.c
@@ -0,0 +1,228 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2011-2012 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <glib/gi18n.h>
+#include <NetworkManager.h>
+
+#include "panel-common.h"
+
+#include "net-vpn.h"
+
+#include "connection-editor/net-connection-editor.h"
+
+struct _NetVpn
+{
+ AdwActionRow parent;
+
+ GtkBox *box;
+ GtkSwitch *device_off_switch;
+
+ NMClient *client;
+ NMConnection *connection;
+ NMActiveConnection *active_connection;
+ gboolean updating_device;
+};
+
+G_DEFINE_TYPE (NetVpn, net_vpn, ADW_TYPE_ACTION_ROW)
+
+static void
+nm_device_refresh_vpn_ui (NetVpn *self)
+{
+ g_autofree char *title_escaped = NULL;
+ const GPtrArray *acs;
+ NMActiveConnection *a;
+ gint i;
+ NMVpnConnectionState state;
+
+ /* update title */
+ title_escaped = g_markup_escape_text (nm_connection_get_id (self->connection),
+ -1);
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self),
+ title_escaped);
+
+ if (self->active_connection) {
+ g_signal_handlers_disconnect_by_func (self->active_connection,
+ nm_device_refresh_vpn_ui,
+ self);
+ g_clear_object (&self->active_connection);
+ }
+
+
+ /* Default to disconnected if there is no active connection */
+ state = NM_VPN_CONNECTION_STATE_DISCONNECTED;
+ acs = nm_client_get_active_connections (self->client);
+ if (acs != NULL) {
+ const gchar *uuid;
+ uuid = nm_connection_get_uuid (self->connection);
+
+ for (i = 0; i < acs->len; i++) {
+ const gchar *auuid;
+
+ a = (NMActiveConnection*)acs->pdata[i];
+
+ auuid = nm_active_connection_get_uuid (a);
+ if (NM_IS_VPN_CONNECTION (a) && strcmp (auuid, uuid) == 0) {
+ self->active_connection = g_object_ref (a);
+ g_signal_connect_object (a, "notify::vpn-state",
+ G_CALLBACK (nm_device_refresh_vpn_ui),
+ self, G_CONNECT_SWAPPED);
+ state = nm_vpn_connection_get_vpn_state (NM_VPN_CONNECTION (a));
+ break;
+ }
+ }
+ }
+
+ self->updating_device = TRUE;
+ gtk_switch_set_active (self->device_off_switch,
+ state != NM_VPN_CONNECTION_STATE_FAILED &&
+ state != NM_VPN_CONNECTION_STATE_DISCONNECTED);
+ self->updating_device = FALSE;
+}
+
+static void
+nm_active_connections_changed (NetVpn *self)
+{
+ nm_device_refresh_vpn_ui (self);
+}
+
+static void
+device_off_toggled (NetVpn *self)
+{
+ const GPtrArray *acs;
+ gboolean active;
+ gint i;
+ NMActiveConnection *a;
+
+ if (self->updating_device)
+ return;
+
+ active = gtk_switch_get_active (self->device_off_switch);
+ if (active) {
+ nm_client_activate_connection_async (self->client,
+ self->connection, NULL, NULL,
+ NULL, NULL, NULL);
+ } else {
+ const gchar *uuid;
+
+ uuid = nm_connection_get_uuid (self->connection);
+ acs = nm_client_get_active_connections (self->client);
+ for (i = 0; acs && i < acs->len; i++) {
+ a = (NMActiveConnection*)acs->pdata[i];
+ if (strcmp (nm_active_connection_get_uuid (a), uuid) == 0) {
+ nm_client_deactivate_connection_async (self->client, a, NULL, NULL, NULL);
+ break;
+ }
+ }
+ }
+}
+
+static void
+editor_done (NetVpn *self)
+{
+ nm_device_refresh_vpn_ui (self);
+}
+
+static void
+edit_connection (NetVpn *self)
+{
+ NetConnectionEditor *editor;
+
+ editor = net_connection_editor_new (self->connection, NULL, NULL, self->client);
+ gtk_window_set_transient_for (GTK_WINDOW (editor), GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (self))));
+ net_connection_editor_set_title (editor, nm_connection_get_id (self->connection));
+
+ g_signal_connect_object (editor, "done", G_CALLBACK (editor_done), self, G_CONNECT_SWAPPED);
+ gtk_window_present (GTK_WINDOW (editor));
+}
+
+static void
+net_vpn_finalize (GObject *object)
+{
+ NetVpn *self = NET_VPN (object);
+
+ if (self->active_connection)
+ g_signal_handlers_disconnect_by_func (self->active_connection,
+ nm_device_refresh_vpn_ui,
+ self);
+
+ g_clear_object (&self->active_connection);
+ g_clear_object (&self->client);
+ g_clear_object (&self->connection);
+
+ G_OBJECT_CLASS (net_vpn_parent_class)->finalize (object);
+}
+
+static void
+net_vpn_class_init (NetVpnClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = net_vpn_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/network-vpn.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, NetVpn, device_off_switch);
+
+ gtk_widget_class_bind_template_callback (widget_class, device_off_toggled);
+ gtk_widget_class_bind_template_callback (widget_class, edit_connection);
+}
+
+static void
+net_vpn_init (NetVpn *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+NetVpn *
+net_vpn_new (NMClient *client,
+ NMConnection *connection)
+{
+ NetVpn *self;
+
+ self = g_object_new (net_vpn_get_type (), NULL);
+ self->client = g_object_ref (client);
+ self->connection = g_object_ref (connection);
+
+ g_signal_connect_object (connection,
+ NM_CONNECTION_CHANGED,
+ G_CALLBACK (nm_device_refresh_vpn_ui),
+ self, G_CONNECT_SWAPPED);
+
+ nm_device_refresh_vpn_ui (self);
+
+ g_signal_connect_object (client,
+ "notify::active-connections",
+ G_CALLBACK (nm_active_connections_changed),
+ self, G_CONNECT_SWAPPED);
+
+ return self;
+}
+
+NMConnection *
+net_vpn_get_connection (NetVpn *self)
+{
+ g_return_val_if_fail (NET_IS_VPN (self), NULL);
+ return self->connection;
+}
diff --git a/panels/network/net-vpn.h b/panels/network/net-vpn.h
new file mode 100644
index 0000000..1835458
--- /dev/null
+++ b/panels/network/net-vpn.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2011 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <adwaita.h>
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (NetVpn, net_vpn, NET, VPN, AdwActionRow)
+
+NetVpn *net_vpn_new (NMClient *client,
+ NMConnection *connection);
+
+NMConnection *net_vpn_get_connection (NetVpn *vpn);
+
+G_END_DECLS
diff --git a/panels/network/network-bluetooth.ui b/panels/network/network-bluetooth.ui
new file mode 100644
index 0000000..fe3f8c1
--- /dev/null
+++ b/panels/network/network-bluetooth.ui
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="NetDeviceBluetooth" parent="AdwActionRow">
+ <property name="activatable_widget">device_off_switch</property>
+ <property name="title" translatable="yes">Wired</property>
+ <child type="suffix">
+ <object class="GtkSwitch" id="device_off_switch">
+ <property name="valign">center</property>
+ <signal name="notify::active" handler="device_off_switch_changed_cb" object="NetDeviceBluetooth" swapped="yes"/>
+ <accessibility>
+ <property name="label" translatable="yes">Turn device off</property>
+ </accessibility>
+ </object>
+ </child>
+ <child type="suffix">
+ <object class="GtkButton" id="options_button">
+ <property name="valign">center</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">emblem-system-symbolic</property>
+ <signal name="clicked" handler="options_button_clicked_cb" object="NetDeviceBluetooth" swapped="yes"/>
+ <accessibility>
+ <property name="label" translatable="yes">Options…</property>
+ </accessibility>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/network-dialogs.c b/panels/network/network-dialogs.c
new file mode 100644
index 0000000..83df99a
--- /dev/null
+++ b/panels/network/network-dialogs.c
@@ -0,0 +1,499 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2011 Giovanni Campagna <scampa.giovanni@gmail.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Portions of this code were taken from network-manager-applet.
+ * Copyright 2008 - 2011 Red Hat, Inc.
+ */
+
+#include <NetworkManager.h>
+#include <nma-wifi-dialog.h>
+#include <nma-mobile-wizard.h>
+
+#include "network-dialogs.h"
+
+typedef struct {
+ NMClient *client;
+} WirelessDialogClosure;
+
+typedef struct {
+ NMClient *client;
+ NMDevice *device;
+} MobileDialogClosure;
+
+static void
+wireless_dialog_closure_closure_notify (gpointer data,
+ GClosure *gclosure)
+{
+ WirelessDialogClosure *closure = data;
+
+ g_clear_object (&closure->client);
+ g_slice_free (WirelessDialogClosure, data);
+}
+
+static void
+mobile_dialog_closure_free (gpointer data)
+{
+ MobileDialogClosure *closure = data;
+
+ g_clear_object (&closure->client);
+ g_clear_object (&closure->device);
+ g_slice_free (MobileDialogClosure, data);
+}
+
+static gboolean
+wifi_can_create_wifi_network (NMClient *client)
+{
+ NMClientPermissionResult perm;
+
+ /* FIXME: check WIFI_SHARE_PROTECTED too, and make the wireless dialog
+ * handle the permissions as well so that admins can restrict open network
+ * creation separately from protected network creation.
+ */
+ perm = nm_client_get_permission_result (client, NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN);
+ if (perm == NM_CLIENT_PERMISSION_RESULT_YES || perm == NM_CLIENT_PERMISSION_RESULT_AUTH)
+ return TRUE;
+
+ return FALSE;
+}
+
+static void
+activate_existing_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+
+ if (!nm_client_activate_connection_finish (NM_CLIENT (source_object), res, &error))
+ g_warning ("Failed to activate connection: (%d) %s", error->code, error->message);
+}
+
+static void
+activate_new_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+
+ if (!nm_client_add_and_activate_connection_finish (NM_CLIENT (source_object), res, &error))
+ g_warning ("Failed to add new connection: (%d) %s", error->code, error->message);
+}
+
+static void
+wireless_dialog_response_cb (GtkDialog *foo,
+ gint response,
+ gpointer user_data)
+{
+ NMAWifiDialog *dialog = NMA_WIFI_DIALOG (foo);
+ WirelessDialogClosure *closure = user_data;
+ g_autoptr(NMConnection) connection = NULL;
+ NMConnection *fuzzy_match = NULL;
+ NMDevice *device;
+ NMAccessPoint *ap;
+ const GPtrArray *all;
+ guint i;
+
+ if (response != GTK_RESPONSE_OK)
+ goto done;
+
+ /* nma_wifi_dialog_get_connection() returns a connection with the
+ * refcount incremented, so the caller must remember to unref it.
+ */
+ connection = nma_wifi_dialog_get_connection (dialog, &device, &ap);
+ g_assert (connection);
+ g_assert (device);
+
+ /* Find a similar connection and use that instead */
+ all = nm_client_get_connections (closure->client);
+ for (i = 0; i < all->len; i++) {
+ if (nm_connection_compare (connection,
+ NM_CONNECTION (g_ptr_array_index (all, i)),
+ (NM_SETTING_COMPARE_FLAG_FUZZY | NM_SETTING_COMPARE_FLAG_IGNORE_ID))) {
+ fuzzy_match = NM_CONNECTION (g_ptr_array_index (all, i));
+ break;
+ }
+ }
+
+ if (fuzzy_match) {
+ nm_client_activate_connection_async (closure->client,
+ fuzzy_match,
+ device,
+ ap ? nm_object_get_path (NM_OBJECT (ap)) : NULL,
+ NULL,
+ activate_existing_cb,
+ NULL);
+ } else {
+ NMSetting *s_con;
+ NMSettingWireless *s_wifi;
+ const char *mode = NULL;
+
+ /* Entirely new connection */
+
+ /* Don't autoconnect adhoc networks by default for now */
+ s_wifi = (NMSettingWireless *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS);
+ if (s_wifi)
+ mode = nm_setting_wireless_get_mode (s_wifi);
+ if (g_strcmp0 (mode, "adhoc") == 0) {
+ s_con = nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
+ if (!s_con) {
+ s_con = nm_setting_connection_new ();
+ nm_connection_add_setting (connection, s_con);
+ }
+ g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, NULL);
+ }
+
+ nm_client_add_and_activate_connection_async (closure->client,
+ connection,
+ device,
+ ap ? nm_object_get_path (NM_OBJECT (ap)) : NULL,
+ NULL,
+ activate_new_cb,
+ NULL);
+ }
+
+done:
+ gtk_widget_hide (GTK_WIDGET (dialog));
+ gtk_window_destroy (GTK_WINDOW (dialog));
+}
+
+static void
+show_wireless_dialog (GtkWidget *toplevel,
+ NMClient *client,
+ GtkWidget *dialog)
+{
+ WirelessDialogClosure *closure;
+
+ g_debug ("About to parent and show a network dialog");
+
+ g_assert (GTK_IS_NATIVE (toplevel));
+ g_object_set (G_OBJECT (dialog),
+ "modal", TRUE,
+ "transient-for", toplevel,
+ NULL);
+
+ closure = g_slice_new (WirelessDialogClosure);
+ closure->client = g_object_ref (client);
+ g_signal_connect_data (dialog, "response",
+ G_CALLBACK (wireless_dialog_response_cb),
+ closure, wireless_dialog_closure_closure_notify, 0);
+
+ g_object_bind_property (G_OBJECT (toplevel), "visible",
+ G_OBJECT (dialog), "visible",
+ G_BINDING_SYNC_CREATE);
+}
+
+void
+cc_network_panel_create_wifi_network (GtkWidget *toplevel,
+ NMClient *client)
+{
+ if (wifi_can_create_wifi_network (client)) {
+ show_wireless_dialog (toplevel, client,
+ nma_wifi_dialog_new_for_create (client));
+ }
+}
+
+void
+cc_network_panel_connect_to_hidden_network (GtkWidget *toplevel,
+ NMClient *client)
+{
+ g_debug ("connect to hidden wifi");
+ show_wireless_dialog (toplevel, client,
+ nma_wifi_dialog_new_for_hidden (client));
+}
+
+void
+cc_network_panel_connect_to_8021x_network (GtkWidget *toplevel,
+ NMClient *client,
+ NMDevice *device,
+ const gchar *arg_access_point)
+{
+ NMConnection *connection;
+ NMSettingConnection *s_con;
+ NMSettingWireless *s_wifi;
+ NMSettingWirelessSecurity *s_wsec;
+ NMSetting8021x *s_8021x;
+ NM80211ApSecurityFlags wpa_flags, rsn_flags;
+ GtkWidget *dialog;
+ g_autofree gchar *uuid = NULL;
+ NMAccessPoint *ap;
+
+ g_debug ("connect to 8021x wifi");
+ ap = nm_device_wifi_get_access_point_by_path (NM_DEVICE_WIFI (device), arg_access_point);
+ if (ap == NULL) {
+ g_warning ("didn't find access point with path %s", arg_access_point);
+ return;
+ }
+
+ /* If the AP is WPA[2]-Enterprise then we need to set up a minimal 802.1x
+ * setting and ask the user for more information.
+ */
+ rsn_flags = nm_access_point_get_rsn_flags (ap);
+ wpa_flags = nm_access_point_get_wpa_flags (ap);
+ if (!(rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)
+ && !(wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) {
+ g_warning ("Network panel loaded with connect-8021x-wifi but the "
+ "access point does not support 802.1x");
+ return;
+ }
+
+ connection = nm_simple_connection_new ();
+
+ /* Need a UUID for the "always ask" stuff in the Dialog of Doom */
+ s_con = (NMSettingConnection *) nm_setting_connection_new ();
+ uuid = nm_utils_uuid_generate ();
+ g_object_set (s_con, NM_SETTING_CONNECTION_UUID, uuid, NULL);
+ nm_connection_add_setting (connection, NM_SETTING (s_con));
+
+ s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
+ nm_connection_add_setting (connection, NM_SETTING (s_wifi));
+ g_object_set (s_wifi,
+ NM_SETTING_WIRELESS_SSID, nm_access_point_get_ssid (ap),
+ NULL);
+
+ s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+ g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap", NULL);
+ nm_connection_add_setting (connection, NM_SETTING (s_wsec));
+
+ s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
+ nm_setting_802_1x_add_eap_method (s_8021x, "ttls");
+ g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, "mschapv2", NULL);
+ nm_connection_add_setting (connection, NM_SETTING (s_8021x));
+
+ dialog = nma_wifi_dialog_new (client, connection, device, ap, FALSE);
+ show_wireless_dialog (toplevel, client, dialog);
+}
+
+static void
+connect_3g (NMConnection *connection,
+ gboolean canceled,
+ gpointer user_data)
+{
+ MobileDialogClosure *closure = user_data;
+
+ if (canceled == FALSE) {
+ g_return_if_fail (connection != NULL);
+
+ /* Ask NM to add the new connection and activate it; NM will fill in the
+ * missing details based on the specific object and the device.
+ */
+ nm_client_add_and_activate_connection_async (closure->client,
+ connection,
+ closure->device,
+ "/",
+ NULL,
+ activate_new_cb,
+ NULL);
+ }
+
+ mobile_dialog_closure_free (closure);
+}
+
+static void
+cdma_mobile_wizard_done (NMAMobileWizard *wizard,
+ gboolean canceled,
+ NMAMobileWizardAccessMethod *method,
+ gpointer user_data)
+{
+ NMConnection *connection = NULL;
+
+ if (!canceled && method) {
+ NMSetting *setting;
+ g_autofree gchar *uuid = NULL;
+ g_autofree gchar *id = NULL;
+
+ if (method->devtype != NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO) {
+ g_warning ("Unexpected device type (not CDMA).");
+ canceled = TRUE;
+ goto done;
+ }
+
+ connection = nm_simple_connection_new ();
+
+ setting = nm_setting_cdma_new ();
+ g_object_set (setting,
+ NM_SETTING_CDMA_NUMBER, "#777",
+ NM_SETTING_CDMA_USERNAME, method->username,
+ NM_SETTING_CDMA_PASSWORD, method->password,
+ NULL);
+ nm_connection_add_setting (connection, setting);
+
+ /* Serial setting */
+ setting = nm_setting_serial_new ();
+ g_object_set (setting,
+ NM_SETTING_SERIAL_BAUD, 115200,
+ NM_SETTING_SERIAL_BITS, 8,
+ NM_SETTING_SERIAL_PARITY, 'n',
+ NM_SETTING_SERIAL_STOPBITS, 1,
+ NULL);
+ nm_connection_add_setting (connection, setting);
+
+ nm_connection_add_setting (connection, nm_setting_ppp_new ());
+
+ setting = nm_setting_connection_new ();
+ if (method->plan_name)
+ id = g_strdup_printf ("%s %s", method->provider_name, method->plan_name);
+ else
+ id = g_strdup_printf ("%s connection", method->provider_name);
+ uuid = nm_utils_uuid_generate ();
+ g_object_set (setting,
+ NM_SETTING_CONNECTION_ID, id,
+ NM_SETTING_CONNECTION_TYPE, NM_SETTING_CDMA_SETTING_NAME,
+ NM_SETTING_CONNECTION_AUTOCONNECT, FALSE,
+ NM_SETTING_CONNECTION_UUID, uuid,
+ NULL);
+ nm_connection_add_setting (connection, setting);
+ }
+
+ done:
+ connect_3g (connection, canceled, user_data);
+ nma_mobile_wizard_destroy (wizard);
+}
+
+static void
+gsm_mobile_wizard_done (NMAMobileWizard *wizard,
+ gboolean canceled,
+ NMAMobileWizardAccessMethod *method,
+ gpointer user_data)
+{
+ NMConnection *connection = NULL;
+
+ if (!canceled && method) {
+ NMSetting *setting;
+ g_autofree gchar *uuid = NULL;
+ g_autofree gchar *id = NULL;
+
+ if (method->devtype != NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS) {
+ g_warning ("Unexpected device type (not GSM).");
+ canceled = TRUE;
+ goto done;
+ }
+
+ connection = nm_simple_connection_new ();
+
+ setting = nm_setting_gsm_new ();
+ g_object_set (setting,
+ NM_SETTING_GSM_NUMBER, "*99#",
+ NM_SETTING_GSM_USERNAME, method->username,
+ NM_SETTING_GSM_PASSWORD, method->password,
+ NM_SETTING_GSM_APN, method->gsm_apn,
+ NULL);
+ nm_connection_add_setting (connection, setting);
+
+ /* Serial setting */
+ setting = nm_setting_serial_new ();
+ g_object_set (setting,
+ NM_SETTING_SERIAL_BAUD, 115200,
+ NM_SETTING_SERIAL_BITS, 8,
+ NM_SETTING_SERIAL_PARITY, 'n',
+ NM_SETTING_SERIAL_STOPBITS, 1,
+ NULL);
+ nm_connection_add_setting (connection, setting);
+
+ nm_connection_add_setting (connection, nm_setting_ppp_new ());
+
+ setting = nm_setting_connection_new ();
+ if (method->plan_name)
+ id = g_strdup_printf ("%s %s", method->provider_name, method->plan_name);
+ else
+ id = g_strdup_printf ("%s connection", method->provider_name);
+ uuid = nm_utils_uuid_generate ();
+ g_object_set (setting,
+ NM_SETTING_CONNECTION_ID, id,
+ NM_SETTING_CONNECTION_TYPE, NM_SETTING_GSM_SETTING_NAME,
+ NM_SETTING_CONNECTION_AUTOCONNECT, FALSE,
+ NM_SETTING_CONNECTION_UUID, uuid,
+ NULL);
+ nm_connection_add_setting (connection, setting);
+ }
+
+done:
+ connect_3g (connection, canceled, user_data);
+ nma_mobile_wizard_destroy (wizard);
+}
+
+static void
+toplevel_shown (GtkWindow *toplevel,
+ GParamSpec *pspec,
+ NMAMobileWizard *wizard)
+{
+ gboolean visible = FALSE;
+
+ g_object_get (G_OBJECT (toplevel), "visible", &visible, NULL);
+ if (visible)
+ nma_mobile_wizard_present (wizard);
+}
+
+static gboolean
+show_wizard_idle_cb (NMAMobileWizard *wizard)
+{
+ nma_mobile_wizard_present (wizard);
+ return FALSE;
+}
+
+void
+cc_network_panel_connect_to_3g_network (GtkWidget *toplevel,
+ NMClient *client,
+ NMDevice *device)
+{
+ MobileDialogClosure *closure;
+ NMAMobileWizard *wizard;
+ NMDeviceModemCapabilities caps;
+ gboolean visible = FALSE;
+
+ g_debug ("connect to 3g");
+ if (!NM_IS_DEVICE_MODEM (device)) {
+ g_warning ("Network panel loaded with connect-3g but the selected device"
+ " is not a modem");
+ return;
+ }
+
+ closure = g_slice_new (MobileDialogClosure);
+ closure->client = g_object_ref (client);
+ closure->device = g_object_ref (device);
+
+ caps = nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (device));
+ if (caps & NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS) {
+ wizard = nma_mobile_wizard_new (GTK_WINDOW (toplevel), NULL, NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS, FALSE,
+ gsm_mobile_wizard_done, closure);
+ if (wizard == NULL) {
+ g_warning ("failed to construct GSM wizard");
+ return;
+ }
+ } else if (caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO) {
+ wizard = nma_mobile_wizard_new (GTK_WINDOW (toplevel), NULL, NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO, FALSE,
+ cdma_mobile_wizard_done, closure);
+ if (wizard == NULL) {
+ g_warning ("failed to construct CDMA wizard");
+ return;
+ }
+ } else {
+ g_warning ("Network panel loaded with connect-3g but the selected device"
+ " does not support GSM or CDMA");
+ mobile_dialog_closure_free (closure);
+ return;
+ }
+
+ g_object_get (G_OBJECT (toplevel), "visible", &visible, NULL);
+ if (visible) {
+ g_debug ("Scheduling showing the Mobile wizard");
+ g_idle_add ((GSourceFunc) show_wizard_idle_cb, wizard);
+ } else {
+ g_debug ("Will show wizard a bit later, toplevel is not visible");
+ g_signal_connect (G_OBJECT (toplevel), "notify::visible",
+ G_CALLBACK (toplevel_shown), wizard);
+ }
+}
diff --git a/panels/network/network-dialogs.h b/panels/network/network-dialogs.h
new file mode 100644
index 0000000..54251c3
--- /dev/null
+++ b/panels/network/network-dialogs.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2011 Giovanni Campagna <scampa.giovanni@gmail.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <NetworkManager.h>
+#include <gtk/gtk.h>
+
+void cc_network_panel_create_wifi_network (GtkWidget *toplevel,
+ NMClient *client);
+
+void cc_network_panel_connect_to_hidden_network (GtkWidget *toplevel,
+ NMClient *client);
+
+void cc_network_panel_connect_to_8021x_network (GtkWidget *toplevel,
+ NMClient *client,
+ NMDevice *device,
+ const gchar *arg_access_point);
+
+void cc_network_panel_connect_to_3g_network (GtkWidget *toplevel,
+ NMClient *client,
+ NMDevice *device);
diff --git a/panels/network/network-ethernet.ui b/panels/network/network-ethernet.ui
new file mode 100644
index 0000000..3651fa8
--- /dev/null
+++ b/panels/network/network-ethernet.ui
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="NetDeviceEthernet" parent="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Wired</property>
+ <property name="header-suffix">
+ <object class="GtkButton">
+ <property name="icon_name">list-add-symbolic</property>
+ <accessibility>
+ <property name="label" translatable="Yes">Add Ethernet connection</property>
+ </accessibility>
+ <signal name="clicked" handler="add_profile_button_clicked_cb" object="NetDeviceEthernet" swapped="yes"/>
+ <style>
+ <class name="flat" />
+ </style>
+ </object>
+ </property>
+
+ <child>
+ <object class="GtkStack" id="connection_stack">
+ <child>
+ <object class="GtkListBox" id="connection_list">
+ <property name="selection-mode">none</property>
+ <signal name="row-activated" handler="connection_list_row_activated_cb" object="NetDeviceEthernet" swapped="yes"/>
+ <style>
+ <class name="boxed-list" />
+ </style>
+ </object>
+ </child>
+
+ <!-- Single profile row -->
+ <child>
+ <object class="GtkListBox" id="details_listbox">
+ <property name="selection_mode">none</property>
+ <style>
+ <class name="boxed-list" />
+ </style>
+ <child>
+ <object class="AdwActionRow" id="details_row">
+ <property name="activatable-widget">device_off_switch</property>
+ <child>
+ <object class="GtkSwitch" id="device_off_switch">
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Active</property>
+ </accessibility>
+ <signal name="notify::active" handler="device_off_switch_changed_cb" object="NetDeviceEthernet" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="details_button">
+ <property name="valign">center</property>
+ <property name="icon-name">emblem-system-symbolic</property>
+ <signal name="clicked" handler="details_button_clicked_cb" object="NetDeviceEthernet" swapped="yes"/>
+ <accessibility>
+ <property name="label" translatable="yes">Options…</property>
+ </accessibility>
+ <style>
+ <class name="flat"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/network-mobile.ui b/panels/network/network-mobile.ui
new file mode 100644
index 0000000..e5d7f55
--- /dev/null
+++ b/panels/network/network-mobile.ui
@@ -0,0 +1,334 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkListStore" id="mobile_connections_list_store">
+ <columns>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ <!-- column-name title -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <template class="NetDeviceMobile" parent="GtkBox">
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="valign">start</property>
+ <property name="row_spacing">10</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="imei_heading_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">IMEI</property>
+ <property name="mnemonic_widget">imei_label</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="provider_heading_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Provider</property>
+ <property name="mnemonic_widget">provider_label</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="imei_label">
+ <property name="xalign">0</property>
+ <property name="label">1234567890</property>
+ <property name="selectable">True</property>
+ <property name="max-width-chars">50</property>
+ <property name="ellipsize">end</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ <property name="column-span">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="provider_label">
+ <property name="xalign">0</property>
+ <property name="label">SuperTel Supremo </property>
+ <property name="selectable">True</property>
+ <property name="max-width-chars">50</property>
+ <property name="ellipsize">end</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ <property name="column-span">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="ipv4_label">
+ <property name="xalign">0</property>
+ <property name="label">127.0.0.1</property>
+ <property name="selectable">True</property>
+ <property name="max-width-chars">50</property>
+ <property name="ellipsize">end</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">4</property>
+ <property name="column-span">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="ipv6_label">
+ <property name="xalign">0</property>
+ <property name="selectable">True</property>
+ <property name="max-width-chars">50</property>
+ <property name="ellipsize">end</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">5</property>
+ <property name="column-span">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="route_label">
+ <property name="xalign">0</property>
+ <property name="selectable">True</property>
+ <property name="max-width-chars">50</property>
+ <property name="ellipsize">end</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">6</property>
+ <property name="column-span">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="dns4_label">
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="wrap">True</property>
+ <property name="selectable">True</property>
+ <property name="max-width-chars">50</property>
+ <property name="ellipsize">end</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">7</property>
+ <property name="column-span">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="dns6_label">
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="wrap">True</property>
+ <property name="selectable">True</property>
+ <property name="max-width-chars">50</property>
+ <property name="ellipsize">end</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">8</property>
+ <property name="column-span">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkAlignment">
+ <property name="halign">end</property>
+ <property name="valign">start</property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="ipv4_heading_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">IP Address</property>
+ <property name="mnemonic_widget">ipv4_label</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">4</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="ipv6_heading_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">IPv6 Address</property>
+ <property name="mnemonic_label">ipv6_label</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">5</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="route_heading_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Default Route</property>
+ <property name="mnemonic_label">route_label</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">6</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="dns4_heading_label">
+ <property name="xalign">1</property>
+ <property name="yalign">0</property>
+ <property name="label" translatable="yes">DNS</property>
+ <property name="mnemonic_widget">dns4_label</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">7</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="dns6_heading_label">
+ <property name="xalign">1</property>
+ <property name="yalign">0</property>
+ <property name="label" translatable="yes">DNS</property>
+ <property name="mnemonic_widget">dns6_label</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">8</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="network_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Network</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="network_combo">
+ <property name="model">mobile_connections_list_store</property>
+ <property name="entry_text_column">1</property>
+ <signal name="changed" handler="network_combo_changed_cb" object="NetDeviceMobile" swapped="yes"/>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ <child>
+ <object class="GtkCellRendererText"/>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ <property name="column-span">3</property>
+ </layout>
+ <child>
+ <object class="GtkImage">
+ <property name="halign">end</property>
+ <property name="valign">start</property>
+ <property name="xalign">1</property>
+ <property name="pixel_size">48</property>
+ <property name="icon_name">network-cellular-connected</property>
+ <property name="icon-size">6</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="valign">start</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">3</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="device_label">
+ <property name="xalign">0</property>
+ <property name="label">Mobile Broadband</property>
+ <property name="ellipsize">end</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ <attribute name="scale" value="1.2"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="status_label">
+ <property name="xalign">0</property>
+ <property name="label">Not connected</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="device_off_switch">
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Active</property>
+ </accessibility>
+ <signal name="notify::active" handler="device_off_switch_changed_cb" object="NetDeviceMobile" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="options_button">
+ <property name="halign">end</property>
+ <property name="valign">end</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="margin-top">12</property>
+ <property name="icon_name">emblem-system-symbolic</property>
+ <signal name="clicked" handler="options_button_clicked_cb" object="NetDeviceMobile" swapped="yes"/>
+ <accessibility>
+ <property name="label" translatable="yes">Options…</property>
+ </accessibility>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/network-proxy.ui b/panels/network/network-proxy.ui
new file mode 100644
index 0000000..f89fa04
--- /dev/null
+++ b/panels/network/network-proxy.ui
@@ -0,0 +1,404 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkAdjustment" id="proxy_port_ftp_adjustment">
+ <property name="upper">65535</property>
+ <property name="step_increment">1</property>
+ </object>
+ <object class="GtkAdjustment" id="proxy_port_http_adjustment">
+ <property name="upper">65535</property>
+ <property name="step_increment">1</property>
+ </object>
+ <object class="GtkAdjustment" id="proxy_port_https_adjustment">
+ <property name="upper">65535</property>
+ <property name="step_increment">1</property>
+ </object>
+ <object class="GtkAdjustment" id="proxy_port_socks_adjustment">
+ <property name="upper">65535</property>
+ <property name="step_increment">1</property>
+ </object>
+ <template class="NetProxy" parent="AdwBin">
+ <child>
+ <object class="GtkListBox">
+ <property name="selection_mode">none</property>
+ <style>
+ <class name="boxed-list" />
+ </style>
+ <child>
+ <object class="GtkListBoxRow">
+ <property name="activatable">False</property>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">12</property>
+ <property name="margin_top">8</property>
+ <property name="margin_bottom">8</property>
+ <property name="margin_start">12</property>
+ <property name="margin_end">12</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Network Proxy</property>
+ <property name="ellipsize">end</property>
+ <property name="xalign">0.0</property>
+ <attributes>
+ <attribute name="weight" value="bold" />
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="status_label">
+ <property name="margin_top">8</property>
+ <property name="margin_bottom">8</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <signal name="clicked" handler="show_dialog_cb" object="NetProxy" swapped="yes"/>
+ <property name="icon_name">emblem-system-symbolic</property>
+ <accessibility>
+ <property name="label" translatable="yes">Options…</property>
+ </accessibility>
+ <style>
+ <class name="flat"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GtkDialog" id="dialog">
+ <property name="use_header_bar">1</property>
+ <property name="default_height">350</property>
+ <property name="modal">True</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="hide-on-close">True</property>
+ <property name="title" translatable="yes">Network Proxy</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">18</property>
+ <property name="margin-bottom">18</property>
+ <property name="margin-start">18</property>
+ <property name="margin-end">18</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="automatic_radio">
+ <property name="label" translatable="yes">Automatic</property>
+ <property name="group">none_radio</property>
+ <signal name="toggled" handler="panel_proxy_mode_radio_changed_cb" object="NetProxy" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="manual_radio">
+ <property name="label" translatable="yes">Manual</property>
+ <property name="group">none_radio</property>
+ <signal name="toggled" handler="panel_proxy_mode_radio_changed_cb" object="NetProxy" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="none_radio">
+ <property name="label" translatable="yes">Disabled</property>
+ <signal name="toggled" handler="panel_proxy_mode_radio_changed_cb" object="NetProxy" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="transition_type">crossfade</property>
+
+ <!-- Disabled (empty box) -->
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">disabled</property>
+ <property name="child">
+ <object class="GtkBox" />
+ </property>
+ </object>
+ </child>
+
+ <!-- Manual -->
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">manual</property>
+ <property name="child">
+ <object class="GtkGrid">
+ <property name="valign">start</property>
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="row_spacing">10</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_HTTP Proxy</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">proxy_http_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">H_TTPS Proxy</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">proxy_https_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">4</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_FTP Proxy</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">proxy_ftp_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">5</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Socks Host</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">proxy_socks_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">6</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Ignore Hosts</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">proxy_ignore_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">7</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="proxy_http_entry">
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSpinButton">
+ <property name="xalign">1</property>
+ <property name="adjustment">proxy_port_http_adjustment</property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">3</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ <accessibility>
+ <property name="label" translatable="yes">HTTP proxy port</property>
+ </accessibility>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="proxy_https_entry">
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">4</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="proxy_ftp_entry">
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">5</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="proxy_socks_entry">
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">6</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="proxy_ignore_entry">
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">7</property>
+ <property name="column-span">2</property>
+ <property name="row-span">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSpinButton">
+ <property name="xalign">1</property>
+ <property name="adjustment">proxy_port_https_adjustment</property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">4</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ <accessibility>
+ <property name="label" translatable="yes">HTTPS proxy port</property>
+ </accessibility>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSpinButton">
+ <property name="xalign">1</property>
+ <property name="adjustment">proxy_port_ftp_adjustment</property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">5</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ <accessibility>
+ <property name="label" translatable="yes">FTP proxy port</property>
+ </accessibility>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSpinButton">
+ <property name="xalign">1</property>
+ <property name="adjustment">proxy_port_socks_adjustment</property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">6</property>
+ <property name="column-span">1</property>
+ <property name="row-span">1</property>
+ </layout>
+ <accessibility>
+ <property name="label" translatable="yes">Socks proxy port</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <!-- Automatic -->
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">automatic</property>
+ <property name="child">
+ <object class="GtkGrid">
+ <property name="row_spacing">12</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Configuration URL</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">proxy_url_entry</property>
+ <layout>
+ <property name="row">0</property>
+ <property name="column">0</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="proxy_url_entry">
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ <layout>
+ <property name="row">0</property>
+ <property name="column">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="proxy_warning_label">
+ <property name="visible">False</property>
+ <property name="xalign">0</property>
+ <property name="wrap">True</property>
+ <property name="width_chars">50</property>
+ <layout>
+ <property name="row">1</property>
+ <property name="column">0</property>
+ <property name="column-span">2</property>
+ </layout>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/panels/network/network-vpn.ui b/panels/network/network-vpn.ui
new file mode 100644
index 0000000..c0c2913
--- /dev/null
+++ b/panels/network/network-vpn.ui
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="NetVpn" parent="AdwActionRow">
+ <property name="activatable-widget">device_off_switch</property>
+ <child type="suffix">
+ <object class="GtkSwitch" id="device_off_switch">
+ <property name="valign">center</property>
+ <signal name="notify::active" handler="device_off_toggled" object="NetVpn" swapped="yes"/>
+ <accessibility>
+ <property name="label" translatable="yes">Turn VPN connection off</property>
+ </accessibility>
+ </object>
+ </child>
+ <child type="suffix">
+ <object class="GtkButton" id="options_button">
+ <property name="valign">center</property>
+ <property name="icon_name">emblem-system-symbolic</property>
+ <signal name="clicked" handler="edit_connection" object="NetVpn" swapped="yes"/>
+ <accessibility>
+ <property name="label" translatable="yes">Options…</property>
+ </accessibility>
+ <style>
+ <class name="flat"/>
+ </style>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/network-wifi.ui b/panels/network/network-wifi.ui
new file mode 100644
index 0000000..be6500d
--- /dev/null
+++ b/panels/network/network-wifi.ui
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="NetDeviceWifi" parent="AdwBin">
+
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="valign">start</property>
+ <property name="vhomogeneous">False</property>
+
+ <child>
+ <object class="GtkStackPage">
+ <property name="child">
+ <object class="GtkBox" id="listbox_box">
+ <property name="orientation">vertical</property>
+ <property name="height-request">140</property>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <!-- Wi-Fi Hotspot deails -->
+ <child>
+ <object class="GtkStackPage">
+ <property name="child">
+ <object class="GtkListBox" id="hotspot_box">
+ <property name="selection-mode">none</property>
+ <style>
+ <class name="boxed-list" />
+ </style>
+ <child>
+ <object class="CcListRow" id="hotspot_name_row">
+ <property name="activatable">False</property>
+ <property name="title" context="Wi-Fi Hotspot" translatable="yes">Network Name</property>
+ </object>
+ </child>
+ <child>
+ <object class="CcListRow" id="hotspot_security_row">
+ <property name="activatable">False</property>
+ <property name="title" context="Wi-Fi Hotspot" translatable="yes">Security type</property>
+ </object>
+ </child>
+ <child>
+ <object class="CcListRow" id="hotspot_password_row">
+ <property name="activatable">False</property>
+ <property name="title" context="Wi-Fi Hotspot" translatable="yes">Password</property>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </template>
+
+ <!-- Center widget -->
+ <object class="GtkBox" id="center_box">
+ <property name="orientation">vertical</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <child>
+ <object class="GtkLabel" id="title_label">
+ <property name="label" translatable="yes">Wi-Fi</property>
+ <style>
+ <class name="title" />
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="status_label">
+ <style>
+ <class name="subtitle" />
+ </style>
+ </object>
+ </child>
+ </object>
+
+ <!-- Box with the On/Off switch + menu button -->
+ <object class="GtkBox" id="header_box">
+ <property name="spacing">6</property>
+ <property name="halign">end</property>
+ <child>
+ <object class="GtkSwitch" id="device_off_switch">
+ <property name="valign">center</property>
+ <signal name="notify::active" handler="device_off_switch_changed_cb" object="NetDeviceWifi" swapped="yes"/>
+ <accessibility>
+ <property name="label" translatable="yes">Turn Wi-Fi off</property>
+ </accessibility>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuButton" id="header_button">
+ <property name="popover">header_button_popover</property>
+ <property name="icon_name">view-more-symbolic</property>
+ <accessibility>
+ <property name="label" translatable="yes">More options…</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+
+ <!-- Menu Popover -->
+ <object class="GtkPopover" id="header_button_popover">
+ <style>
+ <class name="menu" />
+ </style>
+ <child>
+ <object class="GtkListBox">
+ <property name="selection_mode">none</property>
+ <signal name="row_activated" handler="on_popover_row_activated_cb" />
+ <child>
+ <object class="GtkListBoxRow" id="connect_hidden_row">
+ <property name="activatable">True</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">_Connect to Hidden Network…</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkListBoxRow" id="start_hotspot_row">
+ <property name="activatable">True</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">_Turn On Wi-Fi Hotspot…</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkListBoxRow">
+ <property name="activatable">True</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">_Known Wi-Fi Networks</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/panels/network/network.gresource.xml b/panels/network/network.gresource.xml
new file mode 100644
index 0000000..d014387
--- /dev/null
+++ b/panels/network/network.gresource.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/network">
+ <!-- Network panel -->
+ <file preprocess="xml-stripblanks">cc-network-panel.ui</file>
+ <file preprocess="xml-stripblanks">cc-wifi-connection-row.ui</file>
+ <file preprocess="xml-stripblanks">cc-wifi-hotspot-dialog.ui</file>
+ <file preprocess="xml-stripblanks">network-bluetooth.ui</file>
+ <file preprocess="xml-stripblanks">network-proxy.ui</file>
+ <file preprocess="xml-stripblanks">network-vpn.ui</file>
+ <file preprocess="xml-stripblanks">network-wifi.ui</file>
+ <file preprocess="xml-stripblanks">network-mobile.ui</file>
+ <file preprocess="xml-stripblanks">network-ethernet.ui</file>
+
+ <!-- Wi-Fi panel -->
+ <file preprocess="xml-stripblanks">cc-wifi-panel.ui</file>
+ <file>wifi-panel.css</file>
+ </gresource>
+ <gresource prefix="/org/gnome/Settings/icons/scalable/actions">
+ <!-- Wi-Fi panel icons -->
+ <file preprocess="xml-stripblanks">lock-small-symbolic.svg</file>
+ <file preprocess="xml-stripblanks">warning-small-symbolic.svg</file>
+ </gresource>
+</gresources>
diff --git a/panels/network/panel-common.c b/panels/network/panel-common.c
new file mode 100644
index 0000000..7654a56
--- /dev/null
+++ b/panels/network/panel-common.c
@@ -0,0 +1,449 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Richard Hughes <richard@hughsie.com>
+ * Copyright (C) 2012 Thomas Bechtold <thomasbechtold@jpberlin.de>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include "panel-common.h"
+
+static const gchar *
+device_state_to_localized_string (NMDeviceState state)
+{
+ const gchar *value = NULL;
+
+ switch (state) {
+ case NM_DEVICE_STATE_UNKNOWN:
+ /* TRANSLATORS: device status */
+ value = _("Status unknown");
+ break;
+ case NM_DEVICE_STATE_UNMANAGED:
+ /* TRANSLATORS: device status */
+ value = _("Unmanaged");
+ break;
+ case NM_DEVICE_STATE_UNAVAILABLE:
+ /* TRANSLATORS: device status */
+ value = _("Unavailable");
+ break;
+ case NM_DEVICE_STATE_DISCONNECTED:
+ value = NULL;
+ break;
+ case NM_DEVICE_STATE_PREPARE:
+ case NM_DEVICE_STATE_CONFIG:
+ case NM_DEVICE_STATE_IP_CONFIG:
+ case NM_DEVICE_STATE_IP_CHECK:
+ /* TRANSLATORS: device status */
+ value = _("Connecting");
+ break;
+ case NM_DEVICE_STATE_NEED_AUTH:
+ /* TRANSLATORS: device status */
+ value = _("Authentication required");
+ break;
+ case NM_DEVICE_STATE_ACTIVATED:
+ /* TRANSLATORS: device status */
+ value = _("Connected");
+ break;
+ case NM_DEVICE_STATE_DEACTIVATING:
+ /* TRANSLATORS: device status */
+ value = _("Disconnecting");
+ break;
+ case NM_DEVICE_STATE_FAILED:
+ /* TRANSLATORS: device status */
+ value = _("Connection failed");
+ break;
+ default:
+ /* TRANSLATORS: device status */
+ value = _("Status unknown (missing)");
+ break;
+ }
+ return value;
+}
+
+static const gchar *
+device_state_reason_to_localized_string (NMDevice *device)
+{
+ const gchar *value = NULL;
+ NMDeviceStateReason state_reason;
+
+ /* This only covers NMDeviceStateReasons that explain why a connection
+ * failed / can't be attempted, and aren't redundant with the state
+ * (eg, NM_DEVICE_STATE_REASON_CARRIER).
+ */
+
+ state_reason = nm_device_get_state_reason (device);
+ switch (state_reason) {
+ case NM_DEVICE_STATE_REASON_CONFIG_FAILED:
+ /* TRANSLATORS: device status reason */
+ value = _("Configuration failed");
+ break;
+ case NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE:
+ /* TRANSLATORS: device status reason */
+ value = _("IP configuration failed");
+ break;
+ case NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED:
+ /* TRANSLATORS: device status reason */
+ value = _("IP configuration expired");
+ break;
+ case NM_DEVICE_STATE_REASON_NO_SECRETS:
+ /* TRANSLATORS: device status reason */
+ value = _("Secrets were required, but not provided");
+ break;
+ case NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT:
+ /* TRANSLATORS: device status reason */
+ value = _("802.1x supplicant disconnected");
+ break;
+ case NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED:
+ /* TRANSLATORS: device status reason */
+ value = _("802.1x supplicant configuration failed");
+ break;
+ case NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED:
+ /* TRANSLATORS: device status reason */
+ value = _("802.1x supplicant failed");
+ break;
+ case NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT:
+ /* TRANSLATORS: device status reason */
+ value = _("802.1x supplicant took too long to authenticate");
+ break;
+ case NM_DEVICE_STATE_REASON_PPP_START_FAILED:
+ /* TRANSLATORS: device status reason */
+ value = _("PPP service failed to start");
+ break;
+ case NM_DEVICE_STATE_REASON_PPP_DISCONNECT:
+ /* TRANSLATORS: device status reason */
+ value = _("PPP service disconnected");
+ break;
+ case NM_DEVICE_STATE_REASON_PPP_FAILED:
+ /* TRANSLATORS: device status reason */
+ value = _("PPP failed");
+ break;
+ case NM_DEVICE_STATE_REASON_DHCP_START_FAILED:
+ /* TRANSLATORS: device status reason */
+ value = _("DHCP client failed to start");
+ break;
+ case NM_DEVICE_STATE_REASON_DHCP_ERROR:
+ /* TRANSLATORS: device status reason */
+ value = _("DHCP client error");
+ break;
+ case NM_DEVICE_STATE_REASON_DHCP_FAILED:
+ /* TRANSLATORS: device status reason */
+ value = _("DHCP client failed");
+ break;
+ case NM_DEVICE_STATE_REASON_SHARED_START_FAILED:
+ /* TRANSLATORS: device status reason */
+ value = _("Shared connection service failed to start");
+ break;
+ case NM_DEVICE_STATE_REASON_SHARED_FAILED:
+ /* TRANSLATORS: device status reason */
+ value = _("Shared connection service failed");
+ break;
+ case NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED:
+ /* TRANSLATORS: device status reason */
+ value = _("AutoIP service failed to start");
+ break;
+ case NM_DEVICE_STATE_REASON_AUTOIP_ERROR:
+ /* TRANSLATORS: device status reason */
+ value = _("AutoIP service error");
+ break;
+ case NM_DEVICE_STATE_REASON_AUTOIP_FAILED:
+ /* TRANSLATORS: device status reason */
+ value = _("AutoIP service failed");
+ break;
+ case NM_DEVICE_STATE_REASON_MODEM_BUSY:
+ /* TRANSLATORS: device status reason */
+ value = _("Line busy");
+ break;
+ case NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE:
+ /* TRANSLATORS: device status reason */
+ value = _("No dial tone");
+ break;
+ case NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER:
+ /* TRANSLATORS: device status reason */
+ value = _("No carrier could be established");
+ break;
+ case NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT:
+ /* TRANSLATORS: device status reason */
+ value = _("Dialing request timed out");
+ break;
+ case NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED:
+ /* TRANSLATORS: device status reason */
+ value = _("Dialing attempt failed");
+ break;
+ case NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED:
+ /* TRANSLATORS: device status reason */
+ value = _("Modem initialization failed");
+ break;
+ case NM_DEVICE_STATE_REASON_GSM_APN_FAILED:
+ /* TRANSLATORS: device status reason */
+ value = _("Failed to select the specified APN");
+ break;
+ case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING:
+ /* TRANSLATORS: device status reason */
+ value = _("Not searching for networks");
+ break;
+ case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED:
+ /* TRANSLATORS: device status reason */
+ value = _("Network registration denied");
+ break;
+ case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT:
+ /* TRANSLATORS: device status reason */
+ value = _("Network registration timed out");
+ break;
+ case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED:
+ /* TRANSLATORS: device status reason */
+ value = _("Failed to register with the requested network");
+ break;
+ case NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED:
+ /* TRANSLATORS: device status reason */
+ value = _("PIN check failed");
+ break;
+ case NM_DEVICE_STATE_REASON_FIRMWARE_MISSING:
+ /* TRANSLATORS: device status reason */
+ value = _("Firmware for the device may be missing");
+ break;
+ case NM_DEVICE_STATE_REASON_CONNECTION_REMOVED:
+ /* TRANSLATORS: device status reason */
+ value = _("Connection disappeared");
+ break;
+ case NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED:
+ /* TRANSLATORS: device status reason */
+ value = _("Existing connection was assumed");
+ break;
+ case NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND:
+ /* TRANSLATORS: device status reason */
+ value = _("Modem not found");
+ break;
+ case NM_DEVICE_STATE_REASON_BT_FAILED:
+ /* TRANSLATORS: device status reason */
+ value = _("Bluetooth connection failed");
+ break;
+ case NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED:
+ /* TRANSLATORS: device status reason */
+ value = _("SIM Card not inserted");
+ break;
+ case NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED:
+ /* TRANSLATORS: device status reason */
+ value = _("SIM Pin required");
+ break;
+ case NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED:
+ /* TRANSLATORS: device status reason */
+ value = _("SIM Puk required");
+ break;
+ case NM_DEVICE_STATE_REASON_GSM_SIM_WRONG:
+ /* TRANSLATORS: device status reason */
+ value = _("SIM wrong");
+ break;
+ case NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED:
+ /* TRANSLATORS: device status reason */
+ value = _("Connection dependency failed");
+ break;
+ default:
+ /* no StateReason to show */
+ value = "";
+ break;
+ }
+
+ return value;
+}
+
+static gchar *
+get_mac_address_of_connection (NMConnection *connection)
+{
+ if (!connection)
+ return NULL;
+
+ /* check the connection type */
+ if (nm_connection_is_type (connection,
+ NM_SETTING_WIRELESS_SETTING_NAME)) {
+ /* check wireless settings */
+ NMSettingWireless *s_wireless = nm_connection_get_setting_wireless (connection);
+ if (!s_wireless)
+ return NULL;
+ return g_strdup (nm_setting_wireless_get_mac_address (s_wireless));
+ } else if (nm_connection_is_type (connection,
+ NM_SETTING_WIRED_SETTING_NAME)) {
+ /* check wired settings */
+ NMSettingWired *s_wired = nm_connection_get_setting_wired (connection);
+ if (!s_wired)
+ return NULL;
+ return g_strdup (nm_setting_wired_get_mac_address (s_wired));
+ }
+ /* no MAC address found */
+ return NULL;
+}
+
+/* returns TRUE if both MACs are equal */
+static gboolean
+compare_mac_device_with_mac_connection (NMDevice *device,
+ NMConnection *connection)
+{
+ const gchar *mac_dev = NULL;
+ g_autofree gchar *mac_conn = NULL;
+
+ mac_dev = nm_device_get_hw_address (device);
+ if (mac_dev == NULL)
+ return FALSE;
+
+ mac_conn = get_mac_address_of_connection (connection);
+ if (mac_conn == NULL)
+ return FALSE;
+
+ /* compare both MACs */
+ return g_strcmp0 (mac_dev, mac_conn) == 0;
+}
+
+gchar *
+panel_device_status_to_localized_string (NMDevice *nm_device,
+ const gchar *speed)
+{
+ NMDeviceState state;
+ GString *string;
+ const gchar *state_str = NULL, *reason_str = NULL;
+
+ string = g_string_new (NULL);
+
+ state = nm_device_get_state (nm_device);
+ if (state == NM_DEVICE_STATE_UNAVAILABLE) {
+ if (nm_device_get_firmware_missing (nm_device)) {
+ /* TRANSLATORS: device status */
+ state_str = _("Firmware missing");
+ } else if (NM_IS_DEVICE_ETHERNET (nm_device) &&
+ !nm_device_ethernet_get_carrier (NM_DEVICE_ETHERNET (nm_device))) {
+ /* TRANSLATORS: device status */
+ state_str = _("Cable unplugged");
+ }
+ }
+ if (!state_str)
+ state_str = device_state_to_localized_string (state);
+ if (state_str)
+ g_string_append (string, state_str);
+
+ if (state > NM_DEVICE_STATE_UNAVAILABLE && speed) {
+ if (string->len)
+ g_string_append (string, " - ");
+ g_string_append (string, speed);
+ } else if (state == NM_DEVICE_STATE_UNAVAILABLE ||
+ state == NM_DEVICE_STATE_DISCONNECTED ||
+ state == NM_DEVICE_STATE_DEACTIVATING ||
+ state == NM_DEVICE_STATE_FAILED) {
+ reason_str = device_state_reason_to_localized_string (nm_device);
+ if (*reason_str) {
+ if (string->len)
+ g_string_append (string, " - ");
+ g_string_append (string, reason_str);
+ }
+ }
+
+ return g_string_free (string, FALSE);
+}
+
+NMConnection *
+net_device_get_find_connection (NMClient *client, NMDevice *device)
+{
+ GSList *list, *iterator;
+ NMConnection *connection = NULL;
+ NMActiveConnection *ac;
+
+ /* is the device available in a active connection? */
+ ac = nm_device_get_active_connection (device);
+ if (ac)
+ return (NMConnection*) nm_active_connection_get_connection (ac);
+
+ /* not found in active connections - check all available connections */
+ list = net_device_get_valid_connections (client, device);
+ if (list != NULL) {
+ /* if list has only one connection, use this connection */
+ if (g_slist_length (list) == 1) {
+ connection = list->data;
+ goto out;
+ }
+
+ /* is there connection with the MAC address of the device? */
+ for (iterator = list; iterator; iterator = iterator->next) {
+ connection = iterator->data;
+ if (compare_mac_device_with_mac_connection (device,
+ connection)) {
+ goto out;
+ }
+ }
+ }
+
+ /* no connection found for the given device */
+ connection = NULL;
+out:
+ g_slist_free (list);
+ return connection;
+}
+
+GSList *
+net_device_get_valid_connections (NMClient *client, NMDevice *device)
+{
+ GSList *valid;
+ NMConnection *connection;
+ NMSettingConnection *s_con;
+ NMActiveConnection *active_connection;
+ const char *active_uuid;
+ const GPtrArray *all;
+ GPtrArray *filtered;
+ guint i;
+
+ all = nm_client_get_connections (client);
+ filtered = nm_device_filter_connections (device, all);
+
+ active_connection = nm_device_get_active_connection (device);
+ active_uuid = active_connection ? nm_active_connection_get_uuid (active_connection) : NULL;
+
+ valid = NULL;
+ for (i = 0; i < filtered->len; i++) {
+ connection = g_ptr_array_index (filtered, i);
+ s_con = nm_connection_get_setting_connection (connection);
+ if (!s_con)
+ continue;
+
+ if (nm_setting_connection_get_master (s_con) &&
+ g_strcmp0 (nm_setting_connection_get_uuid (s_con), active_uuid) != 0)
+ continue;
+
+ valid = g_slist_prepend (valid, connection);
+ }
+ g_ptr_array_free (filtered, FALSE);
+
+ return g_slist_reverse (valid);
+}
+
+gchar *
+net_device_get_ip6_addresses (NMIPConfig *ipv6_config)
+{
+ g_autoptr(GPtrArray) ipv6 = NULL;
+ GPtrArray *addresses;
+
+ addresses = nm_ip_config_get_addresses (ipv6_config);
+ if (addresses->len == 0) {
+ return NULL;
+ }
+ ipv6 = g_ptr_array_sized_new (addresses->len + 1);
+
+ for (int i = 0; i < addresses->len; i++) {
+ g_ptr_array_add (ipv6, (char *) nm_ip_address_get_address (g_ptr_array_index (addresses, i)));
+ }
+ g_ptr_array_add (ipv6, NULL);
+ return g_strjoinv ("\n", (char **) ipv6->pdata);
+}
diff --git a/panels/network/panel-common.h b/panels/network/panel-common.h
new file mode 100644
index 0000000..32aed09
--- /dev/null
+++ b/panels/network/panel-common.h
@@ -0,0 +1,39 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+gchar *panel_device_status_to_localized_string (NMDevice *nm_device,
+ const gchar *speed);
+
+NMConnection *net_device_get_find_connection (NMClient *client,
+ NMDevice *device);
+
+GSList *net_device_get_valid_connections (NMClient *client,
+ NMDevice *device);
+
+gchar *net_device_get_ip6_addresses (NMIPConfig *ipv6_config);
+
+G_END_DECLS
diff --git a/panels/network/qrcodegen.c b/panels/network/qrcodegen.c
new file mode 100644
index 0000000..7cda965
--- /dev/null
+++ b/panels/network/qrcodegen.c
@@ -0,0 +1,1009 @@
+/*
+ * QR Code generator library (C)
+ *
+ * Copyright (c) Project Nayuki. (MIT License)
+ * https://www.nayuki.io/page/qr-code-generator-library
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ * - The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * - The Software is provided "as is", without warranty of any kind, express or
+ * implied, including but not limited to the warranties of merchantability,
+ * fitness for a particular purpose and noninfringement. In no event shall the
+ * authors or copyright holders be liable for any claim, damages or other
+ * liability, whether in an action of contract, tort or otherwise, arising from,
+ * out of or in connection with the Software or the use or other dealings in the
+ * Software.
+ */
+
+#include <assert.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include "qrcodegen.h"
+
+#ifndef QRCODEGEN_TEST
+ #define testable static // Keep functions private
+#else
+ #define testable // Expose private functions
+#endif
+
+
+/*---- Forward declarations for private functions ----*/
+
+// Regarding all public and private functions defined in this source file:
+// - They require all pointer/array arguments to be not null unless the array length is zero.
+// - They only read input scalar/array arguments, write to output pointer/array
+// arguments, and return scalar values; they are "pure" functions.
+// - They don't read mutable global variables or write to any global variables.
+// - They don't perform I/O, read the clock, print to console, etc.
+// - They allocate a small and constant amount of stack memory.
+// - They don't allocate or free any memory on the heap.
+// - They don't recurse or mutually recurse. All the code
+// could be inlined into the top-level public functions.
+// - They run in at most quadratic time with respect to input arguments.
+// Most functions run in linear time, and some in constant time.
+// There are no unbounded loops or non-obvious termination conditions.
+// - They are completely thread-safe if the caller does not give the
+// same writable buffer to concurrent calls to these functions.
+
+testable void appendBitsToBuffer(unsigned int val, int numBits, uint8_t buffer[], int *bitLen);
+
+testable void addEccAndInterleave(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]);
+testable int getNumDataCodewords(int version, enum qrcodegen_Ecc ecl);
+testable int getNumRawDataModules(int ver);
+
+testable void calcReedSolomonGenerator(int degree, uint8_t result[]);
+testable void calcReedSolomonRemainder(const uint8_t data[], int dataLen,
+ const uint8_t generator[], int degree, uint8_t result[]);
+testable uint8_t finiteFieldMultiply(uint8_t x, uint8_t y);
+
+testable void initializeFunctionModules(int version, uint8_t qrcode[]);
+static void drawWhiteFunctionModules(uint8_t qrcode[], int version);
+static void drawFormatBits(enum qrcodegen_Ecc ecl, enum qrcodegen_Mask mask, uint8_t qrcode[]);
+testable int getAlignmentPatternPositions(int version, uint8_t result[7]);
+static void fillRectangle(int left, int top, int width, int height, uint8_t qrcode[]);
+
+static void drawCodewords(const uint8_t data[], int dataLen, uint8_t qrcode[]);
+static void applyMask(const uint8_t functionModules[], uint8_t qrcode[], enum qrcodegen_Mask mask);
+static long getPenaltyScore(const uint8_t qrcode[]);
+static void addRunToHistory(unsigned char run, unsigned char history[7]);
+static bool hasFinderLikePattern(unsigned char runHistory[7]);
+
+testable bool getModule(const uint8_t qrcode[], int x, int y);
+testable void setModule(uint8_t qrcode[], int x, int y, bool isBlack);
+testable void setModuleBounded(uint8_t qrcode[], int x, int y, bool isBlack);
+static bool getBit(int x, int i);
+
+testable int calcSegmentBitLength(enum qrcodegen_Mode mode, size_t numChars);
+testable int getTotalBits(const struct qrcodegen_Segment segs[], size_t len, int version);
+static int numCharCountBits(enum qrcodegen_Mode mode, int version);
+
+
+
+/*---- Private tables of constants ----*/
+
+// The set of all legal characters in alphanumeric mode, where each character
+// value maps to the index in the string. For checking text and encoding segments.
+static const char *ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";
+
+// For generating error correction codes.
+testable const int8_t ECC_CODEWORDS_PER_BLOCK[4][41] = {
+ // Version: (note that index 0 is for padding, and is set to an illegal value)
+ //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
+ {-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Low
+ {-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28}, // Medium
+ {-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Quartile
+ {-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // High
+};
+
+#define qrcodegen_REED_SOLOMON_DEGREE_MAX 30 // Based on the table above
+
+// For generating error correction codes.
+testable const int8_t NUM_ERROR_CORRECTION_BLOCKS[4][41] = {
+ // Version: (note that index 0 is for padding, and is set to an illegal value)
+ //0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
+ {-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, // Low
+ {-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49}, // Medium
+ {-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68}, // Quartile
+ {-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81}, // High
+};
+
+// For automatic mask pattern selection.
+static const int PENALTY_N1 = 3;
+static const int PENALTY_N2 = 3;
+static const int PENALTY_N3 = 40;
+static const int PENALTY_N4 = 10;
+
+
+
+/*---- High-level QR Code encoding functions ----*/
+
+// Public function - see documentation comment in header file.
+bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[],
+ enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl) {
+
+ size_t textLen = strlen(text);
+ if (textLen == 0)
+ return qrcodegen_encodeSegmentsAdvanced(NULL, 0, ecl, minVersion, maxVersion, mask, boostEcl, tempBuffer, qrcode);
+ size_t bufLen = qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion);
+
+ struct qrcodegen_Segment seg;
+ if (qrcodegen_isNumeric(text)) {
+ if (qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_NUMERIC, textLen) > bufLen)
+ goto fail;
+ seg = qrcodegen_makeNumeric(text, tempBuffer);
+ } else if (qrcodegen_isAlphanumeric(text)) {
+ if (qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_ALPHANUMERIC, textLen) > bufLen)
+ goto fail;
+ seg = qrcodegen_makeAlphanumeric(text, tempBuffer);
+ } else {
+ if (textLen > bufLen)
+ goto fail;
+ for (size_t i = 0; i < textLen; i++)
+ tempBuffer[i] = (uint8_t)text[i];
+ seg.mode = qrcodegen_Mode_BYTE;
+ seg.bitLength = calcSegmentBitLength(seg.mode, textLen);
+ if (seg.bitLength == -1)
+ goto fail;
+ seg.numChars = (int)textLen;
+ seg.data = tempBuffer;
+ }
+ return qrcodegen_encodeSegmentsAdvanced(&seg, 1, ecl, minVersion, maxVersion, mask, boostEcl, tempBuffer, qrcode);
+
+fail:
+ qrcode[0] = 0; // Set size to invalid value for safety
+ return false;
+}
+
+
+// Public function - see documentation comment in header file.
+bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[],
+ enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl) {
+
+ struct qrcodegen_Segment seg;
+ seg.mode = qrcodegen_Mode_BYTE;
+ seg.bitLength = calcSegmentBitLength(seg.mode, dataLen);
+ if (seg.bitLength == -1) {
+ qrcode[0] = 0; // Set size to invalid value for safety
+ return false;
+ }
+ seg.numChars = (int)dataLen;
+ seg.data = dataAndTemp;
+ return qrcodegen_encodeSegmentsAdvanced(&seg, 1, ecl, minVersion, maxVersion, mask, boostEcl, dataAndTemp, qrcode);
+}
+
+
+// Appends the given number of low-order bits of the given value to the given byte-based
+// bit buffer, increasing the bit length. Requires 0 <= numBits <= 16 and val < 2^numBits.
+testable void appendBitsToBuffer(unsigned int val, int numBits, uint8_t buffer[], int *bitLen) {
+ assert(0 <= numBits && numBits <= 16 && (unsigned long)val >> numBits == 0);
+ for (int i = numBits - 1; i >= 0; i--, (*bitLen)++)
+ buffer[*bitLen >> 3] |= ((val >> i) & 1) << (7 - (*bitLen & 7));
+}
+
+
+
+/*---- Low-level QR Code encoding functions ----*/
+
+// Public function - see documentation comment in header file.
+bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len,
+ enum qrcodegen_Ecc ecl, uint8_t tempBuffer[], uint8_t qrcode[]) {
+ return qrcodegen_encodeSegmentsAdvanced(segs, len, ecl,
+ qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, -1, true, tempBuffer, qrcode);
+}
+
+
+// Public function - see documentation comment in header file.
+bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], size_t len, enum qrcodegen_Ecc ecl,
+ int minVersion, int maxVersion, int mask, bool boostEcl, uint8_t tempBuffer[], uint8_t qrcode[]) {
+ assert(segs != NULL || len == 0);
+ assert(qrcodegen_VERSION_MIN <= minVersion && minVersion <= maxVersion && maxVersion <= qrcodegen_VERSION_MAX);
+ assert(0 <= (int)ecl && (int)ecl <= 3 && -1 <= (int)mask && (int)mask <= 7);
+
+ // Find the minimal version number to use
+ int version, dataUsedBits;
+ for (version = minVersion; ; version++) {
+ int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; // Number of data bits available
+ dataUsedBits = getTotalBits(segs, len, version);
+ if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits)
+ break; // This version number is found to be suitable
+ if (version >= maxVersion) { // All versions in the range could not fit the given data
+ qrcode[0] = 0; // Set size to invalid value for safety
+ return false;
+ }
+ }
+ assert(dataUsedBits != -1);
+
+ // Increase the error correction level while the data still fits in the current version number
+ for (int i = (int)qrcodegen_Ecc_MEDIUM; i <= (int)qrcodegen_Ecc_HIGH; i++) { // From low to high
+ if (boostEcl && dataUsedBits <= getNumDataCodewords(version, (enum qrcodegen_Ecc)i) * 8)
+ ecl = (enum qrcodegen_Ecc)i;
+ }
+
+ // Concatenate all segments to create the data bit string
+ memset(qrcode, 0, qrcodegen_BUFFER_LEN_FOR_VERSION(version) * sizeof(qrcode[0]));
+ int bitLen = 0;
+ for (size_t i = 0; i < len; i++) {
+ const struct qrcodegen_Segment *seg = &segs[i];
+ appendBitsToBuffer((int)seg->mode, 4, qrcode, &bitLen);
+ appendBitsToBuffer(seg->numChars, numCharCountBits(seg->mode, version), qrcode, &bitLen);
+ for (int j = 0; j < seg->bitLength; j++)
+ appendBitsToBuffer((seg->data[j >> 3] >> (7 - (j & 7))) & 1, 1, qrcode, &bitLen);
+ }
+ assert(bitLen == dataUsedBits);
+
+ // Add terminator and pad up to a byte if applicable
+ int dataCapacityBits = getNumDataCodewords(version, ecl) * 8;
+ assert(bitLen <= dataCapacityBits);
+ int terminatorBits = dataCapacityBits - bitLen;
+ if (terminatorBits > 4)
+ terminatorBits = 4;
+ appendBitsToBuffer(0, terminatorBits, qrcode, &bitLen);
+ appendBitsToBuffer(0, (8 - bitLen % 8) % 8, qrcode, &bitLen);
+ assert(bitLen % 8 == 0);
+
+ // Pad with alternating bytes until data capacity is reached
+ for (uint8_t padByte = 0xEC; bitLen < dataCapacityBits; padByte ^= 0xEC ^ 0x11)
+ appendBitsToBuffer(padByte, 8, qrcode, &bitLen);
+
+ // Draw function and data codeword modules
+ addEccAndInterleave(qrcode, version, ecl, tempBuffer);
+ initializeFunctionModules(version, qrcode);
+ drawCodewords(tempBuffer, getNumRawDataModules(version) / 8, qrcode);
+ drawWhiteFunctionModules(qrcode, version);
+ initializeFunctionModules(version, tempBuffer);
+
+ // Handle masking
+ if (mask == qrcodegen_Mask_AUTO) { // Automatically choose best mask
+ long minPenalty = LONG_MAX;
+ for (int i = 0; i < 8; i++) {
+ enum qrcodegen_Mask msk = (enum qrcodegen_Mask)i;
+ drawFormatBits(ecl, msk, qrcode);
+ applyMask(tempBuffer, qrcode, msk);
+ long penalty = getPenaltyScore(qrcode);
+ if (penalty < minPenalty) {
+ mask = msk;
+ minPenalty = penalty;
+ }
+ applyMask(tempBuffer, qrcode, msk); // Undoes the mask due to XOR
+ }
+ }
+ assert(0 <= (int)mask && (int)mask <= 7);
+ drawFormatBits(ecl, mask, qrcode);
+ applyMask(tempBuffer, qrcode, mask);
+ return true;
+}
+
+
+
+/*---- Error correction code generation functions ----*/
+
+// Appends error correction bytes to each block of the given data array, then interleaves
+// bytes from the blocks and stores them in the result array. data[0 : dataLen] contains
+// the input data. data[dataLen : rawCodewords] is used as a temporary work area and will
+// be clobbered by this function. The final answer is stored in result[0 : rawCodewords].
+testable void addEccAndInterleave(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]) {
+ // Calculate parameter numbers
+ assert(0 <= (int)ecl && (int)ecl < 4 && qrcodegen_VERSION_MIN <= version && version <= qrcodegen_VERSION_MAX);
+ int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[(int)ecl][version];
+ int blockEccLen = ECC_CODEWORDS_PER_BLOCK [(int)ecl][version];
+ int rawCodewords = getNumRawDataModules(version) / 8;
+ int dataLen = getNumDataCodewords(version, ecl);
+ int numShortBlocks = numBlocks - rawCodewords % numBlocks;
+ int shortBlockDataLen = rawCodewords / numBlocks - blockEccLen;
+
+ // Split data into blocks, calculate ECC, and interleave
+ // (not concatenate) the bytes into a single sequence
+ uint8_t generator[qrcodegen_REED_SOLOMON_DEGREE_MAX];
+ calcReedSolomonGenerator(blockEccLen, generator);
+ const uint8_t *dat = data;
+ for (int i = 0; i < numBlocks; i++) {
+ int datLen = shortBlockDataLen + (i < numShortBlocks ? 0 : 1);
+ uint8_t *ecc = &data[dataLen]; // Temporary storage
+ calcReedSolomonRemainder(dat, datLen, generator, blockEccLen, ecc);
+ for (int j = 0, k = i; j < datLen; j++, k += numBlocks) { // Copy data
+ if (j == shortBlockDataLen)
+ k -= numShortBlocks;
+ result[k] = dat[j];
+ }
+ for (int j = 0, k = dataLen + i; j < blockEccLen; j++, k += numBlocks) // Copy ECC
+ result[k] = ecc[j];
+ dat += datLen;
+ }
+}
+
+
+// Returns the number of 8-bit codewords that can be used for storing data (not ECC),
+// for the given version number and error correction level. The result is in the range [9, 2956].
+testable int getNumDataCodewords(int version, enum qrcodegen_Ecc ecl) {
+ int v = version, e = (int)ecl;
+ assert(0 <= e && e < 4);
+ return getNumRawDataModules(v) / 8
+ - ECC_CODEWORDS_PER_BLOCK [e][v]
+ * NUM_ERROR_CORRECTION_BLOCKS[e][v];
+}
+
+
+// Returns the number of data bits that can be stored in a QR Code of the given version number, after
+// all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8.
+// The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table.
+testable int getNumRawDataModules(int ver) {
+ assert(qrcodegen_VERSION_MIN <= ver && ver <= qrcodegen_VERSION_MAX);
+ int result = (16 * ver + 128) * ver + 64;
+ if (ver >= 2) {
+ int numAlign = ver / 7 + 2;
+ result -= (25 * numAlign - 10) * numAlign - 55;
+ if (ver >= 7)
+ result -= 36;
+ }
+ return result;
+}
+
+
+
+/*---- Reed-Solomon ECC generator functions ----*/
+
+// Calculates the Reed-Solomon generator polynomial of the given degree, storing in result[0 : degree].
+testable void calcReedSolomonGenerator(int degree, uint8_t result[]) {
+ // Start with the monomial x^0
+ assert(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX);
+ memset(result, 0, degree * sizeof(result[0]));
+ result[degree - 1] = 1;
+
+ // Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}),
+ // drop the highest term, and store the rest of the coefficients in order of descending powers.
+ // Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D).
+ uint8_t root = 1;
+ for (int i = 0; i < degree; i++) {
+ // Multiply the current product by (x - r^i)
+ for (int j = 0; j < degree; j++) {
+ result[j] = finiteFieldMultiply(result[j], root);
+ if (j + 1 < degree)
+ result[j] ^= result[j + 1];
+ }
+ root = finiteFieldMultiply(root, 0x02);
+ }
+}
+
+
+// Calculates the remainder of the polynomial data[0 : dataLen] when divided by the generator[0 : degree], where all
+// polynomials are in big endian and the generator has an implicit leading 1 term, storing the result in result[0 : degree].
+testable void calcReedSolomonRemainder(const uint8_t data[], int dataLen,
+ const uint8_t generator[], int degree, uint8_t result[]) {
+
+ // Perform polynomial division
+ assert(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX);
+ memset(result, 0, degree * sizeof(result[0]));
+ for (int i = 0; i < dataLen; i++) {
+ uint8_t factor = data[i] ^ result[0];
+ memmove(&result[0], &result[1], (degree - 1) * sizeof(result[0]));
+ result[degree - 1] = 0;
+ for (int j = 0; j < degree; j++)
+ result[j] ^= finiteFieldMultiply(generator[j], factor);
+ }
+}
+
+#undef qrcodegen_REED_SOLOMON_DEGREE_MAX
+
+
+// Returns the product of the two given field elements modulo GF(2^8/0x11D).
+// All inputs are valid. This could be implemented as a 256*256 lookup table.
+testable uint8_t finiteFieldMultiply(uint8_t x, uint8_t y) {
+ // Russian peasant multiplication
+ uint8_t z = 0;
+ for (int i = 7; i >= 0; i--) {
+ z = (z << 1) ^ ((z >> 7) * 0x11D);
+ z ^= ((y >> i) & 1) * x;
+ }
+ return z;
+}
+
+
+
+/*---- Drawing function modules ----*/
+
+// Clears the given QR Code grid with white modules for the given
+// version's size, then marks every function module as black.
+testable void initializeFunctionModules(int version, uint8_t qrcode[]) {
+ // Initialize QR Code
+ int qrsize = version * 4 + 17;
+ memset(qrcode, 0, ((qrsize * qrsize + 7) / 8 + 1) * sizeof(qrcode[0]));
+ qrcode[0] = (uint8_t)qrsize;
+
+ // Fill horizontal and vertical timing patterns
+ fillRectangle(6, 0, 1, qrsize, qrcode);
+ fillRectangle(0, 6, qrsize, 1, qrcode);
+
+ // Fill 3 finder patterns (all corners except bottom right) and format bits
+ fillRectangle(0, 0, 9, 9, qrcode);
+ fillRectangle(qrsize - 8, 0, 8, 9, qrcode);
+ fillRectangle(0, qrsize - 8, 9, 8, qrcode);
+
+ // Fill numerous alignment patterns
+ uint8_t alignPatPos[7];
+ int numAlign = getAlignmentPatternPositions(version, alignPatPos);
+ for (int i = 0; i < numAlign; i++) {
+ for (int j = 0; j < numAlign; j++) {
+ // Don't draw on the three finder corners
+ if (!((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0)))
+ fillRectangle(alignPatPos[i] - 2, alignPatPos[j] - 2, 5, 5, qrcode);
+ }
+ }
+
+ // Fill version blocks
+ if (version >= 7) {
+ fillRectangle(qrsize - 11, 0, 3, 6, qrcode);
+ fillRectangle(0, qrsize - 11, 6, 3, qrcode);
+ }
+}
+
+
+// Draws white function modules and possibly some black modules onto the given QR Code, without changing
+// non-function modules. This does not draw the format bits. This requires all function modules to be previously
+// marked black (namely by initializeFunctionModules()), because this may skip redrawing black function modules.
+static void drawWhiteFunctionModules(uint8_t qrcode[], int version) {
+ // Draw horizontal and vertical timing patterns
+ int qrsize = qrcodegen_getSize(qrcode);
+ for (int i = 7; i < qrsize - 7; i += 2) {
+ setModule(qrcode, 6, i, false);
+ setModule(qrcode, i, 6, false);
+ }
+
+ // Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules)
+ for (int dy = -4; dy <= 4; dy++) {
+ for (int dx = -4; dx <= 4; dx++) {
+ int dist = abs(dx);
+ if (abs(dy) > dist)
+ dist = abs(dy);
+ if (dist == 2 || dist == 4) {
+ setModuleBounded(qrcode, 3 + dx, 3 + dy, false);
+ setModuleBounded(qrcode, qrsize - 4 + dx, 3 + dy, false);
+ setModuleBounded(qrcode, 3 + dx, qrsize - 4 + dy, false);
+ }
+ }
+ }
+
+ // Draw numerous alignment patterns
+ uint8_t alignPatPos[7];
+ int numAlign = getAlignmentPatternPositions(version, alignPatPos);
+ for (int i = 0; i < numAlign; i++) {
+ for (int j = 0; j < numAlign; j++) {
+ if ((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0))
+ continue; // Don't draw on the three finder corners
+ for (int dy = -1; dy <= 1; dy++) {
+ for (int dx = -1; dx <= 1; dx++)
+ setModule(qrcode, alignPatPos[i] + dx, alignPatPos[j] + dy, dx == 0 && dy == 0);
+ }
+ }
+ }
+
+ // Draw version blocks
+ if (version >= 7) {
+ // Calculate error correction code and pack bits
+ int rem = version; // version is uint6, in the range [7, 40]
+ for (int i = 0; i < 12; i++)
+ rem = (rem << 1) ^ ((rem >> 11) * 0x1F25);
+ long bits = (long)version << 12 | rem; // uint18
+ assert(bits >> 18 == 0);
+
+ // Draw two copies
+ for (int i = 0; i < 6; i++) {
+ for (int j = 0; j < 3; j++) {
+ int k = qrsize - 11 + j;
+ setModule(qrcode, k, i, (bits & 1) != 0);
+ setModule(qrcode, i, k, (bits & 1) != 0);
+ bits >>= 1;
+ }
+ }
+ }
+}
+
+
+// Draws two copies of the format bits (with its own error correction code) based
+// on the given mask and error correction level. This always draws all modules of
+// the format bits, unlike drawWhiteFunctionModules() which might skip black modules.
+static void drawFormatBits(enum qrcodegen_Ecc ecl, enum qrcodegen_Mask mask, uint8_t qrcode[]) {
+ // Calculate error correction code and pack bits
+ assert(0 <= (int)mask && (int)mask <= 7);
+ static const int table[] = {1, 0, 3, 2};
+ int data = table[(int)ecl] << 3 | (int)mask; // errCorrLvl is uint2, mask is uint3
+ int rem = data;
+ for (int i = 0; i < 10; i++)
+ rem = (rem << 1) ^ ((rem >> 9) * 0x537);
+ int bits = (data << 10 | rem) ^ 0x5412; // uint15
+ assert(bits >> 15 == 0);
+
+ // Draw first copy
+ for (int i = 0; i <= 5; i++)
+ setModule(qrcode, 8, i, getBit(bits, i));
+ setModule(qrcode, 8, 7, getBit(bits, 6));
+ setModule(qrcode, 8, 8, getBit(bits, 7));
+ setModule(qrcode, 7, 8, getBit(bits, 8));
+ for (int i = 9; i < 15; i++)
+ setModule(qrcode, 14 - i, 8, getBit(bits, i));
+
+ // Draw second copy
+ int qrsize = qrcodegen_getSize(qrcode);
+ for (int i = 0; i < 8; i++)
+ setModule(qrcode, qrsize - 1 - i, 8, getBit(bits, i));
+ for (int i = 8; i < 15; i++)
+ setModule(qrcode, 8, qrsize - 15 + i, getBit(bits, i));
+ setModule(qrcode, 8, qrsize - 8, true); // Always black
+}
+
+
+// Calculates and stores an ascending list of positions of alignment patterns
+// for this version number, returning the length of the list (in the range [0,7]).
+// Each position is in the range [0,177), and are used on both the x and y axes.
+// This could be implemented as lookup table of 40 variable-length lists of unsigned bytes.
+testable int getAlignmentPatternPositions(int version, uint8_t result[7]) {
+ if (version == 1)
+ return 0;
+ int numAlign = version / 7 + 2;
+ int step = (version == 32) ? 26 :
+ (version*4 + numAlign*2 + 1) / (numAlign*2 - 2) * 2;
+ for (int i = numAlign - 1, pos = version * 4 + 10; i >= 1; i--, pos -= step)
+ result[i] = pos;
+ result[0] = 6;
+ return numAlign;
+}
+
+
+// Sets every pixel in the range [left : left + width] * [top : top + height] to black.
+static void fillRectangle(int left, int top, int width, int height, uint8_t qrcode[]) {
+ for (int dy = 0; dy < height; dy++) {
+ for (int dx = 0; dx < width; dx++)
+ setModule(qrcode, left + dx, top + dy, true);
+ }
+}
+
+
+
+/*---- Drawing data modules and masking ----*/
+
+// Draws the raw codewords (including data and ECC) onto the given QR Code. This requires the initial state of
+// the QR Code to be black at function modules and white at codeword modules (including unused remainder bits).
+static void drawCodewords(const uint8_t data[], int dataLen, uint8_t qrcode[]) {
+ int qrsize = qrcodegen_getSize(qrcode);
+ int i = 0; // Bit index into the data
+ // Do the funny zigzag scan
+ for (int right = qrsize - 1; right >= 1; right -= 2) { // Index of right column in each column pair
+ if (right == 6)
+ right = 5;
+ for (int vert = 0; vert < qrsize; vert++) { // Vertical counter
+ for (int j = 0; j < 2; j++) {
+ int x = right - j; // Actual x coordinate
+ bool upward = ((right + 1) & 2) == 0;
+ int y = upward ? qrsize - 1 - vert : vert; // Actual y coordinate
+ if (!getModule(qrcode, x, y) && i < dataLen * 8) {
+ bool black = getBit(data[i >> 3], 7 - (i & 7));
+ setModule(qrcode, x, y, black);
+ i++;
+ }
+ // If this QR Code has any remainder bits (0 to 7), they were assigned as
+ // 0/false/white by the constructor and are left unchanged by this method
+ }
+ }
+ }
+ assert(i == dataLen * 8);
+}
+
+
+// XORs the codeword modules in this QR Code with the given mask pattern.
+// The function modules must be marked and the codeword bits must be drawn
+// before masking. Due to the arithmetic of XOR, calling applyMask() with
+// the same mask value a second time will undo the mask. A final well-formed
+// QR Code needs exactly one (not zero, two, etc.) mask applied.
+static void applyMask(const uint8_t functionModules[], uint8_t qrcode[], enum qrcodegen_Mask mask) {
+ assert(0 <= (int)mask && (int)mask <= 7); // Disallows qrcodegen_Mask_AUTO
+ int qrsize = qrcodegen_getSize(qrcode);
+ for (int y = 0; y < qrsize; y++) {
+ for (int x = 0; x < qrsize; x++) {
+ if (getModule(functionModules, x, y))
+ continue;
+ bool invert;
+ switch ((int)mask) {
+ case 0: invert = (x + y) % 2 == 0; break;
+ case 1: invert = y % 2 == 0; break;
+ case 2: invert = x % 3 == 0; break;
+ case 3: invert = (x + y) % 3 == 0; break;
+ case 4: invert = (x / 3 + y / 2) % 2 == 0; break;
+ case 5: invert = x * y % 2 + x * y % 3 == 0; break;
+ case 6: invert = (x * y % 2 + x * y % 3) % 2 == 0; break;
+ case 7: invert = ((x + y) % 2 + x * y % 3) % 2 == 0; break;
+ default: assert(false); return;
+ }
+ bool val = getModule(qrcode, x, y);
+ setModule(qrcode, x, y, val ^ invert);
+ }
+ }
+}
+
+
+// Calculates and returns the penalty score based on state of the given QR Code's current modules.
+// This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score.
+static long getPenaltyScore(const uint8_t qrcode[]) {
+ int qrsize = qrcodegen_getSize(qrcode);
+ long result = 0;
+
+ // Adjacent modules in row having same color, and finder-like patterns
+ for (int y = 0; y < qrsize; y++) {
+ unsigned char runHistory[7] = {0};
+ bool color = false;
+ unsigned char runX = 0;
+ for (int x = 0; x < qrsize; x++) {
+ if (getModule(qrcode, x, y) == color) {
+ runX++;
+ if (runX == 5)
+ result += PENALTY_N1;
+ else if (runX > 5)
+ result++;
+ } else {
+ addRunToHistory(runX, runHistory);
+ if (!color && hasFinderLikePattern(runHistory))
+ result += PENALTY_N3;
+ color = getModule(qrcode, x, y);
+ runX = 1;
+ }
+ }
+ addRunToHistory(runX, runHistory);
+ if (color)
+ addRunToHistory(0, runHistory); // Dummy run of white
+ if (hasFinderLikePattern(runHistory))
+ result += PENALTY_N3;
+ }
+ // Adjacent modules in column having same color, and finder-like patterns
+ for (int x = 0; x < qrsize; x++) {
+ unsigned char runHistory[7] = {0};
+ bool color = false;
+ unsigned char runY = 0;
+ for (int y = 0; y < qrsize; y++) {
+ if (getModule(qrcode, x, y) == color) {
+ runY++;
+ if (runY == 5)
+ result += PENALTY_N1;
+ else if (runY > 5)
+ result++;
+ } else {
+ addRunToHistory(runY, runHistory);
+ if (!color && hasFinderLikePattern(runHistory))
+ result += PENALTY_N3;
+ color = getModule(qrcode, x, y);
+ runY = 1;
+ }
+ }
+ addRunToHistory(runY, runHistory);
+ if (color)
+ addRunToHistory(0, runHistory); // Dummy run of white
+ if (hasFinderLikePattern(runHistory))
+ result += PENALTY_N3;
+ }
+
+ // 2*2 blocks of modules having same color
+ for (int y = 0; y < qrsize - 1; y++) {
+ for (int x = 0; x < qrsize - 1; x++) {
+ bool color = getModule(qrcode, x, y);
+ if ( color == getModule(qrcode, x + 1, y) &&
+ color == getModule(qrcode, x, y + 1) &&
+ color == getModule(qrcode, x + 1, y + 1))
+ result += PENALTY_N2;
+ }
+ }
+
+ // Balance of black and white modules
+ int black = 0;
+ for (int y = 0; y < qrsize; y++) {
+ for (int x = 0; x < qrsize; x++) {
+ if (getModule(qrcode, x, y))
+ black++;
+ }
+ }
+ int total = qrsize * qrsize; // Note that size is odd, so black/total != 1/2
+ // Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)%
+ int k = (int)((labs(black * 20L - total * 10L) + total - 1) / total) - 1;
+ result += k * PENALTY_N4;
+ return result;
+}
+
+
+// Inserts the given value to the front of the given array, which shifts over the
+// existing values and deletes the last value. A helper function for getPenaltyScore().
+static void addRunToHistory(unsigned char run, unsigned char history[7]) {
+ memmove(&history[1], &history[0], 6 * sizeof(history[0]));
+ history[0] = run;
+}
+
+
+// Tests whether the given run history has the pattern of ratio 1:1:3:1:1 in the middle, and
+// surrounded by at least 4 on either or both ends. A helper function for getPenaltyScore().
+// Must only be called immediately after a run of white modules has ended.
+static bool hasFinderLikePattern(unsigned char runHistory[7]) {
+ unsigned char n = runHistory[1];
+ // The maximum QR Code size is 177, hence the run length n <= 177.
+ // Arithmetic is promoted to int, so n*4 will not overflow.
+ return n > 0 && runHistory[2] == n && runHistory[4] == n && runHistory[5] == n
+ && runHistory[3] == n * 3 && (runHistory[0] >= n * 4 || runHistory[6] >= n * 4);
+}
+
+
+
+/*---- Basic QR Code information ----*/
+
+// Public function - see documentation comment in header file.
+int qrcodegen_getSize(const uint8_t qrcode[]) {
+ assert(qrcode != NULL);
+ int result = qrcode[0];
+ assert((qrcodegen_VERSION_MIN * 4 + 17) <= result
+ && result <= (qrcodegen_VERSION_MAX * 4 + 17));
+ return result;
+}
+
+
+// Public function - see documentation comment in header file.
+bool qrcodegen_getModule(const uint8_t qrcode[], int x, int y) {
+ assert(qrcode != NULL);
+ int qrsize = qrcode[0];
+ return (0 <= x && x < qrsize && 0 <= y && y < qrsize) && getModule(qrcode, x, y);
+}
+
+
+// Gets the module at the given coordinates, which must be in bounds.
+testable bool getModule(const uint8_t qrcode[], int x, int y) {
+ int qrsize = qrcode[0];
+ assert(21 <= qrsize && qrsize <= 177 && 0 <= x && x < qrsize && 0 <= y && y < qrsize);
+ int index = y * qrsize + x;
+ return getBit(qrcode[(index >> 3) + 1], index & 7);
+}
+
+
+// Sets the module at the given coordinates, which must be in bounds.
+testable void setModule(uint8_t qrcode[], int x, int y, bool isBlack) {
+ int qrsize = qrcode[0];
+ assert(21 <= qrsize && qrsize <= 177 && 0 <= x && x < qrsize && 0 <= y && y < qrsize);
+ int index = y * qrsize + x;
+ int bitIndex = index & 7;
+ int byteIndex = (index >> 3) + 1;
+ if (isBlack)
+ qrcode[byteIndex] |= 1 << bitIndex;
+ else
+ qrcode[byteIndex] &= (1 << bitIndex) ^ 0xFF;
+}
+
+
+// Sets the module at the given coordinates, doing nothing if out of bounds.
+testable void setModuleBounded(uint8_t qrcode[], int x, int y, bool isBlack) {
+ int qrsize = qrcode[0];
+ if (0 <= x && x < qrsize && 0 <= y && y < qrsize)
+ setModule(qrcode, x, y, isBlack);
+}
+
+
+// Returns true iff the i'th bit of x is set to 1. Requires x >= 0 and 0 <= i <= 14.
+static bool getBit(int x, int i) {
+ return ((x >> i) & 1) != 0;
+}
+
+
+
+/*---- Segment handling ----*/
+
+// Public function - see documentation comment in header file.
+bool qrcodegen_isAlphanumeric(const char *text) {
+ assert(text != NULL);
+ for (; *text != '\0'; text++) {
+ if (strchr(ALPHANUMERIC_CHARSET, *text) == NULL)
+ return false;
+ }
+ return true;
+}
+
+
+// Public function - see documentation comment in header file.
+bool qrcodegen_isNumeric(const char *text) {
+ assert(text != NULL);
+ for (; *text != '\0'; text++) {
+ if (*text < '0' || *text > '9')
+ return false;
+ }
+ return true;
+}
+
+
+// Public function - see documentation comment in header file.
+size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars) {
+ int temp = calcSegmentBitLength(mode, numChars);
+ if (temp == -1)
+ return SIZE_MAX;
+ assert(0 <= temp && temp <= INT16_MAX);
+ return ((size_t)temp + 7) / 8;
+}
+
+
+// Returns the number of data bits needed to represent a segment
+// containing the given number of characters using the given mode. Notes:
+// - Returns -1 on failure, i.e. numChars > INT16_MAX or
+// the number of needed bits exceeds INT16_MAX (i.e. 32767).
+// - Otherwise, all valid results are in the range [0, INT16_MAX].
+// - For byte mode, numChars measures the number of bytes, not Unicode code points.
+// - For ECI mode, numChars must be 0, and the worst-case number of bits is returned.
+// An actual ECI segment can have shorter data. For non-ECI modes, the result is exact.
+testable int calcSegmentBitLength(enum qrcodegen_Mode mode, size_t numChars) {
+ // All calculations are designed to avoid overflow on all platforms
+ if (numChars > (unsigned int)INT16_MAX)
+ return -1;
+ long result = (long)numChars;
+ if (mode == qrcodegen_Mode_NUMERIC)
+ result = (result * 10 + 2) / 3; // ceil(10/3 * n)
+ else if (mode == qrcodegen_Mode_ALPHANUMERIC)
+ result = (result * 11 + 1) / 2; // ceil(11/2 * n)
+ else if (mode == qrcodegen_Mode_BYTE)
+ result *= 8;
+ else if (mode == qrcodegen_Mode_KANJI)
+ result *= 13;
+ else if (mode == qrcodegen_Mode_ECI && numChars == 0)
+ result = 3 * 8;
+ else { // Invalid argument
+ assert(false);
+ return -1;
+ }
+ assert(result >= 0);
+ if (result > (unsigned int)INT16_MAX)
+ return -1;
+ return (int)result;
+}
+
+
+// Public function - see documentation comment in header file.
+struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]) {
+ assert(data != NULL || len == 0);
+ struct qrcodegen_Segment result;
+ result.mode = qrcodegen_Mode_BYTE;
+ result.bitLength = calcSegmentBitLength(result.mode, len);
+ assert(result.bitLength != -1);
+ result.numChars = (int)len;
+ if (len > 0)
+ memcpy(buf, data, len * sizeof(buf[0]));
+ result.data = buf;
+ return result;
+}
+
+
+// Public function - see documentation comment in header file.
+struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]) {
+ assert(digits != NULL);
+ struct qrcodegen_Segment result;
+ size_t len = strlen(digits);
+ result.mode = qrcodegen_Mode_NUMERIC;
+ int bitLen = calcSegmentBitLength(result.mode, len);
+ assert(bitLen != -1);
+ result.numChars = (int)len;
+ if (bitLen > 0)
+ memset(buf, 0, ((size_t)bitLen + 7) / 8 * sizeof(buf[0]));
+ result.bitLength = 0;
+
+ unsigned int accumData = 0;
+ int accumCount = 0;
+ for (; *digits != '\0'; digits++) {
+ char c = *digits;
+ assert('0' <= c && c <= '9');
+ accumData = accumData * 10 + (unsigned int)(c - '0');
+ accumCount++;
+ if (accumCount == 3) {
+ appendBitsToBuffer(accumData, 10, buf, &result.bitLength);
+ accumData = 0;
+ accumCount = 0;
+ }
+ }
+ if (accumCount > 0) // 1 or 2 digits remaining
+ appendBitsToBuffer(accumData, accumCount * 3 + 1, buf, &result.bitLength);
+ assert(result.bitLength == bitLen);
+ result.data = buf;
+ return result;
+}
+
+
+// Public function - see documentation comment in header file.
+struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char *text, uint8_t buf[]) {
+ assert(text != NULL);
+ struct qrcodegen_Segment result;
+ size_t len = strlen(text);
+ result.mode = qrcodegen_Mode_ALPHANUMERIC;
+ int bitLen = calcSegmentBitLength(result.mode, len);
+ assert(bitLen != -1);
+ result.numChars = (int)len;
+ if (bitLen > 0)
+ memset(buf, 0, ((size_t)bitLen + 7) / 8 * sizeof(buf[0]));
+ result.bitLength = 0;
+
+ unsigned int accumData = 0;
+ int accumCount = 0;
+ for (; *text != '\0'; text++) {
+ const char *temp = strchr(ALPHANUMERIC_CHARSET, *text);
+ assert(temp != NULL);
+ accumData = accumData * 45 + (unsigned int)(temp - ALPHANUMERIC_CHARSET);
+ accumCount++;
+ if (accumCount == 2) {
+ appendBitsToBuffer(accumData, 11, buf, &result.bitLength);
+ accumData = 0;
+ accumCount = 0;
+ }
+ }
+ if (accumCount > 0) // 1 character remaining
+ appendBitsToBuffer(accumData, 6, buf, &result.bitLength);
+ assert(result.bitLength == bitLen);
+ result.data = buf;
+ return result;
+}
+
+
+// Public function - see documentation comment in header file.
+struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]) {
+ struct qrcodegen_Segment result;
+ result.mode = qrcodegen_Mode_ECI;
+ result.numChars = 0;
+ result.bitLength = 0;
+ if (assignVal < 0)
+ assert(false);
+ else if (assignVal < (1 << 7)) {
+ memset(buf, 0, 1 * sizeof(buf[0]));
+ appendBitsToBuffer(assignVal, 8, buf, &result.bitLength);
+ } else if (assignVal < (1 << 14)) {
+ memset(buf, 0, 2 * sizeof(buf[0]));
+ appendBitsToBuffer(2, 2, buf, &result.bitLength);
+ appendBitsToBuffer(assignVal, 14, buf, &result.bitLength);
+ } else if (assignVal < 1000000L) {
+ memset(buf, 0, 3 * sizeof(buf[0]));
+ appendBitsToBuffer(6, 3, buf, &result.bitLength);
+ appendBitsToBuffer(assignVal >> 10, 11, buf, &result.bitLength);
+ appendBitsToBuffer(assignVal & 0x3FF, 10, buf, &result.bitLength);
+ } else
+ assert(false);
+ result.data = buf;
+ return result;
+}
+
+
+// Calculates the number of bits needed to encode the given segments at the given version.
+// Returns a non-negative number if successful. Otherwise returns -1 if a segment has too
+// many characters to fit its length field, or the total bits exceeds INT16_MAX.
+testable int getTotalBits(const struct qrcodegen_Segment segs[], size_t len, int version) {
+ assert(segs != NULL || len == 0);
+ long result = 0;
+ for (size_t i = 0; i < len; i++) {
+ int numChars = segs[i].numChars;
+ int bitLength = segs[i].bitLength;
+ assert(0 <= numChars && numChars <= INT16_MAX);
+ assert(0 <= bitLength && bitLength <= INT16_MAX);
+ int ccbits = numCharCountBits(segs[i].mode, version);
+ assert(0 <= ccbits && ccbits <= 16);
+ if (numChars >= (1L << ccbits))
+ return -1; // The segment's length doesn't fit the field's bit width
+ result += 4L + ccbits + bitLength;
+ if (result > INT16_MAX)
+ return -1; // The sum might overflow an int type
+ }
+ assert(0 <= result && result <= INT16_MAX);
+ return (int)result;
+}
+
+
+// Returns the bit width of the character count field for a segment in the given mode
+// in a QR Code at the given version number. The result is in the range [0, 16].
+static int numCharCountBits(enum qrcodegen_Mode mode, int version) {
+ assert(qrcodegen_VERSION_MIN <= version && version <= qrcodegen_VERSION_MAX);
+ int i = (version + 7) / 17;
+ switch (mode) {
+ case qrcodegen_Mode_NUMERIC : { static const int temp[] = {10, 12, 14}; return temp[i]; }
+ case qrcodegen_Mode_ALPHANUMERIC: { static const int temp[] = { 9, 11, 13}; return temp[i]; }
+ case qrcodegen_Mode_BYTE : { static const int temp[] = { 8, 16, 16}; return temp[i]; }
+ case qrcodegen_Mode_KANJI : { static const int temp[] = { 8, 10, 12}; return temp[i]; }
+ case qrcodegen_Mode_ECI : return 0;
+ default: assert(false); return -1; // Dummy value
+ }
+}
diff --git a/panels/network/qrcodegen.h b/panels/network/qrcodegen.h
new file mode 100644
index 0000000..55e2bfe
--- /dev/null
+++ b/panels/network/qrcodegen.h
@@ -0,0 +1,311 @@
+/*
+ * QR Code generator library (C)
+ *
+ * Copyright (c) Project Nayuki. (MIT License)
+ * https://www.nayuki.io/page/qr-code-generator-library
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ * - The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * - The Software is provided "as is", without warranty of any kind, express or
+ * implied, including but not limited to the warranties of merchantability,
+ * fitness for a particular purpose and noninfringement. In no event shall the
+ * authors or copyright holders be liable for any claim, damages or other
+ * liability, whether in an action of contract, tort or otherwise, arising from,
+ * out of or in connection with the Software or the use or other dealings in the
+ * Software.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*
+ * This library creates QR Code symbols, which is a type of two-dimension barcode.
+ * Invented by Denso Wave and described in the ISO/IEC 18004 standard.
+ * A QR Code structure is an immutable square grid of black and white cells.
+ * The library provides functions to create a QR Code from text or binary data.
+ * The library covers the QR Code Model 2 specification, supporting all versions (sizes)
+ * from 1 to 40, all 4 error correction levels, and 4 character encoding modes.
+ *
+ * Ways to create a QR Code object:
+ * - High level: Take the payload data and call qrcodegen_encodeText() or qrcodegen_encodeBinary().
+ * - Low level: Custom-make the list of segments and call
+ * qrcodegen_encodeSegments() or qrcodegen_encodeSegmentsAdvanced().
+ * (Note that all ways require supplying the desired error correction level and various byte buffers.)
+ */
+
+
+/*---- Enum and struct types----*/
+
+/*
+ * The error correction level in a QR Code symbol.
+ */
+enum qrcodegen_Ecc {
+ // Must be declared in ascending order of error protection
+ // so that an internal qrcodegen function works properly
+ qrcodegen_Ecc_LOW = 0 , // The QR Code can tolerate about 7% erroneous codewords
+ qrcodegen_Ecc_MEDIUM , // The QR Code can tolerate about 15% erroneous codewords
+ qrcodegen_Ecc_QUARTILE, // The QR Code can tolerate about 25% erroneous codewords
+ qrcodegen_Ecc_HIGH , // The QR Code can tolerate about 30% erroneous codewords
+};
+
+
+/*
+ * The mask pattern used in a QR Code symbol.
+ */
+enum qrcodegen_Mask {
+ // A special value to tell the QR Code encoder to
+ // automatically select an appropriate mask pattern
+ qrcodegen_Mask_AUTO = -1,
+ // The eight actual mask patterns
+ qrcodegen_Mask_0 = 0,
+ qrcodegen_Mask_1,
+ qrcodegen_Mask_2,
+ qrcodegen_Mask_3,
+ qrcodegen_Mask_4,
+ qrcodegen_Mask_5,
+ qrcodegen_Mask_6,
+ qrcodegen_Mask_7,
+};
+
+
+/*
+ * Describes how a segment's data bits are interpreted.
+ */
+enum qrcodegen_Mode {
+ qrcodegen_Mode_NUMERIC = 0x1,
+ qrcodegen_Mode_ALPHANUMERIC = 0x2,
+ qrcodegen_Mode_BYTE = 0x4,
+ qrcodegen_Mode_KANJI = 0x8,
+ qrcodegen_Mode_ECI = 0x7,
+};
+
+
+/*
+ * A segment of character/binary/control data in a QR Code symbol.
+ * The mid-level way to create a segment is to take the payload data
+ * and call a factory function such as qrcodegen_makeNumeric().
+ * The low-level way to create a segment is to custom-make the bit buffer
+ * and initialize a qrcodegen_Segment struct with appropriate values.
+ * Even in the most favorable conditions, a QR Code can only hold 7089 characters of data.
+ * Any segment longer than this is meaningless for the purpose of generating QR Codes.
+ * Moreover, the maximum allowed bit length is 32767 because
+ * the largest QR Code (version 40) has 31329 modules.
+ */
+struct qrcodegen_Segment {
+ // The mode indicator of this segment.
+ enum qrcodegen_Mode mode;
+
+ // The length of this segment's unencoded data. Measured in characters for
+ // numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode.
+ // Always zero or positive. Not the same as the data's bit length.
+ int numChars;
+
+ // The data bits of this segment, packed in bitwise big endian.
+ // Can be null if the bit length is zero.
+ uint8_t *data;
+
+ // The number of valid data bits used in the buffer. Requires
+ // 0 <= bitLength <= 32767, and bitLength <= (capacity of data array) * 8.
+ // The character count (numChars) must agree with the mode and the bit buffer length.
+ int bitLength;
+};
+
+
+
+/*---- Macro constants and functions ----*/
+
+#define qrcodegen_VERSION_MIN 1 // The minimum version number supported in the QR Code Model 2 standard
+#define qrcodegen_VERSION_MAX 40 // The maximum version number supported in the QR Code Model 2 standard
+
+// Calculates the number of bytes needed to store any QR Code up to and including the given version number,
+// as a compile-time constant. For example, 'uint8_t buffer[qrcodegen_BUFFER_LEN_FOR_VERSION(25)];'
+// can store any single QR Code from version 1 to 25 (inclusive). The result fits in an int (or int16).
+// Requires qrcodegen_VERSION_MIN <= n <= qrcodegen_VERSION_MAX.
+#define qrcodegen_BUFFER_LEN_FOR_VERSION(n) ((((n) * 4 + 17) * ((n) * 4 + 17) + 7) / 8 + 1)
+
+// The worst-case number of bytes needed to store one QR Code, up to and including
+// version 40. This value equals 3918, which is just under 4 kilobytes.
+// Use this more convenient value to avoid calculating tighter memory bounds for buffers.
+#define qrcodegen_BUFFER_LEN_MAX qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX)
+
+
+
+/*---- Functions (high level) to generate QR Codes ----*/
+
+/*
+ * Encodes the given text string to a QR Code, returning true if encoding succeeded.
+ * If the data is too long to fit in any version in the given range
+ * at the given ECC level, then false is returned.
+ * - The input text must be encoded in UTF-8 and contain no NULs.
+ * - The variables ecl and mask must correspond to enum constant values.
+ * - Requires 1 <= minVersion <= maxVersion <= 40.
+ * - The arrays tempBuffer and qrcode must each have a length
+ * of at least qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion).
+ * - After the function returns, tempBuffer contains no useful data.
+ * - If successful, the resulting QR Code may use numeric,
+ * alphanumeric, or byte mode to encode the text.
+ * - In the most optimistic case, a QR Code at version 40 with low ECC
+ * can hold any UTF-8 string up to 2953 bytes, or any alphanumeric string
+ * up to 4296 characters, or any digit string up to 7089 characters.
+ * These numbers represent the hard upper limit of the QR Code standard.
+ * - Please consult the QR Code specification for information on
+ * data capacities per version, ECC level, and text encoding mode.
+ */
+bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[],
+ enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl);
+
+
+/*
+ * Encodes the given binary data to a QR Code, returning true if encoding succeeded.
+ * If the data is too long to fit in any version in the given range
+ * at the given ECC level, then false is returned.
+ * - The input array range dataAndTemp[0 : dataLen] should normally be
+ * valid UTF-8 text, but is not required by the QR Code standard.
+ * - The variables ecl and mask must correspond to enum constant values.
+ * - Requires 1 <= minVersion <= maxVersion <= 40.
+ * - The arrays dataAndTemp and qrcode must each have a length
+ * of at least qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion).
+ * - After the function returns, the contents of dataAndTemp may have changed,
+ * and does not represent useful data anymore.
+ * - If successful, the resulting QR Code will use byte mode to encode the data.
+ * - In the most optimistic case, a QR Code at version 40 with low ECC can hold any byte
+ * sequence up to length 2953. This is the hard upper limit of the QR Code standard.
+ * - Please consult the QR Code specification for information on
+ * data capacities per version, ECC level, and text encoding mode.
+ */
+bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[],
+ enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl);
+
+
+/*---- Functions (low level) to generate QR Codes ----*/
+
+/*
+ * Renders a QR Code representing the given segments at the given error correction level.
+ * The smallest possible QR Code version is automatically chosen for the output. Returns true if
+ * QR Code creation succeeded, or false if the data is too long to fit in any version. The ECC level
+ * of the result may be higher than the ecl argument if it can be done without increasing the version.
+ * This function allows the user to create a custom sequence of segments that switches
+ * between modes (such as alphanumeric and byte) to encode text in less space.
+ * This is a low-level API; the high-level API is qrcodegen_encodeText() and qrcodegen_encodeBinary().
+ * To save memory, the segments' data buffers can alias/overlap tempBuffer, and will
+ * result in them being clobbered, but the QR Code output will still be correct.
+ * But the qrcode array must not overlap tempBuffer or any segment's data buffer.
+ */
+bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len,
+ enum qrcodegen_Ecc ecl, uint8_t tempBuffer[], uint8_t qrcode[]);
+
+
+/*
+ * Renders a QR Code representing the given segments with the given encoding parameters.
+ * Returns true if QR Code creation succeeded, or false if the data is too long to fit in the range of versions.
+ * The smallest possible QR Code version within the given range is automatically
+ * chosen for the output. Iff boostEcl is true, then the ECC level of the result
+ * may be higher than the ecl argument if it can be done without increasing the
+ * version. The mask number is either between 0 to 7 (inclusive) to force that
+ * mask, or -1 to automatically choose an appropriate mask (which may be slow).
+ * This function allows the user to create a custom sequence of segments that switches
+ * between modes (such as alphanumeric and byte) to encode text in less space.
+ * This is a low-level API; the high-level API is qrcodegen_encodeText() and qrcodegen_encodeBinary().
+ * To save memory, the segments' data buffers can alias/overlap tempBuffer, and will
+ * result in them being clobbered, but the QR Code output will still be correct.
+ * But the qrcode array must not overlap tempBuffer or any segment's data buffer.
+ */
+bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], size_t len, enum qrcodegen_Ecc ecl,
+ int minVersion, int maxVersion, int mask, bool boostEcl, uint8_t tempBuffer[], uint8_t qrcode[]);
+
+
+/*
+ * Tests whether the given string can be encoded as a segment in alphanumeric mode.
+ * A string is encodable iff each character is in the following set: 0 to 9, A to Z
+ * (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon.
+ */
+bool qrcodegen_isAlphanumeric(const char *text);
+
+
+/*
+ * Tests whether the given string can be encoded as a segment in numeric mode.
+ * A string is encodable iff each character is in the range 0 to 9.
+ */
+bool qrcodegen_isNumeric(const char *text);
+
+
+/*
+ * Returns the number of bytes (uint8_t) needed for the data buffer of a segment
+ * containing the given number of characters using the given mode. Notes:
+ * - Returns SIZE_MAX on failure, i.e. numChars > INT16_MAX or
+ * the number of needed bits exceeds INT16_MAX (i.e. 32767).
+ * - Otherwise, all valid results are in the range [0, ceil(INT16_MAX / 8)], i.e. at most 4096.
+ * - It is okay for the user to allocate more bytes for the buffer than needed.
+ * - For byte mode, numChars measures the number of bytes, not Unicode code points.
+ * - For ECI mode, numChars must be 0, and the worst-case number of bytes is returned.
+ * An actual ECI segment can have shorter data. For non-ECI modes, the result is exact.
+ */
+size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars);
+
+
+/*
+ * Returns a segment representing the given binary data encoded in
+ * byte mode. All input byte arrays are acceptable. Any text string
+ * can be converted to UTF-8 bytes and encoded as a byte mode segment.
+ */
+struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]);
+
+
+/*
+ * Returns a segment representing the given string of decimal digits encoded in numeric mode.
+ */
+struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]);
+
+
+/*
+ * Returns a segment representing the given text string encoded in alphanumeric mode.
+ * The characters allowed are: 0 to 9, A to Z (uppercase only), space,
+ * dollar, percent, asterisk, plus, hyphen, period, slash, colon.
+ */
+struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char *text, uint8_t buf[]);
+
+
+/*
+ * Returns a segment representing an Extended Channel Interpretation
+ * (ECI) designator with the given assignment value.
+ */
+struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]);
+
+
+/*---- Functions to extract raw data from QR Codes ----*/
+
+/*
+ * Returns the side length of the given QR Code, assuming that encoding succeeded.
+ * The result is in the range [21, 177]. Note that the length of the array buffer
+ * is related to the side length - every 'uint8_t qrcode[]' must have length at least
+ * qrcodegen_BUFFER_LEN_FOR_VERSION(version), which equals ceil(size^2 / 8 + 1).
+ */
+int qrcodegen_getSize(const uint8_t qrcode[]);
+
+
+/*
+ * Returns the color of the module (pixel) at the given coordinates, which is false
+ * for white or true for black. The top left corner has the coordinates (x=0, y=0).
+ * If the given coordinates are out of bounds, then false (white) is returned.
+ */
+bool qrcodegen_getModule(const uint8_t qrcode[], int x, int y);
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/panels/network/ui-helpers.c b/panels/network/ui-helpers.c
new file mode 100644
index 0000000..c90ed09
--- /dev/null
+++ b/panels/network/ui-helpers.c
@@ -0,0 +1,38 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2014 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include "ui-helpers.h"
+
+void
+widget_set_error (GtkWidget *widget)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gtk_style_context_add_class (gtk_widget_get_style_context (widget), "error");
+}
+
+void
+widget_unset_error (GtkWidget *widget)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gtk_style_context_remove_class (gtk_widget_get_style_context (widget), "error");
+}
diff --git a/panels/network/ui-helpers.h b/panels/network/ui-helpers.h
new file mode 100644
index 0000000..c9754a4
--- /dev/null
+++ b/panels/network/ui-helpers.h
@@ -0,0 +1,27 @@
+/*
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2014 Red Hat, Inc.
+ */
+
+#ifndef _UI_HELPERS_H_
+#define _UI_HELPERS_H_
+
+#include <gtk/gtk.h>
+
+void widget_set_error (GtkWidget *widget);
+void widget_unset_error (GtkWidget *widget);
+
+#endif /* _UI_HELPERS_H_ */
diff --git a/panels/network/warning-small-symbolic.svg b/panels/network/warning-small-symbolic.svg
new file mode 100644
index 0000000..b4f7d35
--- /dev/null
+++ b/panels/network/warning-small-symbolic.svg
@@ -0,0 +1 @@
+<svg width="10" height="10" xmlns="http://www.w3.org/2000/svg"><path d="M5.014 0a1 1 0 0 0-.909.553l-4 8A1 1 0 0 0 1 10h8a1 1 0 0 0 .895-1.447l-4-8A1 1 0 0 0 5.014 0ZM4 3h2v2.5s0 .5-.5.5h-1C4 6 4 5.5 4 5.5Zm.5 4h1c.277 0 .5.223.5.5v1c0 .277-.223.5-.5.5h-1a.499.499 0 0 1-.5-.5v-1c0-.277.223-.5.5-.5Z" style="fill:#ff7800"/></svg>
diff --git a/panels/network/wifi-panel.css b/panels/network/wifi-panel.css
new file mode 100644
index 0000000..de7d80c
--- /dev/null
+++ b/panels/network/wifi-panel.css
@@ -0,0 +1,5 @@
+.qr-image {
+ background: #fff;
+ padding: 12px;
+}
+
diff --git a/panels/network/wireless-security/eap-method-fast.c b/panels/network/wireless-security/eap-method-fast.c
new file mode 100644
index 0000000..c0f4ad0
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-fast.c
@@ -0,0 +1,399 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* vim: set ft=c ts=4 sts=4 sw=4 noexpandtab smartindent: */
+
+/* EAP-FAST authentication method (RFC4851)
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2012 - 2014 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+
+#include "eap-method.h"
+#include "eap-method-fast.h"
+#include "eap-method-simple.h"
+#include "helpers.h"
+#include "ui-helpers.h"
+#include "ws-file-chooser-button.h"
+
+#define I_NAME_COLUMN 0
+#define I_ID_COLUMN 1
+
+struct _EAPMethodFAST {
+ GtkGrid parent;
+
+ GtkEntry *anon_identity_entry;
+ GtkLabel *anon_identity_label;
+ GtkComboBox *inner_auth_combo;
+ GtkLabel *inner_auth_label;
+ GtkListStore *inner_auth_model;
+ GtkBox *inner_auth_box;
+ WsFileChooserButton *pac_file_button;
+ GtkLabel *pac_file_label;
+ GtkCheckButton *pac_provision_check;
+ GtkComboBox *pac_provision_combo;
+
+ EAPMethodSimple *em_gtc;
+ EAPMethodSimple *em_mschap_v2;
+};
+
+static void eap_method_iface_init (EAPMethodInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (EAPMethodFAST, eap_method_fast, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (eap_method_get_type (), eap_method_iface_init))
+
+static EAPMethod *
+get_inner_method (EAPMethodFAST *self)
+{
+ GtkTreeIter iter;
+ g_autofree gchar *id = NULL;
+
+ if (!gtk_combo_box_get_active_iter (self->inner_auth_combo, &iter))
+ return NULL;
+ gtk_tree_model_get (GTK_TREE_MODEL (self->inner_auth_model), &iter, I_ID_COLUMN, &id, -1);
+
+ if (strcmp (id, "gtc") == 0)
+ return EAP_METHOD (self->em_gtc);
+ if (strcmp (id, "mschapv2") == 0)
+ return EAP_METHOD (self->em_mschap_v2);
+
+ return NULL;
+}
+
+static gboolean
+validate (EAPMethod *parent, GError **error)
+{
+ EAPMethodFAST *self = (EAPMethodFAST *) parent;
+ g_autoptr(GFile) file = NULL;
+ gboolean provisioning;
+ gboolean valid = TRUE;
+
+ provisioning = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->pac_provision_check));
+ file = ws_file_chooser_button_get_file (self->pac_file_button);
+ if (!provisioning && !file) {
+ widget_set_error (GTK_WIDGET (self->pac_file_button));
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing EAP-FAST PAC file"));
+ valid = FALSE;
+ } else
+ widget_unset_error (GTK_WIDGET (self->pac_file_button));
+
+ return eap_method_validate (get_inner_method (self), valid ? error : NULL) && valid;
+}
+
+static void
+add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
+{
+ EAPMethodFAST *self = (EAPMethodFAST *) parent;
+
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->anon_identity_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->pac_file_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->pac_provision_check));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->inner_auth_label));
+
+ eap_method_add_to_size_group (EAP_METHOD (self->em_gtc), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_mschap_v2), group);
+}
+
+static void
+fill_connection (EAPMethod *parent, NMConnection *connection, NMSettingSecretFlags flags)
+{
+ EAPMethodFAST *self = (EAPMethodFAST *) parent;
+ g_autofree gchar *filename = NULL;
+ g_autoptr(GFile) file = NULL;
+ NMSetting8021x *s_8021x;
+ const char *text;
+ gboolean enabled;
+ int pac_provisioning = 0;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ g_assert (s_8021x);
+
+ nm_setting_802_1x_add_eap_method (s_8021x, "fast");
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self->anon_identity_entry));
+ if (text && strlen (text))
+ g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, text, NULL);
+
+ file = ws_file_chooser_button_get_file (self->pac_file_button);
+ filename = file ? g_file_get_path (file) : NULL;
+ g_object_set (s_8021x, NM_SETTING_802_1X_PAC_FILE, filename, NULL);
+
+ enabled = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->pac_provision_check));
+
+ if (!enabled)
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "0", NULL);
+ else {
+ pac_provisioning = gtk_combo_box_get_active (self->pac_provision_combo);
+
+ switch (pac_provisioning) {
+ case 0: /* Anonymous */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "1", NULL);
+ break;
+ case 1: /* Authenticated */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "2", NULL);
+ break;
+ case 2: /* Both - anonymous and authenticated */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "3", NULL);
+ break;
+ default: /* Should not happen */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "1", NULL);
+ break;
+ }
+ }
+
+ eap_method_fill_connection (get_inner_method (self), connection, flags);
+}
+
+static void
+inner_auth_combo_changed_cb (EAPMethodFAST *self)
+{
+ EAPMethod *inner_method;
+ GtkWidget *child;
+
+ inner_method = get_inner_method (self);
+
+ /* Remove the previous method and migrate username/password across */
+ child = gtk_widget_get_first_child (GTK_WIDGET (self->inner_auth_box));
+ if (child != NULL) {
+ EAPMethod *old_eap = EAP_METHOD (child);
+ eap_method_set_username (inner_method, eap_method_get_username (old_eap));
+ eap_method_set_password (inner_method, eap_method_get_password (old_eap));
+ eap_method_set_show_password (inner_method, eap_method_get_show_password (old_eap));
+ gtk_box_remove (self->inner_auth_box, child);
+ }
+
+ gtk_box_append (self->inner_auth_box, g_object_ref (GTK_WIDGET (inner_method)));
+
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+update_secrets (EAPMethod *parent, NMConnection *connection)
+{
+ EAPMethodFAST *self = (EAPMethodFAST *) parent;
+
+ eap_method_update_secrets (EAP_METHOD (self->em_gtc), connection);
+ eap_method_update_secrets (EAP_METHOD (self->em_mschap_v2), connection);
+}
+
+static GtkWidget *
+get_default_field (EAPMethod *parent)
+{
+ EAPMethodFAST *self = (EAPMethodFAST *) parent;
+ return GTK_WIDGET (self->anon_identity_entry);
+}
+
+static const gchar *
+get_password_flags_name (EAPMethod *parent)
+{
+ return NM_SETTING_802_1X_PASSWORD;
+}
+
+static const gchar *
+get_username (EAPMethod *method)
+{
+ EAPMethodFAST *self = EAP_METHOD_FAST (method);
+ return eap_method_get_username (get_inner_method (self));
+}
+
+static void
+set_username (EAPMethod *method, const gchar *username)
+{
+ EAPMethodFAST *self = EAP_METHOD_FAST (method);
+ return eap_method_set_username (get_inner_method (self), username);
+}
+
+static const gchar *
+get_password (EAPMethod *method)
+{
+ EAPMethodFAST *self = EAP_METHOD_FAST (method);
+ return eap_method_get_password (get_inner_method (self));
+}
+
+static void
+set_password (EAPMethod *method, const gchar *password)
+{
+ EAPMethodFAST *self = EAP_METHOD_FAST (method);
+ return eap_method_set_password (get_inner_method (self), password);
+}
+
+static gboolean
+get_show_password (EAPMethod *method)
+{
+ EAPMethodFAST *self = EAP_METHOD_FAST (method);
+ return eap_method_get_show_password (get_inner_method (self));
+}
+
+static void
+set_show_password (EAPMethod *method, gboolean show_password)
+{
+ EAPMethodFAST *self = EAP_METHOD_FAST (method);
+ return eap_method_set_show_password (get_inner_method (self), show_password);
+}
+
+static void
+pac_toggled_cb (EAPMethodFAST *self)
+{
+ gboolean enabled = FALSE;
+
+ enabled = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->pac_provision_check));
+ gtk_widget_set_sensitive (GTK_WIDGET (self->pac_provision_combo), enabled);
+
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+changed_cb (EAPMethodFAST *self)
+{
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+eap_method_fast_init (EAPMethodFAST *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+eap_method_fast_class_init (EAPMethodFASTClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ g_type_ensure (WS_TYPE_FILE_CHOOSER_BUTTON);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/network/eap-method-fast.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodFAST, anon_identity_entry);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodFAST, anon_identity_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodFAST, inner_auth_combo);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodFAST, inner_auth_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodFAST, inner_auth_model);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodFAST, inner_auth_box);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodFAST, pac_file_button);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodFAST, pac_file_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodFAST, pac_provision_check);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodFAST, pac_provision_combo);
+}
+
+static void
+eap_method_iface_init (EAPMethodInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->update_secrets = update_secrets;
+ iface->get_default_field = get_default_field;
+ iface->get_password_flags_name = get_password_flags_name;
+ iface->get_username = get_username;
+ iface->set_username = set_username;
+ iface->get_password = get_password;
+ iface->set_password = set_password;
+ iface->get_show_password = get_show_password;
+ iface->set_show_password = set_show_password;
+}
+
+EAPMethodFAST *
+eap_method_fast_new (NMConnection *connection)
+{
+ EAPMethodFAST *self;
+ GtkFileFilter *filter;
+ NMSetting8021x *s_8021x = NULL;
+ gboolean provisioning_enabled = TRUE;
+ const gchar *phase2_auth = NULL;
+ GtkTreeIter iter;
+
+ self = g_object_new (eap_method_fast_get_type (), NULL);
+
+ if (connection)
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+
+ gtk_combo_box_set_active (self->pac_provision_combo, 0);
+ if (s_8021x) {
+ const char *fast_prov;
+
+ fast_prov = nm_setting_802_1x_get_phase1_fast_provisioning (s_8021x);
+ if (fast_prov) {
+ if (!strcmp (fast_prov, "0"))
+ provisioning_enabled = FALSE;
+ else if (!strcmp (fast_prov, "1"))
+ gtk_combo_box_set_active (self->pac_provision_combo, 0);
+ else if (!strcmp (fast_prov, "2"))
+ gtk_combo_box_set_active (self->pac_provision_combo, 1);
+ else if (!strcmp (fast_prov, "3"))
+ gtk_combo_box_set_active (self->pac_provision_combo, 2);
+ }
+ }
+ gtk_widget_set_sensitive (GTK_WIDGET (self->pac_provision_combo), provisioning_enabled);
+ g_signal_connect_swapped (self->pac_provision_combo, "changed", G_CALLBACK (changed_cb), self);
+
+ gtk_check_button_set_active (self->pac_provision_check, provisioning_enabled);
+ g_signal_connect_swapped (self->pac_provision_check, "toggled", G_CALLBACK (pac_toggled_cb), self);
+
+ if (s_8021x && nm_setting_802_1x_get_anonymous_identity (s_8021x))
+ gtk_editable_set_text (GTK_EDITABLE (self->anon_identity_entry), nm_setting_802_1x_get_anonymous_identity (s_8021x));
+ g_signal_connect_swapped (self->anon_identity_entry, "changed", G_CALLBACK (changed_cb), self);
+
+ g_signal_connect_swapped (self->pac_file_button, "notify::file", G_CALLBACK (changed_cb), self);
+
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_add_pattern (filter, "*.pac");
+ gtk_file_filter_set_name (filter, _("PAC files (*.pac)"));
+ gtk_file_chooser_add_filter (ws_file_chooser_button_get_filechooser (self->pac_file_button), filter);
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_add_pattern (filter, "*");
+ gtk_file_filter_set_name (filter, _("All files"));
+ gtk_file_chooser_add_filter (ws_file_chooser_button_get_filechooser (self->pac_file_button), filter);
+
+ if (connection && s_8021x) {
+ const char *filename = nm_setting_802_1x_get_pac_file (s_8021x);
+ if (filename) {
+ g_autoptr(GFile) file = g_file_new_for_path (filename);
+ ws_file_chooser_button_set_file (self->pac_file_button, file);
+ }
+ }
+
+ self->em_gtc = eap_method_simple_new (connection, "gtc", TRUE, FALSE);
+ gtk_widget_show (GTK_WIDGET (self->em_gtc));
+ g_signal_connect_object (self->em_gtc, "changed", G_CALLBACK (eap_method_emit_changed), self, G_CONNECT_SWAPPED);
+
+ self->em_mschap_v2 = eap_method_simple_new (connection, "mschapv2", TRUE, FALSE);
+ gtk_widget_show (GTK_WIDGET (self->em_mschap_v2));
+ g_signal_connect_object (self->em_mschap_v2, "changed", G_CALLBACK (eap_method_emit_changed), self, G_CONNECT_SWAPPED);
+
+ if (s_8021x) {
+ if (nm_setting_802_1x_get_phase2_auth (s_8021x))
+ phase2_auth = nm_setting_802_1x_get_phase2_auth (s_8021x);
+ else if (nm_setting_802_1x_get_phase2_autheap (s_8021x))
+ phase2_auth = nm_setting_802_1x_get_phase2_autheap (s_8021x);
+ }
+ if (phase2_auth == NULL)
+ phase2_auth = "gtc";
+
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->inner_auth_model), &iter)) {
+ do {
+ g_autofree gchar *id = NULL;
+ gtk_tree_model_get (GTK_TREE_MODEL (self->inner_auth_model), &iter, I_ID_COLUMN, &id, -1);
+ if (strcmp (id, phase2_auth) == 0)
+ gtk_combo_box_set_active_iter (self->inner_auth_combo, &iter);
+ } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->inner_auth_model), &iter));
+ }
+
+ g_signal_connect_swapped (self->inner_auth_combo, "changed", G_CALLBACK (inner_auth_combo_changed_cb), self);
+ inner_auth_combo_changed_cb (self);
+
+ return self;
+}
+
diff --git a/panels/network/wireless-security/eap-method-fast.h b/panels/network/wireless-security/eap-method-fast.h
new file mode 100644
index 0000000..5528ab1
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-fast.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* vim: set ft=c ts=4 sts=4 sw=4 noexpandtab smartindent: */
+
+/* EAP-FAST authentication method (RFC4851)
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2012 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (EAPMethodFAST, eap_method_fast, EAP, METHOD_FAST, GtkGrid)
+
+EAPMethodFAST *eap_method_fast_new (NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/eap-method-fast.ui b/panels/network/wireless-security/eap-method-fast.ui
new file mode 100644
index 0000000..ad63b18
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-fast.ui
@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.4"/>
+ <object class="GtkListStore" id="inner_auth_model">
+ <columns>
+ <!-- column-name label -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">GTC</col>
+ <col id="1">gtc</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">MSCHAPv2</col>
+ <col id="1">mschapv2</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="pac_provision_model">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Anonymous</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Authenticated</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Both</col>
+ </row>
+ </data>
+ </object>
+ <template class="EAPMethodFAST" parent="GtkGrid">
+ <property name="valign">start</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="anon_identity_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Anony_mous identity</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">anon_identity_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="anon_identity_entry">
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="pac_file_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">PAC _file</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">pac_file_button</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="WsFileChooserButton" id="pac_file_button">
+ <property name="hexpand">True</property>
+ <property name="title" translatable="yes">Choose a PAC file</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="inner_auth_box">
+ <property name="orientation">vertical</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="column-span">2</property>
+ <property name="row">4</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="inner_auth_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Inner authentication</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">inner_auth_combo</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="inner_auth_combo">
+ <property name="hexpand">True</property>
+ <property name="model">inner_auth_model</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ </layout>
+ <child>
+ <object class="GtkCellRendererText"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="pac_provision_check">
+ <property name="label" translatable="yes">Allow automatic PAC pro_visioning</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="pac_provision_combo">
+ <property name="hexpand">True</property>
+ <property name="model">pac_provision_model</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ <child>
+ <object class="GtkCellRendererText"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/wireless-security/eap-method-leap.c b/panels/network/wireless-security/eap-method-leap.c
new file mode 100644
index 0000000..95e7a8e
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-leap.c
@@ -0,0 +1,266 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+
+#include "eap-method.h"
+#include "eap-method-leap.h"
+#include "helpers.h"
+#include "nma-ui-utils.h"
+#include "ui-helpers.h"
+
+struct _EAPMethodLEAP {
+ GtkGrid parent;
+
+ GtkEntry *password_entry;
+ GtkLabel *password_label;
+ GtkCheckButton *show_password_check;
+ GtkEntry *username_entry;
+ GtkLabel *username_label;
+};
+
+static void eap_method_iface_init (EAPMethodInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (EAPMethodLEAP, eap_method_leap, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (eap_method_get_type (), eap_method_iface_init))
+
+static void
+show_toggled_cb (EAPMethodLEAP *self)
+{
+ gboolean visible;
+ visible = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->show_password_check));
+ gtk_entry_set_visibility (self->password_entry, visible);
+}
+
+static gboolean
+validate (EAPMethod *parent, GError **error)
+{
+ EAPMethodLEAP *self = (EAPMethodLEAP *)parent;
+ NMSettingSecretFlags secret_flags;
+ const char *text;
+ gboolean ret = TRUE;
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self->username_entry));
+ if (!text || !strlen (text)) {
+ widget_set_error (GTK_WIDGET (self->username_entry));
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing EAP-LEAP username"));
+ ret = FALSE;
+ } else
+ widget_unset_error (GTK_WIDGET (self->username_entry));
+
+ secret_flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->password_entry));
+ if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED) {
+ widget_unset_error (GTK_WIDGET (self->password_entry));
+ return TRUE;
+ }
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+ if (!text || !strlen (text)) {
+ widget_set_error (GTK_WIDGET (self->password_entry));
+ if (ret) {
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing EAP-LEAP password"));
+ ret = FALSE;
+ }
+ } else
+ widget_unset_error (GTK_WIDGET (self->password_entry));
+
+ return ret;
+}
+
+static void
+add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
+{
+ EAPMethodLEAP *self = (EAPMethodLEAP *) parent;
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->username_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->password_label));
+}
+
+static void
+fill_connection (EAPMethod *parent, NMConnection *connection, NMSettingSecretFlags flags)
+{
+ EAPMethodLEAP *self = (EAPMethodLEAP *) parent;
+ NMSetting8021x *s_8021x;
+ NMSettingSecretFlags secret_flags;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ g_assert (s_8021x);
+
+ nm_setting_802_1x_add_eap_method (s_8021x, "leap");
+
+ g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, gtk_editable_get_text (GTK_EDITABLE (self->username_entry)), NULL);
+ g_object_set (s_8021x, NM_SETTING_802_1X_PASSWORD, gtk_editable_get_text (GTK_EDITABLE (self->password_entry)), NULL);
+
+ /* Save 802.1X password flags to the connection */
+ secret_flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->password_entry));
+ nm_setting_set_secret_flags (NM_SETTING (s_8021x), NM_SETTING_802_1X_PASSWORD,
+ secret_flags, NULL);
+
+ /* Update secret flags and popup when editing the connection */
+ nma_utils_update_password_storage (GTK_WIDGET (self->password_entry), secret_flags,
+ NM_SETTING (s_8021x), NM_SETTING_802_1X_PASSWORD);
+}
+
+static void
+update_secrets (EAPMethod *parent, NMConnection *connection)
+{
+ EAPMethodLEAP *self = (EAPMethodLEAP *) parent;
+ helper_fill_secret_entry (connection,
+ self->password_entry,
+ NM_TYPE_SETTING_802_1X,
+ (HelperSecretFunc) nm_setting_802_1x_get_password);
+}
+
+static GtkWidget *
+get_default_field (EAPMethod *parent)
+{
+ EAPMethodLEAP *self = (EAPMethodLEAP *) parent;
+ return GTK_WIDGET (self->username_entry);
+}
+
+static const gchar *
+get_password_flags_name (EAPMethod *parent)
+{
+ return NM_SETTING_802_1X_PASSWORD;
+}
+
+static const gchar *
+get_username (EAPMethod *method)
+{
+ EAPMethodLEAP *self = EAP_METHOD_LEAP (method);
+ return gtk_editable_get_text (GTK_EDITABLE (self->username_entry));
+}
+
+static void
+set_username (EAPMethod *method, const gchar *username)
+{
+ EAPMethodLEAP *self = EAP_METHOD_LEAP (method);
+ gtk_editable_set_text (GTK_EDITABLE (self->username_entry), username);
+}
+
+static const gchar *
+get_password (EAPMethod *method)
+{
+ EAPMethodLEAP *self = EAP_METHOD_LEAP (method);
+ return gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+}
+
+static void
+set_password (EAPMethod *method, const gchar *password)
+{
+ EAPMethodLEAP *self = EAP_METHOD_LEAP (method);
+ gtk_editable_set_text (GTK_EDITABLE (self->password_entry), password);
+}
+
+static gboolean
+get_show_password (EAPMethod *method)
+{
+ EAPMethodLEAP *self = EAP_METHOD_LEAP (method);
+ return gtk_check_button_get_active (GTK_CHECK_BUTTON (self->show_password_check));
+}
+
+static void
+set_show_password (EAPMethod *method, gboolean show_password)
+{
+ EAPMethodLEAP *self = EAP_METHOD_LEAP (method);
+ gtk_check_button_set_active (self->show_password_check, show_password);
+}
+
+static void
+eap_method_leap_dispose (GObject *object)
+{
+ EAPMethodLEAP *self = EAP_METHOD_LEAP (object);
+
+ g_signal_handlers_disconnect_by_data (self, self);
+ g_signal_handlers_disconnect_by_data (self->show_password_check, self);
+
+ G_OBJECT_CLASS (eap_method_leap_parent_class)->dispose (object);
+}
+
+static void
+changed_cb (EAPMethodLEAP *self)
+{
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+eap_method_leap_init (EAPMethodLEAP *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+eap_method_leap_class_init (EAPMethodLEAPClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = eap_method_leap_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/network/eap-method-leap.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodLEAP, password_entry);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodLEAP, password_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodLEAP, show_password_check);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodLEAP, username_entry);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodLEAP, username_label);
+}
+
+static void
+eap_method_iface_init (EAPMethodInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->update_secrets = update_secrets;
+ iface->get_default_field = get_default_field;
+ iface->get_password_flags_name = get_password_flags_name;
+ iface->get_username = get_username;
+ iface->set_username = set_username;
+ iface->get_password = get_password;
+ iface->set_password = set_password;
+ iface->get_show_password = get_show_password;
+ iface->set_show_password = set_show_password;
+}
+
+EAPMethodLEAP *
+eap_method_leap_new (NMConnection *connection)
+{
+ EAPMethodLEAP *self;
+ NMSetting8021x *s_8021x = NULL;
+
+ self = g_object_new (eap_method_leap_get_type (), NULL);
+
+ g_signal_connect_swapped (self->username_entry, "changed", G_CALLBACK (changed_cb), self);
+
+ g_signal_connect_swapped (self->password_entry, "changed", G_CALLBACK (changed_cb), self);
+
+ /* Create password-storage popup menu for password entry under entry's secondary icon */
+ if (connection)
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ nma_utils_setup_password_storage (GTK_WIDGET (self->password_entry), 0, (NMSetting *) s_8021x, NM_SETTING_802_1X_PASSWORD,
+ FALSE, FALSE);
+
+ g_signal_connect_swapped (self->show_password_check, "toggled", G_CALLBACK (show_toggled_cb), self);
+
+ return self;
+}
+
diff --git a/panels/network/wireless-security/eap-method-leap.h b/panels/network/wireless-security/eap-method-leap.h
new file mode 100644
index 0000000..18248a6
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-leap.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (EAPMethodLEAP, eap_method_leap, EAP, METHOD_LEAP, GtkGrid)
+
+EAPMethodLEAP *eap_method_leap_new (NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/eap-method-leap.ui b/panels/network/wireless-security/eap-method-leap.ui
new file mode 100644
index 0000000..3f945bd
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-leap.ui
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.4"/>
+ <template class="EAPMethodLEAP" parent="GtkGrid">
+ <property name="valign">start</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="username_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Username</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">username_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="password_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">password_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="password_entry">
+ <property name="hexpand">True</property>
+ <property name="visibility">False</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="show_password_check">
+ <property name="label" translatable="yes">Sho_w password</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="username_entry">
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/wireless-security/eap-method-peap.c b/panels/network/wireless-security/eap-method-peap.c
new file mode 100644
index 0000000..17eee12
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-peap.c
@@ -0,0 +1,400 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+
+#include "eap-method.h"
+#include "eap-method-peap.h"
+#include "eap-method-simple.h"
+#include "helpers.h"
+#include "ui-helpers.h"
+#include "ws-file-chooser-button.h"
+
+#define I_NAME_COLUMN 0
+#define I_ID_COLUMN 1
+
+struct _EAPMethodPEAP {
+ GtkGrid parent;
+
+ GtkEntry *anon_identity_entry;
+ GtkLabel *anon_identity_label;
+ WsFileChooserButton *ca_cert_button;
+ GtkLabel *ca_cert_label;
+ GtkCheckButton *ca_cert_not_required_check;
+ GtkBox *inner_auth_box;
+ GtkComboBox *inner_auth_combo;
+ GtkLabel *inner_auth_label;
+ GtkListStore *inner_auth_model;
+ GtkComboBox *version_combo;
+ GtkLabel *version_label;
+
+ EAPMethodSimple *em_gtc;
+ EAPMethodSimple *em_md5;
+ EAPMethodSimple *em_mschap_v2;
+};
+
+static void eap_method_iface_init (EAPMethodInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (EAPMethodPEAP, eap_method_peap, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (eap_method_get_type (), eap_method_iface_init))
+
+static EAPMethod *
+get_inner_method (EAPMethodPEAP *self)
+{
+ GtkTreeIter iter;
+ g_autofree gchar *id = NULL;
+
+ if (!gtk_combo_box_get_active_iter (self->inner_auth_combo, &iter))
+ return NULL;
+ gtk_tree_model_get (GTK_TREE_MODEL (self->inner_auth_model), &iter, I_ID_COLUMN, &id, -1);
+
+ if (strcmp (id, "gtc") == 0)
+ return EAP_METHOD (self->em_gtc);
+ if (strcmp (id, "md5") == 0)
+ return EAP_METHOD (self->em_md5);
+ if (strcmp (id, "mschapv2") == 0)
+ return EAP_METHOD (self->em_mschap_v2);
+
+ return NULL;
+}
+
+static gboolean
+validate (EAPMethod *method, GError **error)
+{
+ EAPMethodPEAP *self = EAP_METHOD_PEAP (method);
+ g_autoptr(GError) local_error = NULL;
+
+ if (!eap_method_validate_filepicker (ws_file_chooser_button_get_filechooser (self->ca_cert_button),
+ TYPE_CA_CERT, NULL, NULL, &local_error)) {
+ g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid EAP-PEAP CA certificate: %s"), local_error->message);
+ return FALSE;
+ }
+
+ if (!gtk_check_button_get_active (GTK_CHECK_BUTTON (self->ca_cert_not_required_check))) {
+ g_autoptr(GFile) file = NULL;
+
+ file = ws_file_chooser_button_get_file (self->ca_cert_button);
+ if (file == NULL) {
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid EAP-PEAP CA certificate: no certificate specified"));
+ return FALSE;
+ }
+ }
+
+ return eap_method_validate (get_inner_method (self), error);
+}
+
+static void
+ca_cert_not_required_toggled (EAPMethodPEAP *self)
+{
+ eap_method_ca_cert_not_required_toggled (self->ca_cert_not_required_check,
+ ws_file_chooser_button_get_filechooser (self->ca_cert_button));
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+add_to_size_group (EAPMethod *method, GtkSizeGroup *group)
+{
+ EAPMethodPEAP *self = EAP_METHOD_PEAP (method);
+
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->ca_cert_not_required_check));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->anon_identity_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->ca_cert_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->version_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->inner_auth_label));
+
+ eap_method_add_to_size_group (EAP_METHOD (self->em_gtc), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_md5), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_mschap_v2), group);
+}
+
+static void
+fill_connection (EAPMethod *method, NMConnection *connection, NMSettingSecretFlags flags)
+{
+ EAPMethodPEAP *self = EAP_METHOD_PEAP (method);
+ NMSetting8021x *s_8021x;
+ NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ const char *text;
+ g_autofree gchar *filename = NULL;
+ g_autoptr(GFile) file = NULL;
+ int peapver_active = 0;
+ g_autoptr(GError) error = NULL;
+ gboolean ca_cert_error = FALSE;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ g_assert (s_8021x);
+
+ nm_setting_802_1x_add_eap_method (s_8021x, "peap");
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self->anon_identity_entry));
+ if (text && strlen (text))
+ g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, text, NULL);
+
+ file = ws_file_chooser_button_get_file (self->ca_cert_button);
+ filename = file ? g_file_get_path (file) : NULL;
+ if (!nm_setting_802_1x_set_ca_cert (s_8021x, filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+ g_warning ("Couldn't read CA certificate '%s': %s", filename, error ? error->message : "(unknown)");
+ ca_cert_error = TRUE;
+ }
+ eap_method_ca_cert_ignore_set (method, connection, filename, ca_cert_error);
+
+ peapver_active = gtk_combo_box_get_active (self->version_combo);
+ switch (peapver_active) {
+ case 1: /* PEAP v0 */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_PEAPVER, "0", NULL);
+ break;
+ case 2: /* PEAP v1 */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_PEAPVER, "1", NULL);
+ break;
+ default: /* Automatic */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_PEAPVER, NULL, NULL);
+ break;
+ }
+
+ eap_method_fill_connection (get_inner_method (self), connection, flags);
+}
+
+static void
+inner_auth_combo_changed_cb (EAPMethodPEAP *self)
+{
+ EAPMethod *inner_method;
+ GtkWidget *child;
+
+ inner_method = get_inner_method (self);
+
+ /* Remove the previous method and migrate username/password across */
+ child = gtk_widget_get_first_child (GTK_WIDGET (self->inner_auth_box));
+ if (child != NULL) {
+ EAPMethod *old_eap = EAP_METHOD (child);
+ eap_method_set_username (inner_method, eap_method_get_username (old_eap));
+ eap_method_set_password (inner_method, eap_method_get_password (old_eap));
+ eap_method_set_show_password (inner_method, eap_method_get_show_password (old_eap));
+ gtk_box_remove (self->inner_auth_box, GTK_WIDGET (old_eap));
+ }
+
+ gtk_box_append (self->inner_auth_box, g_object_ref (GTK_WIDGET (inner_method)));
+
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+update_secrets (EAPMethod *method, NMConnection *connection)
+{
+ EAPMethodPEAP *self = EAP_METHOD_PEAP (method);
+
+ eap_method_update_secrets (EAP_METHOD (self->em_gtc), connection);
+ eap_method_update_secrets (EAP_METHOD (self->em_md5), connection);
+ eap_method_update_secrets (EAP_METHOD (self->em_mschap_v2), connection);
+}
+
+static GtkWidget *
+get_default_field (EAPMethod *method)
+{
+ EAPMethodPEAP *self = EAP_METHOD_PEAP (method);
+ return GTK_WIDGET (self->anon_identity_entry);
+}
+
+static const gchar *
+get_password_flags_name (EAPMethod *method)
+{
+ return NM_SETTING_802_1X_PASSWORD;
+}
+
+static const gchar *
+get_username (EAPMethod *method)
+{
+ EAPMethodPEAP *self = EAP_METHOD_PEAP (method);
+ return eap_method_get_username (get_inner_method (self));
+}
+
+static void
+set_username (EAPMethod *method, const gchar *username)
+{
+ EAPMethodPEAP *self = EAP_METHOD_PEAP (method);
+ return eap_method_set_username (get_inner_method (self), username);
+}
+
+static const gchar *
+get_password (EAPMethod *method)
+{
+ EAPMethodPEAP *self = EAP_METHOD_PEAP (method);
+ return eap_method_get_password (get_inner_method (self));
+}
+
+static void
+set_password (EAPMethod *method, const gchar *password)
+{
+ EAPMethodPEAP *self = EAP_METHOD_PEAP (method);
+ return eap_method_set_password (get_inner_method (self), password);
+}
+
+static gboolean
+get_show_password (EAPMethod *method)
+{
+ EAPMethodPEAP *self = EAP_METHOD_PEAP (method);
+ return eap_method_get_show_password (get_inner_method (self));
+}
+
+static void
+set_show_password (EAPMethod *method, gboolean show_password)
+{
+ EAPMethodPEAP *self = EAP_METHOD_PEAP (method);
+ return eap_method_set_show_password (get_inner_method (self), show_password);
+}
+
+static void
+changed_cb (EAPMethodPEAP *self)
+{
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+eap_method_peap_init (EAPMethodPEAP *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+eap_method_peap_class_init (EAPMethodPEAPClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/network/eap-method-peap.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodPEAP, anon_identity_entry);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodPEAP, anon_identity_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodPEAP, ca_cert_button);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodPEAP, ca_cert_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodPEAP, ca_cert_not_required_check);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodPEAP, inner_auth_box);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodPEAP, inner_auth_combo);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodPEAP, inner_auth_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodPEAP, inner_auth_model);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodPEAP, version_combo);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodPEAP, version_label);
+}
+
+static void
+eap_method_iface_init (EAPMethodInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->update_secrets = update_secrets;
+ iface->get_default_field = get_default_field;
+ iface->get_password_flags_name = get_password_flags_name;
+ iface->get_username = get_username;
+ iface->set_username = set_username;
+ iface->get_password = get_password;
+ iface->set_password = set_password;
+ iface->get_show_password = get_show_password;
+ iface->set_show_password = set_show_password;
+}
+
+EAPMethodPEAP *
+eap_method_peap_new (NMConnection *connection)
+{
+ EAPMethodPEAP *self;
+ GtkFileFilter *filter;
+ NMSetting8021x *s_8021x = NULL;
+ const char *filename;
+ const gchar *phase2_auth = NULL;
+ GtkTreeIter iter;
+
+ self = g_object_new (eap_method_peap_get_type (), NULL);
+
+ if (connection)
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+
+ g_signal_connect_swapped (self->ca_cert_not_required_check, "toggled", G_CALLBACK (ca_cert_not_required_toggled), self);
+
+ g_signal_connect_swapped (self->ca_cert_button, "notify::file", G_CALLBACK (changed_cb), self);
+ filter = eap_method_default_file_chooser_filter_new (FALSE);
+ gtk_file_chooser_add_filter (ws_file_chooser_button_get_filechooser (self->ca_cert_button),
+ filter);
+ if (connection && s_8021x) {
+ filename = NULL;
+ if (nm_setting_802_1x_get_ca_cert_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+ filename = nm_setting_802_1x_get_ca_cert_path (s_8021x);
+ if (filename) {
+ g_autoptr(GFile) file = g_file_new_for_path (filename);
+ ws_file_chooser_button_set_file (self->ca_cert_button, file);
+ }
+ }
+ gtk_check_button_set_active (self->ca_cert_not_required_check,
+ !filename && eap_method_ca_cert_ignore_get (EAP_METHOD (self), connection));
+ }
+
+ self->em_mschap_v2 = eap_method_simple_new (connection, "mschapv2", TRUE, FALSE);
+ gtk_widget_show (GTK_WIDGET (self->em_mschap_v2));
+ g_signal_connect_object (self->em_mschap_v2, "changed", G_CALLBACK (eap_method_emit_changed), self, G_CONNECT_SWAPPED);
+
+ self->em_md5 = eap_method_simple_new (connection, "md5", TRUE, FALSE);
+ gtk_widget_show (GTK_WIDGET (self->em_md5));
+ g_signal_connect_object (self->em_md5, "changed", G_CALLBACK (eap_method_emit_changed), self, G_CONNECT_SWAPPED);
+
+ self->em_gtc = eap_method_simple_new (connection, "gtc", TRUE, FALSE);
+ gtk_widget_show (GTK_WIDGET (self->em_gtc));
+ g_signal_connect_object (self->em_gtc, "changed", G_CALLBACK (eap_method_emit_changed), self, G_CONNECT_SWAPPED);
+
+ if (s_8021x) {
+ if (nm_setting_802_1x_get_phase2_auth (s_8021x))
+ phase2_auth = nm_setting_802_1x_get_phase2_auth (s_8021x);
+ else if (nm_setting_802_1x_get_phase2_autheap (s_8021x))
+ phase2_auth = nm_setting_802_1x_get_phase2_autheap (s_8021x);
+ }
+ if (phase2_auth == NULL)
+ phase2_auth = "mschapv2";
+
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->inner_auth_model), &iter)) {
+ do {
+ g_autofree gchar *id = NULL;
+ gtk_tree_model_get (GTK_TREE_MODEL (self->inner_auth_model), &iter, I_ID_COLUMN, &id, -1);
+ if (strcmp (id, phase2_auth) == 0)
+ gtk_combo_box_set_active_iter (self->inner_auth_combo, &iter);
+ } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->inner_auth_model), &iter));
+ }
+
+ g_signal_connect_swapped (self->inner_auth_combo, "changed", G_CALLBACK (inner_auth_combo_changed_cb), self);
+ inner_auth_combo_changed_cb (self);
+
+ gtk_combo_box_set_active (self->version_combo, 0);
+ if (s_8021x) {
+ const char *peapver;
+
+ peapver = nm_setting_802_1x_get_phase1_peapver (s_8021x);
+ if (peapver) {
+ /* Index 0 is "Automatic" */
+ if (!strcmp (peapver, "0"))
+ gtk_combo_box_set_active (self->version_combo, 1);
+ else if (!strcmp (peapver, "1"))
+ gtk_combo_box_set_active (self->version_combo, 2);
+ }
+ }
+ g_signal_connect_swapped (self->version_combo, "changed", G_CALLBACK (changed_cb), self);
+
+ if (s_8021x && nm_setting_802_1x_get_anonymous_identity (s_8021x))
+ gtk_editable_set_text (GTK_EDITABLE (self->anon_identity_entry), nm_setting_802_1x_get_anonymous_identity (s_8021x));
+ g_signal_connect_swapped (self->anon_identity_entry, "changed", G_CALLBACK (changed_cb), self);
+
+ return self;
+}
+
diff --git a/panels/network/wireless-security/eap-method-peap.h b/panels/network/wireless-security/eap-method-peap.h
new file mode 100644
index 0000000..53b2f30
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-peap.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (EAPMethodPEAP, eap_method_peap, EAP, METHOD_PEAP, GtkGrid)
+
+EAPMethodPEAP *eap_method_peap_new (NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/eap-method-peap.ui b/panels/network/wireless-security/eap-method-peap.ui
new file mode 100644
index 0000000..ac04783
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-peap.ui
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.4"/>
+ <object class="GtkListStore" id="inner_auth_model">
+ <columns>
+ <!-- column-name label -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">MSCHAPv2</col>
+ <col id="1">mschapv2</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">MD5</col>
+ <col id="1">md5</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">GTC</col>
+ <col id="1">gtc</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="version_model">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Automatic</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Version 0</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Version 1</col>
+ </row>
+ </data>
+ </object>
+ <template class="EAPMethodPEAP" parent="GtkGrid">
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="anon_identity_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Anony_mous identity</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">anon_identity_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="anon_identity_entry">
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="ca_cert_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">C_A certificate</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">ca_cert_button</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="WsFileChooserButton" id="ca_cert_button">
+ <property name="hexpand">True</property>
+ <property name="title" translatable="yes">Choose a Certificate Authority certificate</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="ca_cert_not_required_check">
+ <property name="label" translatable="yes">No CA certificate is _required</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="version_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">PEAP _version</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">version_combo</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="version_combo">
+ <property name="hexpand">True</property>
+ <property name="model">version_model</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ </layout>
+ <child>
+ <object class="GtkCellRendererText"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="inner_auth_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Inner authentication</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">inner_auth_combo</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">4</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="inner_auth_combo">
+ <property name="hexpand">True</property>
+ <property name="model">inner_auth_model</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">4</property>
+ </layout>
+ <child>
+ <object class="GtkCellRendererText"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="inner_auth_box">
+ <property name="orientation">vertical</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">5</property>
+ <property name="column-span">2</property>
+ </layout>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/wireless-security/eap-method-simple.c b/panels/network/wireless-security/eap-method-simple.c
new file mode 100644
index 0000000..7bb29ec
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-simple.c
@@ -0,0 +1,356 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+
+#include "eap-method.h"
+#include "eap-method-simple.h"
+#include "helpers.h"
+#include "nma-ui-utils.h"
+#include "ui-helpers.h"
+
+struct _EAPMethodSimple {
+ GtkGrid parent;
+
+ GtkEntry *password_entry;
+ GtkLabel *password_label;
+ GtkToggleButton *show_password_check;
+ GtkEntry *username_entry;
+ GtkLabel *username_label;
+
+ gchar *name;
+ gboolean phase2;
+ gboolean autheap_allowed;
+
+ guint idle_func_id;
+};
+
+static void eap_method_iface_init (EAPMethodInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (EAPMethodSimple, eap_method_simple, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (eap_method_get_type (), eap_method_iface_init))
+
+static void
+show_toggled_cb (EAPMethodSimple *self)
+{
+ gboolean visible;
+
+ visible = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->show_password_check));
+ gtk_entry_set_visibility (self->password_entry, visible);
+}
+
+static gboolean
+always_ask_selected (GtkEntry *passwd_entry)
+{
+ return !!( nma_utils_menu_to_secret_flags (GTK_WIDGET (passwd_entry))
+ & NM_SETTING_SECRET_FLAG_NOT_SAVED);
+}
+
+static gboolean
+validate (EAPMethod *method, GError **error)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (method);
+ const char *text;
+ gboolean ret = TRUE;
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self->username_entry));
+ if (!text || !strlen (text)) {
+ widget_set_error (GTK_WIDGET (self->username_entry));
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing EAP username"));
+ ret = FALSE;
+ } else
+ widget_unset_error (GTK_WIDGET (self->username_entry));
+
+ /* Check if the password should always be requested */
+ if (always_ask_selected (self->password_entry))
+ widget_unset_error (GTK_WIDGET (self->password_entry));
+ else {
+ text = gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+ if (!text || !strlen (text)) {
+ widget_set_error (GTK_WIDGET (self->password_entry));
+ if (ret) {
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing EAP password"));
+ ret = FALSE;
+ }
+ } else
+ widget_unset_error (GTK_WIDGET (self->password_entry));
+ }
+
+ return ret;
+}
+
+static void
+add_to_size_group (EAPMethod *method, GtkSizeGroup *group)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (method);
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->username_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->password_label));
+}
+
+static void
+fill_connection (EAPMethod *method, NMConnection *connection, NMSettingSecretFlags prev_flags)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (method);
+ NMSetting8021x *s_8021x;
+ gboolean not_saved = FALSE;
+ NMSettingSecretFlags flags;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ g_assert (s_8021x);
+
+ /* If this is the main EAP method, clear any existing methods because the
+ * user-selected on will replace it.
+ */
+ if (eap_method_get_phase2 (method) == FALSE)
+ nm_setting_802_1x_clear_eap_methods (s_8021x);
+
+ if (eap_method_get_phase2 (method)) {
+ /* If the outer EAP method (TLS, TTLS, PEAP, etc) allows inner/phase2
+ * EAP methods (which only TTLS allows) *and* the inner/phase2 method
+ * supports being an inner EAP method, then set PHASE2_AUTHEAP.
+ * Otherwise the inner/phase2 method goes into PHASE2_AUTH.
+ */
+ if (self->autheap_allowed) {
+ g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP, self->name, NULL);
+ g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, NULL, NULL);
+ } else {
+ g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, self->name, NULL);
+ g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP, NULL, NULL);
+ }
+ } else
+ nm_setting_802_1x_add_eap_method (s_8021x, self->name);
+
+ g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, gtk_editable_get_text (GTK_EDITABLE (self->username_entry)), NULL);
+
+ /* Save the password always ask setting */
+ not_saved = always_ask_selected (self->password_entry);
+ flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->password_entry));
+ nm_setting_set_secret_flags (NM_SETTING (s_8021x), NM_SETTING_802_1X_PASSWORD, flags, NULL);
+
+ /* Fill the connection's password if we're in the applet so that it'll get
+ * back to NM. From the editor though, since the connection isn't going
+ * back to NM in response to a GetSecrets() call, we don't save it if the
+ * user checked "Always Ask".
+ */
+ if (not_saved == FALSE)
+ g_object_set (s_8021x, NM_SETTING_802_1X_PASSWORD, gtk_editable_get_text (GTK_EDITABLE (self->password_entry)), NULL);
+
+ /* Update secret flags and popup when editing the connection */
+ nma_utils_update_password_storage (GTK_WIDGET (self->password_entry), flags,
+ NM_SETTING (s_8021x), NM_SETTING_802_1X_PASSWORD);
+}
+
+static void
+update_secrets (EAPMethod *method, NMConnection *connection)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (method);
+ helper_fill_secret_entry (connection,
+ self->password_entry,
+ NM_TYPE_SETTING_802_1X,
+ (HelperSecretFunc) nm_setting_802_1x_get_password);
+}
+
+static GtkWidget *
+get_default_field (EAPMethod *method)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (method);
+ return GTK_WIDGET (self->username_entry);
+}
+
+static const gchar *
+get_password_flags_name (EAPMethod *method)
+{
+ return NM_SETTING_802_1X_PASSWORD;
+}
+
+static const gboolean
+get_phase2 (EAPMethod *method)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (method);
+ return self->phase2;
+}
+
+static const gchar *
+get_username (EAPMethod *method)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (method);
+ return gtk_editable_get_text (GTK_EDITABLE (self->username_entry));
+}
+
+static void
+set_username (EAPMethod *method, const gchar *username)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (method);
+ if (username)
+ gtk_editable_set_text (GTK_EDITABLE (self->username_entry), username);
+}
+
+static const gchar *
+get_password (EAPMethod *method)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (method);
+ return gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+}
+
+static void
+set_password (EAPMethod *method, const gchar *password)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (method);
+ if (password)
+ gtk_editable_set_text (GTK_EDITABLE (self->password_entry), password);
+}
+
+static gboolean
+get_show_password (EAPMethod *method)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (method);
+ return gtk_check_button_get_active (GTK_CHECK_BUTTON (self->show_password_check));
+}
+
+static void
+set_show_password (EAPMethod *method, gboolean show_password)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (method);
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->show_password_check), show_password);
+}
+
+static gboolean
+stuff_changed (EAPMethodSimple *self)
+{
+ eap_method_emit_changed (EAP_METHOD (self));
+ self->idle_func_id = 0;
+ return FALSE;
+}
+
+static void
+password_storage_changed (EAPMethodSimple *self)
+{
+ gboolean always_ask;
+
+ always_ask = always_ask_selected (self->password_entry);
+
+ if (always_ask) {
+ /* we always clear this button and do not restore it
+ * (because we want to hide the password). */
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->show_password_check), FALSE);
+ }
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->show_password_check), !always_ask);
+
+ if (!self->idle_func_id)
+ self->idle_func_id = g_idle_add ((GSourceFunc) stuff_changed, self);
+}
+
+static void
+eap_method_simple_dispose (GObject *object)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (object);
+
+ g_clear_pointer (&self->name, g_free);
+
+ g_signal_handlers_disconnect_by_data (self, self);
+ g_signal_handlers_disconnect_by_data (self->password_entry, self);
+ g_signal_handlers_disconnect_by_data (self->show_password_check, self);
+
+ if (self->idle_func_id != 0) {
+ g_source_remove (self->idle_func_id);
+ self->idle_func_id = 0;
+ }
+
+ G_OBJECT_CLASS (eap_method_simple_parent_class)->dispose (object);
+}
+
+static void
+changed_cb (EAPMethodSimple *self)
+{
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+eap_method_simple_init (EAPMethodSimple *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+eap_method_simple_class_init (EAPMethodSimpleClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = eap_method_simple_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/network/eap-method-simple.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodSimple, password_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodSimple, username_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodSimple, password_entry);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodSimple, show_password_check);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodSimple, username_entry);
+}
+
+static void
+eap_method_iface_init (EAPMethodInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->update_secrets = update_secrets;
+ iface->get_default_field = get_default_field;
+ iface->get_password_flags_name = get_password_flags_name;
+ iface->get_phase2 = get_phase2;
+ iface->get_username = get_username;
+ iface->set_username = set_username;
+ iface->get_password = get_password;
+ iface->set_password = set_password;
+ iface->get_show_password = get_show_password;
+ iface->set_show_password = set_show_password;
+}
+
+EAPMethodSimple *
+eap_method_simple_new (NMConnection *connection, const gchar *name, gboolean phase2, gboolean autheap_allowed)
+{
+ EAPMethodSimple *self;
+ NMSetting8021x *s_8021x = NULL;
+
+ self = g_object_new (eap_method_simple_get_type (), NULL);
+ self->name = g_strdup (name);
+ self->phase2 = phase2;
+ self->autheap_allowed = autheap_allowed;
+
+ g_signal_connect_swapped (self->username_entry, "changed", G_CALLBACK (changed_cb), self);
+
+ g_signal_connect_swapped (self->password_entry, "changed", G_CALLBACK (changed_cb), self);
+
+ /* Create password-storage popup menu for password entry under entry's secondary icon */
+ if (connection)
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ nma_utils_setup_password_storage (GTK_WIDGET (self->password_entry), 0, (NMSetting *) s_8021x, NM_SETTING_802_1X_PASSWORD,
+ FALSE, FALSE);
+
+ g_signal_connect_swapped (self->password_entry, "notify::secondary-icon-name", G_CALLBACK (password_storage_changed), self);
+
+ g_signal_connect_swapped (self->show_password_check, "toggled", G_CALLBACK (show_toggled_cb), self);
+
+ return self;
+}
+
diff --git a/panels/network/wireless-security/eap-method-simple.h b/panels/network/wireless-security/eap-method-simple.h
new file mode 100644
index 0000000..8645fb1
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-simple.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (EAPMethodSimple, eap_method_simple, EAP, METHOD_SIMPLE, GtkGrid)
+
+typedef enum {
+ /* NOTE: when updating this table, also update eap_methods[] */
+ EAP_METHOD_SIMPLE_TYPE_PAP = 0,
+ EAP_METHOD_SIMPLE_TYPE_MSCHAP,
+ EAP_METHOD_SIMPLE_TYPE_MSCHAP_V2,
+ EAP_METHOD_SIMPLE_TYPE_PLAIN_MSCHAP_V2,
+ EAP_METHOD_SIMPLE_TYPE_MD5,
+ EAP_METHOD_SIMPLE_TYPE_PWD,
+ EAP_METHOD_SIMPLE_TYPE_CHAP,
+ EAP_METHOD_SIMPLE_TYPE_GTC,
+
+ /* Boundary value, do not use */
+ EAP_METHOD_SIMPLE_TYPE_LAST
+} EAPMethodSimpleType;
+
+EAPMethodSimple *eap_method_simple_new (NMConnection *connection,
+ const gchar *name,
+ gboolean phase2,
+ gboolean autheap_allowed);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/eap-method-simple.ui b/panels/network/wireless-security/eap-method-simple.ui
new file mode 100644
index 0000000..e5c37c9
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-simple.ui
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.4"/>
+ <template class="EAPMethodSimple" parent="GtkGrid">
+ <property name="valign">start</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="username_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Username</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">username_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="password_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">password_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="password_entry">
+ <property name="hexpand">True</property>
+ <property name="visibility">False</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="username_entry">
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="hexpand">True</property>
+ <property name="orientation">vertical</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ <child>
+ <object class="GtkCheckButton" id="show_password_check">
+ <property name="label" translatable="yes">Sho_w password</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/wireless-security/eap-method-tls.c b/panels/network/wireless-security/eap-method-tls.c
new file mode 100644
index 0000000..5038915
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-tls.c
@@ -0,0 +1,557 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+
+#include "eap-method.h"
+#include "eap-method-tls.h"
+#include "helpers.h"
+#include "nma-ui-utils.h"
+#include "ui-helpers.h"
+#include "ws-file-chooser-button.h"
+
+struct _EAPMethodTLS {
+ GtkGrid parent;
+
+ WsFileChooserButton *ca_cert_button;
+ GtkLabel *ca_cert_label;
+ GtkCheckButton *ca_cert_not_required_check;
+ GtkEntry *identity_entry;
+ GtkLabel *identity_label;
+ WsFileChooserButton *private_key_button;
+ GtkLabel *private_key_label;
+ GtkEntry *private_key_password_entry;
+ GtkLabel *private_key_password_label;
+ GtkCheckButton *show_password_check;
+ WsFileChooserButton *user_cert_button;
+ GtkLabel *user_cert_label;
+
+ gchar *username;
+ gchar *password;
+ gboolean show_password;
+};
+
+static void eap_method_iface_init (EAPMethodInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (EAPMethodTLS, eap_method_tls, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (eap_method_get_type (), eap_method_iface_init))
+
+static void
+eap_method_tls_dispose (GObject *object)
+{
+ EAPMethodTLS *self = EAP_METHOD_TLS (object);
+
+ g_clear_pointer (&self->username, g_free);
+ g_clear_pointer (&self->password, g_free);
+
+ G_OBJECT_CLASS (eap_method_tls_parent_class)->dispose (object);
+}
+
+static void
+show_toggled_cb (EAPMethodTLS *self)
+{
+ gboolean visible;
+
+ visible = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->show_password_check));
+ gtk_entry_set_visibility (self->private_key_password_entry, visible);
+}
+
+static gboolean
+validate (EAPMethod *method, GError **error)
+{
+ EAPMethodTLS *self = EAP_METHOD_TLS (method);
+ NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ NMSettingSecretFlags secret_flags;
+ const char *password, *identity;
+ g_autoptr(GError) ca_cert_error = NULL;
+ g_autoptr(GError) private_key_error = NULL;
+ g_autoptr(GError) user_cert_error = NULL;
+ gboolean ret = TRUE;
+
+ identity = gtk_editable_get_text (GTK_EDITABLE (self->identity_entry));
+ if (!identity || !strlen (identity)) {
+ widget_set_error (GTK_WIDGET (self->identity_entry));
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing EAP-TLS identity"));
+ ret = FALSE;
+ } else {
+ widget_unset_error (GTK_WIDGET (self->identity_entry));
+ }
+
+ if (!eap_method_validate_filepicker (ws_file_chooser_button_get_filechooser (self->ca_cert_button),
+ TYPE_CA_CERT, NULL, NULL, &ca_cert_error)) {
+ widget_set_error (GTK_WIDGET (self->ca_cert_button));
+ if (ret) {
+ g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid EAP-TLS CA certificate: %s"), ca_cert_error->message);
+ ret = FALSE;
+ }
+ } else if (!gtk_check_button_get_active (GTK_CHECK_BUTTON (self->ca_cert_not_required_check))) {
+ g_autoptr(GFile) file = NULL;
+
+ file = ws_file_chooser_button_get_file (self->ca_cert_button);
+ if (file == NULL) {
+ widget_set_error (GTK_WIDGET (self->ca_cert_button));
+ if (ret) {
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid EAP-TLS CA certificate: no certificate specified"));
+ ret = FALSE;
+ }
+ }
+ }
+
+ password = gtk_editable_get_text (GTK_EDITABLE (self->private_key_password_entry));
+ secret_flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->private_key_password_entry));
+ if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)
+ password = NULL;
+
+ if (!eap_method_validate_filepicker (ws_file_chooser_button_get_filechooser (self->private_key_button),
+ TYPE_PRIVATE_KEY,
+ password,
+ &format,
+ &private_key_error)) {
+ if (ret) {
+ g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid EAP-TLS private-key: %s"), private_key_error->message);
+ ret = FALSE;
+ }
+ widget_set_error (GTK_WIDGET (self->private_key_button));
+ }
+
+ if (format != NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
+ if (!eap_method_validate_filepicker (ws_file_chooser_button_get_filechooser (self->user_cert_button),
+ TYPE_CLIENT_CERT, NULL, NULL, &user_cert_error)) {
+ if (ret) {
+ g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid EAP-TLS user-certificate: %s"), user_cert_error->message);
+ ret = FALSE;
+ }
+ widget_set_error (GTK_WIDGET (self->user_cert_button));
+ }
+ }
+
+ return ret;
+}
+
+static void
+ca_cert_not_required_toggled (EAPMethodTLS *self)
+{
+ eap_method_ca_cert_not_required_toggled (self->ca_cert_not_required_check,
+ ws_file_chooser_button_get_filechooser (self->ca_cert_button));
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+add_to_size_group (EAPMethod *method, GtkSizeGroup *group)
+{
+ EAPMethodTLS *self = EAP_METHOD_TLS (method);
+
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->ca_cert_not_required_check));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->identity_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->user_cert_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->ca_cert_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->private_key_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->private_key_password_label));
+}
+
+static void
+fill_connection (EAPMethod *method, NMConnection *connection, NMSettingSecretFlags flags)
+{
+ EAPMethodTLS *self = EAP_METHOD_TLS (method);
+ NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ NMSetting8021x *s_8021x;
+ NMSettingSecretFlags secret_flags;
+ g_autofree gchar *ca_filename = NULL;
+ g_autoptr(GFile) ca_file = NULL;
+ g_autofree gchar *pk_filename = NULL;
+ g_autoptr(GFile) pk_file = NULL;
+ const char *password = NULL;
+ gboolean ca_cert_error = FALSE;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GError) error2 = NULL;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ g_assert (s_8021x);
+
+ nm_setting_802_1x_add_eap_method (s_8021x, "tls");
+
+ g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, gtk_editable_get_text (GTK_EDITABLE (self->identity_entry)), NULL);
+
+ /* TLS private key */
+ password = gtk_editable_get_text (GTK_EDITABLE (self->private_key_password_entry));
+ secret_flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->private_key_password_entry));
+ if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)
+ password = NULL;
+
+ pk_file = ws_file_chooser_button_get_file (self->private_key_button);
+ g_assert (pk_file);
+ pk_filename = g_file_get_path (pk_file);
+
+ if (!nm_setting_802_1x_set_private_key (s_8021x, pk_filename, password, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error))
+ g_warning ("Couldn't read private key '%s': %s", pk_filename, error ? error->message : "(unknown)");
+
+ /* Save 802.1X password flags to the connection */
+ nm_setting_set_secret_flags (NM_SETTING (s_8021x), NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD,
+ secret_flags, NULL);
+
+ /* Update secret flags and popup when editing the connection */
+ nma_utils_update_password_storage (GTK_WIDGET (self->private_key_password_entry), secret_flags,
+ NM_SETTING (s_8021x), NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD);
+
+ /* TLS client certificate */
+ if (format != NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
+ g_autofree gchar *cc_filename = NULL;
+ g_autoptr(GFile) cc_file = NULL;
+ g_autoptr(GError) error = NULL;
+
+ /* If the key is pkcs#12 nm_setting_802_1x_set_private_key() already
+ * set the client certificate for us.
+ */
+ cc_file = ws_file_chooser_button_get_file (self->private_key_button);
+ g_assert (cc_file);
+ cc_filename = g_file_get_path (cc_file);
+
+ format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ if (!nm_setting_802_1x_set_client_cert (s_8021x, cc_filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error))
+ g_warning ("Couldn't read client certificate '%s': %s", cc_filename, error ? error->message : "(unknown)");
+ }
+
+ /* TLS CA certificate */
+ ca_file = ws_file_chooser_button_get_file (self->private_key_button);
+ ca_filename = ca_file ? g_file_get_path (ca_file) : NULL;
+
+ format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ if (!nm_setting_802_1x_set_ca_cert (s_8021x, ca_filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error2)) {
+ g_warning ("Couldn't read CA certificate '%s': %s", ca_filename, error2 ? error2->message : "(unknown)");
+ ca_cert_error = TRUE;
+ }
+ eap_method_ca_cert_ignore_set (method, connection, ca_filename, ca_cert_error);
+}
+
+static void
+private_key_picker_helper (EAPMethodTLS *self, const char *filename, gboolean changed)
+{
+ g_autoptr(NMSetting8021x) setting = NULL;
+ NMSetting8021xCKFormat cert_format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ const char *password;
+
+ password = gtk_editable_get_text (GTK_EDITABLE (self->private_key_password_entry));
+
+ setting = (NMSetting8021x *) nm_setting_802_1x_new ();
+ nm_setting_802_1x_set_private_key (setting, filename, password, NM_SETTING_802_1X_CK_SCHEME_PATH, &cert_format, NULL);
+
+ /* With PKCS#12, the client cert must be the same as the private key */
+ if (cert_format == NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
+ ws_file_chooser_button_set_file (self->user_cert_button, NULL);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->user_cert_button), FALSE);
+ } else if (changed)
+ gtk_widget_set_sensitive (GTK_WIDGET (self->user_cert_button), TRUE);
+
+ /* Warn the user if the private key is unencrypted */
+ if (!eap_method_is_encrypted_private_key (filename)) {
+ GtkWidget *dialog;
+ GtkNative *native;
+ GtkWindow *parent_window = NULL;
+
+ native = gtk_widget_get_native (GTK_WIDGET (self));
+ if (GTK_IS_WINDOW (native))
+ parent_window = GTK_WINDOW (native);
+
+ dialog = gtk_message_dialog_new (parent_window,
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_OK,
+ "%s",
+ _("Unencrypted private keys are insecure"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s",
+ _("The selected private key does not appear to be protected by a password. This could allow your security credentials to be compromised. Please select a password-protected private key.\n\n(You can password-protect your private key with openssl)"));
+ gtk_window_present (GTK_WINDOW (dialog));
+ }
+}
+
+static void
+private_key_picker_file_set_cb (WsFileChooserButton *chooser, gpointer user_data)
+{
+ EAPMethodTLS *self = user_data;
+ g_autoptr(GFile) file = NULL;
+ g_autofree gchar *filename = NULL;
+
+ file = ws_file_chooser_button_get_file (chooser);
+ filename = file ? g_file_get_path (file) : NULL;
+ if (filename)
+ private_key_picker_helper (self, filename, TRUE);
+}
+
+static void reset_filter (GtkWidget *widget, GParamSpec *spec, gpointer user_data)
+{
+ if (!gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (widget))) {
+ g_signal_handlers_block_by_func (widget, reset_filter, user_data);
+ gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (widget), GTK_FILE_FILTER (user_data));
+ g_signal_handlers_unblock_by_func (widget, reset_filter, user_data);
+ }
+}
+
+typedef const char * (*PathFunc) (NMSetting8021x *setting);
+typedef NMSetting8021xCKScheme (*SchemeFunc) (NMSetting8021x *setting);
+
+static void
+changed_cb (EAPMethodTLS *self)
+{
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+setup_filepicker (EAPMethodTLS *self,
+ WsFileChooserButton *button,
+ const char *title,
+ NMSetting8021x *s_8021x,
+ SchemeFunc scheme_func,
+ PathFunc path_func,
+ gboolean privkey,
+ gboolean client_cert)
+{
+ GtkFileFilter *filter;
+ const char *filename = NULL;
+
+ if (s_8021x && path_func && scheme_func) {
+ if (scheme_func (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+ filename = path_func (s_8021x);
+ if (filename) {
+ g_autoptr(GFile) file = g_file_new_for_path (filename);
+ ws_file_chooser_button_set_file (button, file);
+ }
+ }
+ }
+
+ /* Connect a special handler for private keys to intercept PKCS#12 key types
+ * and desensitize the user cert button.
+ */
+ if (privkey) {
+ g_signal_connect (button, "notify::file",
+ G_CALLBACK (private_key_picker_file_set_cb),
+ self);
+ if (filename)
+ private_key_picker_helper (self, filename, FALSE);
+ }
+
+ g_signal_connect_swapped (button, "notify::file", G_CALLBACK (changed_cb), self);
+
+ filter = eap_method_default_file_chooser_filter_new (privkey);
+ gtk_file_chooser_add_filter (ws_file_chooser_button_get_filechooser (button), filter);
+
+ /* For some reason, GTK+ calls set_current_filter (..., NULL) from
+ * gtkfilechooserdefault.c::show_and_select_files_finished_loading() on our
+ * dialog; so force-reset the filter to what we want it to be whenever
+ * it gets cleared.
+ */
+ if (client_cert)
+ g_signal_connect (button, "notify::filter", (GCallback) reset_filter, filter);
+}
+
+static void
+update_secrets (EAPMethod *method, NMConnection *connection)
+{
+ EAPMethodTLS *self = EAP_METHOD_TLS (method);
+ NMSetting8021x *s_8021x;
+ const char *filename;
+
+ helper_fill_secret_entry (connection,
+ self->private_key_password_entry,
+ NM_TYPE_SETTING_802_1X,
+ (HelperSecretFunc) nm_setting_802_1x_get_private_key_password);
+
+ /* Set the private key filepicker button path if we have a private key */
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (s_8021x && (nm_setting_802_1x_get_private_key_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH)) {
+ filename = nm_setting_802_1x_get_private_key_path (s_8021x);
+ if (filename) {
+ g_autoptr(GFile) file = g_file_new_for_path (filename);
+ ws_file_chooser_button_set_file (self->private_key_button, file);
+ }
+ }
+}
+
+static GtkWidget *
+get_default_field (EAPMethod *method)
+{
+ EAPMethodTLS *self = EAP_METHOD_TLS (method);
+ return GTK_WIDGET (self->identity_entry);
+}
+
+static const gchar *
+get_password_flags_name (EAPMethod *method)
+{
+ return NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD;
+}
+
+static const gchar *
+get_username (EAPMethod *method)
+{
+ EAPMethodTLS *self = EAP_METHOD_TLS (method);
+ return self->username;
+}
+
+static void
+set_username (EAPMethod *method, const gchar *username)
+{
+ EAPMethodTLS *self = EAP_METHOD_TLS (method);
+ g_free (self->username);
+ self->username = g_strdup (username);
+}
+
+static const gchar *
+get_password (EAPMethod *method)
+{
+ EAPMethodTLS *self = EAP_METHOD_TLS (method);
+ return self->password;
+}
+
+static void
+set_password (EAPMethod *method, const gchar *password)
+{
+ EAPMethodTLS *self = EAP_METHOD_TLS (method);
+ g_free (self->password);
+ self->password = g_strdup (password);
+}
+
+static const gboolean
+get_show_password (EAPMethod *method)
+{
+ EAPMethodTLS *self = EAP_METHOD_TLS (method);
+ return self->show_password;
+}
+
+static void
+set_show_password (EAPMethod *method, gboolean show_password)
+{
+ EAPMethodTLS *self = EAP_METHOD_TLS (method);
+ self->show_password = show_password;
+}
+
+static void
+eap_method_tls_init (EAPMethodTLS *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+ self->username = g_strdup ("");
+ self->password = g_strdup ("");
+}
+
+static void
+eap_method_tls_class_init (EAPMethodTLSClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = eap_method_tls_dispose;
+
+ g_type_ensure (WS_TYPE_FILE_CHOOSER_BUTTON);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/network/eap-method-tls.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTLS, ca_cert_button);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTLS, ca_cert_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTLS, ca_cert_not_required_check);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTLS, identity_entry);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTLS, identity_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTLS, private_key_button);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTLS, private_key_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTLS, private_key_password_entry);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTLS, private_key_password_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTLS, show_password_check);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTLS, user_cert_button);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTLS, user_cert_label);
+}
+
+static void
+eap_method_iface_init (EAPMethodInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->update_secrets = update_secrets;
+ iface->get_default_field = get_default_field;
+ iface->get_password_flags_name = get_password_flags_name;
+ iface->get_username = get_username;
+ iface->set_username = set_username;
+ iface->get_password = get_password;
+ iface->set_password = set_password;
+ iface->get_show_password = get_show_password;
+ iface->set_show_password = set_show_password;
+}
+
+EAPMethodTLS *
+eap_method_tls_new (NMConnection *connection)
+{
+ EAPMethodTLS *self;
+ NMSetting8021x *s_8021x = NULL;
+ gboolean ca_not_required = FALSE;
+
+ self = g_object_new (eap_method_tls_get_type (), NULL);
+
+ if (connection)
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+
+ g_signal_connect_swapped (self->ca_cert_not_required_check, "toggled", G_CALLBACK (ca_cert_not_required_toggled), self);
+
+ g_signal_connect_swapped (self->identity_entry, "changed", G_CALLBACK (changed_cb), self);
+ if (s_8021x && nm_setting_802_1x_get_identity (s_8021x))
+ gtk_editable_set_text (GTK_EDITABLE (self->identity_entry), nm_setting_802_1x_get_identity (s_8021x));
+
+ setup_filepicker (self,
+ self->user_cert_button,
+ _("Choose your personal certificate"),
+ s_8021x,
+ nm_setting_802_1x_get_client_cert_scheme,
+ nm_setting_802_1x_get_client_cert_path,
+ FALSE, TRUE);
+ setup_filepicker (self,
+ self->ca_cert_button,
+ _("Choose a Certificate Authority certificate"),
+ s_8021x,
+ nm_setting_802_1x_get_ca_cert_scheme,
+ nm_setting_802_1x_get_ca_cert_path,
+ FALSE, FALSE);
+ setup_filepicker (self,
+ self->private_key_button,
+ _("Choose your private key"),
+ s_8021x,
+ nm_setting_802_1x_get_private_key_scheme,
+ nm_setting_802_1x_get_private_key_path,
+ TRUE, FALSE);
+
+ if (connection && eap_method_ca_cert_ignore_get (EAP_METHOD (self), connection)) {
+ g_autoptr(GFile) file = ws_file_chooser_button_get_file (self->ca_cert_button);
+ ca_not_required = !file;
+ }
+ gtk_check_button_set_active (self->ca_cert_not_required_check, ca_not_required);
+
+ /* Fill secrets, if any */
+ if (connection)
+ update_secrets (EAP_METHOD (self), connection);
+
+ g_signal_connect_swapped (self->private_key_password_entry, "changed", G_CALLBACK (changed_cb), self);
+
+ /* Create password-storage popup menu for password entry under entry's secondary icon */
+ nma_utils_setup_password_storage (GTK_WIDGET (self->private_key_password_entry), 0, (NMSetting *) s_8021x, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD,
+ FALSE, FALSE);
+
+ g_signal_connect_swapped (self->show_password_check, "toggled", G_CALLBACK (show_toggled_cb), self);
+
+ return self;
+}
+
diff --git a/panels/network/wireless-security/eap-method-tls.h b/panels/network/wireless-security/eap-method-tls.h
new file mode 100644
index 0000000..27f3843
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-tls.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (EAPMethodTLS, eap_method_tls, EAP, METHOD_TLS, GtkGrid)
+
+EAPMethodTLS *eap_method_tls_new (NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/eap-method-tls.ui b/panels/network/wireless-security/eap-method-tls.ui
new file mode 100644
index 0000000..69c2610
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-tls.ui
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.4"/>
+ <template class="EAPMethodTLS" parent="GtkGrid">
+ <property name="valign">start</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="identity_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">I_dentity</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">identity_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="identity_entry">
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="user_cert_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_User certificate</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">user_cert_button</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="WsFileChooserButton" id="user_cert_button">
+ <property name="hexpand">True</property>
+ <property name="title" translatable="yes">Choose a Certificate Authority certificate</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="ca_cert_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">C_A certificate</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">ca_cert_button</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="WsFileChooserButton" id="ca_cert_button">
+ <property name="hexpand">True</property>
+ <property name="title" translatable="yes">Choose a Certificate Authority certificate</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="ca_cert_not_required_check">
+ <property name="label" translatable="yes">No CA certificate is _required</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="private_key_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Private _key</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">private_key_button</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">4</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="WsFileChooserButton" id="private_key_button">
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">4</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="private_key_password_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Private key password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">private_key_password_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">5</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="private_key_password_entry">
+ <property name="hexpand">True</property>
+ <property name="visibility">False</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">5</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="show_password_check">
+ <property name="label" translatable="yes">Sho_w password</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">6</property>
+ </layout>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/wireless-security/eap-method-ttls.c b/panels/network/wireless-security/eap-method-ttls.c
new file mode 100644
index 0000000..b41a57f
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-ttls.c
@@ -0,0 +1,415 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+
+#include "eap-method.h"
+#include "eap-method-simple.h"
+#include "eap-method-ttls.h"
+#include "helpers.h"
+#include "ws-file-chooser-button.h"
+
+#define I_NAME_COLUMN 0
+#define I_ID_COLUMN 1
+
+struct _EAPMethodTTLS {
+ GtkGrid parent;
+
+ GtkEntry *anon_identity_entry;
+ GtkLabel *anon_identity_label;
+ WsFileChooserButton *ca_cert_button;
+ GtkLabel *ca_cert_label;
+ GtkCheckButton *ca_cert_not_required_check;
+ GtkEntry *domain_match_entry;
+ GtkLabel *domain_match_label;
+ GtkComboBox *inner_auth_combo;
+ GtkLabel *inner_auth_label;
+ GtkListStore *inner_auth_model;
+ GtkBox *inner_auth_box;
+
+ EAPMethodSimple *em_chap;
+ EAPMethodSimple *em_gtc;
+ EAPMethodSimple *em_md5;
+ EAPMethodSimple *em_mschap;
+ EAPMethodSimple *em_mschap_v2;
+ EAPMethodSimple *em_pap;
+ EAPMethodSimple *em_plain_mschap_v2;
+};
+
+static void eap_method_iface_init (EAPMethodInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (EAPMethodTTLS, eap_method_ttls, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (eap_method_get_type (), eap_method_iface_init))
+
+static EAPMethod *
+get_inner_method (EAPMethodTTLS *self)
+{
+ GtkTreeIter iter;
+ g_autofree gchar *id = NULL;
+
+ if (!gtk_combo_box_get_active_iter (self->inner_auth_combo, &iter))
+ return NULL;
+ gtk_tree_model_get (GTK_TREE_MODEL (self->inner_auth_model), &iter, I_ID_COLUMN, &id, -1);
+
+ if (strcmp (id, "chap") == 0)
+ return EAP_METHOD (self->em_chap);
+ if (strcmp (id, "gtc") == 0)
+ return EAP_METHOD (self->em_gtc);
+ if (strcmp (id, "md5") == 0)
+ return EAP_METHOD (self->em_md5);
+ if (strcmp (id, "mschap") == 0)
+ return EAP_METHOD (self->em_mschap);
+ if (strcmp (id, "mschapv2") == 0)
+ return EAP_METHOD (self->em_mschap_v2);
+ if (strcmp (id, "pap") == 0)
+ return EAP_METHOD (self->em_pap);
+ if (strcmp (id, "plain_mschapv2") == 0)
+ return EAP_METHOD (self->em_plain_mschap_v2);
+
+ return NULL;
+}
+
+static gboolean
+validate (EAPMethod *method, GError **error)
+{
+ EAPMethodTTLS *self = EAP_METHOD_TTLS (method);
+ g_autoptr(GError) local_error = NULL;
+
+ if (!eap_method_validate_filepicker (ws_file_chooser_button_get_filechooser (self->ca_cert_button),
+ TYPE_CA_CERT, NULL, NULL, &local_error)) {
+ g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid EAP-TTLS CA certificate: %s"), local_error->message);
+ return FALSE;
+ }
+ if (!gtk_check_button_get_active (GTK_CHECK_BUTTON (self->ca_cert_not_required_check))) {
+ g_autoptr(GFile) file = NULL;
+
+ file = ws_file_chooser_button_get_file (self->ca_cert_button);
+ if (file == NULL) {
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid EAP-TTLS CA certificate: no certificate specified"));
+ return FALSE;
+ }
+ }
+
+ return eap_method_validate (get_inner_method (self), error);
+}
+
+static void
+ca_cert_not_required_toggled (EAPMethodTTLS *self)
+{
+ eap_method_ca_cert_not_required_toggled (self->ca_cert_not_required_check,
+ ws_file_chooser_button_get_filechooser (self->ca_cert_button));
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+add_to_size_group (EAPMethod *method, GtkSizeGroup *group)
+{
+ EAPMethodTTLS *self = EAP_METHOD_TTLS (method);
+
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->ca_cert_not_required_check));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->anon_identity_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->domain_match_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->ca_cert_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->inner_auth_label));
+
+ eap_method_add_to_size_group (EAP_METHOD (self->em_chap), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_gtc), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_md5), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_mschap), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_mschap_v2), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_pap), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_plain_mschap_v2), group);
+}
+
+static void
+fill_connection (EAPMethod *method, NMConnection *connection, NMSettingSecretFlags flags)
+{
+ EAPMethodTTLS *self = EAP_METHOD_TTLS (method);
+ NMSetting8021x *s_8021x;
+ NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ const char *text;
+ g_autofree gchar *filename = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GFile) file = NULL;
+ gboolean ca_cert_error = FALSE;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ g_assert (s_8021x);
+
+ nm_setting_802_1x_add_eap_method (s_8021x, "ttls");
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self->anon_identity_entry));
+ if (text && strlen (text))
+ g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, text, NULL);
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self->domain_match_entry));
+ if (text && strlen (text))
+ g_object_set (s_8021x, NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH, text, NULL);
+
+ file = ws_file_chooser_button_get_file (self->ca_cert_button);
+ filename = file ? g_file_get_path (file) : NULL;
+ if (!nm_setting_802_1x_set_ca_cert (s_8021x, filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+ g_warning ("Couldn't read CA certificate '%s': %s", filename, error ? error->message : "(unknown)");
+ ca_cert_error = TRUE;
+ }
+ eap_method_ca_cert_ignore_set (method, connection, filename, ca_cert_error);
+
+ eap_method_fill_connection (get_inner_method (self), connection, flags);
+}
+
+static void
+inner_auth_combo_changed_cb (EAPMethodTTLS *self)
+{
+ EAPMethod *inner_method;
+ GtkWidget *child;
+
+ inner_method = get_inner_method (self);
+
+ /* Remove the previous method and migrate username/password across */
+ child = gtk_widget_get_first_child (GTK_WIDGET (self->inner_auth_box));
+ if (child != NULL) {
+ EAPMethod *old_eap = EAP_METHOD (child);
+ eap_method_set_username (inner_method, eap_method_get_username (old_eap));
+ eap_method_set_password (inner_method, eap_method_get_password (old_eap));
+ eap_method_set_show_password (inner_method, eap_method_get_show_password (old_eap));
+ gtk_box_remove (self->inner_auth_box, child);
+ }
+
+ gtk_box_append (self->inner_auth_box, g_object_ref (GTK_WIDGET (inner_method)));
+
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+update_secrets (EAPMethod *method, NMConnection *connection)
+{
+ EAPMethodTTLS *self = EAP_METHOD_TTLS (method);
+
+ eap_method_update_secrets (EAP_METHOD (self->em_chap), connection);
+ eap_method_update_secrets (EAP_METHOD (self->em_gtc), connection);
+ eap_method_update_secrets (EAP_METHOD (self->em_md5), connection);
+ eap_method_update_secrets (EAP_METHOD (self->em_mschap), connection);
+ eap_method_update_secrets (EAP_METHOD (self->em_mschap_v2), connection);
+ eap_method_update_secrets (EAP_METHOD (self->em_pap), connection);
+ eap_method_update_secrets (EAP_METHOD (self->em_plain_mschap_v2), connection);
+}
+
+static GtkWidget *
+get_default_field (EAPMethod *method)
+{
+ EAPMethodTTLS *self = EAP_METHOD_TTLS (method);
+ return GTK_WIDGET (self->anon_identity_entry);
+}
+
+static const gchar *
+get_password_flags_name (EAPMethod *method)
+{
+ return NM_SETTING_802_1X_PASSWORD;
+}
+
+static const gchar *
+get_username (EAPMethod *method)
+{
+ EAPMethodTTLS *self = EAP_METHOD_TTLS (method);
+ return eap_method_get_username (get_inner_method (self));
+}
+
+static void
+set_username (EAPMethod *method, const gchar *username)
+{
+ EAPMethodTTLS *self = EAP_METHOD_TTLS (method);
+ return eap_method_set_username (get_inner_method (self), username);
+}
+
+static const gchar *
+get_password (EAPMethod *method)
+{
+ EAPMethodTTLS *self = EAP_METHOD_TTLS (method);
+ return eap_method_get_password (get_inner_method (self));
+}
+
+static void
+set_password (EAPMethod *method, const gchar *password)
+{
+ EAPMethodTTLS *self = EAP_METHOD_TTLS (method);
+ return eap_method_set_password (get_inner_method (self), password);
+}
+
+static gboolean
+get_show_password (EAPMethod *method)
+{
+ EAPMethodTTLS *self = EAP_METHOD_TTLS (method);
+ return eap_method_get_show_password (get_inner_method (self));
+}
+
+static void
+set_show_password (EAPMethod *method, gboolean show_password)
+{
+ EAPMethodTTLS *self = EAP_METHOD_TTLS (method);
+ return eap_method_set_show_password (get_inner_method (self), show_password);
+}
+
+static void
+changed_cb (EAPMethodTTLS *self)
+{
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+eap_method_ttls_init (EAPMethodTTLS *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+eap_method_ttls_class_init (EAPMethodTTLSClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/network/eap-method-ttls.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTTLS, anon_identity_entry);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTTLS, anon_identity_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTTLS, ca_cert_button);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTTLS, ca_cert_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTTLS, ca_cert_not_required_check);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTTLS, domain_match_entry);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTTLS, domain_match_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTTLS, inner_auth_combo);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTTLS, inner_auth_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTTLS, inner_auth_model);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTTLS, inner_auth_box);
+}
+
+static void
+eap_method_iface_init (EAPMethodInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->update_secrets = update_secrets;
+ iface->get_default_field = get_default_field;
+ iface->get_password_flags_name = get_password_flags_name;
+ iface->get_username = get_username;
+ iface->set_username = set_username;
+ iface->get_password = get_password;
+ iface->set_password = set_password;
+ iface->get_show_password = get_show_password;
+ iface->set_show_password = set_show_password;
+}
+
+EAPMethodTTLS *
+eap_method_ttls_new (NMConnection *connection)
+{
+ EAPMethodTTLS *self;
+ GtkFileFilter *filter;
+ NMSetting8021x *s_8021x = NULL;
+ const char *filename;
+ const char *phase2_auth = NULL;
+ GtkTreeIter iter;
+
+ self = g_object_new (eap_method_ttls_get_type (), NULL);
+
+ if (connection)
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+
+ g_signal_connect_swapped (self->ca_cert_not_required_check, "toggled", G_CALLBACK (ca_cert_not_required_toggled), self);
+
+ g_signal_connect_swapped (self->ca_cert_button, "notify::file", G_CALLBACK (changed_cb), self);
+ filter = eap_method_default_file_chooser_filter_new (FALSE);
+ gtk_file_chooser_add_filter (ws_file_chooser_button_get_filechooser (self->ca_cert_button),
+ filter);
+ if (connection && s_8021x) {
+ filename = NULL;
+ if (nm_setting_802_1x_get_ca_cert_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+ filename = nm_setting_802_1x_get_ca_cert_path (s_8021x);
+ if (filename) {
+ g_autoptr(GFile) file = g_file_new_for_path (filename);
+ ws_file_chooser_button_set_file (self->ca_cert_button, file);
+ }
+ }
+ gtk_check_button_set_active (self->ca_cert_not_required_check,
+ !filename && eap_method_ca_cert_ignore_get (EAP_METHOD (self), connection));
+ }
+
+ if (s_8021x && nm_setting_802_1x_get_anonymous_identity (s_8021x))
+ gtk_editable_set_text (GTK_EDITABLE (self->anon_identity_entry), nm_setting_802_1x_get_anonymous_identity (s_8021x));
+ g_signal_connect_swapped (self->anon_identity_entry, "changed", G_CALLBACK (changed_cb), self);
+ if (s_8021x && nm_setting_802_1x_get_domain_suffix_match (s_8021x))
+ gtk_editable_set_text (GTK_EDITABLE (self->domain_match_entry), nm_setting_802_1x_get_domain_suffix_match (s_8021x));
+ g_signal_connect_swapped (self->domain_match_entry, "changed", G_CALLBACK (changed_cb), self);
+
+ self->em_pap = eap_method_simple_new (connection, "pap", TRUE, FALSE);
+ gtk_widget_show (GTK_WIDGET (self->em_pap));
+ g_signal_connect_object (self->em_pap, "changed", G_CALLBACK (eap_method_emit_changed), self, G_CONNECT_SWAPPED);
+
+ self->em_mschap = eap_method_simple_new (connection, "mschap", TRUE, FALSE);
+ gtk_widget_show (GTK_WIDGET (self->em_mschap));
+ g_signal_connect_object (self->em_mschap, "changed", G_CALLBACK (eap_method_emit_changed), self, G_CONNECT_SWAPPED);
+
+ self->em_mschap_v2 = eap_method_simple_new (connection, "mschapv2", TRUE, TRUE);
+ gtk_widget_show (GTK_WIDGET (self->em_mschap_v2));
+ g_signal_connect_object (self->em_mschap_v2, "changed", G_CALLBACK (eap_method_emit_changed), self, G_CONNECT_SWAPPED);
+
+ self->em_plain_mschap_v2 = eap_method_simple_new (connection, "mschapv2", TRUE, FALSE);
+ gtk_widget_show (GTK_WIDGET (self->em_plain_mschap_v2));
+ g_signal_connect_object (self->em_plain_mschap_v2, "changed", G_CALLBACK (eap_method_emit_changed), self, G_CONNECT_SWAPPED);
+
+ self->em_chap = eap_method_simple_new (connection, "chap", TRUE, FALSE);
+ gtk_widget_show (GTK_WIDGET (self->em_chap));
+ g_signal_connect_object (self->em_chap, "changed", G_CALLBACK (eap_method_emit_changed), self, G_CONNECT_SWAPPED);
+
+ self->em_md5 = eap_method_simple_new (connection, "md5", TRUE, TRUE);
+ gtk_widget_show (GTK_WIDGET (self->em_md5));
+ g_signal_connect_object (self->em_md5, "changed", G_CALLBACK (eap_method_emit_changed), self, G_CONNECT_SWAPPED);
+
+ self->em_gtc = eap_method_simple_new (connection, "gtc", TRUE, TRUE);
+ gtk_widget_show (GTK_WIDGET (self->em_gtc));
+ g_signal_connect_object (self->em_gtc, "changed", G_CALLBACK (eap_method_emit_changed), self, G_CONNECT_SWAPPED);
+
+ if (s_8021x) {
+ if (nm_setting_802_1x_get_phase2_auth (s_8021x))
+ phase2_auth = nm_setting_802_1x_get_phase2_auth (s_8021x);
+ else if (nm_setting_802_1x_get_phase2_autheap (s_8021x))
+ phase2_auth = nm_setting_802_1x_get_phase2_autheap (s_8021x);
+ }
+ if (phase2_auth == NULL)
+ phase2_auth = "pap";
+
+ if (strcmp (phase2_auth, "mschapv2") == 0 && nm_setting_802_1x_get_phase2_auth (s_8021x) != NULL)
+ phase2_auth = "plain_mschapv2";
+
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->inner_auth_model), &iter)) {
+ do {
+ g_autofree gchar *id = NULL;
+ gtk_tree_model_get (GTK_TREE_MODEL (self->inner_auth_model), &iter, I_ID_COLUMN, &id, -1);
+ if (strcmp (id, phase2_auth) == 0)
+ gtk_combo_box_set_active_iter (self->inner_auth_combo, &iter);
+ } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->inner_auth_model), &iter));
+ }
+
+ g_signal_connect_swapped (self->inner_auth_combo, "changed", G_CALLBACK (inner_auth_combo_changed_cb), self);
+ inner_auth_combo_changed_cb (self);
+
+ return self;
+}
+
diff --git a/panels/network/wireless-security/eap-method-ttls.h b/panels/network/wireless-security/eap-method-ttls.h
new file mode 100644
index 0000000..56b7085
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-ttls.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (EAPMethodTTLS, eap_method_ttls, EAP, METHOD_TTLS, GtkGrid)
+
+EAPMethodTTLS *eap_method_ttls_new (NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/eap-method-ttls.ui b/panels/network/wireless-security/eap-method-ttls.ui
new file mode 100644
index 0000000..b10dac2
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-ttls.ui
@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.4"/>
+ <object class="GtkListStore" id="inner_auth_model">
+ <columns>
+ <!-- column-name label -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">PAP</col>
+ <col id="1">pap</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">MSCHAP</col>
+ <col id="1">mschap</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">MSCHAPv2</col>
+ <col id="1">mschapv2</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">MSCHAPv2 (no EAP)</col>
+ <col id="1">plain_mschapv2</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">CHAP</col>
+ <col id="1">chap</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">MD5</col>
+ <col id="1">md5</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">GTC</col>
+ <col id="1">gtc</col>
+ </row>
+ </data>
+ </object>
+ <template class="EAPMethodTTLS" parent="GtkGrid">
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="anon_identity_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Anony_mous identity</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">anon_identity_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="anon_identity_entry">
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="domain_match_label">
+ <property name="label" translatable="yes">_Domain</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">domain_match_entry</property>
+ <property name="xalign">1</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="domain_match_entry">
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="ca_cert_label">
+ <property name="label" translatable="yes">C_A certificate</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">ca_cert_button</property>
+ <property name="xalign">1</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="WsFileChooserButton" id="ca_cert_button">
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="ca_cert_not_required_check">
+ <property name="label" translatable="yes">No CA certificate is _required</property>
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="inner_auth_label">
+ <property name="label" translatable="yes">_Inner authentication</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">inner_auth_combo</property>
+ <property name="xalign">1</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">4</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="inner_auth_combo">
+ <property name="hexpand">True</property>
+ <property name="model">inner_auth_model</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">4</property>
+ </layout>
+ <child>
+ <object class="GtkCellRendererText"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="inner_auth_box">
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">5</property>
+ <property name="column-span">2</property>
+ </layout>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/wireless-security/eap-method.c b/panels/network/wireless-security/eap-method.c
new file mode 100644
index 0000000..a9d11c7
--- /dev/null
+++ b/panels/network/wireless-security/eap-method.c
@@ -0,0 +1,588 @@
+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include <fcntl.h>
+#include <glib/gi18n.h>
+
+#include "eap-method.h"
+#include "helpers.h"
+#include "ui-helpers.h"
+
+G_DEFINE_INTERFACE (EAPMethod, eap_method, G_TYPE_OBJECT)
+
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void
+eap_method_default_init (EAPMethodInterface *iface)
+{
+ signals[CHANGED] =
+ g_signal_new ("changed",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_FIRST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+GtkWidget *
+eap_method_get_default_field (EAPMethod *self)
+{
+ g_return_val_if_fail (self != NULL, NULL);
+
+ return EAP_METHOD_GET_IFACE (self)->get_default_field (self);
+}
+
+const gchar *
+eap_method_get_password_flags_name (EAPMethod *self)
+{
+ g_return_val_if_fail (self != NULL, NULL);
+
+ if (EAP_METHOD_GET_IFACE (self)->get_password_flags_name)
+ return EAP_METHOD_GET_IFACE (self)->get_password_flags_name (self);
+ else
+ return NULL;
+}
+
+gboolean
+eap_method_get_phase2 (EAPMethod *self)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+
+ if (EAP_METHOD_GET_IFACE (self)->get_phase2)
+ return EAP_METHOD_GET_IFACE (self)->get_phase2 (self);
+ else
+ return FALSE;
+}
+
+gboolean
+eap_method_validate (EAPMethod *self, GError **error)
+{
+ gboolean result;
+
+ g_return_val_if_fail (self != NULL, FALSE);
+
+ result = (*(EAP_METHOD_GET_IFACE (self)->validate)) (self, error);
+ if (!result && error && !*error)
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("undefined error in 802.1X security (wpa-eap)"));
+ return result;
+}
+
+void
+eap_method_update_secrets (EAPMethod *self, NMConnection *connection)
+{
+ g_return_if_fail (self != NULL);
+
+ if (EAP_METHOD_GET_IFACE (self)->update_secrets)
+ EAP_METHOD_GET_IFACE (self)->update_secrets (self, connection);
+}
+
+void
+eap_method_add_to_size_group (EAPMethod *self, GtkSizeGroup *group)
+{
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (group != NULL);
+
+ return (*(EAP_METHOD_GET_IFACE (self)->add_to_size_group)) (self, group);
+}
+
+void
+eap_method_fill_connection (EAPMethod *self,
+ NMConnection *connection,
+ NMSettingSecretFlags flags)
+{
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (connection != NULL);
+
+ return (*(EAP_METHOD_GET_IFACE (self)->fill_connection)) (self, connection, flags);
+}
+
+void
+eap_method_emit_changed (EAPMethod *self)
+{
+ g_return_if_fail (EAP_IS_METHOD (self));
+
+ g_signal_emit (self, signals[CHANGED], 0);
+}
+
+const gchar *
+eap_method_get_username (EAPMethod *self)
+{
+ g_return_val_if_fail (EAP_IS_METHOD (self), NULL);
+ return EAP_METHOD_GET_IFACE (self)->get_username (self);
+}
+
+void
+eap_method_set_username (EAPMethod *self, const gchar *username)
+{
+ g_return_if_fail (EAP_IS_METHOD (self));
+ EAP_METHOD_GET_IFACE (self)->set_username (self, username);
+}
+
+const gchar *
+eap_method_get_password (EAPMethod *self)
+{
+ g_return_val_if_fail (EAP_IS_METHOD (self), NULL);
+ return EAP_METHOD_GET_IFACE (self)->get_password (self);
+}
+
+void
+eap_method_set_password (EAPMethod *self, const gchar *password)
+{
+ g_return_if_fail (EAP_IS_METHOD (self));
+ EAP_METHOD_GET_IFACE (self)->set_password (self, password);
+}
+
+gboolean
+eap_method_get_show_password (EAPMethod *self)
+{
+ g_return_val_if_fail (EAP_IS_METHOD (self), FALSE);
+ return EAP_METHOD_GET_IFACE (self)->get_show_password (self);
+}
+
+void
+eap_method_set_show_password (EAPMethod *self, gboolean show_password)
+{
+ g_return_if_fail (EAP_IS_METHOD (self));
+ EAP_METHOD_GET_IFACE (self)->set_show_password (self, show_password);
+}
+
+gboolean
+eap_method_validate_filepicker (GtkFileChooser *chooser,
+ guint32 item_type,
+ const char *password,
+ NMSetting8021xCKFormat *out_format,
+ GError **error)
+{
+ g_autofree gchar *filename = NULL;
+ g_autoptr(NMSetting8021x) setting = NULL;
+ g_autoptr(GFile) file = NULL;
+ gboolean success = TRUE;
+
+ if (item_type == TYPE_PRIVATE_KEY) {
+ if (!password || *password == '\0')
+ success = FALSE;
+ }
+
+ file = gtk_file_chooser_get_file (chooser);
+ if (!file) {
+ if (item_type != TYPE_CA_CERT) {
+ success = FALSE;
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("no file selected"));
+ }
+ goto out;
+ }
+
+ filename = g_file_get_path (file);
+ if (!g_file_test (filename, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
+ success = FALSE;
+ goto out;
+ }
+
+ setting = (NMSetting8021x *) nm_setting_802_1x_new ();
+
+ success = FALSE;
+ if (item_type == TYPE_PRIVATE_KEY) {
+ if (nm_setting_802_1x_set_private_key (setting, filename, password, NM_SETTING_802_1X_CK_SCHEME_PATH, out_format, error))
+ success = TRUE;
+ } else if (item_type == TYPE_CLIENT_CERT) {
+ if (nm_setting_802_1x_set_client_cert (setting, filename, NM_SETTING_802_1X_CK_SCHEME_PATH, out_format, error))
+ success = TRUE;
+ } else if (item_type == TYPE_CA_CERT) {
+ if (nm_setting_802_1x_set_ca_cert (setting, filename, NM_SETTING_802_1X_CK_SCHEME_PATH, out_format, error))
+ success = TRUE;
+ } else
+ g_warning ("%s: invalid item type %d.", __func__, item_type);
+
+out:
+ if (!success && error && !*error)
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("unspecified error validating eap-method file"));
+
+ if (success)
+ widget_unset_error (GTK_WIDGET (chooser));
+ else
+ widget_set_error (GTK_WIDGET (chooser));
+ return success;
+}
+
+static gboolean
+file_is_mime_type (const char *path, const char *mime_types[])
+{
+ g_autoptr(GFile) file = NULL;
+ g_autoptr(GFileInfo) info = NULL;
+ const char *content_type;
+ int i = 0;
+ gboolean found = FALSE;
+
+ file = g_file_new_for_path (path);
+ info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ NULL);
+ if (info) {
+ content_type = g_file_info_get_content_type (info);
+ if (content_type) {
+ while (mime_types[i]) {
+ if (strcmp (content_type, mime_types[i++]) == 0) {
+ found = TRUE;
+ break;
+ }
+ }
+ }
+ }
+
+ return found;
+}
+
+#if !LIBNM_BUILD
+static const char *
+find_tag (const char *tag, const char *buf, gsize len)
+{
+ gsize i, taglen;
+
+ taglen = strlen (tag);
+ if (len < taglen)
+ return NULL;
+
+ for (i = 0; i < len - taglen + 1; i++) {
+ if (memcmp (buf + i, tag, taglen) == 0)
+ return buf + i;
+ }
+ return NULL;
+}
+
+static const char *pem_rsa_key_begin = "-----BEGIN RSA PRIVATE KEY-----";
+static const char *pem_dsa_key_begin = "-----BEGIN DSA PRIVATE KEY-----";
+static const char *pem_pkcs8_enc_key_begin = "-----BEGIN ENCRYPTED PRIVATE KEY-----";
+static const char *pem_pkcs8_dec_key_begin = "-----BEGIN PRIVATE KEY-----";
+static const char *pem_cert_begin = "-----BEGIN CERTIFICATE-----";
+static const char *proc_type_tag = "Proc-Type: 4,ENCRYPTED";
+static const char *dek_info_tag = "DEK-Info:";
+
+static gboolean
+pem_file_is_encrypted (const char *buffer, gsize bytes_read)
+{
+ /* Check if the private key is encrypted or not by looking for the
+ * old OpenSSL-style proc-type and dec-info tags.
+ */
+ if (find_tag (proc_type_tag, (const char *) buffer, bytes_read)) {
+ if (find_tag (dek_info_tag, (const char *) buffer, bytes_read))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+file_is_der_or_pem (const char *filename,
+ gboolean privkey,
+ gboolean *out_privkey_encrypted)
+{
+ int fd;
+ unsigned char buffer[8192];
+ ssize_t bytes_read;
+ gboolean success = FALSE;
+
+ fd = open (filename, O_RDONLY);
+ if (fd < 0)
+ return FALSE;
+
+ bytes_read = read (fd, buffer, sizeof (buffer) - 1);
+ if (bytes_read < 400) /* needs to be lower? */
+ goto out;
+ buffer[bytes_read] = '\0';
+
+ /* Check for DER signature */
+ if (bytes_read > 2 && buffer[0] == 0x30 && buffer[1] == 0x82) {
+ success = TRUE;
+ goto out;
+ }
+
+ /* Check for PEM signatures */
+ if (privkey) {
+ if (find_tag (pem_rsa_key_begin, (const char *) buffer, bytes_read)) {
+ success = TRUE;
+ if (out_privkey_encrypted)
+ *out_privkey_encrypted = pem_file_is_encrypted ((const char *) buffer, bytes_read);
+ goto out;
+ }
+
+ if (find_tag (pem_dsa_key_begin, (const char *) buffer, bytes_read)) {
+ success = TRUE;
+ if (out_privkey_encrypted)
+ *out_privkey_encrypted = pem_file_is_encrypted ((const char *) buffer, bytes_read);
+ goto out;
+ }
+
+ if (find_tag (pem_pkcs8_enc_key_begin, (const char *) buffer, bytes_read)) {
+ success = TRUE;
+ if (out_privkey_encrypted)
+ *out_privkey_encrypted = TRUE;
+ goto out;
+ }
+
+ if (find_tag (pem_pkcs8_dec_key_begin, (const char *) buffer, bytes_read)) {
+ success = TRUE;
+ if (out_privkey_encrypted)
+ *out_privkey_encrypted = FALSE;
+ goto out;
+ }
+ } else {
+ if (find_tag (pem_cert_begin, (const char *) buffer, bytes_read)) {
+ success = TRUE;
+ goto out;
+ }
+ }
+
+out:
+ close (fd);
+ return success;
+}
+#endif
+
+static const char *privkey_mime_types[] = {
+ "application/x-x509-ca-cert", "application/pkcs12", "application/x-pkcs12", "application/pgp-keys", NULL
+};
+static const char *cert_mime_types[] = {
+ "application/x-x509-ca-cert", NULL
+};
+
+static void
+add_mime_types_to_filter (GtkFileFilter *filter,
+ const char **mime_types)
+{
+ int i;
+
+ for (i = 0; mime_types[i] != NULL; i++)
+ gtk_file_filter_add_mime_type (filter, mime_types[i]);
+}
+
+
+GtkFileFilter *
+eap_method_default_file_chooser_filter_new (gboolean privkey)
+{
+ GtkFileFilter *filter;
+
+ filter = gtk_file_filter_new ();
+ if (privkey) {
+ add_mime_types_to_filter (filter, privkey_mime_types);
+ gtk_file_filter_set_name (filter, _("DER, PEM, PKCS#12, or PGP private keys"));
+ } else {
+ add_mime_types_to_filter (filter, cert_mime_types);
+ gtk_file_filter_set_name (filter, _("DER or PEM certificates"));
+ }
+ return filter;
+}
+
+gboolean
+eap_method_is_encrypted_private_key (const char *path)
+{
+ gboolean is_encrypted;
+
+ if (!file_is_mime_type (path, privkey_mime_types))
+ return FALSE;
+
+#if LIBNM_BUILD
+ is_encrypted = FALSE;
+ if (!nm_utils_file_is_private_key (path, &is_encrypted))
+ return FALSE;
+#else
+ is_encrypted = TRUE;
+ if ( !file_is_der_or_pem (path, TRUE, &is_encrypted)
+ && !nm_utils_file_is_pkcs12 (path))
+ return FALSE;
+#endif
+ return is_encrypted;
+}
+
+void
+eap_method_ca_cert_not_required_toggled (GtkCheckButton *id_ca_cert_not_required_checkbutton, GtkFileChooser *id_ca_cert_chooser)
+{
+ g_autoptr(GFile) file = NULL;
+ g_autoptr(GFile) file_old = NULL;
+ gboolean is_not_required;
+
+ g_assert (id_ca_cert_not_required_checkbutton && id_ca_cert_chooser);
+
+ is_not_required = gtk_check_button_get_active (id_ca_cert_not_required_checkbutton);
+
+ file = gtk_file_chooser_get_file (id_ca_cert_chooser);
+ file_old = g_object_steal_data (G_OBJECT (id_ca_cert_chooser), "filename-old");
+ if (is_not_required) {
+ g_clear_object (&file_old);
+ file_old = g_steal_pointer (&file);
+ } else {
+ g_clear_object (&file);
+ file = g_steal_pointer (&file_old);
+ }
+ gtk_widget_set_sensitive (GTK_WIDGET (id_ca_cert_chooser), !is_not_required);
+ if (file)
+ gtk_file_chooser_set_file (id_ca_cert_chooser, file, NULL);
+ g_object_set_data_full (G_OBJECT (id_ca_cert_chooser), "filename-old", g_steal_pointer (&file_old), g_free);
+}
+
+/* Used as both GSettings keys and GObject data tags */
+#define IGNORE_CA_CERT_TAG "ignore-ca-cert"
+#define IGNORE_PHASE2_CA_CERT_TAG "ignore-phase2-ca-cert"
+
+/**
+ * eap_method_ca_cert_ignore_set:
+ * @method: the #EAPMethod object
+ * @connection: the #NMConnection
+ * @filename: the certificate file, if any
+ * @ca_cert_error: %TRUE if an error was encountered loading the given CA
+ * certificate, %FALSE if not or if a CA certificate is not present
+ *
+ * Updates the connection's CA cert ignore value to %TRUE if the "CA certificate
+ * not required" checkbox is checked. If @ca_cert_error is %TRUE, then the
+ * connection's CA cert ignore value will always be set to %FALSE, because it
+ * means that the user selected an invalid certificate (thus he does not want to
+ * ignore the CA cert)..
+ */
+void
+eap_method_ca_cert_ignore_set (EAPMethod *self,
+ NMConnection *connection,
+ const char *filename,
+ gboolean ca_cert_error)
+{
+ NMSetting8021x *s_8021x;
+ gboolean ignore;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (s_8021x) {
+ ignore = !ca_cert_error && filename == NULL;
+ g_object_set_data (G_OBJECT (s_8021x),
+ eap_method_get_phase2 (self) ? IGNORE_PHASE2_CA_CERT_TAG : IGNORE_CA_CERT_TAG,
+ GUINT_TO_POINTER (ignore));
+ }
+}
+
+/**
+ * eap_method_ca_cert_ignore_get:
+ * @method: the #EAPMethod object
+ * @connection: the #NMConnection
+ *
+ * Returns: %TRUE if a missing CA certificate can be ignored, %FALSE if a CA
+ * certificate should be required for the connection to be valid.
+ */
+gboolean
+eap_method_ca_cert_ignore_get (EAPMethod *self, NMConnection *connection)
+{
+ NMSetting8021x *s_8021x;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (s_8021x) {
+ return !!g_object_get_data (G_OBJECT (s_8021x),
+ eap_method_get_phase2 (self) ? IGNORE_PHASE2_CA_CERT_TAG : IGNORE_CA_CERT_TAG);
+ }
+ return FALSE;
+}
+
+static GSettings *
+_get_ca_ignore_settings (NMConnection *connection)
+{
+ GSettings *settings;
+ g_autofree gchar *path = NULL;
+ const char *uuid;
+
+ g_return_val_if_fail (connection, NULL);
+
+ uuid = nm_connection_get_uuid (connection);
+ g_return_val_if_fail (uuid && *uuid, NULL);
+
+ path = g_strdup_printf ("/org/gnome/nm-applet/eap/%s/", uuid);
+ settings = g_settings_new_with_path ("org.gnome.nm-applet.eap", path);
+
+ return settings;
+}
+
+/**
+ * eap_method_ca_cert_ignore_save:
+ * @connection: the connection for which to save CA cert ignore values to GSettings
+ *
+ * Reads the CA cert ignore tags from the 802.1x setting GObject data and saves
+ * then to GSettings if present, using the connection UUID as the index.
+ */
+void
+eap_method_ca_cert_ignore_save (NMConnection *connection)
+{
+ NMSetting8021x *s_8021x;
+ g_autoptr(GSettings) settings = NULL;
+ gboolean ignore = FALSE, phase2_ignore = FALSE;
+
+ g_return_if_fail (connection);
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (s_8021x) {
+ ignore = !!g_object_get_data (G_OBJECT (s_8021x), IGNORE_CA_CERT_TAG);
+ phase2_ignore = !!g_object_get_data (G_OBJECT (s_8021x), IGNORE_PHASE2_CA_CERT_TAG);
+ }
+
+ settings = _get_ca_ignore_settings (connection);
+ if (!settings)
+ return;
+
+ g_settings_set_boolean (settings, IGNORE_CA_CERT_TAG, ignore);
+ g_settings_set_boolean (settings, IGNORE_PHASE2_CA_CERT_TAG, phase2_ignore);
+}
+
+/**
+ * eap_method_ca_cert_ignore_load:
+ * @connection: the connection for which to load CA cert ignore values to GSettings
+ *
+ * Reads the CA cert ignore tags from the 802.1x setting GObject data and saves
+ * then to GSettings if present, using the connection UUID as the index.
+ */
+void
+eap_method_ca_cert_ignore_load (NMConnection *connection)
+{
+ g_autoptr(GSettings) settings = NULL;
+ NMSetting8021x *s_8021x;
+ gboolean ignore, phase2_ignore;
+
+ g_return_if_fail (connection);
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (!s_8021x)
+ return;
+
+ settings = _get_ca_ignore_settings (connection);
+ if (!settings)
+ return;
+
+ ignore = g_settings_get_boolean (settings, IGNORE_CA_CERT_TAG);
+ phase2_ignore = g_settings_get_boolean (settings, IGNORE_PHASE2_CA_CERT_TAG);
+
+ g_object_set_data (G_OBJECT (s_8021x),
+ IGNORE_CA_CERT_TAG,
+ GUINT_TO_POINTER (ignore));
+ g_object_set_data (G_OBJECT (s_8021x),
+ IGNORE_PHASE2_CA_CERT_TAG,
+ GUINT_TO_POINTER (phase2_ignore));
+}
+
diff --git a/panels/network/wireless-security/eap-method.h b/panels/network/wireless-security/eap-method.h
new file mode 100644
index 0000000..d5a8908
--- /dev/null
+++ b/panels/network/wireless-security/eap-method.h
@@ -0,0 +1,108 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_INTERFACE (EAPMethod, eap_method, EAP, METHOD, GObject)
+
+struct _EAPMethodInterface {
+ GTypeInterface g_iface;
+
+ void (*add_to_size_group) (EAPMethod *method, GtkSizeGroup *group);
+ void (*fill_connection) (EAPMethod *method, NMConnection *connection, NMSettingSecretFlags flags);
+ void (*update_secrets) (EAPMethod *method, NMConnection *connection);
+ gboolean (*validate) (EAPMethod *method, GError **error);
+ GtkWidget* (*get_default_field) (EAPMethod *method);
+ const gchar* (*get_password_flags_name) (EAPMethod *method);
+ gboolean (*get_phase2) (EAPMethod *method);
+ const gchar* (*get_username) (EAPMethod *method);
+ void (*set_username) (EAPMethod *method, const gchar *username);
+ const gchar* (*get_password) (EAPMethod *method);
+ void (*set_password) (EAPMethod *method, const gchar *password);
+ gboolean (*get_show_password) (EAPMethod *method);
+ void (*set_show_password) (EAPMethod *method, gboolean show_password);
+};
+
+GtkWidget *eap_method_get_default_field (EAPMethod *method);
+
+const gchar *eap_method_get_password_flags_name (EAPMethod *method);
+
+gboolean eap_method_get_phase2 (EAPMethod *method);
+
+void eap_method_update_secrets (EAPMethod *method, NMConnection *connection);
+
+gboolean eap_method_validate (EAPMethod *method, GError **error);
+
+void eap_method_add_to_size_group (EAPMethod *method, GtkSizeGroup *group);
+
+void eap_method_fill_connection (EAPMethod *method,
+ NMConnection *connection,
+ NMSettingSecretFlags flags);
+
+void eap_method_emit_changed (EAPMethod *method);
+
+const gchar *eap_method_get_username (EAPMethod *method);
+
+void eap_method_set_username (EAPMethod *method, const gchar *username);
+
+const gchar *eap_method_get_password (EAPMethod *method);
+
+void eap_method_set_password (EAPMethod *method, const gchar *password);
+
+gboolean eap_method_get_show_password (EAPMethod *method);
+
+void eap_method_set_show_password (EAPMethod *method, gboolean show_password);
+
+/* Below for internal use only */
+
+GtkFileFilter * eap_method_default_file_chooser_filter_new (gboolean privkey);
+
+gboolean eap_method_is_encrypted_private_key (const char *path);
+
+#define TYPE_CLIENT_CERT 0
+#define TYPE_CA_CERT 1
+#define TYPE_PRIVATE_KEY 2
+
+gboolean eap_method_validate_filepicker (GtkFileChooser *chooser,
+ guint32 item_type,
+ const char *password,
+ NMSetting8021xCKFormat *out_format,
+ GError **error);
+
+void eap_method_ca_cert_not_required_toggled (GtkCheckButton *id_ca_cert_is_not_required_checkbox,
+ GtkFileChooser *id_ca_cert_chooser);
+
+void eap_method_ca_cert_ignore_set (EAPMethod *method,
+ NMConnection *connection,
+ const char *filename,
+ gboolean ca_cert_error);
+gboolean eap_method_ca_cert_ignore_get (EAPMethod *method, NMConnection *connection);
+
+void eap_method_ca_cert_ignore_save (NMConnection *connection);
+void eap_method_ca_cert_ignore_load (NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/helpers.c b/panels/network/wireless-security/helpers.c
new file mode 100644
index 0000000..fc8446b
--- /dev/null
+++ b/panels/network/wireless-security/helpers.c
@@ -0,0 +1,60 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2009 - 2014 Red Hat, Inc.
+ */
+
+#include "helpers.h"
+
+void
+helper_fill_secret_entry (NMConnection *connection,
+ GtkEntry *entry,
+ GType setting_type,
+ HelperSecretFunc func)
+{
+ NMSetting *setting;
+ const char *tmp;
+
+ g_return_if_fail (connection != NULL);
+ g_return_if_fail (entry != NULL);
+ g_return_if_fail (func != NULL);
+
+ setting = nm_connection_get_setting (connection, setting_type);
+ if (setting) {
+ tmp = (*func) (setting);
+ if (tmp) {
+ gtk_editable_set_text (GTK_EDITABLE (entry), tmp);
+ }
+ }
+}
+
+void
+wireless_security_clear_ciphers (NMConnection *connection)
+{
+ NMSettingWirelessSecurity *s_wireless_sec;
+
+ g_return_if_fail (connection != NULL);
+
+ s_wireless_sec = nm_connection_get_setting_wireless_security (connection);
+ g_assert (s_wireless_sec);
+
+ nm_setting_wireless_security_clear_protos (s_wireless_sec);
+ nm_setting_wireless_security_clear_pairwise (s_wireless_sec);
+ nm_setting_wireless_security_clear_groups (s_wireless_sec);
+}
diff --git a/panels/network/wireless-security/helpers.h b/panels/network/wireless-security/helpers.h
new file mode 100644
index 0000000..6a402d8
--- /dev/null
+++ b/panels/network/wireless-security/helpers.h
@@ -0,0 +1,45 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2009 - 2014 Red Hat, Inc.
+ */
+
+#ifndef _HELPERS_H_
+#define _HELPERS_H_
+
+#include <NetworkManager.h>
+#include <gtk/gtk.h>
+
+#define NMA_ERROR (g_quark_from_static_string ("nma-error-quark"))
+
+typedef enum {
+ NMA_ERROR_GENERIC
+} NMAError;
+
+typedef const char * (*HelperSecretFunc)(NMSetting *);
+
+void helper_fill_secret_entry (NMConnection *connection,
+ GtkEntry *entry,
+ GType setting_type,
+ HelperSecretFunc func);
+
+void wireless_security_clear_ciphers (NMConnection *connection);
+
+#endif /* _HELPERS_H_ */
+
diff --git a/panels/network/wireless-security/meson.build b/panels/network/wireless-security/meson.build
new file mode 100644
index 0000000..7f43efc
--- /dev/null
+++ b/panels/network/wireless-security/meson.build
@@ -0,0 +1,73 @@
+name = 'wireless-security'
+
+wireless_security_inc = include_directories('.')
+
+nm_applet_headers = [
+ 'eap-method.h',
+ 'eap-method-fast.h',
+ 'eap-method-leap.h',
+ 'eap-method-peap.h',
+ 'eap-method-simple.h',
+ 'eap-method-tls.h',
+ 'eap-method-ttls.h',
+ 'helpers.h',
+ 'wireless-security.h',
+ 'ws-leap.h',
+ 'ws-dynamic-wep.h',
+ 'ws-file-chooser-button.h',
+ 'ws-sae.h',
+ 'ws-wep-key.h',
+ 'ws-wpa-eap.h',
+ 'ws-wpa-psk.h'
+]
+
+nm_applet_sources = [
+ 'eap-method.c',
+ 'eap-method-fast.c',
+ 'eap-method-leap.c',
+ 'eap-method-peap.c',
+ 'eap-method-simple.c',
+ 'eap-method-tls.c',
+ 'eap-method-ttls.c',
+ 'helpers.c',
+ 'wireless-security.c',
+ 'ws-leap.c',
+ 'ws-dynamic-wep.c',
+ 'ws-file-chooser-button.c',
+ 'ws-sae.c',
+ 'ws-wep-key.c',
+ 'ws-wpa-eap.c',
+ 'ws-wpa-psk.c'
+]
+
+sources = files(nm_applet_sources)
+
+nm_resource_data = [
+ 'eap-method-fast.ui',
+ 'eap-method-leap.ui',
+ 'eap-method-peap.ui',
+ 'eap-method-simple.ui',
+ 'eap-method-tls.ui',
+ 'eap-method-ttls.ui',
+ 'ws-dynamic-wep.ui',
+ 'ws-leap.ui',
+ 'ws-sae.ui',
+ 'ws-wep-key.ui',
+ 'ws-wpa-eap.ui',
+ 'ws-wpa-psk.ui'
+]
+
+sources += gnome.compile_resources(
+ name + '-resources',
+ name + '.gresource.xml',
+ c_name: name.underscorify(),
+ dependencies: files(nm_resource_data),
+ export: true
+)
+
+libwireless_security = static_library(
+ name,
+ sources: sources,
+ include_directories: [top_inc, network_inc],
+ dependencies: deps
+)
diff --git a/panels/network/wireless-security/wireless-security.c b/panels/network/wireless-security/wireless-security.c
new file mode 100644
index 0000000..9f083f6
--- /dev/null
+++ b/panels/network/wireless-security/wireless-security.c
@@ -0,0 +1,101 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+
+#include "helpers.h"
+#include "wireless-security.h"
+#include "wireless-security-resources.h"
+
+G_DEFINE_INTERFACE (WirelessSecurity, wireless_security, G_TYPE_OBJECT)
+
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void
+wireless_security_default_init (WirelessSecurityInterface *iface)
+{
+ g_resources_register (wireless_security_get_resource ());
+
+ signals[CHANGED] =
+ g_signal_new ("changed",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_FIRST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+void
+wireless_security_notify_changed (WirelessSecurity *self)
+{
+ g_return_if_fail (WIRELESS_IS_SECURITY (self));
+
+ g_signal_emit (self, signals[CHANGED], 0);
+}
+
+gboolean
+wireless_security_validate (WirelessSecurity *self, GError **error)
+{
+ gboolean result;
+
+ g_return_val_if_fail (WIRELESS_IS_SECURITY (self), FALSE);
+ g_return_val_if_fail (!error || !*error, FALSE);
+
+ result = WIRELESS_SECURITY_GET_IFACE (self)->validate (self, error);
+ if (!result && error && !*error)
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("Unknown error validating 802.1X security"));
+ return result;
+}
+
+void
+wireless_security_add_to_size_group (WirelessSecurity *self, GtkSizeGroup *group)
+{
+ g_return_if_fail (WIRELESS_IS_SECURITY (self));
+ g_return_if_fail (GTK_IS_SIZE_GROUP (group));
+
+ return WIRELESS_SECURITY_GET_IFACE (self)->add_to_size_group (self, group);
+}
+
+void
+wireless_security_fill_connection (WirelessSecurity *self,
+ NMConnection *connection)
+{
+ g_return_if_fail (WIRELESS_IS_SECURITY (self));
+ g_return_if_fail (connection != NULL);
+
+ return WIRELESS_SECURITY_GET_IFACE (self)->fill_connection (self, connection);
+}
+
+gboolean
+wireless_security_adhoc_compatible (WirelessSecurity *self)
+{
+ if (WIRELESS_SECURITY_GET_IFACE (self)->adhoc_compatible)
+ return WIRELESS_SECURITY_GET_IFACE (self)->adhoc_compatible (self);
+ else
+ return TRUE;
+}
diff --git a/panels/network/wireless-security/wireless-security.gresource.xml b/panels/network/wireless-security/wireless-security.gresource.xml
new file mode 100644
index 0000000..c82860c
--- /dev/null
+++ b/panels/network/wireless-security/wireless-security.gresource.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/Settings/network/">
+ <file preprocess="xml-stripblanks">eap-method-leap.ui</file>
+ <file preprocess="xml-stripblanks">eap-method-fast.ui</file>
+ <file preprocess="xml-stripblanks">eap-method-peap.ui</file>
+ <file preprocess="xml-stripblanks">eap-method-simple.ui</file>
+ <file preprocess="xml-stripblanks">eap-method-tls.ui</file>
+ <file preprocess="xml-stripblanks">eap-method-ttls.ui</file>
+ <file preprocess="xml-stripblanks">ws-dynamic-wep.ui</file>
+ <file preprocess="xml-stripblanks">ws-leap.ui</file>
+ <file preprocess="xml-stripblanks">ws-sae.ui</file>
+ <file preprocess="xml-stripblanks">ws-wep-key.ui</file>
+ <file preprocess="xml-stripblanks">ws-wpa-eap.ui</file>
+ <file preprocess="xml-stripblanks">ws-wpa-psk.ui</file>
+ </gresource>
+</gresources>
diff --git a/panels/network/wireless-security/wireless-security.h b/panels/network/wireless-security/wireless-security.h
new file mode 100644
index 0000000..7f1cbed
--- /dev/null
+++ b/panels/network/wireless-security/wireless-security.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_INTERFACE (WirelessSecurity, wireless_security, WIRELESS, SECURITY, GObject)
+
+struct _WirelessSecurityInterface {
+ GTypeInterface g_iface;
+
+ void (*add_to_size_group) (WirelessSecurity *sec, GtkSizeGroup *group);
+ void (*fill_connection) (WirelessSecurity *sec, NMConnection *connection);
+ gboolean (*validate) (WirelessSecurity *sec, GError **error);
+ gboolean (*adhoc_compatible) (WirelessSecurity *sec);
+};
+
+gboolean wireless_security_validate (WirelessSecurity *sec, GError **error);
+
+void wireless_security_add_to_size_group (WirelessSecurity *sec,
+ GtkSizeGroup *group);
+
+void wireless_security_fill_connection (WirelessSecurity *sec,
+ NMConnection *connection);
+
+gboolean wireless_security_adhoc_compatible (WirelessSecurity *sec);
+
+void wireless_security_notify_changed (WirelessSecurity *sec);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/ws-dynamic-wep.c b/panels/network/wireless-security/ws-dynamic-wep.c
new file mode 100644
index 0000000..87a5bb9
--- /dev/null
+++ b/panels/network/wireless-security/ws-dynamic-wep.c
@@ -0,0 +1,262 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+
+#include "eap-method.h"
+#include "eap-method-fast.h"
+#include "eap-method-leap.h"
+#include "eap-method-peap.h"
+#include "eap-method-simple.h"
+#include "eap-method-tls.h"
+#include "eap-method-ttls.h"
+#include "wireless-security.h"
+#include "ws-dynamic-wep.h"
+
+struct _WirelessSecurityDynamicWEP {
+ GtkGrid parent;
+
+ GtkComboBox *auth_combo;
+ GtkLabel *auth_label;
+ GtkListStore *auth_model;
+ GtkBox *method_box;
+
+ EAPMethodTLS *em_tls;
+ EAPMethodLEAP *em_leap;
+ EAPMethodSimple *em_pwd;
+ EAPMethodFAST *em_fast;
+ EAPMethodTTLS *em_ttls;
+ EAPMethodPEAP *em_peap;
+};
+
+static void wireless_security_iface_init (WirelessSecurityInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (WirelessSecurityDynamicWEP, ws_dynamic_wep, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (wireless_security_get_type (), wireless_security_iface_init));
+
+#define AUTH_NAME_COLUMN 0
+#define AUTH_ID_COLUMN 1
+
+static EAPMethod *
+get_eap (WirelessSecurityDynamicWEP *self)
+{
+ GtkTreeIter iter;
+ g_autofree gchar *id = NULL;
+
+ if (!gtk_combo_box_get_active_iter (self->auth_combo, &iter))
+ return NULL;
+ gtk_tree_model_get (GTK_TREE_MODEL (self->auth_model), &iter, AUTH_ID_COLUMN, &id, -1);
+
+ if (strcmp (id, "tls") == 0)
+ return EAP_METHOD (self->em_tls);
+ if (strcmp (id, "leap") == 0)
+ return EAP_METHOD (self->em_leap);
+ if (strcmp (id, "pwd") == 0)
+ return EAP_METHOD (self->em_pwd);
+ if (strcmp (id, "fast") == 0)
+ return EAP_METHOD (self->em_fast);
+ if (strcmp (id, "ttls") == 0)
+ return EAP_METHOD (self->em_ttls);
+ if (strcmp (id, "peap") == 0)
+ return EAP_METHOD (self->em_peap);
+
+ return NULL;
+}
+
+static gboolean
+validate (WirelessSecurity *security, GError **error)
+{
+ WirelessSecurityDynamicWEP *self = WS_DYNAMIC_WEP (security);
+ return eap_method_validate (get_eap (self), error);
+}
+
+static void
+add_to_size_group (WirelessSecurity *security, GtkSizeGroup *group)
+{
+ WirelessSecurityDynamicWEP *self = WS_DYNAMIC_WEP (security);
+
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->auth_label));
+ eap_method_add_to_size_group (EAP_METHOD (self->em_tls), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_leap), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_pwd), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_fast), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_ttls), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_peap), group);
+}
+
+static void
+fill_connection (WirelessSecurity *security, NMConnection *connection)
+{
+ WirelessSecurityDynamicWEP *self = WS_DYNAMIC_WEP (security);
+ NMSettingWirelessSecurity *s_wireless_sec;
+ NMSetting8021x *s_8021x;
+ NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
+ EAPMethod *eap;
+
+ /* Get the EAPMethod object */
+ eap = get_eap (self);
+
+ /* Get previous pasword flags, if any. Otherwise default to agent-owned secrets */
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (s_8021x)
+ nm_setting_get_secret_flags (NM_SETTING (s_8021x), eap_method_get_password_flags_name (eap), &secret_flags, NULL);
+ else
+ secret_flags = NM_SETTING_SECRET_FLAG_AGENT_OWNED;
+
+ /* Blow away the old wireless security setting by adding a clear one */
+ s_wireless_sec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+ nm_connection_add_setting (connection, (NMSetting *) s_wireless_sec);
+
+ /* Blow away the old 802.1x setting by adding a clear one */
+ s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
+ nm_connection_add_setting (connection, (NMSetting *) s_8021x);
+
+ eap_method_fill_connection (eap, connection, secret_flags);
+
+ g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", NULL);
+}
+
+static gboolean
+adhoc_compatible (WirelessSecurity *security)
+{
+ return FALSE;
+}
+
+static void
+auth_combo_changed_cb (WirelessSecurityDynamicWEP *self)
+{
+ EAPMethod *eap;
+ GtkWidget *eap_default_field;
+ GtkWidget *child;
+
+ eap = get_eap (self);
+
+ /* Remove the previous method and migrate username/password across */
+ child = gtk_widget_get_first_child (GTK_WIDGET (self->method_box));
+ if (child != NULL) {
+ EAPMethod *old_eap = EAP_METHOD (child);
+ eap_method_set_username (eap, eap_method_get_username (old_eap));
+ eap_method_set_password (eap, eap_method_get_password (old_eap));
+ eap_method_set_show_password (eap, eap_method_get_show_password (old_eap));
+ gtk_box_remove (self->method_box, child);
+ }
+
+ gtk_box_append (self->method_box, g_object_ref (GTK_WIDGET (eap)));
+ eap_default_field = eap_method_get_default_field (eap);
+ if (eap_default_field)
+ gtk_widget_grab_focus (eap_default_field);
+
+ wireless_security_notify_changed (WIRELESS_SECURITY (self));
+}
+
+void
+ws_dynamic_wep_init (WirelessSecurityDynamicWEP *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+void
+ws_dynamic_wep_class_init (WirelessSecurityDynamicWEPClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/network/ws-dynamic-wep.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityDynamicWEP, auth_combo);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityDynamicWEP, auth_label);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityDynamicWEP, auth_model);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityDynamicWEP, method_box);
+}
+
+static void
+wireless_security_iface_init (WirelessSecurityInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->adhoc_compatible = adhoc_compatible;
+}
+
+WirelessSecurityDynamicWEP *
+ws_dynamic_wep_new (NMConnection *connection)
+{
+ WirelessSecurityDynamicWEP *self;
+ const gchar *default_method = NULL;
+ GtkTreeIter iter;
+
+ self = g_object_new (ws_dynamic_wep_get_type (), NULL);
+
+ /* Grab the default EAP method out of the security object */
+ if (connection) {
+ NMSetting8021x *s_8021x;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (s_8021x && nm_setting_802_1x_get_num_eap_methods (s_8021x))
+ default_method = nm_setting_802_1x_get_eap_method (s_8021x, 0);
+ }
+ if (default_method == NULL)
+ default_method = "tls";
+
+ self->em_tls = eap_method_tls_new (connection);
+ gtk_widget_show (GTK_WIDGET (self->em_tls));
+ g_signal_connect_object (self->em_tls, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+ self->em_leap = eap_method_leap_new (connection);
+ gtk_widget_show (GTK_WIDGET (self->em_leap));
+ g_signal_connect_object (self->em_leap, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+ self->em_pwd = eap_method_simple_new (connection, "pwd", FALSE, FALSE);
+ gtk_widget_show (GTK_WIDGET (self->em_pwd));
+ g_signal_connect_object (self->em_pwd, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+ self->em_fast = eap_method_fast_new (connection);
+ gtk_widget_show (GTK_WIDGET (self->em_fast));
+ g_signal_connect_object (self->em_fast, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+ self->em_ttls = eap_method_ttls_new (connection);
+ gtk_widget_show (GTK_WIDGET (self->em_ttls));
+ g_signal_connect_object (self->em_ttls, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+ self->em_peap = eap_method_peap_new (connection);
+ gtk_widget_show (GTK_WIDGET (self->em_peap));
+ g_signal_connect_object (self->em_peap, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->auth_model), &iter)) {
+ do {
+ g_autofree gchar *id = NULL;
+ gtk_tree_model_get (GTK_TREE_MODEL (self->auth_model), &iter, AUTH_ID_COLUMN, &id, -1);
+ if (strcmp (id, default_method) == 0)
+ gtk_combo_box_set_active_iter (self->auth_combo, &iter);
+ } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->auth_model), &iter));
+ }
+
+ if (connection) {
+ NMSetting8021x *setting;
+
+ setting = nm_connection_get_setting_802_1x (connection);
+ if (setting) {
+ eap_method_set_username (get_eap (self), nm_setting_802_1x_get_identity (setting));
+ eap_method_set_password (get_eap (self), nm_setting_802_1x_get_password (setting));
+ }
+ }
+
+ g_signal_connect_object (G_OBJECT (self->auth_combo), "changed", G_CALLBACK (auth_combo_changed_cb), self, G_CONNECT_SWAPPED);
+ auth_combo_changed_cb (self);
+
+ return self;
+}
+
diff --git a/panels/network/wireless-security/ws-dynamic-wep.h b/panels/network/wireless-security/ws-dynamic-wep.h
new file mode 100644
index 0000000..80c914b
--- /dev/null
+++ b/panels/network/wireless-security/ws-dynamic-wep.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (WirelessSecurityDynamicWEP, ws_dynamic_wep, WS, DYNAMIC_WEP, GtkGrid)
+
+WirelessSecurityDynamicWEP *ws_dynamic_wep_new (NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/ws-dynamic-wep.ui b/panels/network/wireless-security/ws-dynamic-wep.ui
new file mode 100644
index 0000000..85d6389
--- /dev/null
+++ b/panels/network/wireless-security/ws-dynamic-wep.ui
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.4"/>
+ <object class="GtkListStore" id="auth_model">
+ <columns>
+ <!-- column-name label -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ <!-- column-name visible -->
+ <column type="gboolean"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">TLS</col>
+ <col id="1">tls</col>
+ <col id="2">True</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">LEAP</col>
+ <col id="1">leap</col>
+ <col id="2">True</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">PWD</col>
+ <col id="1">pwd</col>
+ <col id="2">True</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">FAST</col>
+ <col id="1">fast</col>
+ <col id="2">True</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Tunneled TLS</col>
+ <col id="1">ttls</col>
+ <col id="2">True</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Protected EAP (PEAP)</col>
+ <col id="1">peap</col>
+ <col id="2">True</col>
+ </row>
+ </data>
+ </object>
+ <template class="WirelessSecurityDynamicWEP" parent="GtkGrid">
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="auth_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Au_thentication</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">auth_combo</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="auth_combo">
+ <property name="hexpand">True</property>
+ <property name="model">auth_model</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ <child>
+ <object class="GtkCellRendererText"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="method_box">
+ <property name="spacing">6</property>
+ <property name="orientation">vertical</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="column-span">2</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/wireless-security/ws-file-chooser-button.c b/panels/network/wireless-security/ws-file-chooser-button.c
new file mode 100644
index 0000000..998df42
--- /dev/null
+++ b/panels/network/wireless-security/ws-file-chooser-button.c
@@ -0,0 +1,268 @@
+/* cc-file-chooser-button.c
+ *
+ * Copyright 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "ws-file-chooser-button.h"
+
+#include <glib/gi18n.h>
+
+struct _WsFileChooserButton
+{
+ GtkButton parent_instance;
+
+ GtkFileChooser *filechooser;
+ GFile *file;
+ char *title;
+};
+
+G_DEFINE_FINAL_TYPE (WsFileChooserButton, ws_file_chooser_button, GTK_TYPE_BUTTON)
+
+enum
+{
+ PROP_0,
+ PROP_FILE,
+ PROP_TITLE,
+ N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS] = { NULL, };
+
+static const char *
+get_title (WsFileChooserButton *self)
+{
+ return self->title ? self->title : _("Select a file");
+}
+
+static void
+update_label (WsFileChooserButton *self)
+{
+ g_autofree gchar *label = NULL;
+
+ if (self->file)
+ label = g_file_get_basename (self->file);
+ else
+ label = g_strdup (get_title (self));
+
+ gtk_button_set_label (GTK_BUTTON (self), label);
+}
+
+static void
+on_filechooser_dialog_response_cb (GtkFileChooser *filechooser,
+ gint response,
+ WsFileChooserButton *self)
+{
+ if (response == GTK_RESPONSE_ACCEPT)
+ {
+ g_autoptr(GFile) file = NULL;
+
+ file = gtk_file_chooser_get_file (filechooser);
+ ws_file_chooser_button_set_file (self, file);
+ }
+
+ gtk_widget_hide (GTK_WIDGET (filechooser));
+}
+static void
+ensure_filechooser (WsFileChooserButton *self)
+{
+ GtkNative *native;
+ GtkWidget *dialog;
+
+ if (self->filechooser)
+ return;
+
+ native = gtk_widget_get_native (GTK_WIDGET (self));
+
+ dialog = gtk_file_chooser_dialog_new (get_title (self),
+ GTK_WINDOW (native),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ _("Cancel"),
+ GTK_RESPONSE_CANCEL,
+ _("Open"),
+ GTK_RESPONSE_ACCEPT,
+ NULL);
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
+ gtk_window_set_hide_on_close (GTK_WINDOW (dialog), TRUE);
+ gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+
+ if (self->file)
+ gtk_file_chooser_set_file (GTK_FILE_CHOOSER (dialog), self->file, NULL);
+
+ g_signal_connect (dialog, "response", G_CALLBACK (on_filechooser_dialog_response_cb), self);
+
+ self->filechooser = GTK_FILE_CHOOSER (dialog);
+}
+
+
+static void
+ws_file_chooser_button_clicked (GtkButton *button)
+{
+ WsFileChooserButton *self = WS_FILE_CHOOSER_BUTTON (button);
+ GtkNative *native = gtk_widget_get_native (GTK_WIDGET (self));
+
+ ensure_filechooser (self);
+
+ gtk_window_set_transient_for (GTK_WINDOW (self->filechooser), GTK_WINDOW (native));
+ gtk_window_present (GTK_WINDOW (self->filechooser));
+}
+
+static void
+ws_file_chooser_button_finalize (GObject *object)
+{
+ WsFileChooserButton *self = (WsFileChooserButton *)object;
+
+ g_clear_pointer (&self->title, g_free);
+ g_clear_object (&self->file);
+
+ G_OBJECT_CLASS (ws_file_chooser_button_parent_class)->finalize (object);
+}
+
+static void
+ws_file_chooser_button_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ WsFileChooserButton *self = WS_FILE_CHOOSER_BUTTON (object);
+
+ switch (prop_id)
+ {
+ case PROP_FILE:
+ g_value_set_object (value, self->file);
+ break;
+
+ case PROP_TITLE:
+ g_value_set_string (value, self->title);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ws_file_chooser_button_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ WsFileChooserButton *self = WS_FILE_CHOOSER_BUTTON (object);
+
+ switch (prop_id)
+ {
+ case PROP_FILE:
+ ws_file_chooser_button_set_file (self, g_value_get_object (value));
+ break;
+
+ case PROP_TITLE:
+ ws_file_chooser_button_set_title (self, g_value_get_string (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ws_file_chooser_button_class_init (WsFileChooserButtonClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass);
+
+ button_class->clicked = ws_file_chooser_button_clicked;
+
+ object_class->finalize = ws_file_chooser_button_finalize;
+ object_class->get_property = ws_file_chooser_button_get_property;
+ object_class->set_property = ws_file_chooser_button_set_property;
+
+ properties[PROP_FILE] = g_param_spec_object ("file", "", "",
+ G_TYPE_FILE,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+ properties[PROP_TITLE] = g_param_spec_string ("title", "", "", NULL,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+ws_file_chooser_button_init (WsFileChooserButton *self)
+{
+ update_label (self);
+}
+
+GtkWidget *
+ws_file_chooser_button_new (void)
+{
+ return g_object_new (WS_TYPE_FILE_CHOOSER_BUTTON, NULL);
+}
+
+void
+ws_file_chooser_button_set_file (WsFileChooserButton *self,
+ GFile *file)
+{
+ g_return_if_fail (WS_IS_FILE_CHOOSER_BUTTON (self));
+
+ if (g_set_object (&self->file, file))
+ {
+ gtk_file_chooser_set_file (self->filechooser, file, NULL);
+ update_label (self);
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FILE]);
+ }
+}
+
+GFile *
+ws_file_chooser_button_get_file (WsFileChooserButton *self)
+{
+ g_return_val_if_fail (WS_IS_FILE_CHOOSER_BUTTON (self), NULL);
+
+ return self->file ? g_object_ref (self->file) : NULL;
+}
+
+void
+ws_file_chooser_button_set_title (WsFileChooserButton *self,
+ const char *title)
+{
+ g_autofree char *old_title = NULL;
+
+ g_return_if_fail (WS_IS_FILE_CHOOSER_BUTTON (self));
+
+ old_title = g_steal_pointer (&self->title);
+ self->title = g_strdup (title);
+
+ update_label (self);
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TITLE]);
+}
+
+const char *
+ws_file_chooser_button_get_title (WsFileChooserButton *self)
+{
+ g_return_val_if_fail (WS_IS_FILE_CHOOSER_BUTTON (self), NULL);
+
+ return self->title;
+}
+
+GtkFileChooser *
+ws_file_chooser_button_get_filechooser (WsFileChooserButton *self)
+{
+ g_return_val_if_fail (WS_IS_FILE_CHOOSER_BUTTON (self), NULL);
+
+ ensure_filechooser (self);
+
+ return self->filechooser;
+}
diff --git a/panels/network/wireless-security/ws-file-chooser-button.h b/panels/network/wireless-security/ws-file-chooser-button.h
new file mode 100644
index 0000000..db02020
--- /dev/null
+++ b/panels/network/wireless-security/ws-file-chooser-button.h
@@ -0,0 +1,44 @@
+/* ws-file-chooser-button.h
+ *
+ * Copyright 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define WS_TYPE_FILE_CHOOSER_BUTTON (ws_file_chooser_button_get_type())
+G_DECLARE_FINAL_TYPE (WsFileChooserButton, ws_file_chooser_button, WS, FILE_CHOOSER_BUTTON, GtkButton)
+
+GtkWidget *ws_file_chooser_button_new (void);
+
+void ws_file_chooser_button_set_file (WsFileChooserButton *self,
+ GFile *file);
+
+GFile *ws_file_chooser_button_get_file (WsFileChooserButton *self);
+
+void ws_file_chooser_button_set_title (WsFileChooserButton *self,
+ const char *title);
+
+const char *ws_file_chooser_button_get_title (WsFileChooserButton *self);
+
+GtkFileChooser *ws_file_chooser_button_get_filechooser (WsFileChooserButton *self);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/ws-leap.c b/panels/network/wireless-security/ws-leap.c
new file mode 100644
index 0000000..a234015
--- /dev/null
+++ b/panels/network/wireless-security/ws-leap.c
@@ -0,0 +1,211 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+
+#include "helpers.h"
+#include "nma-ui-utils.h"
+#include "ui-helpers.h"
+#include "wireless-security.h"
+#include "ws-leap.h"
+
+struct _WirelessSecurityLEAP {
+ GtkGrid parent;
+
+ GtkEntry *password_entry;
+ GtkLabel *password_label;
+ GtkCheckButton *show_password_check;
+ GtkEntry *username_entry;
+ GtkLabel *username_label;
+};
+
+static void wireless_security_iface_init (WirelessSecurityInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (WirelessSecurityLEAP, ws_leap, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (wireless_security_get_type (), wireless_security_iface_init));
+
+static void
+show_toggled_cb (WirelessSecurityLEAP *self)
+{
+ gboolean visible;
+
+ visible = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->show_password_check));
+ gtk_entry_set_visibility (self->password_entry, visible);
+}
+
+static gboolean
+validate (WirelessSecurity *security, GError **error)
+{
+ WirelessSecurityLEAP *self = WS_LEAP (security);
+ NMSettingSecretFlags secret_flags;
+ const char *text;
+ gboolean ret = TRUE;
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self->username_entry));
+ if (!text || !strlen (text)) {
+ widget_set_error (GTK_WIDGET (self->username_entry));
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing leap-username"));
+ ret = FALSE;
+ } else
+ widget_unset_error (GTK_WIDGET (self->username_entry));
+
+ secret_flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->password_entry));
+ if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED) {
+ widget_unset_error (GTK_WIDGET (self->password_entry));
+ return TRUE;
+ }
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+ if (!text || !strlen (text)) {
+ widget_set_error (GTK_WIDGET (self->password_entry));
+ if (ret) {
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing leap-password"));
+ ret = FALSE;
+ }
+ } else
+ widget_unset_error (GTK_WIDGET (self->password_entry));
+
+ return ret;
+}
+
+static void
+add_to_size_group (WirelessSecurity *security, GtkSizeGroup *group)
+{
+ WirelessSecurityLEAP *self = WS_LEAP (security);
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->username_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->password_label));
+}
+
+static void
+fill_connection (WirelessSecurity *security, NMConnection *connection)
+{
+ WirelessSecurityLEAP *self = WS_LEAP (security);
+ NMSettingWirelessSecurity *s_wireless_sec;
+ NMSettingSecretFlags secret_flags;
+ const char *leap_password = NULL, *leap_username = NULL;
+
+ /* Blow away the old security setting by adding a clear one */
+ s_wireless_sec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+ nm_connection_add_setting (connection, (NMSetting *) s_wireless_sec);
+
+ leap_username = gtk_editable_get_text (GTK_EDITABLE (self->username_entry));
+ leap_password = gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+
+ g_object_set (s_wireless_sec,
+ NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x",
+ NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "leap",
+ NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, leap_username,
+ NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD, leap_password,
+ NULL);
+
+ /* Save LEAP_PASSWORD_FLAGS to the connection */
+ secret_flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->password_entry));
+ nm_setting_set_secret_flags (NM_SETTING (s_wireless_sec), NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD,
+ secret_flags, NULL);
+
+ /* Update secret flags and popup when editing the connection */
+ nma_utils_update_password_storage (GTK_WIDGET (self->password_entry), secret_flags,
+ NM_SETTING (s_wireless_sec), NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD);
+}
+
+static gboolean
+adhoc_compatible (WirelessSecurity *security)
+{
+ return FALSE;
+}
+
+static void
+changed_cb (WirelessSecurityLEAP *self)
+{
+ wireless_security_notify_changed ((WirelessSecurity *) self);
+}
+
+void
+ws_leap_init (WirelessSecurityLEAP *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+void
+ws_leap_class_init (WirelessSecurityLEAPClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/network/ws-leap.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityLEAP, password_entry);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityLEAP, password_label);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityLEAP, show_password_check);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityLEAP, username_entry);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityLEAP, username_label);
+}
+
+static void
+wireless_security_iface_init (WirelessSecurityInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->adhoc_compatible = adhoc_compatible;
+}
+
+WirelessSecurityLEAP *
+ws_leap_new (NMConnection *connection)
+{
+ WirelessSecurityLEAP *self;
+ NMSettingWirelessSecurity *wsec = NULL;
+
+ self = g_object_new (ws_leap_get_type (), NULL);
+
+ if (connection) {
+ wsec = nm_connection_get_setting_wireless_security (connection);
+ if (wsec) {
+ const char *auth_alg;
+
+ /* Ignore if wireless security doesn't specify LEAP */
+ auth_alg = nm_setting_wireless_security_get_auth_alg (wsec);
+ if (!auth_alg || strcmp (auth_alg, "leap"))
+ wsec = NULL;
+ }
+ }
+
+ g_signal_connect_swapped (self->password_entry, "changed", G_CALLBACK (changed_cb), self);
+
+ /* Create password-storage popup menu for password entry under entry's secondary icon */
+ nma_utils_setup_password_storage (GTK_WIDGET (self->password_entry), 0, (NMSetting *) wsec, NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD,
+ FALSE, FALSE);
+
+ if (wsec)
+ helper_fill_secret_entry (connection,
+ self->password_entry,
+ NM_TYPE_SETTING_WIRELESS_SECURITY,
+ (HelperSecretFunc) nm_setting_wireless_security_get_leap_password);
+
+ g_signal_connect_swapped (self->username_entry, "changed", G_CALLBACK (changed_cb), self);
+ if (wsec)
+ gtk_editable_set_text (GTK_EDITABLE (self->username_entry), nm_setting_wireless_security_get_leap_username (wsec));
+
+ g_signal_connect_swapped (self->show_password_check, "toggled", G_CALLBACK (show_toggled_cb), self);
+
+ return self;
+}
+
diff --git a/panels/network/wireless-security/ws-leap.h b/panels/network/wireless-security/ws-leap.h
new file mode 100644
index 0000000..ebe90bb
--- /dev/null
+++ b/panels/network/wireless-security/ws-leap.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (WirelessSecurityLEAP, ws_leap, WS, LEAP, GtkGrid)
+
+WirelessSecurityLEAP *ws_leap_new (NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/ws-leap.ui b/panels/network/wireless-security/ws-leap.ui
new file mode 100644
index 0000000..41e21d6
--- /dev/null
+++ b/panels/network/wireless-security/ws-leap.ui
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.4"/>
+ <template class="WirelessSecurityLEAP" parent="GtkGrid">
+ <property name="valign">start</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="username_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Username</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">username_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="password_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">password_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="password_entry">
+ <property name="hexpand">True</property>
+ <property name="visibility">False</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="show_password_check">
+ <property name="label" translatable="yes">Sho_w password</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="username_entry">
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/wireless-security/ws-sae.c b/panels/network/wireless-security/ws-sae.c
new file mode 100644
index 0000000..c9e4e50
--- /dev/null
+++ b/panels/network/wireless-security/ws-sae.c
@@ -0,0 +1,225 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Jonathan Kang <songchuan.kang@suse.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (c) 2020 SUSE LINUX GmbH, Nuernberg, Germany.
+ */
+
+#include <ctype.h>
+#include <glib/gi18n.h>
+
+#include "helpers.h"
+#include "nma-ui-utils.h"
+#include "ui-helpers.h"
+#include "ws-sae.h"
+#include "wireless-security.h"
+
+#define WPA_PMK_LEN 32
+
+struct _WirelessSecuritySAE
+{
+ GtkGrid parent;
+
+ GtkEntry *password_entry;
+ GtkLabel *password_label;
+ GtkCheckButton *show_password_check;
+ GtkComboBox *type_combo;
+ GtkLabel *type_label;
+};
+
+static void wireless_security_iface_init (WirelessSecurityInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (WirelessSecuritySAE, ws_sae, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (wireless_security_get_type (), wireless_security_iface_init));
+
+static void
+show_toggled_cb (WirelessSecuritySAE *self)
+{
+ gboolean visible;
+
+ visible = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->show_password_check));
+ gtk_entry_set_visibility (self->password_entry, visible);
+}
+
+static gboolean
+validate (WirelessSecurity *security, GError **error)
+{
+ WirelessSecuritySAE *self = WS_SAE (security);
+ NMSettingSecretFlags secret_flags;
+ const char *key;
+
+ secret_flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->password_entry));
+ if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)
+ {
+ widget_unset_error (GTK_WIDGET (self->password_entry));
+ return TRUE;
+ }
+
+ key = gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+
+ if (key == NULL || key[0] == '\0')
+ {
+ widget_set_error (GTK_WIDGET (self->password_entry));
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("Wi-Fi password is missing."));
+ return FALSE;
+ }
+ widget_unset_error (GTK_WIDGET (self->password_entry));
+
+ return TRUE;
+}
+
+static void
+add_to_size_group (WirelessSecurity *security, GtkSizeGroup *group)
+{
+ WirelessSecuritySAE *self = WS_SAE (security);
+
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->type_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->password_label));
+}
+
+static void
+fill_connection (WirelessSecurity *security, NMConnection *connection)
+{
+ WirelessSecuritySAE *self = WS_SAE (security);
+ const char *key;
+ NMSettingWireless *s_wireless;
+ NMSettingWirelessSecurity *s_wireless_sec;
+ NMSettingSecretFlags secret_flags;
+ const char *mode;
+ gboolean is_adhoc = FALSE;
+
+ s_wireless = nm_connection_get_setting_wireless (connection);
+ g_assert (s_wireless);
+
+ mode = nm_setting_wireless_get_mode (s_wireless);
+ if (mode && !g_strcmp0 (mode, "adhoc"))
+ is_adhoc = TRUE;
+
+ /* Blow away the old security setting by adding a clear one */
+ s_wireless_sec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+ nm_connection_add_setting (connection, (NMSetting *) s_wireless_sec);
+
+ key = gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+ g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_PSK, key, NULL);
+
+ /* Save PSK_FLAGS to the connection */
+ secret_flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->password_entry));
+ nm_setting_set_secret_flags (NM_SETTING (s_wireless_sec), NM_SETTING_WIRELESS_SECURITY_PSK,
+ secret_flags, NULL);
+
+ /* Update secret flags and popup when editing the connection */
+ nma_utils_update_password_storage (GTK_WIDGET (self->password_entry), secret_flags,
+ NM_SETTING (s_wireless_sec), NM_SETTING_WIRELESS_SECURITY_PSK);
+
+ wireless_security_clear_ciphers (connection);
+ if (is_adhoc)
+ {
+ /* Ad-Hoc settings as specified by the supplicant */
+ g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "sae", NULL);
+ nm_setting_wireless_security_add_proto (s_wireless_sec, "rsn");
+ nm_setting_wireless_security_add_pairwise (s_wireless_sec, "ccmp");
+ nm_setting_wireless_security_add_group (s_wireless_sec, "ccmp");
+ }
+ else
+ {
+ g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "sae", NULL);
+
+ /* Just leave ciphers and protocol empty, the supplicant will
+ * figure that out magically based on the AP IEs and card capabilities.
+ */
+ }
+}
+
+static gboolean
+adhoc_compatible (WirelessSecurity *security)
+{
+ return FALSE;
+}
+
+static void
+changed_cb (WirelessSecuritySAE *self)
+{
+ wireless_security_notify_changed ((WirelessSecurity *) self);
+}
+
+void
+ws_sae_init (WirelessSecuritySAE *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+void
+ws_sae_class_init (WirelessSecuritySAEClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/network/ws-sae.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecuritySAE, password_entry);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecuritySAE, password_label);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecuritySAE, show_password_check);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecuritySAE, type_combo);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecuritySAE, type_label);
+}
+
+static void
+wireless_security_iface_init (WirelessSecurityInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->adhoc_compatible = adhoc_compatible;
+}
+
+WirelessSecuritySAE *
+ws_sae_new (NMConnection *connection)
+{
+ WirelessSecuritySAE *self;
+ NMSetting *setting = NULL;
+
+ self = g_object_new (ws_sae_get_type (), NULL);
+
+ g_signal_connect_swapped (self->password_entry, "changed", G_CALLBACK (changed_cb), self);
+ gtk_editable_set_width_chars (GTK_EDITABLE (self->password_entry), 28);
+
+ /* Create password-storage popup menu for password entry under entry's secondary icon */
+ if (connection)
+ setting = (NMSetting *) nm_connection_get_setting_wireless_security (connection);
+ nma_utils_setup_password_storage (GTK_WIDGET (self->password_entry),
+ 0, setting, NM_SETTING_WIRELESS_SECURITY_PSK,
+ FALSE, FALSE);
+
+ /* Fill secrets, if any */
+ if (connection)
+ {
+ helper_fill_secret_entry (connection,
+ self->password_entry,
+ NM_TYPE_SETTING_WIRELESS_SECURITY,
+ (HelperSecretFunc) nm_setting_wireless_security_get_psk);
+ }
+
+ g_signal_connect_swapped (self->show_password_check, "toggled",
+ G_CALLBACK (show_toggled_cb), self);
+
+ /* Hide WPA/RSN for now since this can be autodetected by NM and the
+ * supplicant when connecting to the AP.
+ */
+ gtk_widget_hide (GTK_WIDGET (self->type_combo));
+ gtk_widget_hide (GTK_WIDGET (self->type_label));
+
+ return self;
+}
diff --git a/panels/network/wireless-security/ws-sae.h b/panels/network/wireless-security/ws-sae.h
new file mode 100644
index 0000000..770f658
--- /dev/null
+++ b/panels/network/wireless-security/ws-sae.h
@@ -0,0 +1,33 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Jonathan Kang <songchuan.kang@suse.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (c) 2020 SUSE LINUX GmbH, Nuernberg, Germany.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (WirelessSecuritySAE, ws_sae, WS, SAE, GtkGrid)
+
+WirelessSecuritySAE* ws_sae_new (NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/ws-sae.ui b/panels/network/wireless-security/ws-sae.ui
new file mode 100644
index 0000000..028cd9f
--- /dev/null
+++ b/panels/network/wireless-security/ws-sae.ui
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
+<interface domain="nm-applet">
+ <requires lib="gtk+" version="3.10"/>
+ <template class="WirelessSecuritySAE" parent="GtkGrid">
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="password_label">
+ <property name="label" translatable="yes">_Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">password_entry</property>
+ <property name="xalign">1</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="password_entry">
+ <property name="hexpand">True</property>
+ <property name="max_length">64</property>
+ <property name="visibility">False</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="type_label">
+ <property name="label" translatable="yes">_Type</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">type_combo</property>
+ <property name="xalign">1</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="show_password_check">
+ <property name="label" translatable="yes">Sho_w password</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="type_combo">
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/wireless-security/ws-wep-key.c b/panels/network/wireless-security/ws-wep-key.c
new file mode 100644
index 0000000..8b354d5
--- /dev/null
+++ b/panels/network/wireless-security/ws-wep-key.c
@@ -0,0 +1,369 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+
+#include "helpers.h"
+#include "nma-ui-utils.h"
+#include "ui-helpers.h"
+#include "ws-wep-key.h"
+#include "wireless-security.h"
+
+struct _WirelessSecurityWEPKey {
+ GtkGrid parent;
+
+ GtkComboBox *auth_method_combo;
+ GtkLabel *auth_method_label;
+ GtkEntry *key_entry;
+ GtkComboBox *key_index_combo;
+ GtkLabel *key_index_label;
+ GtkLabel *key_label;
+ GtkCheckButton *show_key_check;
+
+ NMWepKeyType type;
+ char keys[4][65];
+ guint8 cur_index;
+};
+
+static void wireless_security_iface_init (WirelessSecurityInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (WirelessSecurityWEPKey, ws_wep_key, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (wireless_security_get_type (), wireless_security_iface_init));
+
+static void
+show_toggled_cb (WirelessSecurityWEPKey *self)
+{
+ gboolean visible;
+
+ visible = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->show_key_check));
+ gtk_entry_set_visibility (self->key_entry, visible);
+}
+
+static void
+key_index_combo_changed_cb (WirelessSecurityWEPKey *self)
+{
+ const char *key;
+ int key_index;
+
+ /* Save WEP key for old key index */
+ key = gtk_editable_get_text (GTK_EDITABLE (self->key_entry));
+ if (key)
+ g_strlcpy (self->keys[self->cur_index], key, sizeof (self->keys[self->cur_index]));
+ else
+ memset (self->keys[self->cur_index], 0, sizeof (self->keys[self->cur_index]));
+
+ key_index = gtk_combo_box_get_active (self->key_index_combo);
+ g_return_if_fail (key_index <= 3);
+ g_return_if_fail (key_index >= 0);
+
+ /* Populate entry with key from new index */
+ gtk_editable_set_text (GTK_EDITABLE (self->key_entry), self->keys[key_index]);
+ self->cur_index = key_index;
+
+ wireless_security_notify_changed ((WirelessSecurity *) self);
+}
+
+static void
+ws_wep_key_dispose (GObject *object)
+{
+ WirelessSecurityWEPKey *self = WS_WEP_KEY (object);
+ int i;
+
+ for (i = 0; i < 4; i++)
+ memset (self->keys[i], 0, sizeof (self->keys[i]));
+
+ G_OBJECT_CLASS (ws_wep_key_parent_class)->dispose (object);
+}
+
+static gboolean
+validate (WirelessSecurity *security, GError **error)
+{
+ WirelessSecurityWEPKey *self = WS_WEP_KEY (security);
+ NMSettingSecretFlags secret_flags;
+ const char *key;
+ int i;
+
+ secret_flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->key_entry));
+ if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED) {
+ widget_unset_error (GTK_WIDGET (self->key_entry));
+ return TRUE;
+ }
+
+ key = gtk_editable_get_text (GTK_EDITABLE (self->key_entry));
+ if (!key) {
+ widget_set_error (GTK_WIDGET (self->key_entry));
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing wep-key"));
+ return FALSE;
+ }
+
+ if (self->type == NM_WEP_KEY_TYPE_KEY) {
+ if ((strlen (key) == 10) || (strlen (key) == 26)) {
+ for (i = 0; i < strlen (key); i++) {
+ if (!g_ascii_isxdigit (key[i])) {
+ widget_set_error (GTK_WIDGET (self->key_entry));
+ g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid wep-key: key with a length of %zu must contain only hex-digits"), strlen (key));
+ return FALSE;
+ }
+ }
+ } else if ((strlen (key) == 5) || (strlen (key) == 13)) {
+ for (i = 0; i < strlen (key); i++) {
+ if (!g_ascii_isprint (key[i])) {
+ widget_set_error (GTK_WIDGET (self->key_entry));
+ g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid wep-key: key with a length of %zu must contain only ascii characters"), strlen (key));
+ return FALSE;
+ }
+ }
+ } else {
+ widget_set_error (GTK_WIDGET (self->key_entry));
+ g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid wep-key: wrong key length %zu. A key must be either of length 5/13 (ascii) or 10/26 (hex)"), strlen (key));
+ return FALSE;
+ }
+ } else if (self->type == NM_WEP_KEY_TYPE_PASSPHRASE) {
+ if (!*key || (strlen (key) > 64)) {
+ widget_set_error (GTK_WIDGET (self->key_entry));
+ if (!*key)
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid wep-key: passphrase must be non-empty"));
+ else
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid wep-key: passphrase must be shorter than 64 characters"));
+ return FALSE;
+ }
+ }
+ widget_unset_error (GTK_WIDGET (self->key_entry));
+
+ return TRUE;
+}
+
+static void
+add_to_size_group (WirelessSecurity *security, GtkSizeGroup *group)
+{
+ WirelessSecurityWEPKey *self = WS_WEP_KEY (security);
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->auth_method_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->key_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->key_index_label));
+}
+
+static void
+fill_connection (WirelessSecurity *security, NMConnection *connection)
+{
+ WirelessSecurityWEPKey *self = WS_WEP_KEY (security);
+ NMSettingWirelessSecurity *s_wsec;
+ NMSettingSecretFlags secret_flags;
+ gint auth_alg;
+ const char *key;
+ int i;
+
+ auth_alg = gtk_combo_box_get_active (self->auth_method_combo);
+
+ key = gtk_editable_get_text (GTK_EDITABLE (self->key_entry));
+ g_strlcpy (self->keys[self->cur_index], key, sizeof (self->keys[self->cur_index]));
+
+ /* Blow away the old security setting by adding a clear one */
+ s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+ nm_connection_add_setting (connection, (NMSetting *) s_wsec);
+
+ g_object_set (s_wsec,
+ NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none",
+ NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, self->cur_index,
+ NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, (auth_alg == 1) ? "shared" : "open",
+ NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, self->type,
+ NULL);
+
+ for (i = 0; i < 4; i++) {
+ if (strlen (self->keys[i]))
+ nm_setting_wireless_security_set_wep_key (s_wsec, i, self->keys[i]);
+ }
+
+ /* Save WEP_KEY_FLAGS to the connection */
+ secret_flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->key_entry));
+ g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, secret_flags, NULL);
+
+ /* Update secret flags and popup when editing the connection */
+ nma_utils_update_password_storage (GTK_WIDGET (self->key_entry), secret_flags,
+ NM_SETTING (s_wsec), NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
+}
+
+static void
+wep_entry_filter_cb (WirelessSecurityWEPKey *self,
+ gchar *text,
+ gint length,
+ gint *position)
+{
+ if (self->type == NM_WEP_KEY_TYPE_KEY) {
+ int i, count = 0;
+ g_autofree gchar *result = g_new (gchar, length+1);
+
+ for (i = 0; i < length; i++) {
+ if (g_ascii_isprint (text[i]))
+ result[count++] = text[i];
+ }
+ result[count] = 0;
+
+ if (count > 0) {
+ g_signal_handlers_block_by_func (self->key_entry, G_CALLBACK (wep_entry_filter_cb), self);
+ gtk_editable_insert_text (GTK_EDITABLE (self->key_entry), result, count, position);
+ g_signal_handlers_unblock_by_func (self->key_entry, G_CALLBACK (wep_entry_filter_cb), self);
+ }
+ g_signal_stop_emission_by_name (self->key_entry, "insert-text");
+ }
+}
+
+static void
+update_secrets (WirelessSecurityWEPKey *self, NMConnection *connection)
+{
+ NMSettingWirelessSecurity *s_wsec;
+ const char *tmp;
+ int i;
+
+ s_wsec = nm_connection_get_setting_wireless_security (connection);
+ for (i = 0; s_wsec && i < 4; i++) {
+ tmp = nm_setting_wireless_security_get_wep_key (s_wsec, i);
+ if (tmp)
+ g_strlcpy (self->keys[i], tmp, sizeof (self->keys[i]));
+ }
+
+ if (strlen (self->keys[self->cur_index]))
+ gtk_editable_set_text (GTK_EDITABLE (self->key_entry), self->keys[self->cur_index]);
+}
+
+static void
+changed_cb (WirelessSecurityWEPKey *self)
+{
+ wireless_security_notify_changed ((WirelessSecurity *) self);
+}
+
+void
+ws_wep_key_init (WirelessSecurityWEPKey *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+void
+ws_wep_key_class_init (WirelessSecurityWEPKeyClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = ws_wep_key_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/network/ws-wep-key.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWEPKey, auth_method_combo);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWEPKey, auth_method_label);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWEPKey, key_entry);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWEPKey, key_index_combo);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWEPKey, key_index_label);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWEPKey, key_label);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWEPKey, show_key_check);
+}
+
+static void
+wireless_security_iface_init (WirelessSecurityInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+}
+
+WirelessSecurityWEPKey *
+ws_wep_key_new (NMConnection *connection,
+ NMWepKeyType type)
+{
+ WirelessSecurityWEPKey *self;
+ NMSettingWirelessSecurity *s_wsec = NULL;
+ NMSetting *setting = NULL;
+ guint8 default_key_idx = 0;
+ gboolean is_adhoc = FALSE;
+ gboolean is_shared_key = FALSE;
+
+ self = g_object_new (ws_wep_key_get_type (), NULL);
+
+ self->type = type;
+
+ gtk_editable_set_width_chars (GTK_EDITABLE (self->key_entry), 28);
+
+ /* Create password-storage popup menu for password entry under entry's secondary icon */
+ if (connection)
+ setting = (NMSetting *) nm_connection_get_setting_wireless_security (connection);
+ nma_utils_setup_password_storage (GTK_WIDGET (self->key_entry), 0, setting, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0,
+ FALSE, FALSE);
+
+ if (connection) {
+ NMSettingWireless *s_wireless;
+ const char *mode, *auth_alg;
+
+ s_wireless = nm_connection_get_setting_wireless (connection);
+ mode = s_wireless ? nm_setting_wireless_get_mode (s_wireless) : NULL;
+ if (mode && !strcmp (mode, "adhoc"))
+ is_adhoc = TRUE;
+
+ s_wsec = nm_connection_get_setting_wireless_security (connection);
+ if (s_wsec) {
+ auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec);
+ if (auth_alg && !strcmp (auth_alg, "shared"))
+ is_shared_key = TRUE;
+ }
+ }
+
+ g_signal_connect_swapped (self->key_entry, "changed", G_CALLBACK (changed_cb), self);
+ g_signal_connect_swapped (self->key_entry, "insert-text", G_CALLBACK (wep_entry_filter_cb), self);
+ if (self->type == NM_WEP_KEY_TYPE_KEY)
+ gtk_entry_set_max_length (self->key_entry, 26);
+ else if (self->type == NM_WEP_KEY_TYPE_PASSPHRASE)
+ gtk_entry_set_max_length (self->key_entry, 64);
+
+ if (connection && s_wsec)
+ default_key_idx = nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec);
+
+ gtk_combo_box_set_active (self->key_index_combo, default_key_idx);
+ self->cur_index = default_key_idx;
+ g_signal_connect_swapped (self->key_index_combo, "changed", G_CALLBACK (key_index_combo_changed_cb), self);
+
+ /* Key index is useless with adhoc networks */
+ if (is_adhoc) {
+ gtk_widget_hide (GTK_WIDGET (self->key_index_combo));
+ gtk_widget_hide (GTK_WIDGET (self->key_index_label));
+ }
+
+ /* Fill the key entry with the key for that index */
+ if (connection)
+ update_secrets (self, connection);
+
+ g_signal_connect_swapped (self->show_key_check, "toggled", G_CALLBACK (show_toggled_cb), self);
+
+ gtk_combo_box_set_active (self->auth_method_combo, is_shared_key ? 1 : 0);
+
+ g_signal_connect_swapped (self->auth_method_combo, "changed", G_CALLBACK (changed_cb), self);
+
+ /* Don't show auth method for adhoc (which always uses open-system) or
+ * when in "simple" mode.
+ */
+ if (is_adhoc) {
+ /* Ad-Hoc connections can't use Shared Key auth */
+ if (is_adhoc)
+ gtk_combo_box_set_active (self->auth_method_combo, 0);
+ gtk_widget_hide (GTK_WIDGET (self->auth_method_combo));
+ gtk_widget_hide (GTK_WIDGET (self->auth_method_label));
+ }
+
+ return self;
+}
+
diff --git a/panels/network/wireless-security/ws-wep-key.h b/panels/network/wireless-security/ws-wep-key.h
new file mode 100644
index 0000000..dc85e8b
--- /dev/null
+++ b/panels/network/wireless-security/ws-wep-key.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (WirelessSecurityWEPKey, ws_wep_key, WS, WEP_KEY, GtkGrid)
+
+WirelessSecurityWEPKey *ws_wep_key_new (NMConnection *connection,
+ NMWepKeyType type);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/ws-wep-key.ui b/panels/network/wireless-security/ws-wep-key.ui
new file mode 100644
index 0000000..49f525e
--- /dev/null
+++ b/panels/network/wireless-security/ws-wep-key.ui
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.4"/>
+ <object class="GtkListStore" id="key_index_model">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">1 (Default)</col>
+ </row>
+ <row>
+ <col id="0">2</col>
+ </row>
+ <row>
+ <col id="0">3</col>
+ </row>
+ <row>
+ <col id="0">4</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="auth_method_model">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Open System</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Shared Key</col>
+ </row>
+ </data>
+ </object>
+ <template class="WirelessSecurityWEPKey" parent="GtkGrid">
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="key_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Key</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">key_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="key_entry">
+ <property name="hexpand">True</property>
+ <property name="max_length">64</property>
+ <property name="visibility">False</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="show_key_check">
+ <property name="label" translatable="yes">Sho_w key</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="auth_method_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Au_thentication</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">auth_method_combo</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="auth_method_combo">
+ <property name="hexpand">True</property>
+ <property name="model">auth_method_model</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ </layout>
+ <child>
+ <object class="GtkCellRendererText"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="key_index_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">WEP inde_x</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">key_index_combo</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="key_index_combo">
+ <property name="hexpand">True</property>
+ <property name="model">key_index_model</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ <child>
+ <object class="GtkCellRendererText"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/wireless-security/ws-wpa-eap.c b/panels/network/wireless-security/ws-wpa-eap.c
new file mode 100644
index 0000000..d2b01b6
--- /dev/null
+++ b/panels/network/wireless-security/ws-wpa-eap.c
@@ -0,0 +1,313 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+
+#include "ws-wpa-eap.h"
+#include "wireless-security.h"
+#include "eap-method.h"
+#include "eap-method-fast.h"
+#include "eap-method-leap.h"
+#include "eap-method-peap.h"
+#include "eap-method-simple.h"
+#include "eap-method-tls.h"
+#include "eap-method-ttls.h"
+
+struct _WirelessSecurityWPAEAP {
+ GtkGrid parent;
+
+ GtkComboBox *auth_combo;
+ GtkLabel *auth_label;
+ GtkListStore *auth_model;
+ GtkBox *method_box;
+
+ EAPMethodSimple *em_md5;
+ EAPMethodTLS *em_tls;
+ EAPMethodLEAP *em_leap;
+ EAPMethodSimple *em_pwd;
+ EAPMethodFAST *em_fast;
+ EAPMethodTTLS *em_ttls;
+ EAPMethodPEAP *em_peap;
+};
+
+static void wireless_security_iface_init (WirelessSecurityInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (WirelessSecurityWPAEAP, ws_wpa_eap, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (wireless_security_get_type (), wireless_security_iface_init));
+
+#define AUTH_NAME_COLUMN 0
+#define AUTH_ID_COLUMN 1
+
+static EAPMethod *
+get_eap (WirelessSecurityWPAEAP *self)
+{
+ GtkTreeIter iter;
+ g_autofree gchar *id = NULL;
+
+ if (!gtk_combo_box_get_active_iter (self->auth_combo, &iter))
+ return NULL;
+ gtk_tree_model_get (GTK_TREE_MODEL (self->auth_model), &iter, AUTH_ID_COLUMN, &id, -1);
+
+ if (strcmp (id, "md5") == 0)
+ return EAP_METHOD (self->em_md5);
+ if (strcmp (id, "tls") == 0)
+ return EAP_METHOD (self->em_tls);
+ if (strcmp (id, "leap") == 0)
+ return EAP_METHOD (self->em_leap);
+ if (strcmp (id, "pwd") == 0)
+ return EAP_METHOD (self->em_pwd);
+ if (strcmp (id, "fast") == 0)
+ return EAP_METHOD (self->em_fast);
+ if (strcmp (id, "ttls") == 0)
+ return EAP_METHOD (self->em_ttls);
+ if (strcmp (id, "peap") == 0)
+ return EAP_METHOD (self->em_peap);
+
+ return NULL;
+}
+
+static gboolean
+validate (WirelessSecurity *security, GError **error)
+{
+ WirelessSecurityWPAEAP *self = WS_WPA_EAP (security);
+ return eap_method_validate (get_eap (self), error);
+}
+
+static void
+add_to_size_group (WirelessSecurity *security, GtkSizeGroup *group)
+{
+ WirelessSecurityWPAEAP *self = WS_WPA_EAP (security);
+
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->auth_label));
+ eap_method_add_to_size_group (EAP_METHOD (self->em_md5), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_tls), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_leap), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_pwd), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_fast), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_ttls), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_peap), group);
+}
+
+static void
+ws_802_1x_fill_connection (WirelessSecurityWPAEAP *self, NMConnection *connection)
+{
+ NMSettingWirelessSecurity *s_wireless_sec;
+ NMSetting8021x *s_8021x;
+ NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
+ EAPMethod *eap;
+
+ /* Get the EAPMethod object */
+ eap = get_eap (self);
+
+ /* Get previous pasword flags, if any. Otherwise default to agent-owned secrets */
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (s_8021x)
+ nm_setting_get_secret_flags (NM_SETTING (s_8021x), eap_method_get_password_flags_name (eap), &secret_flags, NULL);
+ else
+ secret_flags = NM_SETTING_SECRET_FLAG_AGENT_OWNED;
+
+ /* Blow away the old wireless security setting by adding a clear one */
+ s_wireless_sec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+ nm_connection_add_setting (connection, (NMSetting *) s_wireless_sec);
+
+ /* Blow away the old 802.1x setting by adding a clear one */
+ s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
+ nm_connection_add_setting (connection, (NMSetting *) s_8021x);
+
+ eap_method_fill_connection (eap, connection, secret_flags);
+}
+
+static void
+fill_connection (WirelessSecurity *security, NMConnection *connection)
+{
+ WirelessSecurityWPAEAP *self = WS_WPA_EAP (security);
+ NMSettingWirelessSecurity *s_wireless_sec;
+
+ ws_802_1x_fill_connection (self, connection);
+
+ s_wireless_sec = nm_connection_get_setting_wireless_security (connection);
+ g_assert (s_wireless_sec);
+
+ g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap", NULL);
+}
+
+static gboolean
+adhoc_compatible (WirelessSecurity *security)
+{
+ return FALSE;
+}
+
+static void
+auth_combo_changed_cb (WirelessSecurityWPAEAP *self)
+{
+ EAPMethod *eap;
+ GtkWidget *eap_default_field;
+ GtkWidget *child;
+
+ eap = get_eap (self);
+
+ /* Remove the previous method and migrate username/password across */
+ child = gtk_widget_get_first_child (GTK_WIDGET (self->method_box));
+ if (child != NULL) {
+ EAPMethod *old_eap = EAP_METHOD (child);
+ eap_method_set_username (eap, eap_method_get_username (old_eap));
+ eap_method_set_password (eap, eap_method_get_password (old_eap));
+ eap_method_set_show_password (eap, eap_method_get_show_password (old_eap));
+ gtk_box_remove (self->method_box, child);
+ }
+
+ gtk_box_append (self->method_box, g_object_ref (GTK_WIDGET (eap)));
+ eap_default_field = eap_method_get_default_field (eap);
+ if (eap_default_field)
+ gtk_widget_grab_focus (eap_default_field);
+
+ wireless_security_notify_changed (WIRELESS_SECURITY (self));
+}
+
+void
+ws_wpa_eap_init (WirelessSecurityWPAEAP *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+void
+ws_wpa_eap_class_init (WirelessSecurityWPAEAPClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/network/ws-wpa-eap.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWPAEAP, auth_combo);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWPAEAP, auth_label);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWPAEAP, auth_model);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWPAEAP, method_box);
+}
+
+static void
+wireless_security_iface_init (WirelessSecurityInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->adhoc_compatible = adhoc_compatible;
+}
+
+WirelessSecurityWPAEAP *
+ws_wpa_eap_new (NMConnection *connection)
+{
+ WirelessSecurityWPAEAP *self;
+ const gchar *remove_method, *default_method = NULL;
+ gboolean wired = FALSE;
+ GtkTreeIter iter;
+
+ self = g_object_new (ws_wpa_eap_get_type (), NULL);
+
+ /* Grab the default EAP method out of the security object */
+ if (connection) {
+ NMSettingConnection *s_con;
+ NMSetting8021x *s_8021x;
+ const char *ctype = NULL;
+
+ s_con = nm_connection_get_setting_connection (connection);
+ if (s_con)
+ ctype = nm_setting_connection_get_connection_type (s_con);
+ if ((g_strcmp0 (ctype, NM_SETTING_WIRED_SETTING_NAME) == 0)
+ || nm_connection_get_setting_wired (connection))
+ wired = TRUE;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (s_8021x && nm_setting_802_1x_get_num_eap_methods (s_8021x))
+ default_method = nm_setting_802_1x_get_eap_method (s_8021x, 0);
+ }
+ if (wired)
+ remove_method = "leap";
+ else
+ remove_method = "md5";
+ if (default_method == NULL) {
+ if (wired)
+ default_method = "md5";
+ else
+ default_method = "tls";
+ }
+
+ self->em_md5 = eap_method_simple_new (connection, "md5", FALSE, FALSE);
+ gtk_widget_show (GTK_WIDGET (self->em_md5));
+ g_signal_connect_object (self->em_md5, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+ self->em_tls = eap_method_tls_new (connection);
+ gtk_widget_show (GTK_WIDGET (self->em_tls));
+ g_signal_connect_object (self->em_tls, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+ self->em_leap = eap_method_leap_new (connection);
+ gtk_widget_show (GTK_WIDGET (self->em_leap));
+ g_signal_connect_object (self->em_leap, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+ self->em_pwd = eap_method_simple_new (connection, "pwd", FALSE, FALSE);
+ gtk_widget_show (GTK_WIDGET (self->em_pwd));
+ g_signal_connect_object (self->em_pwd, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+ self->em_fast = eap_method_fast_new (connection);
+ gtk_widget_show (GTK_WIDGET (self->em_fast));
+ g_signal_connect_object (self->em_fast, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+ self->em_ttls = eap_method_ttls_new (connection);
+ gtk_widget_show (GTK_WIDGET (self->em_ttls));
+ g_signal_connect_object (self->em_ttls, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+ self->em_peap = eap_method_peap_new (connection);
+ gtk_widget_show (GTK_WIDGET (self->em_peap));
+ g_signal_connect_object (self->em_peap, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->auth_model), &iter)) {
+ do {
+ g_autofree gchar *id = NULL;
+ gtk_tree_model_get (GTK_TREE_MODEL (self->auth_model), &iter, AUTH_ID_COLUMN, &id, -1);
+ if (strcmp (id, remove_method) == 0) {
+ gtk_list_store_remove (self->auth_model, &iter);
+ break;
+ }
+ } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->auth_model), &iter));
+ }
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->auth_model), &iter)) {
+ do {
+ g_autofree gchar *id = NULL;
+ gtk_tree_model_get (GTK_TREE_MODEL (self->auth_model), &iter, AUTH_ID_COLUMN, &id, -1);
+ if (strcmp (id, default_method) == 0)
+ gtk_combo_box_set_active_iter (self->auth_combo, &iter);
+ } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->auth_model), &iter));
+ }
+
+ if (connection) {
+ NMSetting8021x *setting;
+
+ setting = nm_connection_get_setting_802_1x (connection);
+ if (setting) {
+ eap_method_set_username (get_eap (self), nm_setting_802_1x_get_identity (setting));
+ eap_method_set_password (get_eap (self), nm_setting_802_1x_get_password (setting));
+ }
+ }
+
+ g_signal_connect_object (G_OBJECT (self->auth_combo), "changed", G_CALLBACK (auth_combo_changed_cb), self, G_CONNECT_SWAPPED);
+ auth_combo_changed_cb (self);
+
+ return self;
+}
+
+void
+ws_wpa_eap_fill_connection (WirelessSecurityWPAEAP *self, NMConnection *connection)
+{
+ ws_802_1x_fill_connection (self, connection);
+}
diff --git a/panels/network/wireless-security/ws-wpa-eap.h b/panels/network/wireless-security/ws-wpa-eap.h
new file mode 100644
index 0000000..da5aa7f
--- /dev/null
+++ b/panels/network/wireless-security/ws-wpa-eap.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (WirelessSecurityWPAEAP, ws_wpa_eap, WS, WPA_EAP, GtkGrid)
+
+WirelessSecurityWPAEAP *ws_wpa_eap_new (NMConnection *connection);
+
+void ws_wpa_eap_fill_connection (WirelessSecurityWPAEAP *sec,
+ NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/ws-wpa-eap.ui b/panels/network/wireless-security/ws-wpa-eap.ui
new file mode 100644
index 0000000..222eba7
--- /dev/null
+++ b/panels/network/wireless-security/ws-wpa-eap.ui
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.4"/>
+ <object class="GtkListStore" id="auth_model">
+ <columns>
+ <!-- column-name label -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ <!-- column-name visible -->
+ <column type="gboolean"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">MD5</col>
+ <col id="1">md5</col>
+ <col id="2">True</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">TLS</col>
+ <col id="1">tls</col>
+ <col id="2">True</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">LEAP</col>
+ <col id="1">leap</col>
+ <col id="2">True</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">PWD</col>
+ <col id="1">pwd</col>
+ <col id="2">True</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">FAST</col>
+ <col id="1">fast</col>
+ <col id="2">True</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Tunneled TLS</col>
+ <col id="1">ttls</col>
+ <col id="2">True</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Protected EAP (PEAP)</col>
+ <col id="1">peap</col>
+ <col id="2">True</col>
+ </row>
+ </data>
+ </object>
+ <template class="WirelessSecurityWPAEAP" parent="GtkGrid">
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="auth_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Au_thentication</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">auth_combo</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="auth_combo">
+ <property name="hexpand">True</property>
+ <property name="model">auth_model</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ <child>
+ <object class="GtkCellRendererText"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="method_box">
+ <property name="orientation">vertical</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="column-span">2</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/wireless-security/ws-wpa-psk.c b/panels/network/wireless-security/ws-wpa-psk.c
new file mode 100644
index 0000000..b911b36
--- /dev/null
+++ b/panels/network/wireless-security/ws-wpa-psk.c
@@ -0,0 +1,237 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include <ctype.h>
+#include <glib/gi18n.h>
+
+#include "helpers.h"
+#include "nma-ui-utils.h"
+#include "ui-helpers.h"
+#include "ws-wpa-psk.h"
+#include "wireless-security.h"
+
+#define WPA_PMK_LEN 32
+
+struct _WirelessSecurityWPAPSK {
+ GtkGrid parent;
+
+ GtkEntry *password_entry;
+ GtkLabel *password_label;
+ GtkCheckButton *show_password_check;
+ GtkComboBox *type_combo;
+ GtkLabel *type_label;
+};
+
+static void wireless_security_iface_init (WirelessSecurityInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (WirelessSecurityWPAPSK, ws_wpa_psk, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (wireless_security_get_type (), wireless_security_iface_init));
+
+static void
+show_toggled_cb (WirelessSecurityWPAPSK *self)
+{
+ gboolean visible;
+
+ visible = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->show_password_check));
+ gtk_entry_set_visibility (self->password_entry, visible);
+}
+
+static gboolean
+validate (WirelessSecurity *security, GError **error)
+{
+ WirelessSecurityWPAPSK *self = WS_WPA_PSK (security);
+ NMSettingSecretFlags secret_flags;
+ const char *key;
+ gsize len;
+ int i;
+
+ secret_flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->password_entry));
+ if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED) {
+ widget_unset_error (GTK_WIDGET (self->password_entry));
+ return TRUE;
+ }
+
+ key = gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+ len = key ? strlen (key) : 0;
+ if ((len < 8) || (len > 64)) {
+ widget_set_error (GTK_WIDGET (self->password_entry));
+ g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid wpa-psk: invalid key-length %zu. Must be [8,63] bytes or 64 hex digits"), len);
+ return FALSE;
+ }
+
+ if (len == 64) {
+ /* Hex PSK */
+ for (i = 0; i < len; i++) {
+ if (!isxdigit (key[i])) {
+ widget_set_error (GTK_WIDGET (self->password_entry));
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid wpa-psk: cannot interpret key with 64 bytes as hex"));
+ return FALSE;
+ }
+ }
+ }
+ widget_unset_error (GTK_WIDGET (self->password_entry));
+
+ /* passphrase can be between 8 and 63 characters inclusive */
+
+ return TRUE;
+}
+
+static void
+add_to_size_group (WirelessSecurity *security, GtkSizeGroup *group)
+{
+ WirelessSecurityWPAPSK *self = WS_WPA_PSK (security);
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->type_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->password_label));
+}
+
+static void
+fill_connection (WirelessSecurity *security, NMConnection *connection)
+{
+ WirelessSecurityWPAPSK *self = WS_WPA_PSK (security);
+ const char *key;
+ NMSettingWireless *s_wireless;
+ NMSettingWirelessSecurity *s_wireless_sec;
+ NMSettingSecretFlags secret_flags;
+ const char *mode;
+ gboolean is_adhoc = FALSE;
+
+ s_wireless = nm_connection_get_setting_wireless (connection);
+ g_assert (s_wireless);
+
+ mode = nm_setting_wireless_get_mode (s_wireless);
+ if (mode && !strcmp (mode, "adhoc"))
+ is_adhoc = TRUE;
+
+ /* Blow away the old security setting by adding a clear one */
+ s_wireless_sec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+ nm_connection_add_setting (connection, (NMSetting *) s_wireless_sec);
+
+ key = gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+ g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_PSK, key, NULL);
+
+ /* Save PSK_FLAGS to the connection */
+ secret_flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->password_entry));
+ nm_setting_set_secret_flags (NM_SETTING (s_wireless_sec), NM_SETTING_WIRELESS_SECURITY_PSK,
+ secret_flags, NULL);
+
+ /* Update secret flags and popup when editing the connection */
+ nma_utils_update_password_storage (GTK_WIDGET (self->password_entry), secret_flags,
+ NM_SETTING (s_wireless_sec), NM_SETTING_WIRELESS_SECURITY_PSK);
+
+ wireless_security_clear_ciphers (connection);
+ if (is_adhoc) {
+ /* Ad-Hoc settings as specified by the supplicant */
+ g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-none", NULL);
+ nm_setting_wireless_security_add_proto (s_wireless_sec, "wpa");
+ nm_setting_wireless_security_add_pairwise (s_wireless_sec, "none");
+
+ /* Ad-hoc can only have _one_ group cipher... default to TKIP to be more
+ * compatible for now. Maybe we'll support selecting CCMP later.
+ */
+ nm_setting_wireless_security_add_group (s_wireless_sec, "tkip");
+ } else {
+ g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", NULL);
+
+ /* Just leave ciphers and protocol empty, the supplicant will
+ * figure that out magically based on the AP IEs and card capabilities.
+ */
+ }
+}
+
+static gboolean
+adhoc_compatible (WirelessSecurity *security)
+{
+ return FALSE;
+}
+
+static void
+changed_cb (WirelessSecurityWPAPSK *self)
+{
+ wireless_security_notify_changed ((WirelessSecurity *) self);
+}
+
+void
+ws_wpa_psk_init (WirelessSecurityWPAPSK *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+void
+ws_wpa_psk_class_init (WirelessSecurityWPAPSKClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/network/ws-wpa-psk.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWPAPSK, password_entry);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWPAPSK, password_label);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWPAPSK, show_password_check);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWPAPSK, type_combo);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWPAPSK, type_label);
+}
+
+static void
+wireless_security_iface_init (WirelessSecurityInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->adhoc_compatible = adhoc_compatible;
+}
+
+WirelessSecurityWPAPSK *
+ws_wpa_psk_new (NMConnection *connection)
+{
+ WirelessSecurityWPAPSK *self;
+ NMSetting *setting = NULL;
+
+ self = g_object_new (ws_wpa_psk_get_type (), NULL);
+
+ g_signal_connect_swapped (self->password_entry, "changed", G_CALLBACK (changed_cb), self);
+ gtk_editable_set_width_chars (GTK_EDITABLE (self->password_entry), 28);
+
+ /* Create password-storage popup menu for password entry under entry's secondary icon */
+ if (connection)
+ setting = (NMSetting *) nm_connection_get_setting_wireless_security (connection);
+ nma_utils_setup_password_storage (GTK_WIDGET (self->password_entry), 0, setting, NM_SETTING_WIRELESS_SECURITY_PSK,
+ FALSE, FALSE);
+
+ /* Fill secrets, if any */
+ if (connection) {
+ helper_fill_secret_entry (connection,
+ self->password_entry,
+ NM_TYPE_SETTING_WIRELESS_SECURITY,
+ (HelperSecretFunc) nm_setting_wireless_security_get_psk);
+ }
+
+ g_signal_connect_swapped (self->show_password_check, "toggled", G_CALLBACK (show_toggled_cb), self);
+
+ /* Hide WPA/RSN for now since this can be autodetected by NM and the
+ * supplicant when connecting to the AP.
+ */
+
+ gtk_widget_hide (GTK_WIDGET (self->type_combo));
+ gtk_widget_hide (GTK_WIDGET (self->type_label));
+
+ return self;
+}
+
diff --git a/panels/network/wireless-security/ws-wpa-psk.h b/panels/network/wireless-security/ws-wpa-psk.h
new file mode 100644
index 0000000..7ca8676
--- /dev/null
+++ b/panels/network/wireless-security/ws-wpa-psk.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (WirelessSecurityWPAPSK, ws_wpa_psk, WS, WPA_PSK, GtkGrid)
+
+WirelessSecurityWPAPSK *ws_wpa_psk_new (NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/ws-wpa-psk.ui b/panels/network/wireless-security/ws-wpa-psk.ui
new file mode 100644
index 0000000..26c9415
--- /dev/null
+++ b/panels/network/wireless-security/ws-wpa-psk.ui
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.4"/>
+ <template class="WirelessSecurityWPAPSK" parent="GtkGrid">
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="password_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">password_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="password_entry">
+ <property name="hexpand">True</property>
+ <property name="max_length">64</property>
+ <property name="visibility">False</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="type_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Type</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">type_combo</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="show_password_check">
+ <property name="label" translatable="yes">Sho_w password</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="type_combo">
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/notifications/cc-app-notifications-dialog.c b/panels/notifications/cc-app-notifications-dialog.c
new file mode 100644
index 0000000..851ddc4
--- /dev/null
+++ b/panels/notifications/cc-app-notifications-dialog.c
@@ -0,0 +1,399 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2012 Giovanni Campagna <scampa.giovanni@gmail.com>
+ * Copyright (C) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <gio/gdesktopappinfo.h>
+
+#include "cc-notifications-panel.h"
+#include "cc-app-notifications-dialog.h"
+
+/*
+ * Key Switch
+ *
+ * "enable", "notifications-switch" When set to off, all other switches in the dialog are insensitive
+ * "enable-sound-alerts", "sound-alerts-switch"
+ * "show-banners", "notification-banners-switch" Off and insensitive when corresponding panel switch is off
+ * "force-expanded", "notification-banners-content-switch" Off and insensitive when switch above is off
+ * "show-in-lock-screen", "lock-screen-notifications-switch" Off and insensitive when corresponding panel switch is off
+ * "details-in-lock-screen", "lock-screen-content-switch" Off and insensitive when switch above is off
+ */
+
+static void update_banner_switch (CcAppNotificationsDialog *dialog);
+static void update_banner_content_switch (CcAppNotificationsDialog *dialog);
+static void update_lock_screen_switch (CcAppNotificationsDialog *dialog);
+static void update_lock_screen_content_switch (CcAppNotificationsDialog *dialog);
+static void update_sound_switch (CcAppNotificationsDialog *dialog);
+static void update_notification_switch (CcAppNotificationsDialog *dialog);
+
+struct _CcAppNotificationsDialog {
+ GtkDialog parent;
+
+ GSettings *settings;
+ GSettings *master_settings;
+ gchar *app_id;
+ GDBusProxy *perm_store;
+
+ GtkWidget *notifications_switch;
+ GtkWidget *sound_alerts_switch;
+ GtkWidget *notification_banners_switch;
+ GtkWidget *notification_banners_content_switch;
+ GtkWidget *lock_screen_notifications_switch;
+ GtkWidget *lock_screen_content_switch;
+};
+
+G_DEFINE_TYPE (CcAppNotificationsDialog, cc_app_notifications_dialog, GTK_TYPE_DIALOG)
+
+static void
+on_perm_store_set_done (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GVariant) results = NULL;
+ g_autoptr(GError) error = NULL;
+
+ results = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
+ res,
+ &error);
+ if (results == NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to store permissions: %s", error->message);
+ return;
+ }
+}
+
+static void
+set_portal_permissions_for_app (CcAppNotificationsDialog *dialog, GtkSwitch *the_switch)
+{
+ gboolean allow = gtk_switch_get_active (the_switch);
+ g_autoptr(GVariant) perms = NULL;
+ g_autoptr(GVariant) new_perms = NULL;
+ g_autoptr(GVariant) data = NULL;
+ GVariantBuilder builder;
+ gboolean found;
+ int i;
+ const char *yes_strv[] = { "yes", NULL };
+ const char *no_strv[] = { "no", NULL };
+ g_autoptr(GVariant) reply = NULL;
+
+ if (dialog->perm_store == NULL)
+ {
+ g_warning ("Could not find PermissionStore, not syncing notification permissions");
+ return;
+ }
+
+ new_perms = g_variant_new_strv (allow ? yes_strv : no_strv, 1);
+ g_variant_ref_sink (new_perms);
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE("a{sas}"));
+ found = FALSE;
+
+ reply = g_dbus_proxy_call_sync (dialog->perm_store,
+ "Lookup",
+ g_variant_new ("(ss)",
+ "notifications",
+ "notification"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ NULL);
+ if (reply)
+ {
+ g_variant_get (reply, "(@a{sas}v)", &perms, &data);
+
+ for (i = 0; i < g_variant_n_children (perms); i++)
+ {
+ const char *key;
+ g_autoptr(GVariant) value = NULL;
+
+ g_variant_get_child (perms, i, "{&s@as}", &key, &value);
+ if (g_strcmp0 (key, dialog->app_id) == 0)
+ {
+ found = TRUE;
+ g_variant_builder_add (&builder, "{s@as}", key, new_perms);
+ }
+ else
+ g_variant_builder_add (&builder, "{s@as}", key, value);
+ }
+ }
+
+ if (!found)
+ g_variant_builder_add (&builder, "{s@as}", dialog->app_id, new_perms);
+
+ g_dbus_proxy_call (dialog->perm_store,
+ "Set",
+ g_variant_new ("(sbsa{sas}v)",
+ "notifications",
+ TRUE,
+ "notification",
+ &builder,
+ data ? data : g_variant_new_byte (0)),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ on_perm_store_set_done,
+ data);
+}
+
+static void
+notifications_switch_state_set_cb (GtkSwitch *widget,
+ GParamSpec *pspec,
+ CcAppNotificationsDialog *dialog)
+{
+ g_settings_set_boolean (dialog->settings, "enable", gtk_switch_get_active (widget));
+ set_portal_permissions_for_app (dialog, widget);
+ update_sound_switch (dialog);
+ update_banner_switch (dialog);
+ update_banner_content_switch (dialog);
+ update_lock_screen_switch (dialog);
+ update_lock_screen_content_switch (dialog);
+}
+
+static void
+sound_alerts_switch_state_set_cb (GtkSwitch *widget,
+ GParamSpec *pspec,
+ CcAppNotificationsDialog *dialog)
+{
+ g_settings_set_boolean (dialog->settings, "enable-sound-alerts", gtk_switch_get_active (widget));
+}
+
+static void
+notification_banners_switch_state_set_cb (GtkSwitch *widget,
+ GParamSpec *pspec,
+ CcAppNotificationsDialog *dialog)
+{
+ g_settings_set_boolean (dialog->settings, "show-banners", gtk_switch_get_active (widget));
+ update_banner_content_switch (dialog);
+}
+
+static void
+notification_banners_content_switch_state_set_cb (GtkSwitch *widget,
+ GParamSpec *pspec,
+ CcAppNotificationsDialog *dialog)
+{
+ g_settings_set_boolean (dialog->settings, "force-expanded", gtk_switch_get_active (widget));
+}
+
+static void
+lock_screen_notifications_switch_state_set_cb (GtkSwitch *widget,
+ GParamSpec *pspec,
+ CcAppNotificationsDialog *dialog)
+{
+ g_settings_set_boolean (dialog->settings, "show-in-lock-screen", gtk_switch_get_active (widget));
+ update_lock_screen_content_switch (dialog);
+}
+
+static void
+lock_screen_content_switch_state_set_cb (GtkSwitch *widget,
+ GParamSpec *pspec,
+ CcAppNotificationsDialog *dialog)
+{
+ g_settings_set_boolean (dialog->settings, "details-in-lock-screen", gtk_switch_get_active (widget));
+}
+
+static void
+update_switches (CcAppNotificationsDialog *dialog)
+{
+ update_notification_switch (dialog);
+ update_sound_switch (dialog);
+ update_banner_switch (dialog);
+ update_banner_content_switch (dialog);
+ update_lock_screen_switch (dialog);
+ update_lock_screen_content_switch (dialog);
+}
+
+static void
+update_notification_switch (CcAppNotificationsDialog *dialog)
+{
+ g_signal_handlers_block_by_func (G_OBJECT (dialog->notifications_switch), notifications_switch_state_set_cb, dialog);
+ gtk_switch_set_active (GTK_SWITCH (dialog->notifications_switch), g_settings_get_boolean (dialog->settings, "enable"));
+ g_signal_handlers_unblock_by_func (G_OBJECT (dialog->notifications_switch), notifications_switch_state_set_cb, dialog);
+}
+
+static void
+update_sound_switch (CcAppNotificationsDialog *dialog)
+{
+ g_signal_handlers_block_by_func (G_OBJECT (dialog->sound_alerts_switch), sound_alerts_switch_state_set_cb, dialog);
+ gtk_switch_set_active (GTK_SWITCH (dialog->sound_alerts_switch), g_settings_get_boolean (dialog->settings, "enable-sound-alerts"));
+ g_signal_handlers_unblock_by_func (G_OBJECT (dialog->sound_alerts_switch), sound_alerts_switch_state_set_cb, dialog);
+ gtk_widget_set_sensitive (dialog->sound_alerts_switch, g_settings_get_boolean (dialog->settings, "enable"));
+}
+
+static void
+update_banner_switch (CcAppNotificationsDialog *dialog)
+{
+ gboolean notifications_enabled;
+ gboolean show_banners;
+ gboolean active;
+ gboolean sensitive;
+
+ show_banners = g_settings_get_boolean (dialog->master_settings, "show-banners");
+ notifications_enabled = g_settings_get_boolean (dialog->settings, "enable");
+
+ active = g_settings_get_boolean (dialog->settings, "show-banners") &&
+ show_banners;
+ sensitive = notifications_enabled &&
+ show_banners;
+ g_signal_handlers_block_by_func (G_OBJECT (dialog->notification_banners_switch), notification_banners_switch_state_set_cb, dialog);
+ gtk_switch_set_active (GTK_SWITCH (dialog->notification_banners_switch), active);
+ g_signal_handlers_unblock_by_func (G_OBJECT (dialog->notification_banners_switch), notification_banners_switch_state_set_cb, dialog);
+ gtk_widget_set_sensitive (dialog->notification_banners_switch, sensitive);
+}
+
+static void
+update_banner_content_switch (CcAppNotificationsDialog *dialog)
+{
+ gboolean notifications_enabled;
+ gboolean show_banners;
+ gboolean active;
+ gboolean sensitive;
+
+ show_banners = g_settings_get_boolean (dialog->master_settings, "show-banners");
+ notifications_enabled = g_settings_get_boolean (dialog->settings, "enable");
+
+ active = g_settings_get_boolean (dialog->settings, "force-expanded") &&
+ g_settings_get_boolean (dialog->settings, "show-banners") &&
+ show_banners;
+ sensitive = g_settings_get_boolean (dialog->settings, "show-banners") &&
+ notifications_enabled &&
+ show_banners;
+ g_signal_handlers_block_by_func (G_OBJECT (dialog->notification_banners_content_switch), notification_banners_content_switch_state_set_cb, dialog);
+ gtk_switch_set_active (GTK_SWITCH (dialog->notification_banners_content_switch), active);
+ g_signal_handlers_unblock_by_func (G_OBJECT (dialog->notification_banners_content_switch), notification_banners_content_switch_state_set_cb, dialog);
+ gtk_widget_set_sensitive (dialog->notification_banners_content_switch, sensitive);
+}
+
+static void
+update_lock_screen_switch (CcAppNotificationsDialog *dialog)
+{
+ gboolean notifications_enabled;
+ gboolean show_in_lock_screen;
+ gboolean active;
+ gboolean sensitive;
+
+ show_in_lock_screen = g_settings_get_boolean (dialog->master_settings, "show-in-lock-screen");
+ notifications_enabled = g_settings_get_boolean (dialog->settings, "enable");
+
+ active = g_settings_get_boolean (dialog->settings, "show-in-lock-screen") &&
+ show_in_lock_screen;
+ sensitive = notifications_enabled &&
+ show_in_lock_screen;
+
+ g_signal_handlers_block_by_func (G_OBJECT (dialog->lock_screen_notifications_switch), lock_screen_notifications_switch_state_set_cb, dialog);
+ gtk_switch_set_active (GTK_SWITCH (dialog->lock_screen_notifications_switch), active);
+ g_signal_handlers_unblock_by_func (G_OBJECT (dialog->lock_screen_notifications_switch), lock_screen_notifications_switch_state_set_cb, dialog);
+ gtk_widget_set_sensitive (dialog->lock_screen_notifications_switch, sensitive);
+}
+
+static void
+update_lock_screen_content_switch (CcAppNotificationsDialog *dialog)
+{
+ gboolean notifications_enabled;
+ gboolean show_in_lock_screen;
+ gboolean active;
+ gboolean sensitive;
+
+ show_in_lock_screen = g_settings_get_boolean (dialog->master_settings, "show-in-lock-screen");
+ notifications_enabled = g_settings_get_boolean (dialog->settings, "enable");
+
+ active = g_settings_get_boolean (dialog->settings, "details-in-lock-screen") &&
+ g_settings_get_boolean (dialog->settings, "show-in-lock-screen") &&
+ show_in_lock_screen;
+ sensitive = g_settings_get_boolean (dialog->settings, "show-in-lock-screen") &&
+ notifications_enabled &&
+ show_in_lock_screen;
+ g_signal_handlers_block_by_func (G_OBJECT (dialog->lock_screen_content_switch), lock_screen_content_switch_state_set_cb, dialog);
+ gtk_switch_set_active (GTK_SWITCH (dialog->lock_screen_content_switch), active);
+ g_signal_handlers_unblock_by_func (G_OBJECT (dialog->lock_screen_content_switch), lock_screen_content_switch_state_set_cb, dialog);
+ gtk_widget_set_sensitive (dialog->lock_screen_content_switch, sensitive);
+}
+
+static void
+cc_app_notifications_dialog_dispose (GObject *object)
+{
+ CcAppNotificationsDialog *dialog = CC_APP_NOTIFICATIONS_DIALOG (object);
+
+ g_clear_object (&dialog->settings);
+ g_clear_object (&dialog->master_settings);
+ g_clear_pointer (&dialog->app_id, g_free);
+ g_clear_object (&dialog->perm_store);
+
+ G_OBJECT_CLASS (cc_app_notifications_dialog_parent_class)->dispose (object);
+}
+
+static void
+cc_app_notifications_dialog_class_init (CcAppNotificationsDialogClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = cc_app_notifications_dialog_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/notifications/cc-app-notifications-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcAppNotificationsDialog, notifications_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcAppNotificationsDialog, sound_alerts_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcAppNotificationsDialog, notification_banners_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcAppNotificationsDialog, notification_banners_content_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcAppNotificationsDialog, lock_screen_notifications_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcAppNotificationsDialog, lock_screen_content_switch);
+
+ gtk_widget_class_bind_template_callback (widget_class, notifications_switch_state_set_cb);
+ gtk_widget_class_bind_template_callback (widget_class, sound_alerts_switch_state_set_cb);
+ gtk_widget_class_bind_template_callback (widget_class, notification_banners_switch_state_set_cb);
+ gtk_widget_class_bind_template_callback (widget_class, notification_banners_content_switch_state_set_cb);
+ gtk_widget_class_bind_template_callback (widget_class, lock_screen_notifications_switch_state_set_cb);
+ gtk_widget_class_bind_template_callback (widget_class, lock_screen_content_switch_state_set_cb);
+}
+
+void
+cc_app_notifications_dialog_init (CcAppNotificationsDialog *dialog)
+{
+ gtk_widget_init_template (GTK_WIDGET (dialog));
+}
+
+CcAppNotificationsDialog *
+cc_app_notifications_dialog_new (const gchar *app_id,
+ const gchar *title,
+ GSettings *settings,
+ GSettings *master_settings,
+ GDBusProxy *perm_store)
+{
+ CcAppNotificationsDialog *dialog;
+
+ dialog = g_object_new (CC_TYPE_APP_NOTIFICATIONS_DIALOG,
+ "use-header-bar", 1,
+ NULL);
+
+ gtk_window_set_title (GTK_WINDOW (dialog), title);
+ dialog->settings = g_object_ref (settings);
+ dialog->master_settings = g_object_ref (master_settings);
+ dialog->app_id = g_strdup (app_id);
+ dialog->perm_store = g_object_ref (perm_store);
+
+ update_switches (dialog);
+
+ return dialog;
+}
diff --git a/panels/notifications/cc-app-notifications-dialog.h b/panels/notifications/cc-app-notifications-dialog.h
new file mode 100644
index 0000000..99b1e38
--- /dev/null
+++ b/panels/notifications/cc-app-notifications-dialog.h
@@ -0,0 +1,35 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2012 Giovanni Campagna <scampa.giovanni@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_APP_NOTIFICATIONS_DIALOG (cc_app_notifications_dialog_get_type ())
+G_DECLARE_FINAL_TYPE (CcAppNotificationsDialog, cc_app_notifications_dialog, CC, APP_NOTIFICATIONS_DIALOG, GtkDialog)
+
+CcAppNotificationsDialog *cc_app_notifications_dialog_new (const gchar *app_id,
+ const gchar *title,
+ GSettings *settings,
+ GSettings *master_settings,
+ GDBusProxy *perm_store);
+
+G_END_DECLS
diff --git a/panels/notifications/cc-app-notifications-dialog.ui b/panels/notifications/cc-app-notifications-dialog.ui
new file mode 100644
index 0000000..c697eb1
--- /dev/null
+++ b/panels/notifications/cc-app-notifications-dialog.ui
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcAppNotificationsDialog" parent="GtkDialog">
+ <property name="default-width">550</property>
+ <property name="default-height">450</property>
+ <property name="resizable">True</property>
+ <property name="modal">True</property>
+ <child>
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="AdwActionRow">
+ <property name="use-underline">True</property>
+ <property name="title" translatable="yes" context="notifications" comments="This is the per application switch for message tray usage.">_Notifications</property>
+ <property name="activatable-widget">notifications_switch</property>
+ <child>
+ <object class="GtkSwitch" id="notifications_switch">
+ <property name="valign">center</property>
+ <property name="active">True</property>
+ <signal name="notify::active" handler="notifications_switch_state_set_cb" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow">
+ <property name="use-underline">True</property>
+ <property name="title" translatable="yes" context="notifications" comments="This is the setting to configure sounds associated with notifications.">Sound _Alerts</property>
+ <property name="activatable-widget">sound_alerts_switch</property>
+ <child>
+ <object class="GtkSwitch" id="sound_alerts_switch">
+ <property name="valign">center</property>
+ <signal name="notify::active" handler="sound_alerts_switch_state_set_cb" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow">
+ <property name="use-underline">True</property>
+ <property name="title" translatable="yes" context="notifications">Notification _Popups</property>
+ <property name="subtitle" translatable="yes">Notifications will continue to appear in the notification list when popups are disabled.</property>
+ <property name="activatable-widget">notification_banners_switch</property>
+ <child>
+ <object class="GtkSwitch" id="notification_banners_switch">
+ <property name="valign">center</property>
+ <signal name="notify::active" handler="notification_banners_switch_state_set_cb" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow">
+ <property name="use-underline">True</property>
+ <property name="title" translatable="yes" context="notifications" comments="Popups here refers to message tray notifications in the middle of the screen.">Show Message _Content in Popups</property>
+ <property name="activatable-widget">notification_banners_content_switch</property>
+ <child>
+ <object class="GtkSwitch" id="notification_banners_content_switch">
+ <property name="valign">center</property>
+ <signal name="notify::active" handler="notification_banners_content_switch_state_set_cb" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow">
+ <property name="use-underline">True</property>
+ <property name="title" translatable="yes" context="notifications">_Lock Screen Notifications</property>
+ <property name="activatable-widget">lock_screen_notifications_switch</property>
+ <child>
+ <object class="GtkSwitch" id="lock_screen_notifications_switch">
+ <property name="valign">center</property>
+ <signal name="notify::active" handler="lock_screen_notifications_switch_state_set_cb" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow">
+ <property name="use-underline">True</property>
+ <property name="title" translatable="yes" context="notifications">Show Message C_ontent on Lock Screen</property>
+ <property name="activatable-widget">lock_screen_content_switch</property>
+ <child>
+ <object class="GtkSwitch" id="lock_screen_content_switch">
+ <property name="valign">center</property>
+ <signal name="notify::active" handler="lock_screen_content_switch_state_set_cb" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/notifications/cc-notifications-panel.c b/panels/notifications/cc-notifications-panel.c
new file mode 100644
index 0000000..78d1893
--- /dev/null
+++ b/panels/notifications/cc-notifications-panel.c
@@ -0,0 +1,476 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2012 Giovanni Campagna <scampa.giovanni@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "config.h"
+
+#include <adwaita.h>
+#include <string.h>
+#include <glib/gi18n-lib.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <gio/gdesktopappinfo.h>
+
+#include "cc-list-row.h"
+#include "cc-notifications-panel.h"
+#include "cc-notifications-resources.h"
+#include "cc-app-notifications-dialog.h"
+
+#define MASTER_SCHEMA "org.gnome.desktop.notifications"
+#define APP_SCHEMA MASTER_SCHEMA ".application"
+#define APP_PREFIX "/org/gnome/desktop/notifications/application/"
+
+struct _CcNotificationsPanel {
+ CcPanel parent_instance;
+
+ GtkListBox *app_listbox;
+ CcListRow *lock_screen_row;
+ CcListRow *dnd_row;
+ GtkSizeGroup *sizegroup1;
+
+ GSettings *master_settings;
+
+ GCancellable *cancellable;
+
+ GHashTable *known_applications;
+
+ GDBusProxy *perm_store;
+};
+
+struct _CcNotificationsPanelClass {
+ CcPanelClass parent;
+};
+
+typedef struct {
+ char *canonical_app_id;
+ GAppInfo *app_info;
+ GSettings *settings;
+
+ /* Temporary pointer, to pass from the loading thread
+ to the app */
+ CcNotificationsPanel *panel;
+} Application;
+
+static void build_app_store (CcNotificationsPanel *panel);
+static void select_app (CcNotificationsPanel *panel, GtkListBoxRow *row);
+static int sort_apps (gconstpointer one, gconstpointer two, gpointer user_data);
+
+CC_PANEL_REGISTER (CcNotificationsPanel, cc_notifications_panel);
+
+static gboolean
+keynav_failed_cb (CcNotificationsPanel *self,
+ GtkDirectionType direction)
+{
+ GtkWidget *toplevel = GTK_WIDGET (gtk_widget_get_root (GTK_WIDGET (self)));
+
+ if (!toplevel)
+ return FALSE;
+
+ if (direction != GTK_DIR_UP && direction != GTK_DIR_DOWN)
+ return FALSE;
+
+ return gtk_widget_child_focus (toplevel, direction == GTK_DIR_UP ?
+ GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD);
+}
+
+static void
+cc_notifications_panel_dispose (GObject *object)
+{
+ CcNotificationsPanel *panel = CC_NOTIFICATIONS_PANEL (object);
+
+ g_clear_object (&panel->master_settings);
+ g_clear_pointer (&panel->known_applications, g_hash_table_unref);
+
+ G_OBJECT_CLASS (cc_notifications_panel_parent_class)->dispose (object);
+}
+
+static void
+cc_notifications_panel_finalize (GObject *object)
+{
+ CcNotificationsPanel *panel = CC_NOTIFICATIONS_PANEL (object);
+
+ g_clear_object (&panel->perm_store);
+
+ G_OBJECT_CLASS (cc_notifications_panel_parent_class)->finalize (object);
+}
+
+static void
+on_perm_store_ready (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcNotificationsPanel *self;
+ GDBusProxy *proxy;
+ g_autoptr(GError) error = NULL;
+
+ proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+ if (proxy == NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to connect to xdg-app permission store: %s",
+ error->message);
+ return;
+ }
+ self = user_data;
+ self->perm_store = proxy;
+}
+
+static void
+cc_notifications_panel_init (CcNotificationsPanel *panel)
+{
+ g_resources_register (cc_notifications_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (panel));
+
+ panel->known_applications = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, g_free);
+
+ panel->master_settings = g_settings_new (MASTER_SCHEMA);
+
+ g_settings_bind (panel->master_settings, "show-banners",
+ panel->dnd_row,
+ "active", G_SETTINGS_BIND_INVERT_BOOLEAN);
+ g_settings_bind (panel->master_settings, "show-in-lock-screen",
+ panel->lock_screen_row,
+ "active", G_SETTINGS_BIND_DEFAULT);
+
+ gtk_list_box_set_sort_func (panel->app_listbox, (GtkListBoxSortFunc)sort_apps, NULL, NULL);
+
+ build_app_store (panel);
+
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.freedesktop.impl.portal.PermissionStore",
+ "/org/freedesktop/impl/portal/PermissionStore",
+ "org.freedesktop.impl.portal.PermissionStore",
+ cc_panel_get_cancellable (CC_PANEL (panel)),
+ on_perm_store_ready,
+ panel);
+}
+
+static const char *
+cc_notifications_panel_get_help_uri (CcPanel *panel)
+{
+ return "help:gnome-help/shell-notifications";
+}
+
+static void
+cc_notifications_panel_class_init (CcNotificationsPanelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+
+ panel_class->get_help_uri = cc_notifications_panel_get_help_uri;
+
+ /* Separate dispose() and finalize() functions are necessary
+ * to make sure we cancel the running thread before the panel
+ * gets finalized */
+ object_class->dispose = cc_notifications_panel_dispose;
+ object_class->finalize = cc_notifications_panel_finalize;
+
+ g_type_ensure (CC_TYPE_LIST_ROW);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/notifications/cc-notifications-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcNotificationsPanel, app_listbox);
+ gtk_widget_class_bind_template_child (widget_class, CcNotificationsPanel, lock_screen_row);
+ gtk_widget_class_bind_template_child (widget_class, CcNotificationsPanel, dnd_row);
+ gtk_widget_class_bind_template_child (widget_class, CcNotificationsPanel, sizegroup1);
+
+ gtk_widget_class_bind_template_callback (widget_class, select_app);
+ gtk_widget_class_bind_template_callback (widget_class, keynav_failed_cb);
+}
+
+static inline GQuark
+application_quark (void)
+{
+ static GQuark quark;
+
+ if (G_UNLIKELY (quark == 0))
+ quark = g_quark_from_static_string ("cc-application");
+
+ return quark;
+}
+
+static gboolean
+on_off_label_mapping_get (GValue *value,
+ GVariant *variant,
+ gpointer user_data)
+{
+ g_value_set_string (value, g_variant_get_boolean (variant) ? _("On") : _("Off"));
+
+ return TRUE;
+}
+
+static void
+application_free (Application *app)
+{
+ g_free (app->canonical_app_id);
+ g_object_unref (app->app_info);
+ g_object_unref (app->settings);
+
+ g_slice_free (Application, app);
+}
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (Application, application_free)
+
+static void
+add_application (CcNotificationsPanel *panel,
+ Application *app)
+{
+ GtkWidget *w, *row;
+ g_autoptr(GIcon) icon = NULL;
+ const gchar *app_name;
+
+ app_name = g_app_info_get_name (app->app_info);
+ if (app_name == NULL || *app_name == '\0')
+ return;
+
+ icon = g_app_info_get_icon (app->app_info);
+ if (icon == NULL)
+ icon = g_themed_icon_new ("application-x-executable");
+ else
+ g_object_ref (icon);
+
+ row = adw_action_row_new ();
+ gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), TRUE);
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row),
+ g_markup_escape_text (app_name, -1));
+
+ g_object_set_qdata_full (G_OBJECT (row), application_quark (),
+ app, (GDestroyNotify) application_free);
+
+ gtk_list_box_append (panel->app_listbox, row);
+
+ w = gtk_image_new_from_gicon (icon);
+ gtk_style_context_add_class (gtk_widget_get_style_context (w), "lowres-icon");
+ gtk_image_set_icon_size (GTK_IMAGE (w), GTK_ICON_SIZE_LARGE);
+ adw_action_row_add_prefix (ADW_ACTION_ROW (row), w);
+
+ w = gtk_label_new ("");
+ g_settings_bind_with_mapping (app->settings, "enable",
+ w, "label",
+ G_SETTINGS_BIND_GET |
+ G_SETTINGS_BIND_NO_SENSITIVITY,
+ on_off_label_mapping_get,
+ NULL,
+ NULL,
+ NULL);
+ adw_action_row_add_suffix (ADW_ACTION_ROW (row), w);
+
+ w = gtk_image_new_from_icon_name ("go-next-symbolic");
+ adw_action_row_add_suffix (ADW_ACTION_ROW (row), w);
+
+ g_hash_table_add (panel->known_applications, g_strdup (app->canonical_app_id));
+}
+
+static void
+maybe_add_app_id (CcNotificationsPanel *panel,
+ const char *canonical_app_id)
+{
+ Application *app;
+ g_autofree gchar *path = NULL;
+ g_autofree gchar *full_app_id = NULL;
+ g_autoptr(GSettings) settings = NULL;
+ g_autoptr(GAppInfo) app_info = NULL;
+
+ if (*canonical_app_id == '\0')
+ return;
+
+ if (g_hash_table_contains (panel->known_applications,
+ canonical_app_id))
+ return;
+
+ path = g_strconcat (APP_PREFIX, canonical_app_id, "/", NULL);
+ settings = g_settings_new_with_path (APP_SCHEMA, path);
+
+ full_app_id = g_settings_get_string (settings, "application-id");
+ app_info = G_APP_INFO (g_desktop_app_info_new (full_app_id));
+
+ if (app_info == NULL) {
+ g_debug ("Not adding application '%s' (canonical app ID: %s)",
+ full_app_id, canonical_app_id);
+ /* The application cannot be found, probably it was uninstalled */
+ return;
+ }
+
+ app = g_slice_new (Application);
+ app->canonical_app_id = g_strdup (canonical_app_id);
+ app->settings = g_object_ref (settings);
+ app->app_info = g_object_ref (app_info);
+
+ g_debug ("Adding application '%s' (canonical app ID: %s)",
+ full_app_id, canonical_app_id);
+
+ add_application (panel, app);
+}
+
+static char *
+app_info_get_id (GAppInfo *app_info)
+{
+ const char *desktop_id;
+ g_autofree gchar *ret = NULL;
+ const char *filename;
+ int l;
+
+ desktop_id = g_app_info_get_id (app_info);
+ if (desktop_id != NULL)
+ {
+ ret = g_strdup (desktop_id);
+ }
+ else
+ {
+ filename = g_desktop_app_info_get_filename (G_DESKTOP_APP_INFO (app_info));
+ ret = g_path_get_basename (filename);
+ }
+
+ if (G_UNLIKELY (g_str_has_suffix (ret, ".desktop") == FALSE))
+ return NULL;
+
+ l = strlen (ret);
+ *(ret + l - strlen(".desktop")) = '\0';
+ return g_steal_pointer (&ret);
+}
+
+static void
+process_app_info (CcNotificationsPanel *panel,
+ GAppInfo *app_info)
+{
+ Application *app;
+ g_autofree gchar *app_id = NULL;
+ g_autofree gchar *path = NULL;
+ g_autoptr(GSettings) settings = NULL;
+ guint i;
+
+ app_id = app_info_get_id (app_info);
+ g_strcanon (app_id,
+ "0123456789"
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "-",
+ '-');
+ for (i = 0; app_id[i] != '\0'; i++)
+ app_id[i] = g_ascii_tolower (app_id[i]);
+
+ path = g_strconcat (APP_PREFIX, app_id, "/", NULL);
+ settings = g_settings_new_with_path (APP_SCHEMA, path);
+
+ app = g_slice_new (Application);
+ app->canonical_app_id = g_steal_pointer (&app_id);
+ app->settings = g_object_ref (settings);
+ app->app_info = g_object_ref (app_info);
+ app->panel = g_object_ref (panel);
+
+ if (g_hash_table_contains (panel->known_applications,
+ app->canonical_app_id))
+ return;
+
+ g_debug ("Processing queued application %s", app->canonical_app_id);
+
+ add_application (panel, app);
+}
+
+static void
+load_apps (CcNotificationsPanel *panel)
+{
+ GList *iter, *apps;
+
+ apps = g_app_info_get_all ();
+
+ for (iter = apps; iter; iter = iter->next)
+ {
+ GDesktopAppInfo *app;
+
+ app = iter->data;
+ if (g_desktop_app_info_get_boolean (app, "X-GNOME-UsesNotifications")) {
+ process_app_info (panel, G_APP_INFO (app));
+ g_debug ("Processing app '%s'", g_app_info_get_id (G_APP_INFO (app)));
+ } else {
+ g_debug ("Skipped app '%s', doesn't use notifications", g_app_info_get_id (G_APP_INFO (app)));
+ }
+ }
+
+ g_list_free_full (apps, g_object_unref);
+}
+
+static void
+children_changed (CcNotificationsPanel *panel,
+ const char *key)
+{
+ int i;
+ g_auto (GStrv) new_app_ids = NULL;
+
+ g_settings_get (panel->master_settings,
+ "application-children",
+ "^as", &new_app_ids);
+ for (i = 0; new_app_ids[i]; i++)
+ maybe_add_app_id (panel, new_app_ids[i]);
+}
+
+static void
+build_app_store (CcNotificationsPanel *panel)
+{
+ /* Build application entries for known applications */
+ children_changed (panel, NULL);
+ g_signal_connect_object (panel->master_settings,
+ "changed::application-children",
+ G_CALLBACK (children_changed), panel, G_CONNECT_SWAPPED);
+
+ /* Scan applications that statically declare to show notifications */
+ load_apps (panel);
+}
+
+static void
+select_app (CcNotificationsPanel *panel,
+ GtkListBoxRow *row)
+{
+ Application *app;
+ g_autofree gchar *app_id = NULL;
+ CcAppNotificationsDialog *dialog;
+ GtkWidget *toplevel;
+ CcShell *shell;
+
+ shell = cc_panel_get_shell (CC_PANEL (panel));
+ toplevel = cc_shell_get_toplevel (shell);
+
+ app = g_object_get_qdata (G_OBJECT (row), application_quark ());
+
+ app_id = g_strdup (g_app_info_get_id (app->app_info));
+ if (g_str_has_suffix (app_id, ".desktop"))
+ app_id[strlen (app_id) - strlen (".desktop")] = '\0';
+
+ dialog = cc_app_notifications_dialog_new (app_id, g_app_info_get_name (app->app_info), app->settings, panel->master_settings, panel->perm_store);
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel));
+ gtk_widget_show (GTK_WIDGET (dialog));
+}
+
+static int
+sort_apps (gconstpointer one,
+ gconstpointer two,
+ gpointer user_data)
+{
+ Application *a1, *a2;
+
+ a1 = g_object_get_qdata (G_OBJECT (one), application_quark ());
+ a2 = g_object_get_qdata (G_OBJECT (two), application_quark ());
+
+ return g_utf8_collate (g_app_info_get_name (a1->app_info),
+ g_app_info_get_name (a2->app_info));
+}
diff --git a/panels/notifications/cc-notifications-panel.h b/panels/notifications/cc-notifications-panel.h
new file mode 100644
index 0000000..386e3d8
--- /dev/null
+++ b/panels/notifications/cc-notifications-panel.h
@@ -0,0 +1,31 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2012 Giovanni Campagna <scampa.giovanni@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <gio/gio.h>
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_NOTIFICATIONS_PANEL (cc_notifications_panel_get_type ())
+
+G_DECLARE_FINAL_TYPE (CcNotificationsPanel, cc_notifications_panel, CC, NOTIFICATIONS_PANEL, CcPanel)
+
+G_END_DECLS
diff --git a/panels/notifications/cc-notifications-panel.ui b/panels/notifications/cc-notifications-panel.ui
new file mode 100644
index 0000000..acba49f
--- /dev/null
+++ b/panels/notifications/cc-notifications-panel.ui
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcNotificationsPanel" parent="CcPanel">
+ <child type="content">
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="CcListRow" id="dnd_row">
+ <property name="title" translatable="yes">_Do Not Disturb</property>
+ <property name="use-underline">True</property>
+ <property name="show-switch">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="CcListRow" id="lock_screen_row">
+ <property name="title" translatable="yes" comments="Translators: Whether to show notifications on the lock screen">_Lock Screen Notifications</property>
+ <property name="use-underline">True</property>
+ <property name="show-switch">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup" id="app_group">
+ <property name="title" translatable="yes" comments="List of applications.">Applications</property>
+ <child>
+ <object class="GtkListBox" id="app_listbox">
+ <property name="selection_mode">none</property>
+ <signal name="row-activated" handler="select_app" object="CcNotificationsPanel" swapped="yes" />
+ <signal name="keynav-failed" handler="keynav_failed_cb" object="CcNotificationsPanel" swapped="yes"/>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ <accessibility>
+ <relation name="labelled-by">app_group</relation>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GtkSizeGroup" id="sizegroup1">
+ <property name="mode">both</property>
+ </object>
+</interface>
diff --git a/panels/notifications/gnome-notifications-panel.desktop.in.in b/panels/notifications/gnome-notifications-panel.desktop.in.in
new file mode 100644
index 0000000..325a264
--- /dev/null
+++ b/panels/notifications/gnome-notifications-panel.desktop.in.in
@@ -0,0 +1,19 @@
+[Desktop Entry]
+Name=Notifications
+Comment=Control which notifications are displayed and what they show
+Exec=gnome-control-center notifications
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-notifications-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-PersonalizationSettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=Notifications
+X-GNOME-Bugzilla-Version=@VERSION@
+X-GNOME-Settings-Panel=notifications
+# Translators: Search terms to find the Notifications panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=Notifications;Banner;Message;Tray;Popup;
diff --git a/panels/notifications/icons/meson.build b/panels/notifications/icons/meson.build
new file mode 100644
index 0000000..bb2bde2
--- /dev/null
+++ b/panels/notifications/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-notifications-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/notifications/icons/scalable/org.gnome.Settings-notifications-symbolic.svg b/panels/notifications/icons/scalable/org.gnome.Settings-notifications-symbolic.svg
new file mode 100644
index 0000000..13bea30
--- /dev/null
+++ b/panels/notifications/icons/scalable/org.gnome.Settings-notifications-symbolic.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <path d="m 8 0 c -0.828125 0 -1.5 0.671875 -1.5 1.5 c 0 0.078125 0.007812 0.152344 0.019531 0.230469 c -2.089843 0.648437 -3.515625 2.582031 -3.519531 4.769531 v 4.5 h -0.5 c -0.554688 0 -1 0.445312 -1 1 s 0.445312 1 1 1 h 11 c 0.554688 0 1 -0.445312 1 -1 s -0.445312 -1 -1 -1 h -0.5 v -4.5 c 0 -2.191406 -1.425781 -4.125 -3.515625 -4.777344 c 0.007813 -0.074218 0.015625 -0.148437 0.015625 -0.222656 c 0 -0.828125 -0.671875 -1.5 -1.5 -1.5 z m -2 14 c 0 0.714844 0.382812 1.375 1 1.730469 c 0.617188 0.359375 1.382812 0.359375 2 0 c 0.617188 -0.355469 1 -1.015625 1 -1.730469 z m 0 0" fill="#2e3436"/>
+</svg>
diff --git a/panels/notifications/meson.build b/panels/notifications/meson.build
new file mode 100644
index 0000000..89233b2
--- /dev/null
+++ b/panels/notifications/meson.build
@@ -0,0 +1,45 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+sources = files(
+ 'cc-notifications-panel.c',
+ 'cc-app-notifications-dialog.c'
+)
+
+resource_data = files(
+ 'cc-app-notifications-dialog.ui',
+ 'cc-notifications-panel.ui'
+)
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname,
+ dependencies: resource_data,
+ export: true
+)
+
+panels_libs += static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [ top_inc, common_inc ],
+ dependencies: common_deps,
+ c_args: cflags
+)
+
+subdir('icons')
diff --git a/panels/notifications/notifications.gresource.xml b/panels/notifications/notifications.gresource.xml
new file mode 100644
index 0000000..8f1d5db
--- /dev/null
+++ b/panels/notifications/notifications.gresource.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/notifications">
+ <file preprocess="xml-stripblanks">cc-app-notifications-dialog.ui</file>
+ <file preprocess="xml-stripblanks">cc-notifications-panel.ui</file>
+ </gresource>
+</gresources>
diff --git a/panels/online-accounts/cc-online-account-provider-row.c b/panels/online-accounts/cc-online-account-provider-row.c
new file mode 100644
index 0000000..d581d15
--- /dev/null
+++ b/panels/online-accounts/cc-online-account-provider-row.c
@@ -0,0 +1,135 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright 2020 Canonical Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+
+#include "cc-online-account-provider-row.h"
+#include "cc-online-accounts-resources.h"
+
+struct _CcOnlineAccountProviderRow
+{
+ AdwActionRow parent;
+
+ GtkImage *icon_image;
+
+ GVariant *provider;
+};
+
+G_DEFINE_TYPE (CcOnlineAccountProviderRow, cc_online_account_provider_row, ADW_TYPE_ACTION_ROW)
+
+static gboolean
+is_gicon_symbolic (GtkWidget *widget,
+ GIcon *icon)
+{
+ g_autoptr(GtkIconPaintable) icon_paintable = NULL;
+ GtkIconTheme *icon_theme;
+
+ icon_theme = gtk_icon_theme_get_for_display (gdk_display_get_default ());
+ icon_paintable = gtk_icon_theme_lookup_by_gicon (icon_theme,
+ icon,
+ 32,
+ gtk_widget_get_scale_factor (widget),
+ gtk_widget_get_direction (widget),
+ 0);
+
+ return icon_paintable && gtk_icon_paintable_is_symbolic (icon_paintable);
+}
+
+static void
+cc_online_account_provider_row_dispose (GObject *object)
+{
+ CcOnlineAccountProviderRow *self = CC_ONLINE_ACCOUNT_PROVIDER_ROW (object);
+
+ g_clear_pointer (&self->provider, g_variant_unref);
+
+ G_OBJECT_CLASS (cc_online_account_provider_row_parent_class)->dispose (object);
+}
+
+static void
+cc_online_account_provider_row_class_init (CcOnlineAccountProviderRowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_online_account_provider_row_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/online-accounts/cc-online-account-provider-row.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcOnlineAccountProviderRow, icon_image);
+}
+
+static void
+cc_online_account_provider_row_init (CcOnlineAccountProviderRow *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+CcOnlineAccountProviderRow *
+cc_online_account_provider_row_new (GVariant *provider)
+{
+ CcOnlineAccountProviderRow *self;
+ g_autoptr(GIcon) icon = NULL;
+ g_autofree gchar *name = NULL;
+
+ self = g_object_new (cc_online_account_provider_row_get_type (), NULL);
+
+ if (provider == NULL)
+ {
+ icon = g_themed_icon_new_with_default_fallbacks ("goa-account");
+ name = g_strdup (C_("Online Account", "Other"));
+ }
+ else
+ {
+ g_autoptr(GVariant) icon_variant = NULL;
+
+ self->provider = g_variant_ref (provider);
+
+ g_variant_get (provider, "(ssviu)",
+ NULL,
+ &name,
+ &icon_variant,
+ NULL,
+ NULL);
+
+ icon = g_icon_deserialize (icon_variant);
+ }
+
+ gtk_image_set_from_gicon (self->icon_image, icon);
+ if (is_gicon_symbolic (GTK_WIDGET (self), icon))
+ {
+ gtk_image_set_icon_size (self->icon_image, GTK_ICON_SIZE_NORMAL);
+ gtk_widget_add_css_class (GTK_WIDGET (self->icon_image), "symbolic-circular");
+ }
+ else
+ {
+ gtk_image_set_icon_size (self->icon_image, GTK_ICON_SIZE_LARGE);
+ gtk_widget_add_css_class (GTK_WIDGET (self->icon_image), "lowres-icon");
+ }
+
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self), name);
+
+ return self;
+}
+
+GVariant *
+cc_online_account_provider_row_get_provider (CcOnlineAccountProviderRow *self)
+{
+ g_return_val_if_fail (CC_IS_ONLINE_ACCOUNT_PROVIDER_ROW (self), NULL);
+ return self->provider;
+}
diff --git a/panels/online-accounts/cc-online-account-provider-row.h b/panels/online-accounts/cc-online-account-provider-row.h
new file mode 100644
index 0000000..6f75a5b
--- /dev/null
+++ b/panels/online-accounts/cc-online-account-provider-row.h
@@ -0,0 +1,32 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright 2020 Canonical Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <adwaita.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (CcOnlineAccountProviderRow, cc_online_account_provider_row, CC, ONLINE_ACCOUNT_PROVIDER_ROW, AdwActionRow)
+
+CcOnlineAccountProviderRow *cc_online_account_provider_row_new (GVariant *provider);
+
+GVariant *cc_online_account_provider_row_get_provider (CcOnlineAccountProviderRow *row);
+
+G_END_DECLS
diff --git a/panels/online-accounts/cc-online-account-provider-row.ui b/panels/online-accounts/cc-online-account-provider-row.ui
new file mode 100644
index 0000000..6c51df7
--- /dev/null
+++ b/panels/online-accounts/cc-online-account-provider-row.ui
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcOnlineAccountProviderRow" parent="AdwActionRow">
+ <property name="activatable">True</property>
+ <child type="prefix">
+ <object class="GtkImage" id="icon_image">
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/online-accounts/cc-online-account-row.c b/panels/online-accounts/cc-online-account-row.c
new file mode 100644
index 0000000..1406a3d
--- /dev/null
+++ b/panels/online-accounts/cc-online-account-row.c
@@ -0,0 +1,140 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright 2020 Canonical Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+
+#include "cc-online-account-row.h"
+#include "cc-online-accounts-resources.h"
+
+struct _CcOnlineAccountRow
+{
+ AdwActionRow parent;
+
+ GtkImage *icon_image;
+ GtkImage *warning_image;
+
+ GoaObject *object;
+};
+
+G_DEFINE_TYPE (CcOnlineAccountRow, cc_online_account_row, ADW_TYPE_ACTION_ROW)
+
+static gboolean
+is_gicon_symbolic (GtkWidget *widget,
+ GIcon *icon)
+{
+ g_autoptr(GtkIconPaintable) icon_paintable = NULL;
+ GtkIconTheme *icon_theme;
+
+ icon_theme = gtk_icon_theme_get_for_display (gdk_display_get_default ());
+ icon_paintable = gtk_icon_theme_lookup_by_gicon (icon_theme,
+ icon,
+ 32,
+ gtk_widget_get_scale_factor (widget),
+ gtk_widget_get_direction (widget),
+ 0);
+
+ return icon_paintable && gtk_icon_paintable_is_symbolic (icon_paintable);
+}
+
+static void
+cc_online_account_row_dispose (GObject *object)
+{
+ CcOnlineAccountRow *self = CC_ONLINE_ACCOUNT_ROW (object);
+
+ g_clear_object (&self->object);
+
+ G_OBJECT_CLASS (cc_online_account_row_parent_class)->dispose (object);
+}
+
+static void
+cc_online_account_row_class_init (CcOnlineAccountRowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_online_account_row_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/online-accounts/cc-online-account-row.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcOnlineAccountRow, icon_image);
+ gtk_widget_class_bind_template_child (widget_class, CcOnlineAccountRow, warning_image);
+}
+
+static void
+cc_online_account_row_init (CcOnlineAccountRow *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+CcOnlineAccountRow *
+cc_online_account_row_new (GoaObject *object)
+{
+ CcOnlineAccountRow *self;
+ GoaAccount *account;
+ g_autoptr(GIcon) gicon = NULL;
+ g_autoptr(GError) error = NULL;
+
+ self = g_object_new (cc_online_account_row_get_type (), NULL);
+
+ self->object = g_object_ref (object);
+
+ account = goa_object_peek_account (object);
+
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self),
+ goa_account_get_provider_name (account));
+ adw_action_row_set_subtitle (ADW_ACTION_ROW (self),
+ goa_account_get_presentation_identity (account));
+
+ gicon = g_icon_new_for_string (goa_account_get_provider_icon (account), &error);
+ if (error != NULL)
+ {
+ g_warning ("Error creating GIcon for account: %s (%s, %d)",
+ error->message,
+ g_quark_to_string (error->domain),
+ error->code);
+ }
+ else
+ {
+ gtk_image_set_from_gicon (self->icon_image, gicon);
+
+ if (is_gicon_symbolic (GTK_WIDGET (self), gicon))
+ {
+ gtk_image_set_icon_size (self->icon_image, GTK_ICON_SIZE_NORMAL);
+ gtk_widget_add_css_class (GTK_WIDGET (self->icon_image), "symbolic-circular");
+ }
+ else
+ {
+ gtk_image_set_icon_size (self->icon_image, GTK_ICON_SIZE_LARGE);
+ gtk_widget_add_css_class (GTK_WIDGET (self->icon_image), "lowres-icon");
+ }
+ }
+
+ g_object_bind_property (account, "attention-needed",
+ self->warning_image, "visible",
+ G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
+
+ return self;
+}
+
+GoaObject *
+cc_online_account_row_get_object (CcOnlineAccountRow *self)
+{
+ g_return_val_if_fail (CC_IS_ONLINE_ACCOUNT_ROW (self), NULL);
+ return self->object;
+}
diff --git a/panels/online-accounts/cc-online-account-row.h b/panels/online-accounts/cc-online-account-row.h
new file mode 100644
index 0000000..aa0df4b
--- /dev/null
+++ b/panels/online-accounts/cc-online-account-row.h
@@ -0,0 +1,35 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright 2020 Canonical Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <adwaita.h>
+
+#define GOA_API_IS_SUBJECT_TO_CHANGE
+#include <goa/goa.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (CcOnlineAccountRow, cc_online_account_row, CC, ONLINE_ACCOUNT_ROW, AdwActionRow)
+
+CcOnlineAccountRow *cc_online_account_row_new (GoaObject *object);
+
+GoaObject *cc_online_account_row_get_object (CcOnlineAccountRow *row);
+
+G_END_DECLS
diff --git a/panels/online-accounts/cc-online-account-row.ui b/panels/online-accounts/cc-online-account-row.ui
new file mode 100644
index 0000000..15dee53
--- /dev/null
+++ b/panels/online-accounts/cc-online-account-row.ui
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcOnlineAccountRow" parent="AdwActionRow">
+ <property name="activatable">True</property>
+ <child type="prefix">
+ <object class="GtkImage" id="icon_image">
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ </object>
+ </child>
+ <child type="suffix">
+ <object class="GtkImage" id="warning_image">
+ <property name="icon-name">dialog-warning-symbolic</property>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/online-accounts/cc-online-accounts-panel.c b/panels/online-accounts/cc-online-accounts-panel.c
new file mode 100644
index 0000000..f4d1a92
--- /dev/null
+++ b/panels/online-accounts/cc-online-accounts-panel.c
@@ -0,0 +1,947 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2011 - 2017 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include "config.h"
+
+#include <gio/gio.h>
+#include <string.h>
+#include <glib/gi18n-lib.h>
+
+#define GOA_API_IS_SUBJECT_TO_CHANGE
+#include <goa/goa.h>
+
+#include "cc-online-accounts-panel.h"
+#include "cc-online-account-provider-row.h"
+#include "cc-online-account-row.h"
+#include "cc-online-accounts-resources.h"
+
+#ifdef GDK_WINDOWING_X11
+#include <gdk/x11/gdkx.h>
+#endif
+#ifdef GDK_WINDOWING_WAYLAND
+#include <gdk/wayland/gdkwayland.h>
+#endif
+
+struct _CcOnlineAccountsPanel
+{
+ CcPanel parent_instance;
+
+ GtkFrame *accounts_frame;
+ GtkListBox *accounts_listbox;
+ GtkWidget *close_notification_button;
+ GtkDialog *edit_account_dialog;
+ GtkHeaderBar *edit_account_headerbar;
+ GtkBox *editor_box;
+ GtkLabel *notification_label;
+ GtkRevealer *notification_revealer;
+ GtkLabel *offline_label;
+ GtkListBox *providers_listbox;
+ GtkButton *remove_account_button;
+ GtkBox *accounts_vbox;
+
+ GoaClient *client;
+ GoaObject *active_object;
+ GoaObject *removed_object;
+
+ guint remove_account_timeout_id;
+ gchar *window_export_handle;
+};
+
+static gboolean remove_account_timeout_cb (gpointer user_data);
+
+CC_PANEL_REGISTER (CcOnlineAccountsPanel, cc_online_accounts_panel);
+
+enum {
+ PROP_0,
+ PROP_PARAMETERS
+};
+
+/* Rows methods */
+
+typedef void (*RowForAccountCallback) (CcOnlineAccountsPanel *self, GtkWidget *row, GList *other_rows);
+
+static void
+hide_row_for_account_cb (CcOnlineAccountsPanel *self,
+ GtkWidget *row,
+ GList *other_rows)
+{
+ gtk_widget_hide (row);
+ gtk_widget_set_visible (GTK_WIDGET (self->accounts_frame), other_rows != NULL);
+}
+
+static void
+remove_row_for_account_cb (CcOnlineAccountsPanel *self,
+ GtkWidget *row,
+ GList *other_rows)
+{
+ gtk_list_box_remove (self->accounts_listbox, row);
+ gtk_widget_set_visible (GTK_WIDGET (self->accounts_frame), other_rows != NULL);
+}
+
+static void
+show_row_for_account_cb (CcOnlineAccountsPanel *self,
+ GtkWidget *row,
+ GList *other_rows)
+{
+ gtk_widget_show (row);
+ gtk_widget_show (GTK_WIDGET (self->accounts_frame));
+}
+
+static void
+modify_row_for_account (CcOnlineAccountsPanel *self,
+ GoaObject *object,
+ RowForAccountCallback callback)
+{
+ GtkWidget *child;
+ GList *children = NULL;
+ GList *l;
+
+ for (child = gtk_widget_get_first_child (GTK_WIDGET (self->accounts_listbox));
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ {
+ children = g_list_prepend (children, child);
+ }
+
+ children = g_list_reverse (children);
+
+ for (l = children; l != NULL; l = l->next)
+ {
+ GoaObject *row_object;
+
+ row_object = cc_online_account_row_get_object (CC_ONLINE_ACCOUNT_ROW (l->data));
+ if (row_object == object)
+ {
+ GtkWidget *row = GTK_WIDGET (l->data);
+
+ children = g_list_remove_link (children, l);
+ callback (self, row, children);
+ g_list_free (l);
+ break;
+ }
+ }
+
+ g_list_free (children);
+}
+
+/* Auxiliary methods */
+
+G_GNUC_NULL_TERMINATED
+static char *
+run_goa_helper_sync (const char *command,
+ ...)
+{
+ g_autoptr(GPtrArray) argv = NULL;
+ g_autofree char *output = NULL;
+ g_autoptr(GError) error = NULL;
+ const char *param;
+ va_list args;
+ int status;
+
+ argv = g_ptr_array_new_with_free_func (g_free);
+ g_ptr_array_add (argv, g_strdup (LIBEXECDIR "/gnome-control-center-goa-helper"));
+ g_ptr_array_add (argv, g_strdup (command));
+
+ va_start (args, command);
+ while ((param = va_arg (args, const char*)) != NULL)
+ g_ptr_array_add (argv, g_strdup (param));
+ va_end (args);
+
+ g_ptr_array_add (argv, NULL);
+
+ if (!g_spawn_sync (NULL,
+ (char **) argv->pdata,
+ NULL,
+ 0,
+ NULL,
+ NULL,
+ &output,
+ NULL,
+ &status,
+ &error))
+ {
+ g_warning ("Failed to run online accounts helper: %s", error->message);
+ return NULL;
+ }
+
+ if (!g_spawn_check_wait_status (status, NULL))
+ return NULL;
+
+ if (output == NULL || *output == '\0')
+ return NULL;
+
+ return g_steal_pointer (&output);
+}
+
+static void
+run_goa_helper_in_thread_func (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ g_autofree char *output = NULL;
+ g_autoptr(GError) error = NULL;
+ GPtrArray *argv = task_data;
+ int status;
+
+ g_spawn_sync (NULL,
+ (char **) argv->pdata,
+ NULL, 0, NULL, NULL,
+ &output,
+ NULL,
+ &status,
+ &error);
+
+ if (error)
+ {
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ if (!g_spawn_check_wait_status (status, &error))
+ {
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ g_task_return_pointer (task, g_steal_pointer (&output), g_free);
+}
+
+static void
+run_goa_helper_async (const gchar *command,
+ const gchar *param,
+ const gchar *window_handle,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GPtrArray) argv = NULL;
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ argv = g_ptr_array_new_with_free_func (g_free);
+ g_ptr_array_add (argv, g_strdup (LIBEXECDIR "/gnome-control-center-goa-helper"));
+ g_ptr_array_add (argv, g_strdup (command));
+ g_ptr_array_add (argv, g_strdup (param));
+ g_ptr_array_add (argv, g_strdup (window_handle));
+ g_ptr_array_add (argv, NULL);
+
+ task = g_task_new (NULL, cancellable, callback, user_data);
+ g_task_set_source_tag (task, run_goa_helper_async);
+ g_task_set_task_data (task, g_steal_pointer (&argv), (GDestroyNotify) g_ptr_array_unref);
+ g_task_run_in_thread (task, run_goa_helper_in_thread_func);
+}
+
+static void
+cancel_notification_timeout (CcOnlineAccountsPanel *self)
+{
+ g_clear_handle_id (&self->remove_account_timeout_id, g_source_remove);
+ self->removed_object = NULL;
+}
+
+static void
+start_remove_account_timeout (CcOnlineAccountsPanel *self)
+{
+ GoaAccount *account;
+ g_autofree gchar *id = NULL;
+ g_autofree gchar *label = NULL;
+
+ if (self->active_object == NULL)
+ return;
+
+ if (self->removed_object != NULL)
+ gtk_widget_activate (self->close_notification_button);
+
+ self->removed_object = g_steal_pointer (&self->active_object);
+
+ account = goa_object_peek_account (self->removed_object);
+ id = g_strdup_printf ("<b>%s</b>", goa_account_get_presentation_identity (account));
+ /* Translators: The %s is the username (eg., debarshi.ray@gmail.com
+ * or rishi).
+ */
+ label = g_strdup_printf (_("%s removed"), id);
+ gtk_label_set_markup (self->notification_label, label);
+ gtk_revealer_set_reveal_child (self->notification_revealer, TRUE);
+
+ modify_row_for_account (self, self->removed_object, hide_row_for_account_cb);
+ self->remove_account_timeout_id = g_timeout_add_seconds (10, remove_account_timeout_cb, self);
+}
+
+static void
+on_show_account_finish_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ CcOnlineAccountsPanel *self = CC_ONLINE_ACCOUNTS_PANEL (user_data);
+ g_autofree char *output = NULL;
+ g_autoptr(GError) error = NULL;
+
+ output = g_task_propagate_pointer (G_TASK (result), &error);
+
+ if (error)
+ {
+ g_warning ("Error showing account: %s", error->message);
+ return;
+ }
+
+ if (g_strcmp0 (output, "remove") == 0)
+ start_remove_account_timeout (self);
+
+ self->active_object = NULL;
+}
+
+static void
+show_account (CcOnlineAccountsPanel *self,
+ GoaObject *object)
+{
+ GoaAccount *account;
+
+ if (!self->window_export_handle)
+ return;
+
+ self->active_object = g_object_ref (object);
+
+ account = goa_object_peek_account (object);
+ run_goa_helper_async ("show-account",
+ goa_account_get_id (account),
+ self->window_export_handle,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ on_show_account_finish_cb,
+ self);
+}
+
+static void
+on_create_account_finish_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ CcOnlineAccountsPanel *self = CC_ONLINE_ACCOUNTS_PANEL (user_data);
+ g_autofree char *new_account_id = NULL;
+ g_autoptr(GoaObject) object = NULL;
+ g_autoptr(GError) error = NULL;
+
+ new_account_id = g_task_propagate_pointer (G_TASK (result), &error);
+
+ if (error)
+ {
+ g_warning ("Error showing account: %s", error->message);
+ return;
+ }
+
+ if (new_account_id)
+ object = goa_client_lookup_by_id (self->client, new_account_id);
+
+ if (object)
+ show_account (self, object);
+}
+
+static void
+create_account (CcOnlineAccountsPanel *self,
+ GVariant *provider)
+{
+ g_autofree char *provider_type = NULL;
+
+ if (!self->window_export_handle)
+ return;
+
+ g_variant_get (provider, "(ssviu)", &provider_type, NULL, NULL, NULL, NULL);
+
+ run_goa_helper_async ("create-account",
+ provider_type,
+ self->window_export_handle,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ on_create_account_finish_cb,
+ self);
+}
+
+static void
+add_provider_row (CcOnlineAccountsPanel *self,
+ GVariant *provider)
+{
+ CcOnlineAccountProviderRow *row;
+
+ row = cc_online_account_provider_row_new (provider);
+
+ gtk_widget_show (GTK_WIDGET (row));
+ gtk_list_box_append (self->providers_listbox, GTK_WIDGET (row));
+}
+
+static void
+list_providers (CcOnlineAccountsPanel *self)
+{
+ g_autoptr(GVariant) providers_variant = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autofree char *providers = NULL;
+ GVariantIter iter;
+ GVariant *provider;
+
+ providers = run_goa_helper_sync ("list-providers", NULL);
+
+ if (!providers)
+ return;
+
+ providers_variant = g_variant_parse (G_VARIANT_TYPE ("a(ssviu)"),
+ providers,
+ NULL,
+ NULL,
+ &error);
+
+ if (error)
+ {
+ g_warning ("Error listing providers: %s", error->message);
+ return;
+ }
+
+ g_variant_iter_init (&iter, providers_variant);
+
+ while ((provider = g_variant_iter_next_value (&iter)))
+ add_provider_row (self, provider);
+}
+
+static void
+add_account (CcOnlineAccountsPanel *self,
+ GoaObject *object)
+{
+ CcOnlineAccountRow *row;
+
+ row = cc_online_account_row_new (object);
+
+ /* Add to the listbox */
+ gtk_list_box_append (self->accounts_listbox, GTK_WIDGET (row));
+ gtk_widget_show (GTK_WIDGET (self->accounts_frame));
+}
+
+static void
+fill_accounts_listbox (CcOnlineAccountsPanel *self)
+{
+ g_autolist(GoaAccount) accounts = NULL;
+ GList *l;
+
+ accounts = goa_client_get_accounts (self->client);
+
+ for (l = accounts; l != NULL; l = l->next)
+ add_account (self, l->data);
+}
+
+#ifdef GDK_WINDOWING_WAYLAND
+static void
+wayland_window_exported_cb (GdkToplevel *toplevel,
+ const char *handle,
+ gpointer data)
+
+{
+ CcOnlineAccountsPanel *self = data;
+
+ self->window_export_handle = g_strdup_printf ("wayland:%s", handle);
+}
+#endif
+
+static void
+export_window_handle (CcOnlineAccountsPanel *self)
+{
+ GtkNative *native = gtk_widget_get_native (GTK_WIDGET (self));
+
+#ifdef GDK_WINDOWING_X11
+ if (GDK_IS_X11_DISPLAY (gtk_widget_get_display (GTK_WIDGET (native))))
+ {
+ GdkSurface *surface = gtk_native_get_surface (native);
+ guint32 xid = (guint32) gdk_x11_surface_get_xid (surface);
+
+ self->window_export_handle = g_strdup_printf ("x11:%x", xid);
+ }
+#endif
+#ifdef GDK_WINDOWING_WAYLAND
+ if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (GTK_WIDGET (native))))
+ {
+ GdkSurface *surface = gtk_native_get_surface (native);
+
+ gdk_wayland_toplevel_export_handle (GDK_TOPLEVEL (surface),
+ wayland_window_exported_cb,
+ self,
+ NULL);
+ }
+#endif
+}
+
+static void
+unexport_window_handle (CcOnlineAccountsPanel *self)
+{
+ if (!self->window_export_handle)
+ return;
+
+#ifdef GDK_WINDOWING_WAYLAND
+ GtkNative *native = gtk_widget_get_native (GTK_WIDGET (self));
+
+ if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (GTK_WIDGET (native))))
+ {
+ GdkSurface *surface = gtk_native_get_surface (native);
+ gdk_wayland_toplevel_unexport_handle (GDK_TOPLEVEL (surface));
+ }
+#endif
+}
+
+static void
+select_account_by_id (CcOnlineAccountsPanel *self,
+ const gchar *account_id)
+{
+ GtkWidget *child;
+
+ for (child = gtk_widget_get_first_child (GTK_WIDGET (self->accounts_listbox));
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ {
+ GoaAccount *account;
+ GoaObject *row_object;
+
+ row_object = cc_online_account_row_get_object (CC_ONLINE_ACCOUNT_ROW (child));
+ account = goa_object_peek_account (row_object);
+
+ if (g_strcmp0 (goa_account_get_id (account), account_id) == 0)
+ {
+ show_account (self, row_object);
+ break;
+ }
+ }
+}
+
+static void
+command_add (CcOnlineAccountsPanel *self,
+ GVariant *parameters)
+{
+ const gchar *provider_name = NULL;
+ g_autoptr(GVariant) v = NULL;
+
+ g_assert (self != NULL);
+ g_assert (parameters != NULL);
+
+ switch (g_variant_n_children (parameters))
+ {
+ case 2:
+ g_variant_get_child (parameters, 1, "v", &v);
+ if (g_variant_is_of_type (v, G_VARIANT_TYPE_STRING))
+ provider_name = g_variant_get_string (v, NULL);
+ else
+ g_warning ("Wrong type for the second argument (provider name) GVariant, expected 's' but got '%s'",
+ (gchar *)g_variant_get_type (v));
+ break;
+
+ default:
+ g_warning ("Unexpected parameters found, ignore request");
+ return;
+ }
+
+ if (provider_name != NULL)
+ {
+ GtkWidget *child;
+ GVariant *provider;
+
+ for (child = gtk_widget_get_first_child (GTK_WIDGET (self->providers_listbox));
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ {
+ g_autofree gchar *provider_type = NULL;
+
+ provider = cc_online_account_provider_row_get_provider (CC_ONLINE_ACCOUNT_PROVIDER_ROW (child));
+ g_variant_get (provider, "(ssviu)", &provider_type, NULL, NULL, NULL, NULL);
+
+ if (g_strcmp0 (provider_type, provider_name) == 0)
+ break;
+ }
+
+ if (child == NULL)
+ {
+ g_warning ("Unable to get a provider for type '%s'", provider_name);
+ return;
+ }
+
+ create_account (self, provider);
+ }
+}
+
+static void
+load_custom_css (void)
+{
+ g_autoptr(GtkCssProvider) provider = NULL;
+
+ provider = gtk_css_provider_new ();
+ gtk_css_provider_load_from_resource (provider, "/org/gnome/control-center/online-accounts/online-accounts.css");
+ gtk_style_context_add_provider_for_display (gdk_display_get_default (),
+ GTK_STYLE_PROVIDER (provider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+}
+
+/* Callbacks */
+
+static gint
+sort_accounts_func (GtkListBoxRow *a,
+ GtkListBoxRow *b,
+ gpointer user_data)
+{
+ GoaAccount *a_account, *b_account;
+ GoaObject *a_object, *b_object;
+
+ a_object = cc_online_account_row_get_object (CC_ONLINE_ACCOUNT_ROW (a));
+ a_account = goa_object_peek_account (a_object);
+
+ b_object = cc_online_account_row_get_object (CC_ONLINE_ACCOUNT_ROW (b));
+ b_account = goa_object_peek_account (b_object);
+
+ return g_strcmp0 (goa_account_get_id (a_account), goa_account_get_id (b_account));
+}
+
+static gint
+sort_providers_func (GtkListBoxRow *a,
+ GtkListBoxRow *b,
+ gpointer user_data)
+{
+ GVariant *a_provider, *b_provider;
+ gboolean a_branded, b_branded;
+ gint a_features, b_features;
+
+ a_provider = cc_online_account_provider_row_get_provider (CC_ONLINE_ACCOUNT_PROVIDER_ROW (a));
+ b_provider = cc_online_account_provider_row_get_provider (CC_ONLINE_ACCOUNT_PROVIDER_ROW (b));
+
+ g_variant_get (a_provider, "(ssviu)", NULL, NULL, NULL, &a_features, NULL);
+ g_variant_get (b_provider, "(ssviu)", NULL, NULL, NULL, &b_features, NULL);
+
+ /* FIXME: this needs to go away once libgoa-backend is ported to GTK4 */
+#define FEATURE_BRANDED (1 << 1)
+
+ a_branded = (a_features & FEATURE_BRANDED) != 0;
+ b_branded = (a_features & FEATURE_BRANDED) != 0;
+
+#undef FEATURE_BRANDED
+
+ if (a_branded != b_branded)
+ {
+ if (a_branded)
+ return -1;
+ else
+ return 1;
+ }
+
+ return gtk_list_box_row_get_index (b) - gtk_list_box_row_get_index (a);
+}
+
+static void
+on_account_added_cb (GoaClient *client,
+ GoaObject *object,
+ CcOnlineAccountsPanel *self)
+{
+ add_account (self, object);
+}
+
+static void
+on_account_changed_cb (GoaClient *client,
+ GoaObject *object,
+ CcOnlineAccountsPanel *self)
+{
+ if (self->active_object == object)
+ show_account (self, self->active_object);
+}
+
+static void
+on_account_removed_cb (GoaClient *client,
+ GoaObject *object,
+ CcOnlineAccountsPanel *self)
+{
+ modify_row_for_account (self, object, remove_row_for_account_cb);
+}
+
+static void
+on_accounts_listbox_row_activated (CcOnlineAccountsPanel *self,
+ GtkListBoxRow *activated_row)
+{
+ GoaObject *object = cc_online_account_row_get_object (CC_ONLINE_ACCOUNT_ROW (activated_row));
+
+ show_account (self, object);
+}
+
+static void
+on_client_remove_account_finish_cb (GoaAccount *account,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(CcOnlineAccountsPanel) self = CC_ONLINE_ACCOUNTS_PANEL (user_data);
+ g_autoptr(GError) error = NULL;
+
+ goa_account_call_remove_finish (account, res, &error);
+
+ if (error)
+ {
+ GtkWidget *dialog;
+ dialog = gtk_message_dialog_new (GTK_WINDOW (cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (self)))),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ _("Error removing account"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s",
+ error->message);
+ gtk_window_present (GTK_WINDOW (dialog));
+ }
+}
+
+static void
+on_notification_closed_cb (GtkButton *button,
+ CcOnlineAccountsPanel *self)
+{
+ goa_account_call_remove (goa_object_peek_account (self->removed_object),
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ (GAsyncReadyCallback) on_client_remove_account_finish_cb,
+ g_object_ref (self));
+
+ gtk_revealer_set_reveal_child (self->notification_revealer, FALSE);
+
+ cancel_notification_timeout (self);
+ self->removed_object = NULL;
+}
+
+static void
+on_undo_button_clicked_cb (GtkButton *button,
+ CcOnlineAccountsPanel *self)
+{
+ /* Simply show the account row and hide the notification */
+ modify_row_for_account (self, self->removed_object, show_row_for_account_cb);
+ gtk_revealer_set_reveal_child (self->notification_revealer, FALSE);
+
+ cancel_notification_timeout (self);
+ self->removed_object = NULL;
+}
+
+static void
+on_provider_row_activated_cb (CcOnlineAccountsPanel *self,
+ GtkListBoxRow *activated_row)
+{
+ GVariant *provider = cc_online_account_provider_row_get_provider (CC_ONLINE_ACCOUNT_PROVIDER_ROW (activated_row));
+
+ create_account (self, provider);
+}
+
+static gboolean
+remove_account_timeout_cb (gpointer user_data)
+{
+ CcOnlineAccountsPanel *self = CC_ONLINE_ACCOUNTS_PANEL (user_data);
+
+ gtk_widget_activate (self->close_notification_button);
+
+ return G_SOURCE_REMOVE;
+}
+
+/* CcPanel overrides */
+
+static const char *
+cc_online_accounts_panel_get_help_uri (CcPanel *panel)
+{
+ return "help:gnome-help/accounts";
+}
+
+/* GtkWidget overrides */
+
+static void
+cc_online_accounts_panel_realize (GtkWidget *widget)
+{
+ GTK_WIDGET_CLASS (cc_online_accounts_panel_parent_class)->realize (widget);
+
+ export_window_handle (CC_ONLINE_ACCOUNTS_PANEL (widget));
+}
+
+static void
+cc_online_accounts_panel_unrealize (GtkWidget *widget)
+{
+ unexport_window_handle (CC_ONLINE_ACCOUNTS_PANEL (widget));
+
+ GTK_WIDGET_CLASS (cc_online_accounts_panel_parent_class)->unrealize (widget);
+}
+
+/* GObject overrides */
+
+static void
+cc_online_accounts_panel_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id)
+ {
+ case PROP_PARAMETERS:
+ {
+ GVariant *parameters;
+ g_autoptr(GVariant) v = NULL;
+ const gchar *first_arg = NULL;
+
+ parameters = g_value_get_variant (value);
+ if (parameters == NULL)
+ return;
+
+ if (g_variant_n_children (parameters) > 0)
+ {
+ g_variant_get_child (parameters, 0, "v", &v);
+ if (g_variant_is_of_type (v, G_VARIANT_TYPE_STRING))
+ first_arg = g_variant_get_string (v, NULL);
+ else
+ g_warning ("Wrong type for the second argument GVariant, expected 's' but got '%s'",
+ (gchar *)g_variant_get_type (v));
+ }
+
+ if (g_strcmp0 (first_arg, "add") == 0)
+ command_add (CC_ONLINE_ACCOUNTS_PANEL (object), parameters);
+ else if (first_arg != NULL)
+ select_account_by_id (CC_ONLINE_ACCOUNTS_PANEL (object), first_arg);
+
+ return;
+ }
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+cc_online_accounts_panel_constructed (GObject *object)
+{
+ CcOnlineAccountsPanel *self = CC_ONLINE_ACCOUNTS_PANEL (object);
+
+ G_OBJECT_CLASS (cc_online_accounts_panel_parent_class)->constructed (object);
+
+ list_providers (self);
+}
+
+static void
+cc_online_accounts_panel_finalize (GObject *object)
+{
+ CcOnlineAccountsPanel *panel = CC_ONLINE_ACCOUNTS_PANEL (object);
+
+ if (panel->removed_object != NULL)
+ {
+ g_autoptr(GError) error = NULL;
+ goa_account_call_remove_sync (goa_object_peek_account (panel->removed_object),
+ NULL, /* GCancellable */
+ &error);
+
+ if (error != NULL)
+ {
+ g_warning ("Error removing account: %s (%s, %d)",
+ error->message,
+ g_quark_to_string (error->domain),
+ error->code);
+ }
+ }
+
+ g_clear_object (&panel->client);
+
+ G_OBJECT_CLASS (cc_online_accounts_panel_parent_class)->finalize (object);
+}
+
+static void
+cc_online_accounts_panel_class_init (CcOnlineAccountsPanelClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+
+ panel_class->get_help_uri = cc_online_accounts_panel_get_help_uri;
+
+ object_class->set_property = cc_online_accounts_panel_set_property;
+ object_class->finalize = cc_online_accounts_panel_finalize;
+ object_class->constructed = cc_online_accounts_panel_constructed;
+
+ widget_class->realize = cc_online_accounts_panel_realize;
+ widget_class->unrealize = cc_online_accounts_panel_unrealize;
+
+ g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters");
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/online-accounts/cc-online-accounts-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcOnlineAccountsPanel, accounts_frame);
+ gtk_widget_class_bind_template_child (widget_class, CcOnlineAccountsPanel, accounts_listbox);
+ gtk_widget_class_bind_template_child (widget_class, CcOnlineAccountsPanel, close_notification_button);
+ gtk_widget_class_bind_template_child (widget_class, CcOnlineAccountsPanel, notification_label);
+ gtk_widget_class_bind_template_child (widget_class, CcOnlineAccountsPanel, notification_revealer);
+ gtk_widget_class_bind_template_child (widget_class, CcOnlineAccountsPanel, offline_label);
+ gtk_widget_class_bind_template_child (widget_class, CcOnlineAccountsPanel, providers_listbox);
+
+ gtk_widget_class_bind_template_callback (widget_class, on_accounts_listbox_row_activated);
+ gtk_widget_class_bind_template_callback (widget_class, on_notification_closed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_provider_row_activated_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_undo_button_clicked_cb);
+}
+
+static void
+cc_online_accounts_panel_init (CcOnlineAccountsPanel *self)
+{
+ g_autoptr(GError) error = NULL;
+ GNetworkMonitor *monitor;
+
+ g_resources_register (cc_online_accounts_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ gtk_list_box_set_sort_func (self->accounts_listbox,
+ sort_accounts_func,
+ self,
+ NULL);
+
+ gtk_list_box_set_sort_func (self->providers_listbox,
+ sort_providers_func,
+ self,
+ NULL);
+
+ monitor = g_network_monitor_get_default();
+ g_object_bind_property (monitor,
+ "network-available",
+ self->offline_label,
+ "visible",
+ G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN);
+
+ g_object_bind_property (monitor,
+ "network-available",
+ self->providers_listbox,
+ "sensitive",
+ G_BINDING_SYNC_CREATE);
+
+ /* TODO: probably want to avoid _sync() ... */
+ self->client = goa_client_new_sync (cc_panel_get_cancellable (CC_PANEL (self)), &error);
+ if (self->client == NULL)
+ {
+ g_warning ("Error getting a GoaClient: %s (%s, %d)",
+ error->message, g_quark_to_string (error->domain), error->code);
+ gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
+ return;
+ }
+
+ g_signal_connect (self->client,
+ "account-added",
+ G_CALLBACK (on_account_added_cb),
+ self);
+
+ g_signal_connect (self->client,
+ "account-changed",
+ G_CALLBACK (on_account_changed_cb),
+ self);
+
+ g_signal_connect (self->client,
+ "account-removed",
+ G_CALLBACK (on_account_removed_cb),
+ self);
+
+ fill_accounts_listbox (self);
+ load_custom_css ();
+}
diff --git a/panels/online-accounts/cc-online-accounts-panel.h b/panels/online-accounts/cc-online-accounts-panel.h
new file mode 100644
index 0000000..e7404a6
--- /dev/null
+++ b/panels/online-accounts/cc-online-accounts-panel.h
@@ -0,0 +1,31 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_ONLINE_ACCOUTS_PANEL (cc_online_accounts_panel_get_type ())
+
+G_DECLARE_FINAL_TYPE (CcOnlineAccountsPanel, cc_online_accounts_panel, CC, ONLINE_ACCOUNTS_PANEL, CcPanel)
+
+G_END_DECLS
diff --git a/panels/online-accounts/cc-online-accounts-panel.ui b/panels/online-accounts/cc-online-accounts-panel.ui
new file mode 100644
index 0000000..87a0232
--- /dev/null
+++ b/panels/online-accounts/cc-online-accounts-panel.ui
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcOnlineAccountsPanel" parent="CcPanel">
+ <child type="content">
+ <object class="GtkOverlay">
+ <child type="overlay">
+ <object class="GtkRevealer" id="notification_revealer">
+ <property name="halign">center</property>
+ <property name="valign">start</property>
+ <property name="transition_type">slide-down</property>
+ <child>
+ <object class="GtkFrame">
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="notification_label">
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="undo_button">
+ <property name="label" translatable="yes">Undo</property>
+ <signal name="clicked" handler="on_undo_button_clicked_cb" object="CcOnlineAccountsPanel" swapped="no" />
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="close_notification_button">
+ <property name="icon-name">window-close-symbolic</property>
+ <accessibility>
+ <property name="label" translatable="yes">Close the notification</property>
+ </accessibility>
+ <signal name="clicked" handler="on_notification_closed_cb" object="CcOnlineAccountsPanel" swapped="no" />
+ <style>
+ <class name="flat" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <style>
+ <class name="app-notification" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesPage">
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="GtkLabel" id="accounts_label">
+ <property name="wrap">True</property>
+ <property name="justify">center</property>
+ <property name="label" translatable="yes">Connect to your data in the cloud</property>
+ <style>
+ <class name="title-1" />
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="offline_label">
+ <property name="margin-top">24</property>
+ <property name="wrap">True</property>
+ <property name="label" translatable="yes">No internet connection — connect to set up new online accounts</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup" id="accounts_frame">
+ <property name="visible">False</property>
+ <child>
+ <object class="GtkListBox" id="accounts_listbox">
+ <property name="hexpand">True</property>
+ <property name="selection_mode">none</property>
+ <signal name="row-activated" handler="on_accounts_listbox_row_activated" object="CcOnlineAccountsPanel" swapped="yes" />
+ <style>
+ <class name="boxed-list" />
+ </style>
+ <accessibility>
+ <relation name="labelled-by">accounts_label</relation>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Add an account</property>
+ <child>
+ <object class="GtkListBox" id="providers_listbox">
+ <property name="selection_mode">none</property>
+ <signal name="row-activated" handler="on_provider_row_activated_cb" object="CcOnlineAccountsPanel" swapped="yes" />
+ <style>
+ <class name="boxed-list" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+
+</interface>
diff --git a/panels/online-accounts/gnome-control-center-goa-helper.c b/panels/online-accounts/gnome-control-center-goa-helper.c
new file mode 100644
index 0000000..1b40c84
--- /dev/null
+++ b/panels/online-accounts/gnome-control-center-goa-helper.c
@@ -0,0 +1,505 @@
+/*
+ * Copyright (C) 2022 Endless OS Foundation, LLC
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author:
+ * Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+ */
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#define GOA_API_IS_SUBJECT_TO_CHANGE
+#define GOA_BACKEND_API_IS_SUBJECT_TO_CHANGE
+#include <goabackend/goabackend.h>
+
+#ifdef HAVE_GTK_X11
+#include <gdk/gdkx.h>
+#endif
+#ifdef HAVE_GTK_WAYLAND
+#include <gdk/gdkwayland.h>
+#endif
+
+static GdkDisplay *
+get_wayland_display (void)
+{
+ static GdkDisplay *wayland_display = NULL;
+
+ if (wayland_display)
+ return wayland_display;
+
+ gdk_set_allowed_backends ("wayland");
+ wayland_display = gdk_display_open (NULL);
+ gdk_set_allowed_backends (NULL);
+ if (!wayland_display)
+ g_warning ("Failed to open Wayland display");
+
+ return wayland_display;
+}
+
+static GdkDisplay *
+get_x11_display (void)
+{
+ static GdkDisplay *x11_display = NULL;
+
+ if (x11_display)
+ return x11_display;
+
+ gdk_set_allowed_backends ("x11");
+ x11_display = gdk_display_open (NULL);
+ gdk_set_allowed_backends (NULL);
+ if (!x11_display)
+ g_warning ("Failed to open X11 display");
+
+ return x11_display;
+}
+
+static void
+set_external_parent_from_handle (GtkApplication *application,
+ GtkWindow *dialog,
+ const char *handle_str)
+{
+ GdkDisplay *display;
+ GtkWindow *fake_parent;
+ GdkScreen *screen;
+
+#ifdef HAVE_GTK_X11
+ {
+ const char *x11_prefix = "x11:";
+ if (g_str_has_prefix (handle_str, x11_prefix))
+ {
+ display = get_x11_display ();
+ if (!display)
+ {
+ g_warning ("No X display connection, ignoring X11 parent");
+ return;
+ }
+ }
+ }
+#endif
+#ifdef HAVE_GTK_WAYLAND
+ {
+ const char *wayland_prefix = "wayland:";
+
+ if (g_str_has_prefix (handle_str, wayland_prefix))
+ {
+ display = get_wayland_display ();
+ if (!display)
+ {
+ g_warning ("No Wayland display connection, ignoring Wayland parent");
+ return;
+ }
+ }
+ }
+#endif
+
+ screen = gdk_display_get_default_screen (gdk_display_get_default ());
+ fake_parent = g_object_new (GTK_TYPE_APPLICATION_WINDOW,
+ "application", application,
+ "type", GTK_WINDOW_TOPLEVEL,
+ "screen", screen,
+ NULL);
+ g_object_ref_sink (fake_parent);
+
+ gtk_window_set_transient_for (dialog, GTK_WINDOW (fake_parent));
+ gtk_window_set_modal (dialog, TRUE);
+ gtk_widget_realize (GTK_WIDGET (dialog));
+
+#ifdef HAVE_GTK_X11
+ {
+ const char *x11_prefix = "x11:";
+ if (g_str_has_prefix (handle_str, x11_prefix))
+ {
+ GdkWindow *foreign_gdk_window;
+ int xid;
+
+ errno = 0;
+ xid = strtol (handle_str + strlen (x11_prefix), NULL, 16);
+ if (errno != 0)
+ {
+ g_warning ("Failed to reference external X11 window, invalid XID %s", handle_str);
+ return;
+ }
+
+ foreign_gdk_window = gdk_x11_window_foreign_new_for_display (display, xid);
+ if (!foreign_gdk_window)
+ {
+ g_warning ("Failed to create foreign window for XID %d", xid);
+ return;
+ }
+
+ gdk_window_set_transient_for (gtk_widget_get_window (GTK_WIDGET (dialog)),
+ foreign_gdk_window);
+ }
+ }
+#endif
+#ifdef HAVE_GTK_WAYLAND
+ {
+ const char *wayland_prefix = "wayland:";
+
+ if (g_str_has_prefix (handle_str, wayland_prefix))
+ {
+ const char *wayland_handle_str = handle_str + strlen (wayland_prefix);
+
+ if (!gdk_wayland_window_set_transient_for_exported (gtk_widget_get_window (GTK_WIDGET (dialog)),
+ (char *) wayland_handle_str))
+ {
+ g_warning ("Failed to set window transient for external parent");
+ return;
+ }
+ }
+ }
+#endif
+
+ gtk_window_present (dialog);
+}
+
+/* create-account */
+
+static void
+on_application_activate_create_account_cb (GtkApplication *application,
+ char **argv)
+{
+ g_autoptr(GoaProvider) provider = NULL;
+ g_autoptr(GoaClient) client = NULL;
+ g_autoptr(GError) error = NULL;
+ GoaAccount *account;
+ GtkWidget *content_area;
+ GtkWidget *dialog;
+ GoaObject *object;
+
+ client = goa_client_new_sync (NULL, &error);
+ if (error)
+ {
+ g_printerr ("Error retrieving online accounts client");
+ exit (EXIT_FAILURE);
+ return;
+ }
+
+
+ /* Find the provider with a matching type */
+ provider = goa_provider_get_for_provider_type (argv[2]);
+ if (!provider)
+ {
+ g_printerr ("Provider type not supported");
+ exit (EXIT_FAILURE);
+ return;
+ }
+
+ dialog = g_object_new (GTK_TYPE_DIALOG,
+ "use-header-bar", 1,
+ "default-width", 500,
+ "default-height", 350,
+ NULL);
+ g_signal_connect_swapped (dialog, "response", G_CALLBACK (g_application_quit), application);
+ set_external_parent_from_handle (application, GTK_WINDOW (dialog), argv[3]);
+
+ content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+ gtk_container_set_border_width (GTK_CONTAINER (content_area), 0);
+
+ object = goa_provider_add_account (provider,
+ client,
+ GTK_DIALOG (dialog),
+ GTK_BOX (content_area),
+ &error);
+ if (error)
+ {
+ g_printerr ("Failed to create account: %s", error->message);
+ exit (EXIT_FAILURE);
+ return;
+ }
+
+ account = goa_object_peek_account (object);
+ g_print ("%s", goa_account_get_id (account));
+}
+
+static int
+create_account (int argc,
+ char **argv)
+{
+ g_autoptr(GtkApplication) application = NULL;
+
+ gtk_init (&argc, &argv);
+
+ if (argc != 4)
+ {
+ g_printerr ("Not enough arguments");
+ return EXIT_FAILURE;
+ }
+
+ application = gtk_application_new ("org.gnome.Settings.GoaHelper",
+ G_APPLICATION_FLAGS_NONE);
+ g_signal_connect (application, "activate", G_CALLBACK (on_application_activate_create_account_cb), argv);
+
+ return g_application_run (G_APPLICATION (application), 0, NULL);
+}
+
+/* list-providers */
+
+typedef struct {
+ GMainLoop *mainloop;
+ GList *providers;
+ GError *error;
+} GetAllProvidersData;
+
+static void
+get_all_providers_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autolist(GoaProvider) providers = NULL;
+ GetAllProvidersData *data;
+
+ data = user_data;
+
+ goa_provider_get_all_finish (&providers, res, &data->error);
+ if (data->error)
+ goto out;
+
+ data->providers = g_steal_pointer (&providers);
+
+out:
+ g_main_loop_quit (data->mainloop);
+}
+
+static GList *
+get_all_providers (GError **error)
+{
+ GetAllProvidersData data = (GetAllProvidersData) {
+ .mainloop = g_main_loop_new (NULL, FALSE),
+ .providers = NULL,
+ .error = NULL,
+ };
+
+ goa_provider_get_all (get_all_providers_cb, &data);
+
+ g_main_loop_run (data.mainloop);
+
+ if (data.error)
+ g_propagate_error (error, data.error);
+
+ return data.providers;
+}
+
+static int
+list_providers (int argc,
+ char **argv)
+{
+ g_autofree char *serialized_result = NULL;
+ g_autolist(GoaProvider) providers = NULL;
+ g_autoptr(GVariant) result = NULL;
+ g_autoptr(GError) error = NULL;
+ GVariantBuilder b;
+ GList *l;
+
+ providers = get_all_providers (&error);
+
+ if (error)
+ {
+ g_printerr ("%s", error->message);
+ return EXIT_FAILURE;
+ }
+
+ g_variant_builder_init (&b, G_VARIANT_TYPE ("a(ssviu)"));
+ for (l = providers; l; l = l->next)
+ {
+ GoaProvider *provider = l->data;
+ g_autofree char *name = NULL;
+ g_autoptr(GVariant) icon_variant = NULL;
+ g_autoptr(GIcon) icon = NULL;
+
+ name = goa_provider_get_provider_name (provider, NULL);
+ icon = goa_provider_get_provider_icon (provider, NULL);
+ icon_variant = g_icon_serialize (icon);
+
+ g_variant_builder_add (&b, "(ssviu)",
+ goa_provider_get_provider_type (provider),
+ name,
+ icon_variant,
+ goa_provider_get_provider_features (provider),
+ goa_provider_get_credentials_generation (provider));
+ }
+ result = g_variant_builder_end (&b);
+
+ serialized_result = g_variant_print (result, TRUE);
+ g_print ("%s", serialized_result);
+
+ return EXIT_SUCCESS;
+}
+
+/* show-account */
+
+static void
+on_remove_button_clicked_cb (GtkButton *button,
+ GApplication *application)
+{
+ g_print ("remove");
+ g_application_quit (application);
+}
+
+static void
+on_application_activate_show_account_cb (GtkApplication *application,
+ char **argv)
+{
+ g_autoptr(GoaProvider) provider = NULL;
+ g_autoptr(GoaObject) object = NULL;
+ g_autoptr(GoaClient) client = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autofree char *title = NULL;
+ GoaAccount *account;
+ GtkWidget *content_area;
+ GtkWidget *button;
+ GtkWidget *dialog;
+ GtkWidget *box;
+ const char *provider_type;
+
+ client = goa_client_new_sync (NULL, &error);
+ if (error)
+ {
+ g_printerr ("Error retrieving online accounts client");
+ exit (EXIT_FAILURE);
+ return;
+ }
+
+ object = goa_client_lookup_by_id (client, argv[2]);
+ if (!object)
+ {
+ g_printerr ("Online account does not exist");
+ exit (EXIT_FAILURE);
+ return;
+ }
+
+ /* Find the provider with a matching type */
+ account = goa_object_get_account (object);
+ provider_type = goa_account_get_provider_type (account);
+ provider = goa_provider_get_for_provider_type (provider_type);
+ if (!provider)
+ {
+ g_printerr ("Provider type not supported");
+ exit (EXIT_FAILURE);
+ return;
+ }
+
+ dialog = g_object_new (GTK_TYPE_DIALOG,
+ "use-header-bar", 1,
+ NULL);
+ /* Keep account alive so that the switches are still bound to it */
+ g_object_set_data_full (G_OBJECT (dialog), "goa-account", account, g_object_unref);
+ g_signal_connect_swapped (dialog, "response", G_CALLBACK (g_application_quit), application);
+ set_external_parent_from_handle (application, GTK_WINDOW (dialog), argv[3]);
+
+ box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 42);
+ gtk_widget_set_margin_bottom (box, 24);
+
+ content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+ gtk_container_set_border_width (GTK_CONTAINER (content_area), 0);
+ gtk_container_add (GTK_CONTAINER (content_area), box);
+
+ goa_provider_show_account (provider,
+ client,
+ object,
+ GTK_BOX (box),
+ NULL,
+ NULL);
+
+ /*
+ * The above call doesn't set any widgets to visible, so we have to do that.
+ * https://gitlab.gnome.org/GNOME/gnome-online-accounts/issues/56
+ */
+ gtk_widget_show_all (box);
+
+ /* translators: This is the title of the "Show Account" dialog. The
+ * %s is the name of the provider. e.g., 'Google'. */
+ title = g_strdup_printf (_("%s Account"), goa_account_get_provider_name (account));
+ gtk_window_set_title (GTK_WINDOW (dialog), title);
+
+ button = gtk_button_new_with_label (_("Remove Account"));
+ gtk_widget_set_margin_start (box, 24);
+ gtk_widget_set_margin_end (box, 24);
+ gtk_widget_set_halign (button, GTK_ALIGN_END);
+ gtk_widget_set_valign (button, GTK_ALIGN_END);
+ gtk_widget_set_visible (button, !goa_account_get_is_locked (account));
+ gtk_style_context_add_class (gtk_widget_get_style_context (button), "destructive-action");
+ gtk_container_add (GTK_CONTAINER (box), button);
+ g_signal_connect (button, "clicked", G_CALLBACK (on_remove_button_clicked_cb), application);
+}
+
+static int
+show_account (int argc,
+ char **argv)
+{
+ g_autoptr(GtkApplication) application = NULL;
+
+ gtk_init (&argc, &argv);
+
+ if (argc != 4)
+ {
+ g_printerr ("Not enough arguments");
+ return EXIT_FAILURE;
+ }
+
+ application = gtk_application_new ("org.gnome.Settings.GoaHelper",
+ G_APPLICATION_FLAGS_NONE);
+ g_signal_connect (application, "activate", G_CALLBACK (on_application_activate_show_account_cb), argv);
+
+ return g_application_run (G_APPLICATION (application), 0, NULL);
+}
+
+struct {
+ const char *command_name;
+ int (*command_func) (int argc,
+ char **argv);
+} commands[] = {
+ { "create-account", create_account, },
+ { "list-providers", list_providers, },
+ { "show-account", show_account, },
+};
+
+
+static void
+log_handler (const gchar *domain,
+ GLogLevelFlags log_level,
+ const gchar *message,
+ gpointer user_data)
+{
+ g_printerr ("%s: %s", domain, message);
+}
+
+int
+main (int argc,
+ char **argv)
+{
+ gsize i;
+
+ bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ if (argc < 2)
+ return EXIT_FAILURE;
+
+ g_log_set_default_handler (log_handler, NULL);
+
+ for (i = 0; i < G_N_ELEMENTS (commands); i++)
+ {
+ if (g_strcmp0 (commands[i].command_name, argv[1]) == 0)
+ return commands[i].command_func (argc, argv);
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/panels/online-accounts/gnome-online-accounts-panel.desktop.in.in b/panels/online-accounts/gnome-online-accounts-panel.desktop.in.in
new file mode 100644
index 0000000..fe77f8e
--- /dev/null
+++ b/panels/online-accounts/gnome-online-accounts-panel.desktop.in.in
@@ -0,0 +1,21 @@
+[Desktop Entry]
+Name=Online Accounts
+Comment=Connect to your online accounts and decide what to use them for
+Exec=gnome-control-center online-accounts
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-online-accounts-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-AccountSettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=Online Accounts
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: Search terms to find the Online Accounts panel.
+# Do NOT translate or localize the semicolons!
+# The list MUST also end with a semicolon!
+# For ReadItLater and Pocket, see http://en.wikipedia.org/wiki/Pocket_(application)
+Keywords=Google;Facebook;Twitter;Yahoo;Web;Online;Chat;Calendar;Mail;Contact;ownCloud;Kerberos;IMAP;SMTP;Pocket;ReadItLater;
diff --git a/panels/online-accounts/icons/meson.build b/panels/online-accounts/icons/meson.build
new file mode 100644
index 0000000..9482f1c
--- /dev/null
+++ b/panels/online-accounts/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-online-accounts-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/online-accounts/icons/scalable/org.gnome.Settings-online-accounts-symbolic.svg b/panels/online-accounts/icons/scalable/org.gnome.Settings-online-accounts-symbolic.svg
new file mode 100644
index 0000000..6a2a682
--- /dev/null
+++ b/panels/online-accounts/icons/scalable/org.gnome.Settings-online-accounts-symbolic.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <path d="m 7.664062 0.0078125 c -2.613281 0.1093755 -5.003906 1.4882815 -6.410156 3.6953125 c -1.90625 3 -1.609375 6.898437 0.734375 9.574219 c 2.347657 2.667968 6.175781 3.472656 9.398438 1.96875 c 0.5 -0.234375 0.714843 -0.828125 0.484375 -1.328125 c -0.234375 -0.5 -0.828125 -0.71875 -1.332032 -0.484375 c -2.414062 1.132812 -5.289062 0.53125 -7.046874 -1.476563 c -1.761719 -2.003906 -1.988282 -4.933593 -0.550782 -7.179687 c 1.429688 -2.253906 4.175782 -3.289063 6.738282 -2.539063 c 2.5625 0.746094 4.324218 3.09375 4.320312 5.761719 v 0.039062 v 0.960938 c 0 0.359375 -0.1875 0.683594 -0.5 0.863281 c -0.308594 0.179688 -0.6875 0.179688 -1 0 c -0.308594 -0.175781 -0.5 -0.507812 -0.5 -0.863281 v -1 c 0 -2.199219 -1.800781 -4 -4 -4 c -2.195312 0 -4 1.800781 -4 4 c 0 2.195312 1.804688 4 4 4 c 1.046875 0 1.992188 -0.417969 2.707031 -1.078125 c 0.222657 0.265625 0.484375 0.496094 0.792969 0.675781 c 0.929688 0.535156 2.074219 0.535156 3 0 c 0.929688 -0.539062 1.5 -1.527344 1.5 -2.597656 v -1 c 0 -3.558594 -2.347656 -6.683594 -5.761719 -7.683594 c -0.835937 -0.2421872 -1.703125 -0.347656 -2.574219 -0.3085935 z m 0.335938 5.9921875 c 1.117188 0 2 0.882812 2 2 c 0 1.113281 -0.882812 2 -2 2 c -1.113281 0 -2 -0.886719 -2 -2 c 0 -1.117188 0.886719 -2 2 -2 z m 0 0" fill="#2e3436"/>
+</svg>
diff --git a/panels/online-accounts/meson.build b/panels/online-accounts/meson.build
new file mode 100644
index 0000000..9d1b918
--- /dev/null
+++ b/panels/online-accounts/meson.build
@@ -0,0 +1,84 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+cflags += [
+ '-DLIBEXECDIR="@0@"'.format(control_center_libexecdir),
+]
+
+sources = files(
+ 'cc-online-account-provider-row.c',
+ 'cc-online-account-row.c',
+ 'cc-online-accounts-panel.c',
+)
+
+resource_data = files(
+ 'cc-online-account-provider-row.ui',
+ 'cc-online-account-row.ui',
+ 'cc-online-accounts-panel.ui',
+ 'online-accounts.css',
+)
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname.underscorify(),
+ dependencies: resource_data,
+ export: true
+)
+
+deps = common_deps + [
+ goa_dep,
+]
+
+panels_libs += static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [ top_inc, common_inc ],
+ dependencies: deps,
+ c_args: cflags
+)
+
+goa_helper_deps = [
+ dependency('goa-backend-1.0', version: goa_req_version),
+]
+
+goa_helper_cflags = cflags + [
+ '-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir),
+]
+
+gtk_x11_dep = dependency('gtk+-x11-3.0', required: false)
+if gtk_x11_dep.found()
+ goa_helper_cflags += ['-DHAVE_GTK_X11']
+endif
+
+gtk_wayland_dep = dependency('gtk+-wayland-3.0', required: false)
+if gtk_wayland_dep.found()
+ goa_helper_cflags += ['-DHAVE_GTK_WAYLAND']
+endif
+
+executable(
+ 'gnome-control-center-goa-helper',
+ 'gnome-control-center-goa-helper.c',
+ include_directories: [ top_inc ],
+ dependencies: goa_helper_deps,
+ c_args: goa_helper_cflags,
+ install: true,
+ install_dir: control_center_libexecdir,
+)
+
+subdir('icons')
diff --git a/panels/online-accounts/online-accounts.css b/panels/online-accounts/online-accounts.css
new file mode 100644
index 0000000..08a60b6
--- /dev/null
+++ b/panels/online-accounts/online-accounts.css
@@ -0,0 +1,6 @@
+image.symbolic-circular {
+ background-color: alpha(currentColor, 0.08);
+ min-width: 32px;
+ min-height: 32px;
+ border-radius: 50%;
+}
diff --git a/panels/online-accounts/online-accounts.gresource.xml b/panels/online-accounts/online-accounts.gresource.xml
new file mode 100644
index 0000000..0e452b6
--- /dev/null
+++ b/panels/online-accounts/online-accounts.gresource.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/online-accounts">
+ <file preprocess="xml-stripblanks">cc-online-account-provider-row.ui</file>
+ <file preprocess="xml-stripblanks">cc-online-account-row.ui</file>
+ <file preprocess="xml-stripblanks">cc-online-accounts-panel.ui</file>
+ <file>online-accounts.css</file>
+ </gresource>
+</gresources>
diff --git a/panels/panel-app-icons.svg b/panels/panel-app-icons.svg
new file mode 100644
index 0000000..e96d4c1
--- /dev/null
+++ b/panels/panel-app-icons.svg
@@ -0,0 +1,1246 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ version="1.1"
+ width="1024"
+ height="800"
+ id="svg7384"
+ inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
+ sodipodi:docname="panel-app-icons.svg"
+ viewBox="0 0 1024 800"
+ shape-rendering="crispEdges"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <metadata
+ id="metadata90">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Gnome Symbolic Icon Theme</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#f4f5f6"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="1"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="1011"
+ id="namedview88"
+ showgrid="true"
+ inkscape:zoom="1"
+ inkscape:cx="659"
+ inkscape:cy="205"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer16"
+ showborder="false"
+ inkscape:snap-nodes="true"
+ inkscape:snap-bbox="true"
+ inkscape:bbox-paths="true"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:snap-to-guides="true"
+ inkscape:snap-grids="true"
+ inkscape:snap-global="true"
+ inkscape:object-nodes="true"
+ inkscape:snap-bbox-midpoints="false"
+ inkscape:object-paths="true"
+ inkscape:snap-others="true"
+ inkscape:bbox-nodes="true"
+ inkscape:snap-bbox-edge-midpoints="true"
+ inkscape:measure-start="56,310.597"
+ inkscape:measure-end="0,0"
+ inkscape:document-rotation="0"
+ inkscape:snap-intersection-paths="true"
+ inkscape:pagecheckerboard="false"
+ inkscape:snap-smooth-nodes="true"
+ inkscape:snap-midpoints="true"
+ inkscape:snap-page="true"
+ inkscape:snap-object-midpoints="true"
+ inkscape:snap-center="true"
+ inkscape:snap-text-baseline="true">
+ <inkscape:grid
+ type="xygrid"
+ id="grid4866"
+ empspacing="4"
+ visible="true"
+ enabled="true"
+ snapvisiblegridlinesonly="true"
+ spacingx="1px"
+ spacingy="1px"
+ color="#8e8eb0"
+ opacity="0.29411765"
+ empcolor="#3f3fff"
+ empopacity="0.45882353"
+ originx="0"
+ originy="0" />
+ <inkscape:grid
+ type="xygrid"
+ id="grid25939"
+ empspacing="4"
+ spacingy="0.5"
+ spacingx="0.5"
+ dotted="false" />
+ </sodipodi:namedview>
+ <title
+ id="title9167">Gnome Symbolic Icon Theme</title>
+ <defs
+ id="defs7386">
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect38750"
+ is_visible="true"
+ lpeversion="1"
+ satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.99302884,0,1 @ F,0,0,1,0,0.99302884,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,0.988281,0,1 @ F,0,0,1,0,0.988281,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false" />
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect38360"
+ is_visible="true"
+ lpeversion="1"
+ satellites_param="F,0,0,1,0,1,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,1,0,1 | F,0,0,1,0,0.5,0,1 @ F,0,1,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.5,0,1 | F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 | F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false" />
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect36801"
+ is_visible="true"
+ lpeversion="1"
+ satellites_param="F,0,0,1,0,1,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,4,0,1 @ F,0,0,1,0,1,0,1 | F,0,0,1,0,0.5,0,1 @ F,0,1,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.5,0,1 | F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 | F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false" />
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect48889"
+ is_visible="true"
+ lpeversion="1"
+ satellites_param="F,0,0,1,0,0.999996,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.999996,0,1"
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false" />
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect48685"
+ is_visible="true"
+ lpeversion="1"
+ satellites_param="F,0,0,1,0,0.999996,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.999996,0,1"
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false" />
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect39298"
+ is_visible="true"
+ lpeversion="1"
+ satellites_param="F,0,0,1,0,0.999996,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.999996,0,1"
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false" />
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect10862"
+ is_visible="true"
+ lpeversion="1"
+ satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.51562,0,1 @ F,0,0,1,0,1.51562,0,1 @ F,0,0,1,0,0,0,1"
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false" />
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect104916"
+ is_visible="true"
+ lpeversion="1"
+ satellites_param="F,0,0,1,0,0.999996,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.999996,0,1"
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false" />
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect104888"
+ is_visible="true"
+ lpeversion="1"
+ satellites_param="F,0,0,1,0,0.999996,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.999996,0,1"
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false" />
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 400 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="1024 : 400 : 1"
+ inkscape:persp3d-origin="512 : 266.66667 : 1"
+ id="perspective148323" />
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect69553"
+ is_visible="true"
+ lpeversion="1"
+ satellites_param="F,0,0,1,0,2.00018,0,1 @ F,0,0,1,0,2.00018,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.99982,0,1 @ F,0,0,1,0,1.99982,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 | F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false" />
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect65055"
+ is_visible="true"
+ lpeversion="1"
+ satellites_param="F,0,0,1,0,1.00012,0,1 @ F,0,0,1,0,1.00002,0,1 @ F,0,0,1,0,0.99998,0,1 @ F,0,0,1,0,0.99998,0,1 @ F,0,0,1,0,3.00002,0,1 @ F,0,0,1,0,1.00012,0,1"
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false" />
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect34948"
+ is_visible="true"
+ lpeversion="1"
+ satellites_param="F,0,0,1,0,0.999996,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.999996,0,1"
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false" />
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect27117"
+ is_visible="true"
+ lpeversion="1"
+ satellites_param="F,0,0,1,0,0.999996,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.999996,0,1 @ F,0,0,1,0,0.999996,0,1"
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false" />
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect26982"
+ is_visible="true"
+ lpeversion="1"
+ satellites_param="F,0,0,1,0,0.999996,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.999996,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.000004,0,1 @ F,0,0,1,0,0.994146,0,1"
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false" />
+ </defs>
+ <g
+ inkscape:groupmode="layer"
+ id="layer16"
+ inkscape:label="apps">
+ <text
+ id="text3375"
+ y="30.339233"
+ x="22.822998"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12px;line-height:125%;font-family:Cantarell;-inkscape-font-specification:Cantarell;text-align:start;text-anchor:start;display:inline;fill:#2e3436;fill-opacity:1;stroke:none;enable-background:new"
+ xml:space="preserve"><tspan
+ y="30.339233"
+ x="22.822998"
+ id="tspan3373"
+ sodipodi:role="line">apps</tspan></text>
+ <g
+ inkscape:label="preferences system notifications bell notification ring alarm feedback control"
+ id="g2982"
+ style="display:inline;enable-background:new"
+ transform="translate(12.01713,-628.00474)">
+ <title
+ id="title2975">org.gnome.Settings-notifications</title>
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:0.514644;fill:none;fill-opacity:1;stroke:none;stroke-width:3;marker:none;enable-background:accumulate"
+ id="rect2977"
+ width="16"
+ height="16"
+ x="11.982551"
+ y="668.00458" />
+ <g
+ id="g3014"
+ transform="translate(0.28081117,-5.4690528)">
+ <path
+ id="path2984-3"
+ style="display:inline;fill:#2e3436;stroke-width:2;stroke-linecap:square;stroke-linejoin:round;stroke-dasharray:8, 8"
+ d="m 608,700 a 1.5,1.5 0 0 0 -1.5,1.5 1.5,1.5 0 0 0 0.0195,0.23047 A 5,5 0 0 0 603,706.5 v 4.5 h -0.5 c -0.554,0 -1,0.446 -1,1 0,0.554 0.446,1 1,1 h 11 c 0.554,0 1,-0.446 1,-1 0,-0.554 -0.446,-1 -1,-1 H 613 v -4.5 A 5,5 0 0 0 609.48242,701.72461 1.5,1.5 0 0 0 609.5,701.5 1.5,1.5 0 0 0 608,700 Z m -2,14 a 2,2 0 0 0 1,1.73242 2,2 0 0 0 2,0 A 2,2 0 0 0 610,714 Z"
+ transform="translate(-588.29794,-26.526207)" />
+ </g>
+ </g>
+ <g
+ inkscape:label="preferences system time date timezone country location 24 12 hour format local"
+ id="g2236"
+ style="display:inline;enable-background:new"
+ transform="translate(72.01713,-628.00474)">
+ <title
+ id="title2226">org.gnome.Settings-time</title>
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:0.514644;fill:none;fill-opacity:1;stroke:none;stroke-width:3;marker:none;enable-background:accumulate"
+ id="rect2228"
+ width="16"
+ height="16"
+ x="11.982551"
+ y="668.00458" />
+ <g
+ id="g2234"
+ transform="translate(-5.5887817e-5,-0.49983764)">
+ <path
+ style="color:#000000;fill:#2e3436;stroke-linecap:round;stroke-linejoin:round;-inkscape-stroke:none"
+ d="m 19.982422,668.50391 c -4.406384,0 -8,3.59361 -8,8 0,4.40638 3.593616,8 8,8 4.406384,0 8,-3.59362 8,-8 0,-4.40639 -3.593616,-8 -8,-8 z m 0,2 c 3.325505,0 6,2.67449 6,6 0,3.3255 -2.674495,6 -6,6 -3.325505,0 -6,-2.6745 -6,-6 0,-3.32551 2.674495,-6 6,-6 z"
+ id="circle2230" />
+ <path
+ style="color:#000000;fill:#2e3436;stroke-linecap:round;stroke-linejoin:round;-inkscape-stroke:none"
+ d="m 16.914062,673.45898 a 0.5,0.5 0 0 0 -0.351562,0.15039 0.5,0.5 0 0 0 0.0078,0.70704 l 3.111329,3.04492 a 0.5,0.5 0 0 0 0.386718,0.1289 h 2.914063 a 0.5,0.5 0 0 0 0.5,-0.5 0.5,0.5 0 0 0 -0.5,-0.5 h -2.761719 l -2.951172,-2.88867 a 0.5,0.5 0 0 0 -0.355469,-0.14258 z"
+ id="path2232" />
+ </g>
+ </g>
+ <g
+ inkscape:label="preferences system privacy security camera location microphone thunderbolt history trash screen lock diagnostics"
+ id="g6928"
+ style="display:inline;enable-background:new"
+ transform="translate(52.01713,-628.00474)">
+ <title
+ id="title6871">org.gnome.Settings-privacy</title>
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:0.514644;fill:none;fill-opacity:1;stroke:none;stroke-width:3;marker:none;enable-background:accumulate"
+ id="rect6873"
+ width="16"
+ height="16"
+ x="11.982551"
+ y="668.00458" />
+ <g
+ id="g3835"
+ inkscape:label="preferences-system-privacy"
+ transform="translate(-260.01745,221.00474)"
+ style="enable-background:new">
+ <path
+ style="display:inline;opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;enable-background:new"
+ d="m 280.00007,446.99998 c 0.554,0 1.00001,0.446 1,1 L 281,454.5 c 0,0 -7e-5,0.50002 0.49993,0.50002 0.5,0 0.50007,-0.50002 0.50007,-0.50002 l 7e-5,-4.50002 c 1e-5,-0.554 0.446,-1 1,-1 0.554,0 1,0.446 1,1 L 284,458.5 c 0,0.5 0.5,0.5 0.5,0.5 l 1.79304,-1.70706 c 0.18827,-0.19354 0.44679,-0.30271 0.71679,-0.30273 1.0856,0.0854 1.14809,1.26597 0.69724,1.71682 l -3,3 C 284,462.5 282.94992,462.99456 282,463 h -6 c -3,0 -3,-3 -3,-3 v -6 -2 c 0,-0.554 0.446,-1 1,-1 0.554,0 1,0.446 1,1 v 3.5 c 0,0 0,0.5 0.5,0.5 0.5,0 0.5,-0.5 0.5,-0.5 V 449 c 0,-0.554 0.446,-1 1,-1 0.554,0 1,0.446 1,1 v 5.5 c 0,0 0,0.5 0.5,0.5 0.5,0 0.5,-0.5 0.5,-0.5 V 448 c 0,-0.554 0.446,-1 1,-1 z"
+ id="path6023"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cscscsssccccscccccssscscssscscssc" />
+ </g>
+ </g>
+ <g
+ id="g56882"
+ inkscape:label="settings power battery level saver suspend timeout"
+ transform="translate(-36.00032,-640)">
+ <title
+ id="title57206">org.gnome.Settings-power</title>
+ <path
+ id="path10036-3-0"
+ style="fill:#2e3434;fill-opacity:1"
+ d="m 85,700 c -1,0 -1,1 -1,1 v 1 h -1 c 0,0 -0.708596,-0.0137 -1.447266,0.35547 C 80.814074,702.72465 80,703.6664 80,705 v 8 c 0,0 -0.0138,0.70891 0.355469,1.44727 C 80.724789,715.18562 81.6668,716 83,716 h 3 c 0.552285,0 1,-0.44772 1,-1 0,-0.55228 -0.447715,-1 -1,-1 h -3 c -0.554,0 -1,-0.446 -1,-1 v -8 c 0,-0.554 0.446,-1 1,-1 h 3 3 c 0.554,0 1,0.446 1,1 h 2 c 0,-1.3336 -0.814074,-2.27535 -1.552734,-2.64453 C 89.708596,701.98628 89,702 89,702 h -1 v -1 c 0,-1 -1,-1 -1,-1 z m 5,6 c -1.934866,0.27585 -2.723575,2.89654 -3,4 h -2 c -0.552285,0 -1,0.44772 -1,1 0,0.55228 0.447715,1 1,1 h 2 c 0.276425,1.10344 1.065134,3.72415 3,4 h 2 c 0,0 1,0 1,-1 v -1 h 3 v -2 h -3 v -2 h 3 v -2 h -3 v -1 c 0,0 0,-1 -1,-1 z" />
+ <rect
+ y="-96"
+ x="700.00079"
+ height="16"
+ width="16"
+ id="rect56907"
+ transform="rotate(90)"
+ style="fill:none" />
+ </g>
+ <g
+ id="g142624-6"
+ inkscape:label="settings audio speaker output sound music listen "
+ transform="translate(-76,-420)">
+ <title
+ id="title142961-2">org.gnome.Settings-sound</title>
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:0.1;fill:none;fill-opacity:1;stroke:none;stroke-width:1;marker:none"
+ id="rect6203-3-9"
+ width="16"
+ height="16"
+ x="140.0004"
+ y="480" />
+ <path
+ id="path9704-1"
+ d="m 152.03906,480.00391 c -0.25893,-0.0108 -0.52442,0.0756 -0.72656,0.28125 L 148,483.57812 V 485 h 1.39062 l 3.30469,-3.29883 c 0.40435,-0.40437 0.36131,-1.04131 0.0293,-1.39258 -0.17445,-0.18457 -0.42662,-0.29384 -0.68555,-0.30468 z M 147,481.00586 c -0.29553,-10e-4 -0.57652,0.12805 -0.76758,0.35352 L 143,485 h -1 c -1.09467,0 -2,0.84432 -2,2 v 2 c 0,1.0907 0.9093,2 2,2 h 1 l 3.23242,3.64062 c 0.2107,0.25221 0.49171,0.3619 0.76758,0.35938 z M 148,487 v 2 h 6 c 0.7496,0 0.9993,-0.50135 1,-1.00195 C 155.00069,487.49863 154.75,487 154,487 Z m 0,4 v 1.42188 l 3.32227,3.29296 c 0.40429,0.41126 1.06516,0.34571 1.41406,-0.0234 0.33201,-0.35127 0.3731,-0.98821 -0.0312,-1.39258 L 149.39062,491 Z"
+ style="fill:#2e3436;fill-opacity:1" />
+ </g>
+ <g
+ id="g3561"
+ inkscape:label="settings locale language i18n international"
+ transform="translate(152,-388)"
+ style="enable-background:new">
+ <title
+ id="title82486">org.gnome.Settings-region</title>
+ <path
+ id="path3535"
+ d="m -65,448 a 1.0001,1.0001 0 0 0 -1,1 v 1 1 4 8 1 h 2 v -1 -7 h 2.38281 l 0.72266,1.44727 A 1.0001,1.0001 0 0 0 -60,458 h 5 a 1.0001,1.0001 0 0 0 1,-1 v -6 a 1.0001,1.0001 0 0 0 -1,-1 h -3.38281 l -0.72266,-1.44727 A 1.0001,1.0001 0 0 0 -60,448 Z"
+ style="fill:#2e3436;fill-opacity:1" />
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:1.781;marker:none;enable-background:new"
+ id="rect3543"
+ y="448"
+ x="-68"
+ height="16"
+ width="16" />
+ </g>
+ <g
+ inkscape:label="system users two group multiple people person humans"
+ id="g10173"
+ style="display:inline;enable-background:new"
+ transform="translate(112.01713,-628.00474)">
+ <title
+ id="title10163">org.gnome.Settings-users</title>
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:0.514644;fill:none;fill-opacity:1;stroke:none;stroke-width:3;marker:none;enable-background:accumulate"
+ id="rect10165"
+ width="16"
+ height="16"
+ x="11.982551"
+ y="668.00458" />
+ <path
+ id="path11086"
+ d="m 16.98287,669.00474 a 2.5,2.5 0 0 0 -2.5,2.5 2.5,2.5 0 0 0 2.5,2.5 2.5,2.5 0 0 0 2.5,-2.5 2.5,2.5 0 0 0 -2.5,-2.5 z m 6,3 a 2.5,2.5 0 0 0 -2.5,2.5 2.5,2.5 0 0 0 2.5,2.5 2.5,2.5 0 0 0 2.5,-2.5 2.5,2.5 0 0 0 -2.5,-2.5 z m -8,3 c -1.662,0 -3,1.338 -3,3 v 2 c 0,0.554 0.446,1 1,1 h 4.07617 c 0,-2.04174 1.58175,-3.73269 3.58008,-3.9082 a 3.4998422,3.4998422 0 0 1 -1.10937,-2.04102 c -0.17719,-0.0324 -0.36005,-0.0508 -0.54688,-0.0508 z m 6,3 c -1.662,0 -3,1.338 -3,3 v 2 c 0,0.554 0.446,1 1,1 h 8 c 0.554,0 1,-0.446 1,-1 v -2 c 0,-1.662 -1.338,-3 -3,-3 z"
+ style="fill:#2e3436;fill-opacity:1" />
+ <g
+ id="g10171"
+ transform="translate(-5.5887817e-5,0.50016236)">
+ <g
+ id="g4110"
+ inkscape:label="system-users"
+ style="enable-background:new"
+ transform="translate(-0.01758804,200.50442)">
+ <g
+ id="path11395" />
+ </g>
+ </g>
+ </g>
+ <g
+ inkscape:label="preferences desktop multitasking switching windows workspaces"
+ id="g18802"
+ style="display:inline;enable-background:new"
+ transform="translate(132.01713,-628.00474)">
+ <path
+ id="rect20168"
+ d="m 17.98255,668.00474 c -1.6447,0 -3,1.3553 -3,3 v 10 c 0,1.6447 1.3553,3 3,3 h 4 c 1.6447,0 3,-1.3553 3,-3 v -10 c 0,-1.6447 -1.3553,-3 -3,-3 z m 0,2 h 4 c 0.5713,0 1,0.4287 1,1 v 10 c 0,0.57129 -0.4287,1 -1,1 h -4 c -0.5713,0 -1,-0.42871 -1,-1 v -10 c 0,-0.5713 0.4287,-1 1,-1 z m -5,1 c -0.554,0 -1,0.446 -1,1 v 8 c 0,0.554 0.446,1 1,1 0.554,0 1,-0.446 1,-1 v -8 c 0,-0.554 -0.446,-1 -1,-1 z m 14,0 c -0.554,0 -1,0.446 -1,1 v 8 c 0,0.554 0.446,1 1,1 0.554,0 1,-0.446 1,-1 v -8 c 0,-0.554 -0.446,-1 -1,-1 z"
+ style="fill:#2e3436;fill-opacity:1" />
+ <title
+ id="title18784">org.gnome.Settings-multitasking</title>
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:0.514644;fill:none;fill-opacity:1;stroke:none;stroke-width:3;marker:none;enable-background:accumulate"
+ id="rect18786"
+ width="16"
+ height="16"
+ x="11.982551"
+ y="668.00458" />
+ </g>
+ <g
+ inkscape:label="preferences online accounts providers service email cloud login enterprise remote"
+ id="g23645"
+ style="display:inline;enable-background:new"
+ transform="translate(152.01713,-628.00474)">
+ <title
+ id="title23637">org.gnome.Settings-online-accounts</title>
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:0.514644;fill:none;fill-opacity:1;stroke:none;stroke-width:3;marker:none;enable-background:accumulate"
+ id="rect23639"
+ width="16"
+ height="16"
+ x="11.982551"
+ y="668.00458" />
+ <g
+ style="enable-background:new"
+ id="g4252"
+ transform="translate(-260.0155,181.00383)"
+ inkscape:label="goa-panel">
+ <g
+ id="g4335"
+ inkscape:label="goa-panel">
+ <path
+ transform="translate(60,-45)"
+ id="path2-5"
+ d="m 219.66211,532.00781 a 8.007,8.007 0 0 0 -6.41016,3.69531 8.009,8.009 0 0 0 0.73633,9.57422 8.006,8.006 0 0 0 9.39649,1.97071 1.0000477,1.0000477 0 1 0 -0.84571,-1.8125 5.993,5.993 0 0 1 -7.04883,-1.47852 5.99,5.99 0 0 1 -0.55078,-7.17969 5.99,5.99 0 0 1 6.73828,-2.53711 A 5.991,5.991 0 0 1 226,540 a 1,1 0 0 0 0,0.041 V 541 c 0,0.359 -0.189,0.68623 -0.5,0.86523 -0.31,0.18 -0.689,0.18 -1,0 A 0.995,0.995 0 0 1 224,541 v -1 c 0,-2.197 -1.803,-4 -4,-4 -2.197,0 -4,1.803 -4,4 0,2.197 1.803,4 4,4 1.04356,0 1.99031,-0.41555 2.70508,-1.07812 0.22194,0.26526 0.48659,0.49783 0.79492,0.67578 a 3.004,3.004 0 0 0 3,0 A 3.003,3.003 0 0 0 228,541 v -1 a 8.008,8.008 0 0 0 -5.76172,-7.68164 7.983,7.983 0 0 0 -2.57617,-0.31055 z M 220,538 c 1.117,0 2,0.884 2,2 0,1.116 -0.883,2 -2,2 -1.116,0 -2,-0.884 -2,-2 0,-1.116 0.884,-2 2,-2 z"
+ style="color:#000000;font-weight:400;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;text-transform:none;text-orientation:mixed;white-space:normal;shape-padding:0;overflow:visible;isolation:auto;mix-blend-mode:normal;solid-color:#000000;solid-opacity:1;fill:#2e3436;stroke:none" />
+ </g>
+ </g>
+ </g>
+ <g
+ style="display:inline;fill:none;fill-opacity:1"
+ inkscape:label="edit find search loupe"
+ id="use8034"
+ transform="rotate(90,219.06941,95.93344)">
+ <title
+ id="title6784">org.gnome.Settings-search</title>
+ <rect
+ y="195.00317"
+ x="163.1358"
+ height="16"
+ width="16"
+ id="rect6786"
+ style="fill:none;fill-opacity:1" />
+ <path
+ id="path6788"
+ d="m 163.13581,204.50317 c 0,3.5779 2.9221,6.5 6.5,6.5 3.5779,0 6.49805,-2.9221 6.49805,-6.5 0,-1.42901 -0.46837,-2.75273 -1.25586,-3.82812 l 3.94531,-3.94532 c 0.93804,-0.95834 -0.49946,-2.36459 -1.4375,-1.40625 l -3.92969,3.92969 c -1.07377,-0.78482 -2.39435,-1.25 -3.82031,-1.25 -3.5779,0 -6.5,2.9221 -6.5,6.5 z m 2,0 c 0,-2.497 2.003,-4.5 4.5,-4.5 2.497,0 4.49805,2.003 4.49805,4.5 0,2.497 -2.00105,4.5 -4.49805,4.5 -2.497,0 -4.5,-2.003 -4.5,-4.5 z"
+ style="fill:#2e3436;fill-opacity:1" />
+ </g>
+ <g
+ id="g9367"
+ inkscape:label="preferences settings accessibility a11y universal"
+ transform="translate(32.01713,-468)"
+ style="display:inline;enable-background:new">
+ <title
+ id="title15947">org.gnome.Settings-accessibility</title>
+ <path
+ id="path9341"
+ d="m 20,508 c 1.104569,0 2,0.89543 2,2 0,1.10457 -0.895431,2 -2,2 -1.104569,0 -2,-0.89543 -2,-2 0,-1.10457 0.895431,-2 2,-2 z"
+ style="display:inline;overflow:visible;visibility:visible;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:2;marker:none"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="sssss" />
+ <path
+ id="path2318"
+ style="color:#000000;display:inline;fill:#2e3436;stroke-linecap:square;-inkscape-stroke:none"
+ d="m 13.982551,515 h 3 v 9 h 2 v -4 c 0,-0.55228 0.447715,-1 1,-1 0.552285,0 1,0.44772 1,1 v 4 h 2 v -5 -4 h 3 v -2 h -12 z"
+ sodipodi:nodetypes="ccccssscccccccc" />
+ <rect
+ y="508.00458"
+ x="11.982551"
+ height="16"
+ width="16"
+ id="rect9343"
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:0.514644;fill:none;stroke:none;stroke-width:3;marker:none;enable-background:accumulate" />
+ </g>
+ <g
+ id="g7027"
+ inkscape:label="settings applications permissions flatpak apps "
+ transform="translate(-576,-664)">
+ <title
+ id="title7029">org.gnome.Settings-applications</title>
+ <g
+ id="g4039"
+ inkscape:label=""
+ style="enable-background:new"
+ transform="translate(428,236)">
+ <title
+ id="title61874">preferences-desktop-apps</title>
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:1;marker:none"
+ id="rect4074"
+ width="16"
+ height="16"
+ x="172.00606"
+ y="488" />
+ </g>
+ <path
+ id="rect56785"
+ d="m 602,724 c -1.0907,0 -2,0.9093 -2,2 v 3 c 0,1.0907 0.9093,2 2,2 h 3 c 1.0907,0 2,-0.9093 2,-2 v -3 c 0,-1.0907 -0.9093,-2 -2,-2 z m 8,0 c -1.0907,0 -2,0.9093 -2,2 v 3 c 0,1.0907 0.9093,2 2,2 h 3 c 1.0907,0 2,-0.9093 2,-2 v -3 c 0,-1.0907 -0.9093,-2 -2,-2 z m -8,2 h 3 v 3 h -3 z m 8,0 h 3 v 3 h -3 z m -8,6 c -1.0907,0 -2,0.9093 -2,2 v 3 c 0,1.0907 0.9093,2 2,2 h 3 c 1.0907,0 2,-0.9093 2,-2 v -3 c 0,-1.0907 -0.9093,-2 -2,-2 z m 8,0 c -1.0907,0 -2,0.9093 -2,2 v 3 c 0,1.0907 0.9093,2 2,2 h 3 c 1.0907,0 2,-0.9093 2,-2 v -3 c 0,-1.0907 -0.9093,-2 -2,-2 z m -8,2 h 3 v 3 h -3 z m 8,0 h 3 v 3 h -3 z"
+ style="fill:#2e3436;fill-opacity:1" />
+ </g>
+ <g
+ id="g6202"
+ inkscape:label="settings locale language i18n international"
+ transform="translate(172,-388)"
+ style="enable-background:new">
+ <title
+ id="title6196">org.gnome.Settings-appearance</title>
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:1.781;marker:none;enable-background:new"
+ id="rect6200"
+ y="448"
+ x="-68"
+ height="16"
+ width="16" />
+ <path
+ d="m -64.98828,449 c -1.64453,0 -3,1.35547 -3,3 v 6 c 0,1.64453 1.35547,3 3,3 h 10 c 1.64453,0 3,-1.35547 3,-3 v -6 c 0,-0.57031 -0.16797,-1.10156 -0.44922,-1.55859 l -1.55078,1.55468 V 458 c 0,0.57031 -0.42969,1 -1,1 h -10 c -0.57031,0 -1,-0.42969 -1,-1 v -6 c 0,-0.57031 0.42969,-1 1,-1 h 5.96875 l 2.00781,-2 z m 0,0"
+ fill="#2e3436"
+ id="path5778" />
+ <path
+ d="m -56.98828,455 c 0,1.65625 -1.33984,3.00781 -3,3 h -3 v -3 c 0,-1.66016 1.34375,-3 3,-3 1.66016,0 3,1.33984 3,3 z m 0,0"
+ fill="#2e3436"
+ id="path5812" />
+ <path
+ d="m -54.58984,448 -3.46875,3.45703 c 0.68359,0.35547 1.23437,0.91016 1.58984,1.58985 l 0.17188,-0.17188 0.008,0.008 4.30078,-4.30078 v -0.58203 z m 0,0"
+ fill="#2e3436"
+ id="path5814" />
+ <path
+ d="m -62.98828,462 c -1.10547,0 -2,0.89453 -2,2 h 10 c 0,-1.10547 -0.89453,-2 -2,-2 z m 0,0"
+ fill="#2e3436"
+ id="path5820" />
+ </g>
+ <g
+ id="g6416"
+ inkscape:label="settings locale language i18n international"
+ transform="translate(192,-388)"
+ style="enable-background:new">
+ <title
+ id="title6404">org.gnome.Settings-bluetooth</title>
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:1.781;marker:none;enable-background:new"
+ id="rect6406"
+ y="448"
+ x="-68"
+ height="16"
+ width="16" />
+ <path
+ d="m -60.414935,448.0907 c -0.35547,0.16407 -0.58594,0.51953 -0.58594,0.91016 v 5.29687 l -2.34375,-2.04687 c -0.41406,-0.36328 -1.04297,-0.32422 -1.40625,0.0898 -0.36328,0.41797 -0.32422,1.04688 0.0937,1.41016 l 2.56641,2.25 -2.56641,2.25 c -0.41797,0.36328 -0.45703,0.99219 -0.0937,1.40625 0.36328,0.41797 0.99219,0.45703 1.40625,0.0937 l 2.34375,-2.04679 v 5.29688 c 0,0.39062 0.23047,0.74609 0.58594,0.91016 0.35937,0.16015 0.77734,0.10156 1.07031,-0.16016 l 4,-3.5 c 0.21875,-0.1875 0.34375,-0.46094 0.34375,-0.75 0,-0.28906 -0.125,-0.5625 -0.34375,-0.75 l -3.14062,-2.75 3.14062,-2.75 c 0.21875,-0.1875 0.34375,-0.46094 0.34375,-0.75 0,-0.28906 -0.125,-0.5625 -0.34375,-0.75 l -4,-3.5 c -0.29297,-0.26172 -0.71094,-0.32422 -1.07031,-0.16016 z m 1.41406,3.11328 1.48438,1.29688 -1.48438,1.29687 z m 0,7 1.48438,1.29688 -1.48438,1.29687 z m 0,0"
+ fill="#2e3436"
+ id="path6738"
+ style="enable-background:new" />
+ </g>
+ <g
+ id="g47292"
+ inkscape:label="camera photography pictures "
+ transform="translate(-56,-500)">
+ <title
+ id="title47294">org.gnome.Settings-camera</title>
+ <rect
+ y="-216"
+ x="560"
+ height="16"
+ width="16"
+ id="rect37542"
+ style="fill:none;fill-opacity:1"
+ transform="rotate(90)" />
+ <path
+ id="path37587"
+ d="m 206.5,560 c -0.2652,5e-5 -0.51952,0.10543 -0.70703,0.29297 L 204.08594,562 H 203 c -1.6447,0 -3,1.3553 -3,3 v 7 c 0,1.6447 1.3553,3 3,3 h 10 c 1.6447,0 3,-1.3553 3,-3 v -7 c 0,-1.6447 -1.3553,-3 -3,-3 h -1.08594 l -1.70703,-1.70703 C 210.01952,560.10543 209.7652,560.00005 209.5,560 Z m 0.41406,2 h 2.17188 l 1.70703,1.70703 c 0.18751,0.18754 0.44183,0.29292 0.70703,0.29297 h 1.5 c 0.5713,0 1,0.4287 1,1 v 7 c 0,0.5713 -0.4287,1 -1,1 h -10 c -0.5713,0 -1,-0.4287 -1,-1 v -7 c 0,-0.5713 0.4287,-1 1,-1 h 1.5 c 0.2652,-5e-5 0.51952,-0.10543 0.70703,-0.29297 z M 208,565 c -1.64501,0 -3,1.35499 -3,3 0,1.64501 1.58579,3 3,3 1.41421,0 3,-1.35499 3,-3 0,-1.64501 -1.35499,-3 -3,-3 z m 0,2 c 0.56413,0 1,0.43587 1,1 0,0.56413 -0.43587,1 -1,1 -0.56413,0 -1,-0.43587 -1,-1 0,-0.56413 0.43587,-1 1,-1 z"
+ style="fill:#2e3434;fill-opacity:1"
+ sodipodi:nodetypes="cccssssssssccccccccsssssssscccssasssssss" />
+ </g>
+ <g
+ id="g7659"
+ inkscape:label="camera photography pictures "
+ transform="translate(-36,-500)">
+ <title
+ id="title7653">org.gnome.Settings-color</title>
+ <rect
+ y="-216"
+ x="560"
+ height="16"
+ width="16"
+ id="rect7655"
+ style="fill:none;fill-opacity:1"
+ transform="rotate(90)" />
+ <g
+ color="#000000"
+ fill="#474747"
+ id="g7640"
+ transform="translate(200.08694,559)">
+ <path
+ d="m 8,1.015625 c -2.203,0 -4,1.797 -4,4 0,2.203 1.797,4 4,4 2.203,0 4,-1.797 4,-4 0,-2.203 -1.797,-4 -4,-4 z m 1.544e-4,1.97225 c 1.1211644,-0.00307 2.0308196,0.9065856 2.0277496,2.02775 0.0031,1.1211644 -0.9065852,2.0308196 -2.0277496,2.02775 C 6.8792599,7.0460608 5.9700277,6.1365185 5.9730956,5.015625 5.9700277,3.8947315 6.8792599,2.9851892 8.0001544,2.987875 Z"
+ style="line-height:normal;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;text-transform:none;text-orientation:mixed;shape-padding:0;isolation:auto;mix-blend-mode:normal;fill:#2e3434;fill-opacity:1;marker:none"
+ font-weight="400"
+ font-family="sans-serif"
+ overflow="visible"
+ id="path7632"
+ sodipodi:nodetypes="sssssccccc" />
+ <path
+ d="m 3.9843754,8.0156258 c -2.2202112,0 -4.0312504,1.8110392 -4.0312504,4.0312512 0,2.22021 1.8110392,4.03125 4.0312504,4.03125 2.2202112,0 4.0312504,-1.81104 4.0312504,-4.03125 0,-2.220212 -1.8110392,-4.0312512 -4.0312504,-4.0312512 z m 1.556e-4,1.9876582 c 1.1299236,-0.0031 2.0466856,0.913669 2.043592,2.043593 0.00309,1.129922 -0.9136684,2.046686 -2.043592,2.043592 -1.1296515,0.0027 -2.0459873,-0.913942 -2.0428954,-2.043592 -0.00309,-1.129652 0.9132439,-2.0463 2.0428954,-2.043593 z"
+ style="line-height:normal;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;text-transform:none;text-orientation:mixed;shape-padding:0;isolation:auto;mix-blend-mode:normal;fill:#2e3434;fill-opacity:1;stroke:none;stroke-width:1;stroke-opacity:1;marker:none"
+ font-weight="400"
+ font-family="sans-serif"
+ overflow="visible"
+ id="path7634"
+ sodipodi:nodetypes="sssssccccc" />
+ <path
+ d="m 15.904253,12.000002 a 4.0000005,4.0000005 0 0 1 -3.998002,4.000001 4.0000005,4.0000005 0 0 1 -3.9999999,-4.000001 4.0000005,4.0000005 0 0 1 3.9999999,-4.000001 4.0000005,4.0000005 0 0 1 3.998002,4.000001 z"
+ style="fill:#2e3434;fill-opacity:1;stroke-width:1;marker:none"
+ overflow="visible"
+ id="path7636" />
+ <path
+ d="M 6.8125939,12 A 2.8124996,2.8124996 0 0 1 4.0000942,14.8125 2.8124996,2.8124996 0 0 1 1.1884058,12 2.8124996,2.8124996 0 0 1 4.0000942,9.1874996 2.8124996,2.8124996 0 0 1 6.8125939,12 Z"
+ style="opacity:1;fill:#2e3434;fill-opacity:0.5;stroke-width:1;marker:none"
+ overflow="visible"
+ opacity="0.5"
+ id="path7638" />
+ </g>
+ </g>
+ <g
+ id="g21774"
+ inkscape:label="settings applications permissions flatpak apps "
+ transform="translate(-576,-644)">
+ <title
+ id="title21764">org.gnome.Settings-default-apps</title>
+ <g
+ id="g21770"
+ inkscape:label=""
+ style="enable-background:new"
+ transform="translate(428,236)">
+ <title
+ id="title21766">preferences-desktop-apps</title>
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:1;marker:none"
+ id="rect21768"
+ width="16"
+ height="16"
+ x="172.00606"
+ y="488" />
+ </g>
+ <path
+ d="m 607.98828,724.00778 c -0.42969,0 -0.8125,0.27344 -0.94922,0.6836 l -1.44922,4.33984 L 601,729.01562 c -0.98047,-0.004 -1.38282,1.25781 -0.58203,1.82031 l 3.625,2.55469 -1.5,4.28516 c -0.31641,0.90234 0.6875,1.6914 1.49218,1.17187 l 4.00391,-2.59375 3.89453,2.58594 c 0.80078,0.53125 1.81641,-0.25781 1.5,-1.16016 l -1.50391,-4.28906 3.64454,-2.57812 C 616.36328,730.25 615.96875,729.0039 615,729 l -4.66016,-0.0156 -1.40234,-4.28516 c -0.13282,-0.41016 -0.51563,-0.6875 -0.94922,-0.69141 z m 0,0"
+ fill="#2e3436"
+ id="path21755" />
+ </g>
+ <g
+ id="g22104"
+ inkscape:label="settings locale language i18n international"
+ transform="translate(112,-368)"
+ style="enable-background:new">
+ <title
+ id="title22092">org.gnome.Settings-diagnostics</title>
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:1.781;marker:none;enable-background:new"
+ id="rect22094"
+ y="448"
+ x="-68"
+ height="16"
+ width="16" />
+ <path
+ id="path22096"
+ d="m 47.011719,81 c -1.64453,0 -3,1.35547 -3,3 v 6 c 0,1.64453 1.35547,3 3,3 h 0.995252 A 0.99302884,0.99302884 135 0 0 49,92.006971 v -0.01394 A 0.99302884,0.99302884 45 0 0 48.006971,91 h -0.995252 c -0.57031,0 -1,-0.42969 -1,-1 v -6 c 0,-0.57031 0.42969,-1 1,-1 h 3.007812 2.960938 3.007812 c 0.57031,0 1,0.42969 1,1 v 0.01172 A 0.988281,0.988281 45 0 0 57.976562,85 H 58 a 0.988281,0.988281 135 0 0 0.988281,-0.988281 V 84 c 0,-1.64453 -1.35547,-3 -3,-3 h -1 -6.976562 z"
+ transform="translate(-112,368)"
+ sodipodi:nodetypes="ssssccssssccssccssccs"
+ style="fill:#2e3436;fill-opacity:1"
+ inkscape:path-effect="#path-effect38750"
+ inkscape:original-d="m 47.011719,81 c -1.64453,0 -3,1.35547 -3,3 v 6 c 0,1.64453 1.35547,3 3,3 H 49 v -2 h -1.988281 c -0.57031,0 -1,-0.42969 -1,-1 v -6 c 0,-0.57031 0.42969,-1 1,-1 h 3.007812 2.960938 3.007812 c 0.57031,0 1,0.42969 1,1 v 1 h 2 v -1 c 0,-1.64453 -1.35547,-3 -3,-3 h -1 -6.976562 z" />
+ <path
+ d="m -62.98828,462 c -1.10547,0 -2,0.89453 -2,2 h 10 c 0,-1.10547 -0.89453,-2 -2,-2 z m 0,0"
+ fill="#2e3436"
+ id="path22102" />
+ <path
+ id="path22303"
+ style="font-variation-settings:normal;vector-effect:none;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;marker:none;stop-color:#000000"
+ d="m -58.5,452 a 4.5,4.5 0 0 0 -4.5,4.5 4.5,4.5 0 0 0 4.5,4.5 4.5,4.5 0 0 0 2.392578,-0.69336 l 2.400391,2.40039 a 1,1 0 0 0 1.414062,0 1,1 0 0 0 0,-1.41406 l -2.40039,-2.40039 A 4.5,4.5 0 0 0 -54,456.5 4.5,4.5 0 0 0 -58.5,452 Z m 0,2 a 2.5,2.5 0 0 1 2.5,2.5 2.5,2.5 0 0 1 -2.5,2.5 2.5,2.5 0 0 1 -2.5,-2.5 2.5,2.5 0 0 1 2.5,-2.5 z" />
+ </g>
+ <g
+ id="g24911"
+ inkscape:label="settings display monitor layout panel lcd crt tv"
+ transform="translate(132,-368)"
+ style="enable-background:new">
+ <title
+ id="title24901">org.gnome.Settings-display</title>
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:1.781;marker:none;enable-background:new"
+ id="rect24903"
+ y="448"
+ x="-68"
+ height="16"
+ width="16" />
+ <path
+ d="m -56,449 c 1.662,0 3,1.338 3,3 v 6 c 0,1.662 -1.338,3 -3,3 h -8 c -1.662,0 -3,-1.338 -3,-3 v -6 c 0,-1.662 1.338,-3 3,-3 z m 0,2 h -8 c -0.554,0 -1,0.446 -1,1 v 6 c 0,0.554 0.446,1 1,1 h 8 c 0.554,0 1,-0.446 1,-1 v -6 c 0,-0.554 -0.446,-1 -1,-1 z m -4,11 c -5,0 -5,1 -5,1 0,1 1,1 1,1 h 8 c 1,0 1,-1 1,-1 0,0 0,-1 -5,-1 z"
+ style="marker:none"
+ overflow="visible"
+ color="#bebebe"
+ fill="#2e3436"
+ id="path24892" />
+ </g>
+ <g
+ id="g25400"
+ inkscape:label="settings about info"
+ transform="translate(152,-368)"
+ style="enable-background:new">
+ <title
+ id="title25394">org.gnome.Settings-about</title>
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:1.781;marker:none;enable-background:new"
+ id="rect25396"
+ y="448"
+ x="-68"
+ height="16"
+ width="16" />
+ <path
+ d="m -60,448 c -4.421875,0 -8,3.57813 -8,8 0,4.42188 3.578125,8 8,8 4.421875,0 8,-3.57812 8,-8 0,-4.42187 -3.578125,-8 -8,-8 z m 0,3.875 c 0.621094,0 1.125,0.50391 1.125,1.125 0,0.6211 -0.503906,1.125 -1.125,1.125 -0.621094,0 -1.125,-0.5039 -1.125,-1.125 0,-0.62109 0.503906,-1.125 1.125,-1.125 z M -61.523438,455 h 0.02344 2.5 v 4 h 0.5 c 0.277344,0 0.5,0.22266 0.5,0.5 0,0.27735 -0.222656,0.5 -0.5,0.5 h -2.5 v -4 h -0.5 c -0.277344,0 -0.5,-0.22265 -0.5,-0.5 0,-0.26953 0.210938,-0.48828 0.476562,-0.5 z m 0,0"
+ fill="#2e3436"
+ id="path25385" />
+ </g>
+ <g
+ id="g25991"
+ inkscape:label="settings about info"
+ transform="translate(172,-368)"
+ style="enable-background:new">
+ <title
+ id="title25985">org.gnome.Settings-keyboard</title>
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:1.781;marker:none;enable-background:new"
+ id="rect25987"
+ y="448"
+ x="-68"
+ height="16"
+ width="16" />
+ <path
+ d="m -65.5,450 c -1.367188,0 -2.5,1.13281 -2.5,2.5 v 7 c 0,1.36719 1.132812,2.5 2.5,2.5 h 11 c 1.367188,0 2.5,-1.13281 2.5,-2.5 v -7 c 0,-1.36719 -1.132812,-2.5 -2.5,-2.5 z m 0,2 h 1 c 0.277344,0 0.5,0.22266 0.5,0.5 v 1 c 0,0.27734 -0.222656,0.5 -0.5,0.5 h -1 c -0.277344,0 -0.5,-0.22266 -0.5,-0.5 v -1 c 0,-0.24219 0.171875,-0.44531 0.398438,-0.48828 0.03125,-0.008 0.06641,-0.0117 0.101562,-0.0117 z m 3,0 h 1 c 0.277344,0 0.5,0.22266 0.5,0.5 v 1 c 0,0.27734 -0.222656,0.5 -0.5,0.5 h -1 c -0.277344,0 -0.5,-0.22266 -0.5,-0.5 v -1 c 0,-0.27734 0.222656,-0.5 0.5,-0.5 z m 3,0 h 1 c 0.277344,0 0.5,0.22266 0.5,0.5 v 1 c 0,0.27734 -0.222656,0.5 -0.5,0.5 h -1 c -0.277344,0 -0.5,-0.22266 -0.5,-0.5 v -1 c 0,-0.27734 0.222656,-0.5 0.5,-0.5 z m 3,0 h 1 c 0.277344,0 0.5,0.22266 0.5,0.5 v 1 c 0,0.27734 -0.222656,0.5 -0.5,0.5 h -1 c -0.277344,0 -0.5,-0.22266 -0.5,-0.5 v -1 c 0,-0.27734 0.222656,-0.5 0.5,-0.5 z m -8,3 h 1 c 0.277344,0 0.5,0.22266 0.5,0.5 v 1 c 0,0.27734 -0.222656,0.5 -0.5,0.5 h -1 c -0.277344,0 -0.5,-0.22266 -0.5,-0.5 v -1 c 0,-0.27734 0.222656,-0.5 0.5,-0.5 z m 3,0 h 1 c 0.277344,0 0.5,0.22266 0.5,0.5 v 1 c 0,0.27734 -0.222656,0.5 -0.5,0.5 h -1 c -0.277344,0 -0.5,-0.22266 -0.5,-0.5 v -1 c 0,-0.27734 0.222656,-0.5 0.5,-0.5 z m 3,0 h 1 c 0.277344,0 0.5,0.22266 0.5,0.5 v 1 c 0,0.27734 -0.222656,0.5 -0.5,0.5 h -1 c -0.277344,0 -0.5,-0.22266 -0.5,-0.5 v -1 c 0,-0.27734 0.222656,-0.5 0.5,-0.5 z m 3,0 h 1 c 0.277344,0 0.5,0.22266 0.5,0.5 v 1 c 0,0.27734 -0.222656,0.5 -0.5,0.5 h -1 c -0.277344,0 -0.5,-0.22266 -0.5,-0.5 v -1 c 0,-0.27734 0.222656,-0.5 0.5,-0.5 z m -10,3 h 1 c 0.277344,0 0.5,0.22266 0.5,0.5 v 1 c 0,0.27734 -0.222656,0.5 -0.5,0.5 h -1 c -0.277344,0 -0.5,-0.22266 -0.5,-0.5 v -1 c 0,-0.27734 0.222656,-0.5 0.5,-0.5 z m 3,0 h 4 c 0.277344,0 0.5,0.22266 0.5,0.5 v 1 c 0,0.27734 -0.222656,0.5 -0.5,0.5 h -4 c -0.277344,0 -0.5,-0.22266 -0.5,-0.5 v -1 c 0,-0.27734 0.222656,-0.5 0.5,-0.5 z m 6,0 h 1 c 0.277344,0 0.5,0.22266 0.5,0.5 v 1 c 0,0.27734 -0.222656,0.5 -0.5,0.5 h -1 c -0.277344,0 -0.5,-0.22266 -0.5,-0.5 v -1 c 0,-0.27734 0.222656,-0.5 0.5,-0.5 z m 0,0"
+ fill="#2e3436"
+ id="path25976" />
+ </g>
+ <g
+ id="g33839"
+ inkscape:label="settings about geolocation geo gps location tracking"
+ transform="translate(192,-368)"
+ style="enable-background:new">
+ <title
+ id="title33833">org.gnome.Settings-location</title>
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:1.781;marker:none;enable-background:new"
+ id="rect33835"
+ y="448"
+ x="-68"
+ height="16"
+ width="16" />
+ <path
+ d="m -60,449 a 5,5 0 0 0 -5,5 c 0,0.172 0.014,0.332 0.031,0.5 0.014,0.167 0.036,0.336 0.063,0.5 0.572,3.513 2.906,6.003 4.906,8.003 2,-2 4.334,-4.489 4.906,-8.003 0.027,-0.164 0.05,-0.333 0.063,-0.5 0.017,-0.168 0.031,-0.328 0.031,-0.5 a 5,5 0 0 0 -5,-5 z m 0,3 a 2,2 0 1 1 0,4 2,2 0 0 1 0,-4 z"
+ style="isolation:auto;mix-blend-mode:normal;marker:none"
+ color="#000000"
+ overflow="visible"
+ fill="#2e3436"
+ id="path33921" />
+ </g>
+ <g
+ transform="translate(22,-318)"
+ inkscape:label="file browser manager folders data personal"
+ id="g14600-21-3"
+ style="enable-background:new">
+ <title
+ id="title83763">org.gnome.Settings-file-history</title>
+ <path
+ id="path76916"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;enable-background:accumulate"
+ d="m 644,720 c -1.6447,0 -3,1.3553 -3,3 v 9 c 0,1.6447 1.3553,3 3,3 h 8 c 1.6447,0 3,-1.3553 3,-3 v -9 c 0,-1.6447 -1.3553,-3 -3,-3 z m 0,2 h 8 c 0.5713,0 1,0.4287 1,1 v 4 h -10 v -4 c 0,-0.5713 0.4287,-1 1,-1 z m 2.46484,1.42969 c -0.0192,10e-4 -0.0391,0.004 -0.0586,0.008 -0.0208,-10e-4 -0.0417,-10e-4 -0.0625,0 -0.21416,0.0702 -0.35495,0.27491 -0.34375,0.5 V 724 c 0,0.54535 0.45465,1 1,1 h 2 c 0.54535,0 1,-0.45465 1,-1 v -0.0625 c 0.01,-0.67616 -1.01,-0.67616 -1,0 V 724 h -2 v -0.0625 c 0.005,-0.29749 -0.24671,-0.52907 -0.53516,-0.50781 z M 643,728 h 10 v 4 c 0,0.5713 -0.4287,1 -1,1 h -8 c -0.5713,0 -1,-0.4287 -1,-1 z m 3.46484,1.42969 c -0.0192,10e-4 -0.0391,0.004 -0.0586,0.008 -0.0208,-10e-4 -0.0417,-10e-4 -0.0625,0 -0.21416,0.0702 -0.35495,0.27491 -0.34375,0.5 V 730 c 0,0.54535 0.45465,1 1,1 h 2 c 0.54535,0 1,-0.45465 1,-1 v -0.0625 c 0.01,-0.67616 -1.01,-0.67616 -1,0 V 730 h -2 v -0.0625 c 0.005,-0.29749 -0.24671,-0.52907 -0.53516,-0.50781 z"
+ transform="translate(-518,-322)"
+ sodipodi:nodetypes="ssssssssssssccssccccsssscccccscssssscscccsssscccccssc" />
+ <rect
+ style="fill:none;stroke:none"
+ id="rect3620-8-8-0"
+ width="16"
+ height="16"
+ x="122.0002"
+ y="398"
+ rx="0"
+ ry="0" />
+ </g>
+ <g
+ transform="translate(42,-318)"
+ inkscape:label="file browser manager folders data personal"
+ id="g34396"
+ style="enable-background:new">
+ <title
+ id="title34390">org.gnome.Settings-screen-lock</title>
+ <rect
+ style="fill:none;stroke:none"
+ id="rect34394"
+ width="16"
+ height="16"
+ x="122.0002"
+ y="398"
+ rx="0"
+ ry="0" />
+ <path
+ d="m 130,399 c -2.19922,0 -4,1.80078 -4,4 v 2 c -1.10937,0 -2,0.89062 -2,2 v 5 c 0,0.55469 0.44531,1 1,1 h 10 c 0.55469,0 1,-0.44531 1,-1 v -5 c 0,-1.10938 -0.89062,-2 -2,-2 v -2 c 0,-2.19922 -1.80078,-4 -4,-4 z m 0,2 c 1.125,0 2,0.875 2,2 v 2 h -4 v -2 c 0,-1.125 0.875,-2 2,-2 z m 0,0"
+ fill="#2e3436"
+ id="path34478" />
+ </g>
+ <g
+ id="g34642"
+ inkscape:label="settings mic mike microphone volume"
+ transform="translate(-576,-624)">
+ <title
+ id="title34632">org.gnome.Settings-microphone</title>
+ <g
+ id="g34638"
+ inkscape:label=""
+ style="enable-background:new"
+ transform="translate(428,236)">
+ <title
+ id="title34634">preferences-desktop-apps</title>
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:1;marker:none"
+ id="rect34636"
+ width="16"
+ height="16"
+ x="172.00606"
+ y="488" />
+ </g>
+ <path
+ d="m 608,724 c -1.662,0 -3,1.338 -3,3 v 5 c 0,1.662 1.338,3 3,3 1.662,0 3,-1.338 3,-3 v -5 c 0,-1.662 -1.338,-3 -3,-3 z m -6,6 v 2.00977 c 0,2.96574 2.16538,5.4238 5,5.90039 V 740 h 2 v -2.08984 c 2.83462,-0.47659 5,-2.93465 5,-5.90039 V 730 h -1.5 v 2.00977 c 0,2.50009 -1.99331,4.49023 -4.5,4.49023 -2.50669,0 -4.5,-1.99014 -4.5,-4.49023 V 730 Z"
+ style="line-height:normal;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;text-transform:none;text-orientation:mixed;white-space:normal;shape-padding:0;isolation:auto;mix-blend-mode:normal;solid-color:#000000;solid-opacity:1"
+ color="#000000"
+ font-weight="400"
+ font-family="sans-serif"
+ overflow="visible"
+ fill="#2e3436"
+ id="path34724" />
+ </g>
+ <g
+ id="g35045"
+ inkscape:label="settings mouse input"
+ transform="translate(-556,-624)">
+ <title
+ id="title35035">org.gnome.Settings-mouse</title>
+ <g
+ id="g35041"
+ inkscape:label=""
+ style="enable-background:new"
+ transform="translate(428,236)">
+ <title
+ id="title35037">preferences-desktop-apps</title>
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:1;marker:none"
+ id="rect35039"
+ width="16"
+ height="16"
+ x="172.00606"
+ y="488" />
+ </g>
+ <path
+ d="m 607.03125,724 c -2.75391,0 -5,2.24609 -5,5 v 6 c 0,2.75391 2.24609,5 5,5 H 609 c 2.75391,0 5,-2.24609 5,-5 v -6 c 0,-2.75391 -2.24609,-5 -5,-5 z m 0,2 H 609 c 1.67969,0 3,1.32031 3,3 v 6 c 0,1.67969 -1.32031,3 -3,3 h -1.96875 c -1.67969,0 -3,-1.32031 -3,-3 v -6 c 0,-1.67969 1.32031,-3 3,-3 z M 608,727 c -0.55469,0 -1,0.44531 -1,1 v 2 c 0,0.55469 0.44531,1 1,1 0.55469,0 1,-0.44531 1,-1 v -2 c 0,-0.55469 -0.44531,-1 -1,-1 z m 0,0"
+ fill="#2e3436"
+ id="path35127" />
+ </g>
+ <g
+ id="g35460"
+ inkscape:label="settings network wifi ethernet workgroup"
+ transform="translate(-536,-624)">
+ <title
+ id="title35450">org.gnome.Settings-network</title>
+ <g
+ id="g35456"
+ inkscape:label=""
+ style="enable-background:new"
+ transform="translate(428,236)">
+ <title
+ id="title35452">preferences-desktop-apps</title>
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:1;marker:none"
+ id="rect35454"
+ width="16"
+ height="16"
+ x="172.00606"
+ y="488" />
+ </g>
+ <g
+ fill="#2e3436"
+ id="g35546"
+ transform="translate(600,724)">
+ <path
+ d="M 3.75,0.00390625 C 2.796875,0.0078125 2,0.804688 2,1.753906 V 7.25 C 2,8.203125 2.796875,9 3.75,9 H 4.5 C 4.5,9 5,9.007812 5,9.507812 5,10 4.5,10 4.5,10 H 4 v 1.992188 h 8 v -2 H 11.5 C 11.5,9.992188 11,10 11,9.5 11,9 11.5,8.992188 11.5,8.992188 h 0.75 c 0.953125,0 1.75,-0.796876 1.75,-1.75 V 1.75 C 14,0.796875 13.203125,0 12.25,0 Z M 4,2.003906 12,2 V 6.992188 L 4,7 Z m 0,0"
+ id="path35542" />
+ <path
+ d="M 6.96875,10.003906 7,14 H 1.5 C 1.222656,14 1,14.222656 1,14.5 v 1 C 1,15.777344 1.222656,16 1.5,16 h 13 c 0.277344,0 0.5,-0.222656 0.5,-0.5 v -1 C 15,14.222656 14.777344,14 14.5,14 H 9 v -4 z m 0,0"
+ fill-rule="evenodd"
+ id="path35544" />
+ </g>
+ </g>
+ <g
+ id="g35901"
+ inkscape:label="settings printers cups magic sorcery"
+ transform="translate(-516,-624)">
+ <title
+ id="title35887">org.gnome.Settings-printers</title>
+ <g
+ id="g35893"
+ inkscape:label=""
+ style="enable-background:new"
+ transform="translate(428,236)">
+ <title
+ id="title35889">preferences-desktop-apps</title>
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:1;marker:none"
+ id="rect35891"
+ width="16"
+ height="16"
+ x="172.00606"
+ y="488" />
+ </g>
+ <g
+ fill="#2e3436"
+ id="g35989"
+ transform="translate(600,724)">
+ <path
+ d="m 4,2 v 1 h 8 V 2 C 12,1.449219 11.550781,1 11,1 H 5 C 4.449219,1 4,1.449219 4,2 Z m 0,0"
+ id="path35983" />
+ <path
+ d="M 4,8 C 2.910156,8 2,8.910156 2,10 v 3 c 0,1.089844 0.910156,2 2,2 h 8 c 1.089844,0 2,-0.910156 2,-2 V 10 C 14,8.910156 13.089844,8 12,8 Z m 0,2 h 8 v 3 H 4 Z m 0,0"
+ id="path35985" />
+ <path
+ d="M 2,4 C 0.890625,4 0,4.890625 0,6 v 4 c 0,1.109375 0.890625,2 2,2 H 3 V 10 C 3,9.445312 3.445312,9 4,9 h 8 c 0.554688,0 1,0.445312 1,1 v 2 h 1 c 1.109375,0 2,-0.890625 2,-2 V 6 C 16,4.890625 15.109375,4 14,4 Z m 0,0"
+ id="path35987" />
+ </g>
+ </g>
+ <g
+ id="g36539"
+ inkscape:label="settings usb thumbdrive flash memory removable media"
+ transform="translate(-496,-624)">
+ <title
+ id="title36523">org.gnome.Settings-removable-media</title>
+ <g
+ id="g36529"
+ inkscape:label=""
+ style="enable-background:new"
+ transform="translate(428,236)">
+ <title
+ id="title36525">preferences-desktop-apps</title>
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:1;marker:none"
+ id="rect36527"
+ width="16"
+ height="16"
+ x="172.00606"
+ y="488" />
+ </g>
+ <path
+ d="m 612,730 0,5 a 4,4 135 0 1 -4,4 4,4 45 0 1 -4,-4 v -5 a 1,1 135 0 1 1,-1 h 6 a 1,1 45 0 1 1,1 z m -7,-5.5 v 3.5 h 6 v -3.5 a 0.5,0.5 45 0 0 -0.5,-0.5 h -5 a 0.5,0.5 135 0 0 -0.5,0.5 z m 1,0.5 h 1 v 1 h -1 z m 3,0 h 1 v 1 h -1 z"
+ fill="#474747"
+ id="path36621"
+ sodipodi:nodetypes="cccccccccccccccccccc"
+ inkscape:path-effect="#path-effect36801"
+ inkscape:original-d="m 612,729 v 10 h -8 v -10 z m -7,-5 v 4 h 6 v -4 z m 1,1 h 1 v 1 h -1 z m 3,0 h 1 v 1 h -1 z" />
+ </g>
+ <g
+ id="g38356"
+ inkscape:label="settings sharing remote drive file smb ssh remote desktop"
+ transform="translate(-476,-624)">
+ <title
+ id="title38346">org.gnome.Settings-sharing</title>
+ <g
+ id="g38352"
+ inkscape:label=""
+ style="enable-background:new"
+ transform="translate(428,236)">
+ <title
+ id="title38348">preferences-desktop-apps</title>
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:1;marker:none"
+ id="rect38350"
+ width="16"
+ height="16"
+ x="172.00606"
+ y="488" />
+ </g>
+ <g
+ fill="#2e3436"
+ id="g38450"
+ transform="translate(599.96875,724.00391)">
+ <path
+ d="m 6.03125,7.996094 c 0,1.65625 -1.34375,3 -3,3 -1.65625,0 -3,-1.34375 -3,-3 0,-1.65625 1.34375,-3 3,-3 1.65625,0 3,1.34375 3,3 z m 0,0"
+ id="path38442" />
+ <path
+ d="M 12.585938,2.101562 0.796875,7.996094 12.585938,13.890625 13.480469,12.101562 5.269531,7.996094 13.480469,3.890625 Z m 0,0"
+ id="path38444" />
+ <path
+ d="m 16.03125,2.996094 c 0,1.65625 -1.34375,3 -3,3 -1.65625,0 -3,-1.34375 -3,-3 0,-1.65625 1.34375,-3.00000025 3,-3.00000025 1.65625,0 3,1.34375025 3,3.00000025 z m 0,0"
+ id="path38446" />
+ <path
+ d="m 16.03125,12.996094 c 0,1.65625 -1.34375,3 -3,3 -1.65625,0 -3,-1.34375 -3,-3 0,-1.65625 1.34375,-3 3,-3 1.65625,0 3,1.34375 3,3 z m 0,0"
+ id="path38448" />
+ </g>
+ </g>
+ <g
+ id="g39233"
+ inkscape:label="settings thunderbolt usb-3"
+ transform="translate(-456,-624)">
+ <title
+ id="title39215">org.gnome.Settings-thunderbolt</title>
+ <g
+ id="g39221"
+ inkscape:label=""
+ style="enable-background:new"
+ transform="translate(428,236)">
+ <title
+ id="title39217">preferences-desktop-apps</title>
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:1;marker:none"
+ id="rect39219"
+ width="16"
+ height="16"
+ x="172.00606"
+ y="488" />
+ </g>
+ <path
+ d="M 607.80469,730 H 611.5 l -4.33984,6.24219 1.67188,0.17187 -4.1836,3.57813 1.96485,-1.03516 c 0.3164,0.0391 1.00781,0.0625 1.33593,0.0625 3.86719,0 7.00391,-3.13672 7.00391,-7.00391 -0.0156,-2.46875 -1.28125,-5.00781 -4.00391,-6.32812 l 0.16016,-1.67969 z m -6.85156,2.01562 c 0,2.625 1.44141,4.91797 3.58203,6.11329 l 0.31641,-3.71875 1.01172,1.20312 L 607.66797,732 h -3.71484 l 3.16016,-6.93359 c -3.46875,0.41406 -6.16016,3.36718 -6.16016,6.94921"
+ fill="#2e3434"
+ id="path39315" />
+ </g>
+ <g
+ id="g296"
+ inkscape:label="settings tablet wacom xp=pen stylus digitizer"
+ transform="translate(-436,-624)">
+ <title
+ id="title286">org.gnome.Settings-wacom</title>
+ <g
+ id="g292"
+ inkscape:label=""
+ style="enable-background:new"
+ transform="translate(428,236)">
+ <title
+ id="title288">preferences-desktop-apps</title>
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:1;marker:none"
+ id="rect290"
+ width="16"
+ height="16"
+ x="172.00606"
+ y="488" />
+ </g>
+ <path
+ d="m 608.00001,724 v 1.5 c 0,0.13281 -0.0547,0.26172 -0.14453,0.35547 -0.0937,0.0937 -0.21875,0.14453 -0.34766,0.14453 h -3.01172 c -0.53515,0 -1.03125,0.28906 -1.29687,0.75 -0.26563,0.46484 -0.26563,1.03516 0,1.5 0.26562,0.46094 0.76172,0.75 1.29687,0.75 h 3.00782 c 0.17968,0 0.33984,0.0937 0.42968,0.25 0.043,0.0742 0.0664,0.16406 0.0664,0.25 v 0.5 h -5 c -1.64453,0 -3,1.35547 -3,3 v 4 c 0,1.64453 1.35547,3 3,3 h 10 c 1.64453,0 3,-1.35547 3,-3 v -4 c 0,-0.86719 -0.37891,-1.64844 -0.97266,-2.19922 l -1.41015,1.40234 c 0.23438,0.17969 0.38282,0.46094 0.38282,0.79688 v 3 c 0,0.55469 -0.44531,1 -1,1 h -10 c -0.55469,0 -1,-0.44531 -1,-1 v -3 c 0,-0.57031 0.5,-1 1,-1 h 5.19141 l 1.99218,-2 h -1.18359 v -0.5 c 0,-0.25781 -0.0664,-0.51563 -0.19922,-0.75 -0.26562,-0.46094 -0.76172,-0.75 -1.29687,-0.75 h -3.00782 c -0.17968,0 -0.33984,-0.0937 -0.42968,-0.25 -0.0899,-0.15234 -0.0899,-0.34766 0,-0.5 0.0898,-0.15625 0.25,-0.25 0.42968,-0.25 h 3.01172 c 0.39844,0 0.77735,-0.16016 1.05469,-0.44141 0.28125,-0.28125 0.4375,-0.66015 0.4375,-1.05859 V 724 Z m 7,3 c -0.26563,0 -0.51953,0.10547 -0.70313,0.29297 h -0.004 l -6.29287,6.3164 V 735 h 1.39062 l 6.31641,-6.29297 -0.004,-0.004 c 0.1915,-0.1835 0.29697,-0.43741 0.29697,-0.70303 0,-0.55078 -0.44922,-1 -1,-1 z m 0,0"
+ fill="#2e3436"
+ id="path582" />
+ </g>
+ <g
+ id="g806"
+ inkscape:label="settings tablet wacom xp=pen stylus digitizer"
+ transform="translate(-576,-604)">
+ <title
+ id="title796">org.gnome.Settings-mobile-network</title>
+ <g
+ id="g802"
+ inkscape:label=""
+ style="enable-background:new"
+ transform="translate(428,236)">
+ <title
+ id="title798">preferences-desktop-apps</title>
+ <rect
+ style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:1;marker:none"
+ id="rect800"
+ width="16"
+ height="16"
+ x="172.00606"
+ y="488" />
+ </g>
+ <path
+ d="m 614,725 c -0.55469,0 -1,0.44531 -1,1 v 12 c 0,0.55469 0.44531,1 1,1 h 1 c 0.55469,0 1,-0.44531 1,-1 v -12 c 0,-0.55469 -0.44531,-1 -1,-1 z m -4,3 c -0.55469,0 -1,0.44531 -1,1 v 9 c 0,0.55469 0.44531,1 1,1 h 1 c 0.55469,0 1,-0.44531 1,-1 v -9 c 0,-0.55469 -0.44531,-1 -1,-1 z m -4,3 c -0.55469,0 -1,0.44531 -1,1 v 6 c 0,0.55469 0.44531,1 1,1 h 1 c 0.55469,0 1,-0.44531 1,-1 v -6 c 0,-0.55469 -0.44531,-1 -1,-1 z m -4,3 c -0.55469,0 -1,0.44531 -1,1 v 3 c 0,0.55469 0.44531,1 1,1 h 1 c 0.55469,0 1,-0.44531 1,-1 v -3 c 0,-0.55469 -0.44531,-1 -1,-1 z m 0,0"
+ fill="#2e3436"
+ id="path888" />
+ </g>
+ </g>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:125%;font-family:Cantarell;-inkscape-font-specification:Cantarell;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;opacity:1;fill:#2e3436;fill-opacity:1;stroke:none"
+ x="21"
+ y="-44"
+ id="text4574"><tspan
+ sodipodi:role="line"
+ id="tspan4576"
+ x="21"
+ y="-44"
+ style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-family:Cantarell;-inkscape-font-specification:'Cantarell Ultra-Bold'">Settings Icons</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:125%;font-family:Cantarell;-inkscape-font-specification:Cantarell;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;opacity:1;fill:#2e3436;fill-opacity:1;stroke:none"
+ x="23"
+ y="-8"
+ id="text4526"><tspan
+ sodipodi:role="line"
+ id="tspan4524"
+ x="23"
+ y="-8"
+ style="font-size:13.3333px">Export using Symbolic Preview.</tspan></text>
+</svg>
diff --git a/panels/power/battery-levels.css b/panels/power/battery-levels.css
new file mode 100644
index 0000000..f8c7330
--- /dev/null
+++ b/panels/power/battery-levels.css
@@ -0,0 +1,14 @@
+levelbar block.warning-battery-offset {
+ background-color: @error_color;
+ border-color: @error_color;
+}
+
+levelbar block.low-battery-offset {
+ background-color: @warning_color;
+ border-color: @warning_color;
+}
+
+levelbar block.high-battery-offset {
+ background-color: @success_color;
+ border-color: @success_color;
+}
diff --git a/panels/power/cc-battery-row.c b/panels/power/cc-battery-row.c
new file mode 100644
index 0000000..fe80622
--- /dev/null
+++ b/panels/power/cc-battery-row.c
@@ -0,0 +1,357 @@
+/* cc-brightness-scale.c
+ *
+ * Copyright (C) 2010 Red Hat, Inc
+ * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
+ * Copyright (C) 2010,2015 Richard Hughes <richard@hughsie.com>
+ * Copyright (C) 2020 System76, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <glib/gi18n.h>
+
+#include "cc-battery-row.h"
+
+struct _CcBatteryRow {
+ GtkListBoxRow parent_instance;
+
+ GtkBox *battery_box;
+ GtkLabel *details_label;
+ GtkImage *icon;
+ GtkLevelBar *levelbar;
+ GtkLabel *name_label;
+ GtkLabel *percentage_label;
+ GtkBox *primary_bottom_box;
+ GtkLabel *primary_percentage_label;
+
+ UpDeviceKind kind;
+ gboolean primary;
+};
+
+G_DEFINE_TYPE (CcBatteryRow, cc_battery_row, GTK_TYPE_LIST_BOX_ROW)
+
+static void
+cc_battery_row_class_init (CcBatteryRowClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/power/cc-battery-row.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, battery_box);
+ gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, details_label);
+ gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, icon);
+ gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, levelbar);
+ gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, name_label);
+ gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, percentage_label);
+ gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, primary_bottom_box);
+ gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, primary_percentage_label);
+}
+
+static void
+cc_battery_row_init (CcBatteryRow *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static gchar *
+get_timestring (guint64 time_secs)
+{
+ gchar* timestring = NULL;
+ gint hours;
+ gint minutes;
+
+ /* Add 0.5 to do rounding */
+ minutes = (int) ( ( time_secs / 60.0 ) + 0.5 );
+
+ if (minutes == 0)
+ return g_strdup (_("Unknown time"));
+
+ if (minutes < 60)
+ return timestring = g_strdup_printf (ngettext ("%i minute",
+ "%i minutes",
+ minutes), minutes);
+
+ hours = minutes / 60;
+ minutes = minutes % 60;
+
+ if (minutes == 0)
+ return timestring = g_strdup_printf (ngettext (
+ "%i hour",
+ "%i hours",
+ hours), hours);
+
+ /* TRANSLATOR: "%i %s %i %s" are "%i hours %i minutes"
+ * Swap order with "%2$s %2$i %1$s %1$i if needed */
+ return timestring = g_strdup_printf (_("%i %s %i %s"),
+ hours, ngettext ("hour", "hours", hours),
+ minutes, ngettext ("minute", "minutes", minutes));
+}
+
+static gchar *
+get_details_string (gdouble percentage, UpDeviceState state, guint64 time)
+{
+ g_autofree gchar *details = NULL;
+
+ if (time > 0)
+ {
+ g_autofree gchar *time_string = NULL;
+
+ time_string = get_timestring (time);
+ switch (state)
+ {
+ case UP_DEVICE_STATE_CHARGING:
+ /* TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" */
+ details = g_strdup_printf (_("%s until fully charged"), time_string);
+ break;
+ case UP_DEVICE_STATE_DISCHARGING:
+ case UP_DEVICE_STATE_PENDING_DISCHARGE:
+ if (percentage < 20)
+ {
+ /* TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" */
+ details = g_strdup_printf (_("Caution: %s remaining"), time_string);
+ }
+ else
+ {
+ /* TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" */
+ details = g_strdup_printf (_("%s remaining"), time_string);
+ }
+ break;
+ case UP_DEVICE_STATE_FULLY_CHARGED:
+ /* TRANSLATORS: primary battery */
+ details = g_strdup (_("Fully charged"));
+ break;
+ case UP_DEVICE_STATE_PENDING_CHARGE:
+ /* TRANSLATORS: primary battery */
+ details = g_strdup (_("Not charging"));
+ break;
+ case UP_DEVICE_STATE_EMPTY:
+ /* TRANSLATORS: primary battery */
+ details = g_strdup (_("Empty"));
+ break;
+ default:
+ details = g_strdup_printf ("error: %s", up_device_state_to_string (state));
+ break;
+ }
+ }
+ else
+ {
+ switch (state)
+ {
+ case UP_DEVICE_STATE_CHARGING:
+ /* TRANSLATORS: primary battery */
+ details = g_strdup (_("Charging"));
+ break;
+ case UP_DEVICE_STATE_DISCHARGING:
+ case UP_DEVICE_STATE_PENDING_DISCHARGE:
+ /* TRANSLATORS: primary battery */
+ details = g_strdup (_("Discharging"));
+ break;
+ case UP_DEVICE_STATE_FULLY_CHARGED:
+ /* TRANSLATORS: primary battery */
+ details = g_strdup (_("Fully charged"));
+ break;
+ case UP_DEVICE_STATE_PENDING_CHARGE:
+ /* TRANSLATORS: primary battery */
+ details = g_strdup (_("Not charging"));
+ break;
+ case UP_DEVICE_STATE_EMPTY:
+ /* TRANSLATORS: primary battery */
+ details = g_strdup (_("Empty"));
+ break;
+ default:
+ details = g_strdup_printf ("error: %s",
+ up_device_state_to_string (state));
+ break;
+ }
+ }
+
+ return g_steal_pointer (&details);
+}
+
+static const char *
+kind_to_description (UpDeviceKind kind)
+{
+ switch (kind)
+ {
+ case UP_DEVICE_KIND_MOUSE:
+ /* TRANSLATORS: secondary battery */
+ return N_("Wireless mouse");
+ case UP_DEVICE_KIND_KEYBOARD:
+ /* TRANSLATORS: secondary battery */
+ return N_("Wireless keyboard");
+ case UP_DEVICE_KIND_UPS:
+ /* TRANSLATORS: secondary battery */
+ return N_("Uninterruptible power supply");
+ case UP_DEVICE_KIND_PDA:
+ /* TRANSLATORS: secondary battery */
+ return N_("Personal digital assistant");
+ case UP_DEVICE_KIND_PHONE:
+ /* TRANSLATORS: secondary battery */
+ return N_("Cellphone");
+ case UP_DEVICE_KIND_MEDIA_PLAYER:
+ /* TRANSLATORS: secondary battery */
+ return N_("Media player");
+ case UP_DEVICE_KIND_TABLET:
+ /* TRANSLATORS: secondary battery */
+ return N_("Tablet");
+ case UP_DEVICE_KIND_COMPUTER:
+ /* TRANSLATORS: secondary battery */
+ return N_("Computer");
+ case UP_DEVICE_KIND_GAMING_INPUT:
+ /* TRANSLATORS: secondary battery */
+ return N_("Gaming input device");
+ default:
+ /* TRANSLATORS: secondary battery, misc */
+ return N_("Battery");
+ }
+
+ g_assert_not_reached ();
+}
+
+CcBatteryRow*
+cc_battery_row_new (UpDevice *device,
+ gboolean primary)
+{
+ g_autofree gchar *details = NULL;
+ gdouble percentage;
+ UpDeviceKind kind;
+ UpDeviceState state;
+ g_autofree gchar *s = NULL;
+ g_autofree gchar *icon_name = NULL;
+ const gchar *name;
+ CcBatteryRow *self;
+ guint64 time_empty, time_full, time;
+ gdouble energy_full, energy_rate;
+ gboolean is_kind_battery;
+ UpDeviceLevel battery_level;
+
+ self = g_object_new (CC_TYPE_BATTERY_ROW, NULL);
+
+ g_object_get (device,
+ "kind", &kind,
+ "state", &state,
+ "model", &name,
+ "percentage", &percentage,
+ "icon-name", &icon_name,
+ "time-to-empty", &time_empty,
+ "time-to-full", &time_full,
+ "energy-full", &energy_full,
+ "energy-rate", &energy_rate,
+ "battery-level", &battery_level,
+ NULL);
+ if (state == UP_DEVICE_STATE_DISCHARGING)
+ time = time_empty;
+ else
+ time = time_full;
+
+ is_kind_battery = (kind == UP_DEVICE_KIND_BATTERY || kind == UP_DEVICE_KIND_UPS);
+
+ /* Name label */
+ if (is_kind_battery)
+ {
+ if (g_object_get_data (G_OBJECT (device), "is-main-battery") != NULL)
+ name = C_("Battery name", "Main");
+ else
+ name = C_("Battery name", "Extra");
+ }
+ else if (name == NULL || name[0] == '\0')
+ {
+ name = _(kind_to_description (kind));
+ }
+ gtk_label_set_text (self->name_label, name);
+
+ /* Icon */
+ if (is_kind_battery && icon_name != NULL && icon_name[0] != '\0')
+ {
+ gtk_image_set_from_icon_name (self->icon, icon_name);
+ gtk_widget_show (GTK_WIDGET (self->icon));
+ }
+ else
+ gtk_widget_hide (GTK_WIDGET (self->icon));
+
+ /* Percentage label */
+ if (battery_level == UP_DEVICE_LEVEL_NONE)
+ {
+ s = g_strdup_printf ("%d%%", (int)percentage);
+ gtk_label_set_text (self->percentage_label, s);
+ gtk_label_set_text (self->primary_percentage_label, s);
+ }
+
+ /* Level bar */
+ gtk_level_bar_set_value (self->levelbar, percentage / 100.0);
+
+ /* Details label (primary only) */
+ details = get_details_string (percentage, state, time);
+ gtk_label_set_text (self->details_label, details);
+
+ /* Handle "primary" row differently */
+ gtk_widget_set_visible (GTK_WIDGET (self->battery_box), !primary);
+ gtk_widget_set_visible (GTK_WIDGET (self->percentage_label), !primary);
+ gtk_widget_set_visible (GTK_WIDGET (self->primary_bottom_box), primary);
+ /*
+ gtk_accessible_update_relation (GTK_ACCESSIBLE (self->levelbar),
+ GTK_ACCESSIBLE_RELATION_LABELLED_BY, primary ? self->primary_percentage_label
+ : self->percentage_label,
+ NULL);
+ */
+
+ self->kind = kind;
+ self->primary = primary;
+
+ return self;
+}
+
+
+
+void
+cc_battery_row_set_level_sizegroup (CcBatteryRow *self,
+ GtkSizeGroup *sizegroup)
+{
+ gtk_size_group_add_widget (sizegroup, GTK_WIDGET (self->levelbar));
+}
+
+void
+cc_battery_row_set_row_sizegroup (CcBatteryRow *self,
+ GtkSizeGroup *sizegroup)
+{
+ gtk_size_group_add_widget (sizegroup, GTK_WIDGET (self));
+}
+
+void
+cc_battery_row_set_charge_sizegroup (CcBatteryRow *self,
+ GtkSizeGroup *sizegroup)
+{
+ gtk_size_group_add_widget (sizegroup, GTK_WIDGET (self->percentage_label));
+}
+
+void
+cc_battery_row_set_battery_sizegroup (CcBatteryRow *self,
+ GtkSizeGroup *sizegroup)
+{
+ gtk_size_group_add_widget (sizegroup, GTK_WIDGET (self->battery_box));
+}
+
+gboolean
+cc_battery_row_get_primary (CcBatteryRow *self)
+{
+ return self->primary;
+}
+
+UpDeviceKind
+cc_battery_row_get_kind (CcBatteryRow *self)
+{
+ return self->kind;
+}
diff --git a/panels/power/cc-battery-row.h b/panels/power/cc-battery-row.h
new file mode 100644
index 0000000..8a5b5fa
--- /dev/null
+++ b/panels/power/cc-battery-row.h
@@ -0,0 +1,49 @@
+/* cc-brightness-scale.h
+ *
+ * Copyright (C) 2020 System76, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <libupower-glib/upower.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_BATTERY_ROW (cc_battery_row_get_type())
+G_DECLARE_FINAL_TYPE (CcBatteryRow, cc_battery_row, CC, BATTERY_ROW, GtkListBoxRow)
+
+CcBatteryRow* cc_battery_row_new (UpDevice *device,
+ gboolean primary);
+
+void cc_battery_row_set_level_sizegroup (CcBatteryRow *row,
+ GtkSizeGroup *sizegroup);
+
+void cc_battery_row_set_row_sizegroup (CcBatteryRow *row,
+ GtkSizeGroup *sizegroup);
+
+void cc_battery_row_set_charge_sizegroup (CcBatteryRow *row,
+ GtkSizeGroup *sizegroup);
+
+void cc_battery_row_set_battery_sizegroup (CcBatteryRow *row,
+ GtkSizeGroup *sizegroup);
+
+gboolean cc_battery_row_get_primary (CcBatteryRow *row);
+UpDeviceKind cc_battery_row_get_kind (CcBatteryRow *row);
+
+G_END_DECLS \ No newline at end of file
diff --git a/panels/power/cc-battery-row.ui b/panels/power/cc-battery-row.ui
new file mode 100644
index 0000000..a99d80f
--- /dev/null
+++ b/panels/power/cc-battery-row.ui
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcBatteryRow" parent="GtkListBoxRow">
+ <property name="selectable">False</property>
+ <property name="activatable">False</property>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="valign">center</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="margin-top">16</property>
+ <property name="margin-bottom">14</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkBox" id="battery_box">
+ <property name="orientation">horizontal</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="name_label">
+ <property name="ellipsize">end</property>
+ <property name="xalign">0</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage" id="icon">
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="percentage_label">
+ <property name="halign">end</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLevelBar" id="levelbar">
+ <property name="hexpand">True</property>
+ <property name="halign">fill</property>
+ <property name="valign">center</property>
+ <offsets>
+ <offset name="warning-battery-offset" value="0.03"/>
+ <offset name="low-battery-offset" value="0.1"/>
+ <offset name="high-battery-offset" value="1.0"/>
+ </offsets>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="primary_bottom_box">
+ <property name="orientation">horizontal</property>
+ <child>
+ <object class="GtkLabel" id="details_label">
+ <property name="hexpand">True</property>
+ <property name="ellipsize">end</property>
+ <property name="xalign">0</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="primary_percentage_label" />
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
+
diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c
new file mode 100644
index 0000000..9fb0bbd
--- /dev/null
+++ b/panels/power/cc-power-panel.c
@@ -0,0 +1,1539 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2010 Red Hat, Inc
+ * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
+ * Copyright (C) 2010,2015 Richard Hughes <richard@hughsie.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+
+#include <libupower-glib/upower.h>
+#include <glib/gi18n.h>
+#include <gnome-settings-daemon/gsd-enums.h>
+#include <gio/gdesktopappinfo.h>
+
+#include "shell/cc-object-storage.h"
+#include "cc-battery-row.h"
+#include "cc-power-profile-row.h"
+#include "cc-power-profile-info-row.h"
+#include "cc-power-panel.h"
+#include "cc-power-resources.h"
+#include "cc-util.h"
+
+struct _CcPowerPanel
+{
+ CcPanel parent_instance;
+
+ GtkListBoxRow *als_row;
+ GtkSwitch *als_switch;
+ GtkDialog *automatic_suspend_dialog;
+ GtkLabel *automatic_suspend_label;
+ GtkListBoxRow *automatic_suspend_row;
+ GtkListBox *battery_listbox;
+ AdwActionRow *battery_percentage_row;
+ GtkSwitch *battery_percentage_switch;
+ GtkSizeGroup *battery_row_sizegroup;
+ AdwPreferencesGroup *battery_section;
+ AdwComboRow *blank_screen_row;
+ GtkListBox *device_listbox;
+ AdwPreferencesGroup *device_section;
+ GtkListBoxRow *dim_screen_row;
+ GtkSwitch *dim_screen_switch;
+ AdwPreferencesGroup *general_section;
+ GtkSizeGroup *level_sizegroup;
+ AdwComboRow *power_button_row;
+ GtkListBox *power_profile_listbox;
+ GtkListBox *power_profile_info_listbox;
+ AdwPreferencesGroup *power_profile_section;
+ AdwActionRow *power_saver_low_battery_row;
+ GtkSwitch *power_saver_low_battery_switch;
+ GtkSizeGroup *row_sizegroup;
+ GtkComboBox *suspend_on_battery_delay_combo;
+ GtkLabel *suspend_on_battery_delay_label;
+ GtkLabel *suspend_on_battery_label;
+ GtkSwitch *suspend_on_battery_switch;
+ GtkComboBox *suspend_on_ac_delay_combo;
+ GtkLabel *suspend_on_ac_label;
+ GtkSwitch *suspend_on_ac_switch;
+
+ GSettings *gsd_settings;
+ GSettings *session_settings;
+ GSettings *interface_settings;
+ UpClient *up_client;
+ GPtrArray *devices;
+ gboolean has_batteries;
+ char *chassis_type;
+
+ GDBusProxy *iio_proxy;
+ guint iio_proxy_watch_id;
+ gboolean has_brightness;
+
+ GDBusProxy *power_profiles_proxy;
+ guint power_profiles_prop_id;
+ CcPowerProfileRow *power_profiles_row[NUM_CC_POWER_PROFILES];
+ gboolean power_profiles_in_update;
+ gboolean has_performance_degraded;
+};
+
+CC_PANEL_REGISTER (CcPowerPanel, cc_power_panel)
+
+enum
+{
+ ACTION_MODEL_TEXT,
+ ACTION_MODEL_VALUE
+};
+
+static const char *
+cc_power_panel_get_help_uri (CcPanel *panel)
+{
+ return "help:gnome-help/power";
+}
+
+static char *
+get_chassis_type (GCancellable *cancellable)
+{
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) inner = NULL;
+ g_autoptr(GVariant) variant = NULL;
+ g_autoptr(GDBusConnection) connection = NULL;
+
+ connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM,
+ cancellable,
+ &error);
+ if (!connection)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("system bus not available: %s", error->message);
+ return NULL;
+ }
+
+ variant = g_dbus_connection_call_sync (connection,
+ "org.freedesktop.hostname1",
+ "/org/freedesktop/hostname1",
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ g_variant_new ("(ss)",
+ "org.freedesktop.hostname1",
+ "Chassis"),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ &error);
+ if (!variant)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_debug ("Failed to get property '%s': %s", "Chassis", error->message);
+ return NULL;
+ }
+
+ g_variant_get (variant, "(v)", &inner);
+ return g_variant_dup_string (inner, NULL);
+}
+
+static void
+load_custom_css (CcPowerPanel *self,
+ const char *path)
+{
+ g_autoptr(GtkCssProvider) provider = NULL;
+
+ /* use custom CSS */
+ provider = gtk_css_provider_new ();
+ gtk_css_provider_load_from_resource (provider, path);
+ gtk_style_context_add_provider_for_display (gdk_display_get_default (),
+ GTK_STYLE_PROVIDER (provider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+}
+
+static void
+add_battery (CcPowerPanel *panel, UpDevice *device, gboolean primary)
+{
+ CcBatteryRow *row = cc_battery_row_new (device, primary);
+ cc_battery_row_set_level_sizegroup (row, panel->level_sizegroup);
+ cc_battery_row_set_row_sizegroup (row, panel->battery_row_sizegroup);
+
+ gtk_list_box_append (panel->battery_listbox, GTK_WIDGET (row));
+ gtk_widget_set_visible (GTK_WIDGET (panel->battery_section), TRUE);
+}
+
+static void
+add_device (CcPowerPanel *self, UpDevice *device)
+{
+ CcBatteryRow *row = cc_battery_row_new (device, FALSE);
+ cc_battery_row_set_level_sizegroup (row, self->level_sizegroup);
+ cc_battery_row_set_row_sizegroup (row, self->row_sizegroup);
+
+ gtk_list_box_append (self->device_listbox, GTK_WIDGET (row));
+ gtk_widget_set_visible (GTK_WIDGET (self->device_section), TRUE);
+}
+
+static void
+empty_listbox (GtkListBox *listbox)
+{
+ GtkWidget *child;
+
+ while ((child = gtk_widget_get_first_child (GTK_WIDGET (listbox))) != NULL)
+ gtk_list_box_remove (listbox, child);
+}
+
+static void
+update_power_saver_low_battery_row_visibility (CcPowerPanel *self)
+{
+ g_autoptr(UpDevice) composite = NULL;
+ UpDeviceKind kind;
+
+ composite = up_client_get_display_device (self->up_client);
+ g_object_get (composite, "kind", &kind, NULL);
+ gtk_widget_set_visible (GTK_WIDGET (self->power_saver_low_battery_row),
+ self->power_profiles_proxy && kind == UP_DEVICE_KIND_BATTERY);
+}
+
+static void
+up_client_changed (CcPowerPanel *self)
+{
+ gint i;
+ UpDeviceKind kind;
+ guint n_batteries;
+ gboolean on_ups;
+ g_autoptr(UpDevice) composite = NULL;
+
+ empty_listbox (self->battery_listbox);
+ gtk_widget_hide (GTK_WIDGET (self->battery_section));
+
+ empty_listbox (self->device_listbox);
+ gtk_widget_hide (GTK_WIDGET (self->device_section));
+
+ on_ups = FALSE;
+ n_batteries = 0;
+ composite = up_client_get_display_device (self->up_client);
+ g_object_get (composite, "kind", &kind, NULL);
+ if (kind == UP_DEVICE_KIND_UPS)
+ {
+ on_ups = TRUE;
+ }
+ else
+ {
+ gboolean is_extra_battery = FALSE;
+
+ /* Count the batteries */
+ for (i = 0; self->devices != NULL && i < self->devices->len; i++)
+ {
+ UpDevice *device = (UpDevice*) g_ptr_array_index (self->devices, i);
+ gboolean is_power_supply = FALSE;
+ g_object_get (device,
+ "kind", &kind,
+ "power-supply", &is_power_supply,
+ NULL);
+ if (kind == UP_DEVICE_KIND_BATTERY &&
+ is_power_supply)
+ {
+ n_batteries++;
+ if (is_extra_battery == FALSE)
+ {
+ is_extra_battery = TRUE;
+ g_object_set_data (G_OBJECT (device), "is-main-battery", GINT_TO_POINTER(TRUE));
+ }
+ }
+ }
+ }
+
+ if (n_batteries > 1)
+ adw_preferences_group_set_title (self->battery_section, _("Batteries"));
+ else
+ adw_preferences_group_set_title (self->battery_section, _("Battery"));
+
+ if (!on_ups && n_batteries > 1)
+ add_battery (self, composite, TRUE);
+
+ for (i = 0; self->devices != NULL && i < self->devices->len; i++)
+ {
+ UpDevice *device = (UpDevice*) g_ptr_array_index (self->devices, i);
+ gboolean is_power_supply = FALSE;
+ g_object_get (device,
+ "kind", &kind,
+ "power-supply", &is_power_supply,
+ NULL);
+ if (kind == UP_DEVICE_KIND_LINE_POWER)
+ {
+ /* do nothing */
+ }
+ else if (kind == UP_DEVICE_KIND_UPS && on_ups)
+ {
+ add_battery (self, device, TRUE);
+ }
+ else if (kind == UP_DEVICE_KIND_BATTERY && is_power_supply && !on_ups && n_batteries == 1)
+ {
+ add_battery (self, device, TRUE);
+ }
+ else if (kind == UP_DEVICE_KIND_BATTERY && is_power_supply)
+ {
+ add_battery (self, device, FALSE);
+ }
+ else
+ {
+ add_device (self, device);
+ }
+ }
+
+ update_power_saver_low_battery_row_visibility (self);
+}
+
+static void
+up_client_device_removed (CcPowerPanel *self,
+ const char *object_path)
+{
+ guint i;
+
+ if (self->devices == NULL)
+ return;
+
+ for (i = 0; i < self->devices->len; i++)
+ {
+ UpDevice *device = g_ptr_array_index (self->devices, i);
+
+ if (g_strcmp0 (object_path, up_device_get_object_path (device)) == 0)
+ {
+ g_ptr_array_remove_index (self->devices, i);
+ break;
+ }
+ }
+
+ up_client_changed (self);
+}
+
+static void
+up_client_device_added (CcPowerPanel *self,
+ UpDevice *device)
+{
+ g_ptr_array_add (self->devices, g_object_ref (device));
+ g_signal_connect_object (G_OBJECT (device), "notify",
+ G_CALLBACK (up_client_changed), self, G_CONNECT_SWAPPED);
+ up_client_changed (self);
+}
+
+static void
+als_switch_changed_cb (CcPowerPanel *self)
+{
+ gboolean enabled;
+ enabled = gtk_switch_get_active (self->als_switch);
+ g_debug ("Setting ALS enabled %s", enabled ? "on" : "off");
+ g_settings_set_boolean (self->gsd_settings, "ambient-enabled", enabled);
+}
+
+static void
+als_enabled_state_changed (CcPowerPanel *self)
+{
+ gboolean enabled;
+ gboolean visible = FALSE;
+
+ if (self->iio_proxy != NULL)
+ {
+ g_autoptr(GVariant) v = g_dbus_proxy_get_cached_property (self->iio_proxy, "HasAmbientLight");
+ if (v != NULL)
+ visible = g_variant_get_boolean (v);
+ }
+
+ if (gtk_widget_get_visible (GTK_WIDGET (self->als_row)) == visible)
+ return;
+
+ enabled = g_settings_get_boolean (self->gsd_settings, "ambient-enabled");
+ g_debug ("ALS enabled: %s", enabled ? "on" : "off");
+ g_signal_handlers_block_by_func (self->als_switch, als_switch_changed_cb, self);
+ gtk_switch_set_active (self->als_switch, enabled);
+ gtk_widget_set_visible (GTK_WIDGET (self->als_row), visible && self->has_brightness);
+ g_signal_handlers_unblock_by_func (self->als_switch, als_switch_changed_cb, self);
+}
+
+static void
+combo_time_changed_cb (CcPowerPanel *self, GtkWidget *widget)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ gint value;
+ gboolean ret;
+ const gchar *key = (const gchar *)g_object_get_data (G_OBJECT(widget), "_gsettings_key");
+
+ /* no selection */
+ ret = gtk_combo_box_get_active_iter (GTK_COMBO_BOX(widget), &iter);
+ if (!ret)
+ return;
+
+ /* get entry */
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX(widget));
+ gtk_tree_model_get (model, &iter,
+ 1, &value,
+ -1);
+
+ /* set both keys */
+ g_settings_set_int (self->gsd_settings, key, value);
+}
+
+static void
+set_value_for_combo (GtkComboBox *combo_box, gint value)
+{
+ GtkTreeIter iter;
+ g_autoptr(GtkTreeIter) insert = NULL;
+ GtkTreeIter new;
+ GtkTreeModel *model;
+ gint value_tmp;
+ gint value_last = 0;
+ g_autofree gchar *text = NULL;
+ gboolean ret;
+
+ /* get entry */
+ model = gtk_combo_box_get_model (combo_box);
+ ret = gtk_tree_model_get_iter_first (model, &iter);
+ if (!ret)
+ return;
+
+ /* try to make the UI match the setting */
+ do
+ {
+ gtk_tree_model_get (model, &iter,
+ ACTION_MODEL_VALUE, &value_tmp,
+ -1);
+ if (value_tmp == value)
+ {
+ gtk_combo_box_set_active_iter (combo_box, &iter);
+ return;
+ }
+
+ /* Insert before if the next value is larger or the value is lower
+ * again (i.e. "Never" is zero and last). */
+ if (!insert && (value_tmp > value || value_last > value_tmp))
+ insert = gtk_tree_iter_copy (&iter);
+
+ value_last = value_tmp;
+ } while (gtk_tree_model_iter_next (model, &iter));
+
+ /* The value is not listed, so add it at the best point (or the end). */
+ gtk_list_store_insert_before (GTK_LIST_STORE (model), &new, insert);
+
+ text = cc_util_time_to_string_text (value * 1000);
+ gtk_list_store_set (GTK_LIST_STORE (model), &new,
+ ACTION_MODEL_TEXT, text,
+ ACTION_MODEL_VALUE, value,
+ -1);
+ gtk_combo_box_set_active_iter (combo_box, &new);
+}
+
+static void
+set_value_for_combo_row (AdwComboRow *combo_row, gint value)
+{
+ g_autoptr (GObject) new_item = NULL;
+ gboolean insert = FALSE;
+ guint insert_before = 0;
+ guint i;
+ GListModel *model;
+ gint value_last = 0;
+ g_autofree gchar *text = NULL;
+
+ /* try to make the UI match the setting */
+ model = adw_combo_row_get_model (combo_row);
+ for (i = 0; i < g_list_model_get_n_items (model); i++)
+ {
+ g_autoptr (GObject) item = g_list_model_get_item (model, i);
+ gint value_tmp = GPOINTER_TO_UINT (g_object_get_data (item, "value"));
+ if (value_tmp == value)
+ {
+ adw_combo_row_set_selected (combo_row, i);
+ return;
+ }
+
+ /* Insert before if the next value is larger or the value is lower
+ * again (i.e. "Never" is zero and last). */
+ if (!insert && (value_tmp > value || value_last > value_tmp))
+ {
+ insert = TRUE;
+ insert_before = i;
+ }
+
+ value_last = value_tmp;
+ }
+
+ /* The value is not listed, so add it at the best point (or the end). */
+ text = cc_util_time_to_string_text (value * 1000);
+ gtk_string_list_append (GTK_STRING_LIST (model), text);
+
+ new_item = g_list_model_get_item (model, i);
+ g_object_set_data (G_OBJECT (new_item), "value", GUINT_TO_POINTER (value));
+
+ adw_combo_row_set_selected (combo_row, insert_before);
+}
+
+static void
+set_ac_battery_ui_mode (CcPowerPanel *self)
+{
+ GPtrArray *devices;
+ guint i;
+
+ self->has_batteries = FALSE;
+ devices = up_client_get_devices2 (self->up_client);
+ g_debug ("got %d devices from upower\n", devices ? devices->len : 0);
+
+ for (i = 0; devices != NULL && i < devices->len; i++)
+ {
+ UpDevice *device;
+ gboolean is_power_supply;
+ UpDeviceKind kind;
+
+ device = g_ptr_array_index (devices, i);
+ g_object_get (device,
+ "kind", &kind,
+ "power-supply", &is_power_supply,
+ NULL);
+ if (kind == UP_DEVICE_KIND_UPS ||
+ (kind == UP_DEVICE_KIND_BATTERY && is_power_supply))
+ {
+ self->has_batteries = TRUE;
+ break;
+ }
+ }
+ g_clear_pointer (&devices, g_ptr_array_unref);
+
+ if (!self->has_batteries)
+ {
+ gtk_widget_hide (GTK_WIDGET (self->suspend_on_battery_switch));
+ gtk_widget_hide (GTK_WIDGET (self->suspend_on_battery_label));
+ gtk_widget_hide (GTK_WIDGET (self->suspend_on_battery_delay_label));
+ gtk_widget_hide (GTK_WIDGET (self->suspend_on_battery_delay_combo));
+ gtk_label_set_label (self->suspend_on_ac_label, _("When _idle"));
+ }
+}
+
+static gboolean
+keynav_failed_cb (CcPowerPanel *self, GtkDirectionType direction, GtkWidget *list)
+{
+ if (direction != GTK_DIR_UP && direction != GTK_DIR_DOWN)
+ return FALSE;
+
+ direction = GTK_DIR_UP ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD;
+
+ return gtk_widget_child_focus (GTK_WIDGET (self), direction);
+}
+
+static void
+blank_screen_row_changed_cb (CcPowerPanel *self)
+{
+ g_autoptr (GObject) item = NULL;
+ GListModel *model;
+ gint selected_index;
+ gint value;
+
+ model = adw_combo_row_get_model (self->blank_screen_row);
+ selected_index = adw_combo_row_get_selected (self->blank_screen_row);
+ if (selected_index == -1)
+ return;
+
+ item = g_list_model_get_item (model, selected_index);
+ value = GPOINTER_TO_UINT (g_object_get_data (item, "value"));
+
+ g_settings_set_uint (self->session_settings, "idle-delay", value);
+}
+
+static void
+power_button_row_changed_cb (CcPowerPanel *self)
+{
+ g_autoptr (GObject) item = NULL;
+ GListModel *model;
+ gint selected_index;
+ gint value;
+
+ model = adw_combo_row_get_model (self->power_button_row);
+ selected_index = adw_combo_row_get_selected (self->power_button_row);
+ if (selected_index == -1)
+ return;
+
+ item = g_list_model_get_item (model, selected_index);
+ value = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (item), "value"));
+
+ g_settings_set_enum (self->gsd_settings, "power-button-action", value);
+}
+
+static void
+als_enabled_setting_changed (CcPowerPanel *self)
+{
+ als_enabled_state_changed (self);
+}
+
+static void
+iio_proxy_appeared_cb (GDBusConnection *connection,
+ const gchar *name,
+ const gchar *name_owner,
+ gpointer user_data)
+{
+ CcPowerPanel *self = CC_POWER_PANEL (user_data);
+ g_autoptr(GError) error = NULL;
+
+ self->iio_proxy =
+ cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "net.hadess.SensorProxy",
+ "/net/hadess/SensorProxy",
+ "net.hadess.SensorProxy",
+ NULL, &error);
+ if (error != NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Could not create IIO sensor proxy: %s", error->message);
+ return;
+ }
+
+ g_signal_connect_object (G_OBJECT (self->iio_proxy), "g-properties-changed",
+ G_CALLBACK (als_enabled_state_changed), self,
+ G_CONNECT_SWAPPED);
+ als_enabled_state_changed (self);
+}
+
+static void
+iio_proxy_vanished_cb (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ CcPowerPanel *self = CC_POWER_PANEL (user_data);
+ g_clear_object (&self->iio_proxy);
+ als_enabled_state_changed (self);
+}
+
+static void
+automatic_suspend_row_activated_cb (CcPowerPanel *self)
+{
+ GtkWidget *toplevel;
+ CcShell *shell;
+
+ shell = cc_panel_get_shell (CC_PANEL (self));
+ toplevel = cc_shell_get_toplevel (shell);
+ gtk_window_set_transient_for (GTK_WINDOW (self->automatic_suspend_dialog), GTK_WINDOW (toplevel));
+ gtk_window_set_modal (GTK_WINDOW (self->automatic_suspend_dialog), TRUE);
+ gtk_window_present (GTK_WINDOW (self->automatic_suspend_dialog));
+}
+
+static gboolean
+automatic_suspend_label_mnemonic_activate_cb (CcPowerPanel *self)
+{
+ automatic_suspend_row_activated_cb (self);
+ return TRUE;
+}
+
+static gboolean
+get_sleep_type (GValue *value,
+ GVariant *variant,
+ gpointer data)
+{
+ gboolean enabled;
+
+ if (g_strcmp0 (g_variant_get_string (variant, NULL), "nothing") == 0)
+ enabled = FALSE;
+ else
+ enabled = TRUE;
+
+ g_value_set_boolean (value, enabled);
+
+ return TRUE;
+}
+
+static GVariant *
+set_sleep_type (const GValue *value,
+ const GVariantType *expected_type,
+ gpointer data)
+{
+ GVariant *res;
+
+ if (g_value_get_boolean (value))
+ res = g_variant_new_string ("suspend");
+ else
+ res = g_variant_new_string ("nothing");
+
+ return res;
+}
+
+static void
+populate_power_button_row (AdwComboRow *combo_row,
+ gboolean can_suspend,
+ gboolean can_hibernate)
+{
+ g_autoptr (GtkStringList) string_list = NULL;
+ struct {
+ char *name;
+ GsdPowerButtonActionType value;
+ } actions[] = {
+ { N_("Suspend"), GSD_POWER_BUTTON_ACTION_SUSPEND },
+ { N_("Power Off"), GSD_POWER_BUTTON_ACTION_INTERACTIVE },
+ { N_("Hibernate"), GSD_POWER_BUTTON_ACTION_HIBERNATE },
+ { N_("Nothing"), GSD_POWER_BUTTON_ACTION_NOTHING }
+ };
+ guint item_index = 0;
+ guint i;
+
+ string_list = gtk_string_list_new (NULL);
+ for (i = 0; i < G_N_ELEMENTS (actions); i++)
+ {
+ g_autoptr (GObject) item = NULL;
+
+ if (!can_suspend && actions[i].value == GSD_POWER_BUTTON_ACTION_SUSPEND)
+ continue;
+
+ if (!can_hibernate && actions[i].value == GSD_POWER_BUTTON_ACTION_HIBERNATE)
+ continue;
+
+ gtk_string_list_append (string_list, _(actions[i].name));
+
+ item = g_list_model_get_item (G_LIST_MODEL (string_list), item_index++);
+ g_object_set_data (item, "value", GUINT_TO_POINTER (actions[i].value));
+ }
+
+ adw_combo_row_set_model (combo_row, G_LIST_MODEL (string_list));
+}
+
+#define NEVER 0
+
+static void
+update_automatic_suspend_label (CcPowerPanel *self)
+{
+ GsdPowerActionType ac_action;
+ GsdPowerActionType battery_action;
+ gint ac_timeout;
+ gint battery_timeout;
+ const gchar *s;
+
+ ac_action = g_settings_get_enum (self->gsd_settings, "sleep-inactive-ac-type");
+ battery_action = g_settings_get_enum (self->gsd_settings, "sleep-inactive-battery-type");
+ ac_timeout = g_settings_get_int (self->gsd_settings, "sleep-inactive-ac-timeout");
+ battery_timeout = g_settings_get_int (self->gsd_settings, "sleep-inactive-battery-timeout");
+
+ if (ac_timeout < 0)
+ g_warning ("Invalid negative timeout for 'sleep-inactive-ac-timeout': %d", ac_timeout);
+ if (battery_timeout < 0)
+ g_warning ("Invalid negative timeout for 'sleep-inactive-battery-timeout': %d", battery_timeout);
+
+ if (ac_action == GSD_POWER_ACTION_NOTHING || ac_timeout < 0)
+ ac_timeout = NEVER;
+ if (battery_action == GSD_POWER_ACTION_NOTHING || battery_timeout < 0)
+ battery_timeout = NEVER;
+
+ if (self->has_batteries)
+ {
+ if (ac_timeout == NEVER && battery_timeout == NEVER)
+ s = _("Off");
+ else if (ac_timeout == NEVER && battery_timeout > 0)
+ s = _("When on battery power");
+ else if (ac_timeout > 0 && battery_timeout == NEVER)
+ s = _("When plugged in");
+ else
+ s = _("On");
+ }
+ else
+ {
+ if (ac_timeout == NEVER)
+ s = _("Off");
+ else
+ s = _("On");
+ }
+
+ if (self->automatic_suspend_label)
+ gtk_label_set_label (self->automatic_suspend_label, s);
+}
+
+static void
+on_suspend_settings_changed (CcPowerPanel *self,
+ const char *key)
+{
+ if (g_str_has_prefix (key, "sleep-inactive-"))
+ {
+ update_automatic_suspend_label (self);
+ }
+}
+
+static gboolean
+can_suspend_or_hibernate (CcPowerPanel *self,
+ const char *method_name)
+{
+ g_autoptr(GDBusConnection) connection = NULL;
+ g_autoptr(GVariant) variant = NULL;
+ g_autoptr(GError) error = NULL;
+ const char *s;
+
+ connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ &error);
+ if (!connection)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("system bus not available: %s", error->message);
+ return FALSE;
+ }
+
+ variant = g_dbus_connection_call_sync (connection,
+ "org.freedesktop.login1",
+ "/org/freedesktop/login1",
+ "org.freedesktop.login1.Manager",
+ method_name,
+ NULL,
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ &error);
+
+ if (!variant)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_debug ("Failed to call %s(): %s", method_name, error->message);
+ return FALSE;
+ }
+
+ g_variant_get (variant, "(&s)", &s);
+ return g_strcmp0 (s, "yes") == 0;
+}
+
+static void
+got_brightness_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GVariant) result = NULL;
+ g_autoptr(GError) error = NULL;
+ gint32 brightness = -1.0;
+ CcPowerPanel *self;
+
+ result = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object), res, &error);
+ if (!result)
+ {
+ g_debug ("Failed to get Brightness property: %s", error->message);
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+ }
+ else
+ {
+ g_autoptr(GVariant) v = NULL;
+ g_variant_get (result, "(v)", &v);
+ brightness = v ? g_variant_get_int32 (v) : -1.0;
+ }
+
+ self = user_data;
+ self->has_brightness = brightness >= 0.0;
+
+ gtk_widget_set_visible (GTK_WIDGET (self->dim_screen_row), self->has_brightness);
+ als_enabled_state_changed (self);
+}
+
+static void
+populate_blank_screen_row (AdwComboRow *combo_row)
+{
+ g_autoptr (GtkStringList) string_list = NULL;
+ g_autoptr (GObject) never_object = NULL;
+ gint minutes[] = { 1, 2, 3, 4, 5, 8, 10, 12, 15 };
+ guint i;
+
+ string_list = gtk_string_list_new (NULL);
+ for (i = 0; i < G_N_ELEMENTS (minutes); i++)
+ {
+ g_autoptr (GObject) item = NULL;
+ gchar *text = NULL;
+
+ /* Translators: Option for "Blank Screen" in "Power" panel */
+ text = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE, "%d minute", "%d minutes", minutes[i]), minutes[i]);
+ gtk_string_list_append (string_list, text);
+
+ item = g_list_model_get_item (G_LIST_MODEL (string_list), i);
+ g_object_set_data (item, "value", GUINT_TO_POINTER (minutes[i] * 60));
+ }
+
+ gtk_string_list_append (string_list, C_("Idle time", "Never"));
+ never_object = g_list_model_get_item (G_LIST_MODEL (string_list), i);
+ g_object_set_data (never_object, "value", GUINT_TO_POINTER (0));
+
+ adw_combo_row_set_model (combo_row, G_LIST_MODEL (string_list));
+}
+
+static void
+setup_power_saving (CcPowerPanel *self)
+{
+ g_autoptr(GDBusConnection) connection = NULL;
+ g_autoptr(GError) error = NULL;
+ int value;
+
+ /* ambient light sensor */
+ self->iio_proxy_watch_id =
+ g_bus_watch_name (G_BUS_TYPE_SYSTEM,
+ "net.hadess.SensorProxy",
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ iio_proxy_appeared_cb,
+ iio_proxy_vanished_cb,
+ self, NULL);
+ g_signal_connect_object (self->gsd_settings, "changed",
+ G_CALLBACK (als_enabled_setting_changed), self, G_CONNECT_SWAPPED);
+
+ connection = g_bus_get_sync (G_BUS_TYPE_SESSION,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ &error);
+ if (connection)
+ {
+ g_dbus_connection_call (connection,
+ "org.gnome.SettingsDaemon.Power",
+ "/org/gnome/SettingsDaemon/Power",
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ g_variant_new ("(ss)",
+ "org.gnome.SettingsDaemon.Power.Screen",
+ "Brightness"),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ got_brightness_cb,
+ self);
+ }
+ else
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("session bus not available: %s", error->message);
+ }
+
+
+ g_settings_bind (self->gsd_settings, "idle-dim",
+ self->dim_screen_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_signal_handlers_block_by_func (self->blank_screen_row, blank_screen_row_changed_cb, self);
+ populate_blank_screen_row (self->blank_screen_row);
+ value = g_settings_get_uint (self->session_settings, "idle-delay");
+ set_value_for_combo_row (self->blank_screen_row, value);
+ g_signal_handlers_unblock_by_func (self->blank_screen_row, blank_screen_row_changed_cb, self);
+
+ /* The default values for these settings are unfortunate for us;
+ * timeout == 0, action == suspend means 'do nothing' - just
+ * as timout === anything, action == nothing.
+ * For our switch/combobox combination, the second choice works
+ * much better, so translate the first to the second here.
+ */
+ if (g_settings_get_int (self->gsd_settings, "sleep-inactive-ac-timeout") == 0)
+ {
+ g_settings_set_enum (self->gsd_settings, "sleep-inactive-ac-type", GSD_POWER_ACTION_NOTHING);
+ g_settings_set_int (self->gsd_settings, "sleep-inactive-ac-timeout", 3600);
+ }
+ if (g_settings_get_int (self->gsd_settings, "sleep-inactive-battery-timeout") == 0)
+ {
+ g_settings_set_enum (self->gsd_settings, "sleep-inactive-battery-type", GSD_POWER_ACTION_NOTHING);
+ g_settings_set_int (self->gsd_settings, "sleep-inactive-battery-timeout", 1800);
+ }
+
+ /* Automatic suspend row */
+ if (can_suspend_or_hibernate (self, "CanSuspend"))
+ {
+ gtk_widget_show (GTK_WIDGET (self->automatic_suspend_row));
+ gtk_accessible_update_property (GTK_ACCESSIBLE (self->automatic_suspend_row),
+ GTK_ACCESSIBLE_PROPERTY_LABEL, _("Automatic suspend"),
+ -1);
+
+ g_signal_connect_object (self->gsd_settings, "changed", G_CALLBACK (on_suspend_settings_changed), self, G_CONNECT_SWAPPED);
+
+ g_settings_bind_with_mapping (self->gsd_settings, "sleep-inactive-battery-type",
+ self->suspend_on_battery_switch, "active",
+ G_SETTINGS_BIND_DEFAULT,
+ get_sleep_type, set_sleep_type, NULL, NULL);
+
+ g_object_set_data (G_OBJECT (self->suspend_on_battery_delay_combo), "_gsettings_key", "sleep-inactive-battery-timeout");
+ value = g_settings_get_int (self->gsd_settings, "sleep-inactive-battery-timeout");
+ set_value_for_combo (self->suspend_on_battery_delay_combo, value);
+ g_signal_connect_object (self->suspend_on_battery_delay_combo, "changed",
+ G_CALLBACK (combo_time_changed_cb), self, G_CONNECT_SWAPPED);
+ g_object_bind_property (self->suspend_on_battery_switch, "active", self->suspend_on_battery_delay_combo, "sensitive",
+ G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
+
+ g_settings_bind_with_mapping (self->gsd_settings, "sleep-inactive-ac-type",
+ self->suspend_on_ac_switch, "active",
+ G_SETTINGS_BIND_DEFAULT,
+ get_sleep_type, set_sleep_type, NULL, NULL);
+
+ g_object_set_data (G_OBJECT (self->suspend_on_ac_delay_combo), "_gsettings_key", "sleep-inactive-ac-timeout");
+ value = g_settings_get_int (self->gsd_settings, "sleep-inactive-ac-timeout");
+ set_value_for_combo (self->suspend_on_ac_delay_combo, value);
+ g_signal_connect_object (self->suspend_on_ac_delay_combo, "changed",
+ G_CALLBACK (combo_time_changed_cb), self, G_CONNECT_SWAPPED);
+ g_object_bind_property (self->suspend_on_ac_switch, "active", self->suspend_on_ac_delay_combo, "sensitive",
+ G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
+
+ set_ac_battery_ui_mode (self);
+ update_automatic_suspend_label (self);
+ }
+}
+
+static const char *
+variant_lookup_string (GVariant *dict,
+ const char *key)
+{
+ GVariant *variant;
+
+ variant = g_variant_lookup_value (dict, key, G_VARIANT_TYPE_STRING);
+ if (!variant)
+ return NULL;
+ return g_variant_get_string (variant, NULL);
+}
+
+static void
+performance_profile_set_active (CcPowerPanel *self,
+ const char *profile_str)
+{
+ CcPowerProfile profile = cc_power_profile_from_str (profile_str);
+ GtkCheckButton *button;
+
+ button = cc_power_profile_row_get_radio_button (CC_POWER_PROFILE_ROW (self->power_profiles_row[profile]));
+ if (!button) {
+ g_warning ("Not setting profile '%s' as it doesn't have a widget", profile_str);
+ return;
+ }
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (button), TRUE);
+}
+
+static void
+power_profile_update_info_boxes (CcPowerPanel *self)
+{
+ g_autoptr(GVariant) degraded_variant = NULL;
+ g_autoptr(GVariant) holds_variant = NULL;
+ g_autoptr(GVariant) profile_variant = NULL;
+ guint i, num_children;
+ const char *degraded = NULL;
+ const char *profile;
+ CcPowerProfileInfoRow *row;
+ int next_insert = 0;
+
+ empty_listbox (self->power_profile_info_listbox);
+ gtk_widget_hide (GTK_WIDGET (self->power_profile_info_listbox));
+
+ profile_variant = g_dbus_proxy_get_cached_property (self->power_profiles_proxy, "ActiveProfile");
+ if (!profile_variant)
+ {
+ g_warning ("No 'ActiveProfile' property on power-profiles-daemon service");
+ return;
+ }
+ profile = g_variant_get_string (profile_variant, NULL);
+
+ degraded_variant = g_dbus_proxy_get_cached_property (self->power_profiles_proxy, "PerformanceDegraded");
+ if (degraded_variant)
+ degraded = g_variant_get_string (degraded_variant, NULL);
+ if (degraded && *degraded != '\0')
+ {
+ const char *text;
+
+ gtk_widget_show (GTK_WIDGET (self->power_profile_info_listbox));
+
+ if (g_str_equal (degraded, "high-operating-temperature"))
+ text = _("Performance mode temporarily disabled due to high operating temperature.");
+ else if (g_str_equal (degraded, "lap-detected"))
+ text = _("Lap detected: performance mode temporarily unavailable. Move the device to a stable surface to restore.");
+ else
+ text = _("Performance mode temporarily disabled.");
+
+ row = cc_power_profile_info_row_new (text);
+ gtk_list_box_append (self->power_profile_info_listbox, GTK_WIDGET (row));
+ if (g_str_equal (profile, "performance"))
+ next_insert = 1;
+ }
+
+ holds_variant = g_dbus_proxy_get_cached_property (self->power_profiles_proxy, "ActiveProfileHolds");
+ if (!holds_variant)
+ {
+ g_warning ("No 'ActiveProfileHolds' property on power-profiles-daemon service");
+ return;
+ }
+
+ num_children = g_variant_n_children (holds_variant);
+ for (i = 0; i < num_children; i++)
+ {
+ g_autoptr(GDesktopAppInfo) app_info = NULL;
+ g_autoptr(GVariant) hold_variant = NULL;
+ g_autofree char *text = NULL;
+ const char *app_id, *held_profile, *reason, *name;
+
+ hold_variant = g_variant_get_child_value (holds_variant, i);
+ if (!hold_variant || !g_variant_is_of_type (hold_variant, G_VARIANT_TYPE ("a{sv}")))
+ continue;
+
+ app_id = variant_lookup_string (hold_variant, "ApplicationId");
+ if (!app_id)
+ continue;
+
+ gtk_widget_show (GTK_WIDGET (self->power_profile_info_listbox));
+
+ app_info = g_desktop_app_info_new (app_id);
+ name = app_info ? g_app_info_get_name (G_APP_INFO (app_info)) : app_id;
+ held_profile = variant_lookup_string (hold_variant, "Profile");
+ reason = variant_lookup_string (hold_variant, "Reason");
+ g_debug ("Adding info row for %s hold by %s: %s", held_profile, app_id, reason);
+
+ if (g_strcmp0 (held_profile, "power-saver") == 0 &&
+ g_strcmp0 (app_id, "org.gnome.SettingsDaemon.Power") == 0)
+ {
+ text = g_strdup (_("Low battery: power saver enabled. Previous mode will be restored when battery is sufficiently charged."));
+ }
+ else
+ {
+ switch (cc_power_profile_from_str (held_profile))
+ {
+ case CC_POWER_PROFILE_POWER_SAVER:
+ /* translators: "%s" is an application name */
+ text = g_strdup_printf (_("Power Saver mode activated by “%s”."), name);
+ break;
+ case CC_POWER_PROFILE_PERFORMANCE:
+ /* translators: "%s" is an application name */
+ text = g_strdup_printf (_("Performance mode activated by “%s”."), name);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ }
+
+ row = cc_power_profile_info_row_new (text);
+ gtk_widget_show (GTK_WIDGET (row));
+ if (g_strcmp0 (held_profile, profile) != 0)
+ gtk_list_box_insert (GTK_LIST_BOX (self->power_profile_info_listbox), GTK_WIDGET (row), -1);
+ else
+ gtk_list_box_insert (GTK_LIST_BOX (self->power_profile_info_listbox), GTK_WIDGET (row), next_insert);
+ }
+}
+
+static void
+power_profiles_row_activated_cb (GtkListBox *box,
+ GtkListBoxRow *box_row,
+ gpointer user_data)
+{
+ if (!gtk_widget_is_sensitive (GTK_WIDGET (box_row)))
+ return;
+
+ cc_power_profile_row_set_active (CC_POWER_PROFILE_ROW(box_row), TRUE);
+}
+
+static gint
+perf_profile_list_box_sort (GtkListBoxRow *row1,
+ GtkListBoxRow *row2,
+ gpointer user_data)
+{
+ CcPowerProfile row1_profile, row2_profile;
+
+ row1_profile = cc_power_profile_row_get_profile (CC_POWER_PROFILE_ROW (row1));
+ row2_profile = cc_power_profile_row_get_profile (CC_POWER_PROFILE_ROW (row2));
+
+ if (row1_profile < row2_profile)
+ return -1;
+ if (row1_profile > row2_profile)
+ return 1;
+ return 0;
+}
+
+static void
+power_profiles_properties_changed_cb (CcPowerPanel *self,
+ GVariant *changed_properties,
+ GStrv invalidated_properties,
+ GDBusProxy *proxy)
+{
+ g_autoptr(GVariantIter) iter = NULL;
+ const char *key;
+ g_autoptr(GVariant) value = NULL;
+
+ g_variant_get (changed_properties, "a{sv}", &iter);
+ while (g_variant_iter_next (iter, "{&sv}", &key, &value))
+ {
+ if (g_strcmp0 (key, "PerformanceDegraded") == 0 ||
+ g_strcmp0 (key, "ActiveProfileHolds") == 0)
+ {
+ power_profile_update_info_boxes (self);
+ }
+ else if (g_strcmp0 (key, "ActiveProfile") == 0)
+ {
+ self->power_profiles_in_update = TRUE;
+ performance_profile_set_active (self, g_variant_get_string (value, NULL));
+ self->power_profiles_in_update = FALSE;
+ }
+ else
+ {
+ g_debug ("Unhandled change on '%s' property", key);
+ }
+ }
+}
+
+static void
+set_active_profile_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GVariant) variant = NULL;
+ g_autoptr(GError) error = NULL;
+
+ variant = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ res, &error);
+ if (!variant)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Could not set active profile: %s", error->message);
+ }
+}
+
+static void
+power_profile_button_toggled_cb (CcPowerProfileRow *row,
+ gpointer user_data)
+{
+ CcPowerPanel *self = user_data;
+ CcPowerProfile profile;
+ g_autoptr(GDBusConnection) connection = NULL;
+ g_autoptr(GError) error = NULL;
+
+ if (!cc_power_profile_row_get_active (row))
+ return;
+ if (self->power_profiles_in_update)
+ return;
+
+ profile = cc_power_profile_row_get_profile (row);
+
+ connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ &error);
+ if (!connection)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("system bus not available: %s", error->message);
+ return;
+ }
+
+ g_dbus_connection_call (connection,
+ "net.hadess.PowerProfiles",
+ "/net/hadess/PowerProfiles",
+ "org.freedesktop.DBus.Properties",
+ "Set",
+ g_variant_new ("(ssv)",
+ "net.hadess.PowerProfiles",
+ "ActiveProfile",
+ g_variant_new_string (cc_power_profile_to_str (profile))),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ set_active_profile_cb,
+ NULL);
+}
+
+static void
+setup_power_profiles (CcPowerPanel *self)
+{
+ g_autoptr(GDBusConnection) connection = NULL;
+ g_autoptr(GVariant) variant = NULL;
+ g_autoptr(GVariant) props = NULL;
+ guint i, num_children;
+ g_autoptr(GError) error = NULL;
+ const char *performance_degraded;
+ const char *active_profile;
+ g_autoptr(GVariant) profiles = NULL;
+ GtkCheckButton *last_button;
+
+ self->power_profiles_proxy = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "net.hadess.PowerProfiles",
+ "/net/hadess/PowerProfiles",
+ "net.hadess.PowerProfiles",
+ NULL,
+ &error);
+
+ if (!self->power_profiles_proxy)
+ {
+ g_debug ("Could not create Power Profiles proxy: %s", error->message);
+ return;
+ }
+
+ connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ &error);
+ if (!connection)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("system bus not available: %s", error->message);
+ return;
+ }
+
+ variant = g_dbus_connection_call_sync (connection,
+ "net.hadess.PowerProfiles",
+ "/net/hadess/PowerProfiles",
+ "org.freedesktop.DBus.Properties",
+ "GetAll",
+ g_variant_new ("(s)",
+ "net.hadess.PowerProfiles"),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if (!variant)
+ {
+ g_debug ("Failed to get properties for Power Profiles: %s",
+ error->message);
+ g_clear_object (&self->power_profiles_proxy);
+ return;
+ }
+
+ gtk_widget_show (GTK_WIDGET (self->power_profile_section));
+
+ props = g_variant_get_child_value (variant, 0);
+ performance_degraded = variant_lookup_string (props, "PerformanceDegraded");
+ self->has_performance_degraded = performance_degraded != NULL;
+ active_profile = variant_lookup_string (props, "ActiveProfile");
+
+ last_button = NULL;
+ profiles = g_variant_lookup_value (props, "Profiles", NULL);
+ num_children = g_variant_n_children (profiles);
+ for (i = 0; i < num_children; i++)
+ {
+ g_autoptr(GVariant) profile_variant;
+ const char *name;
+ GtkCheckButton *button;
+ CcPowerProfile profile;
+ CcPowerProfileRow *row;
+
+ profile_variant = g_variant_get_child_value (profiles, i);
+ if (!profile_variant ||
+ !g_variant_is_of_type (profile_variant, G_VARIANT_TYPE ("a{sv}")))
+ continue;
+
+ name = variant_lookup_string (profile_variant, "Profile");
+ if (!name)
+ continue;
+ g_debug ("Adding row for profile '%s' (driver: %s)",
+ name, variant_lookup_string (profile_variant, "Driver"));
+
+ profile = cc_power_profile_from_str (name);
+ row = cc_power_profile_row_new (cc_power_profile_from_str (name));
+ g_signal_connect_object (G_OBJECT (row), "button-toggled",
+ G_CALLBACK (power_profile_button_toggled_cb), self,
+ 0);
+ self->power_profiles_row[profile] = row;
+ gtk_widget_show (GTK_WIDGET (row));
+ gtk_list_box_append (self->power_profile_listbox, GTK_WIDGET (row));
+ gtk_size_group_add_widget (self->row_sizegroup, GTK_WIDGET (row));
+
+ /* Connect radio button to group */
+ button = cc_power_profile_row_get_radio_button (row);
+ gtk_check_button_set_group (button, last_button);
+ last_button = button;
+ }
+
+ self->power_profiles_in_update = TRUE;
+ performance_profile_set_active (self, active_profile);
+ self->power_profiles_in_update = FALSE;
+
+ self->power_profiles_prop_id = g_signal_connect_object (G_OBJECT (self->power_profiles_proxy), "g-properties-changed",
+ G_CALLBACK (power_profiles_properties_changed_cb), self, G_CONNECT_SWAPPED);
+
+ if (self->has_performance_degraded)
+ power_profile_update_info_boxes (self);
+
+ update_power_saver_low_battery_row_visibility (self);
+}
+
+static void
+setup_general_section (CcPowerPanel *self)
+{
+ gboolean can_suspend, can_hibernate, show_section = FALSE;
+
+ can_suspend = can_suspend_or_hibernate (self, "CanSuspend");
+ can_hibernate = can_suspend_or_hibernate (self, "CanHibernate");
+
+ if ((can_hibernate || can_suspend) &&
+ g_strcmp0 (self->chassis_type, "vm") != 0 &&
+ g_strcmp0 (self->chassis_type, "tablet") != 0 &&
+ g_strcmp0 (self->chassis_type, "handset") != 0)
+ {
+ gtk_widget_show (GTK_WIDGET (self->power_button_row));
+
+ g_signal_handlers_block_by_func (self->power_button_row,
+ power_button_row_changed_cb,
+ self);
+ populate_power_button_row (self->power_button_row,
+ can_suspend,
+ can_hibernate);
+ set_value_for_combo_row (self->power_button_row,
+ g_settings_get_enum (self->gsd_settings, "power-button-action"));
+ g_signal_handlers_unblock_by_func (self->power_button_row,
+ power_button_row_changed_cb,
+ self);
+
+ show_section = TRUE;
+ }
+
+ if (self->has_batteries)
+ {
+ gtk_widget_show (GTK_WIDGET (self->battery_percentage_row));
+
+ g_settings_bind (self->interface_settings, "show-battery-percentage",
+ self->battery_percentage_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ show_section = TRUE;
+ }
+
+ gtk_widget_set_visible (GTK_WIDGET (self->general_section), show_section);
+}
+
+static gint
+battery_sort_func (GtkListBoxRow *a, GtkListBoxRow *b, gpointer data)
+{
+ CcBatteryRow *row_a = CC_BATTERY_ROW (a);
+ CcBatteryRow *row_b = CC_BATTERY_ROW (b);
+ gboolean a_primary;
+ gboolean b_primary;
+ UpDeviceKind a_kind;
+ UpDeviceKind b_kind;
+
+ a_primary = cc_battery_row_get_primary(row_a);
+ b_primary = cc_battery_row_get_primary(row_b);
+
+ if (a_primary)
+ return -1;
+ else if (b_primary)
+ return 1;
+
+ a_kind = cc_battery_row_get_kind(row_a);
+ b_kind = cc_battery_row_get_kind(row_b);
+
+ return a_kind - b_kind;
+}
+
+static void
+cc_power_panel_dispose (GObject *object)
+{
+ CcPowerPanel *self = CC_POWER_PANEL (object);
+
+ g_signal_handlers_disconnect_by_func (self->blank_screen_row, blank_screen_row_changed_cb, self);
+ g_signal_handlers_disconnect_by_func (self->power_button_row, power_button_row_changed_cb, self);
+
+ g_clear_pointer (&self->chassis_type, g_free);
+ g_clear_object (&self->gsd_settings);
+ g_clear_object (&self->session_settings);
+ g_clear_object (&self->interface_settings);
+ g_clear_pointer ((GtkWindow **) &self->automatic_suspend_dialog, gtk_window_destroy);
+ g_clear_pointer (&self->devices, g_ptr_array_unref);
+ g_clear_object (&self->up_client);
+ g_clear_object (&self->iio_proxy);
+ g_clear_object (&self->power_profiles_proxy);
+ if (self->iio_proxy_watch_id != 0)
+ g_bus_unwatch_name (self->iio_proxy_watch_id);
+ self->iio_proxy_watch_id = 0;
+
+ G_OBJECT_CLASS (cc_power_panel_parent_class)->dispose (object);
+}
+
+static void
+cc_power_panel_class_init (CcPowerPanelClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+
+ object_class->dispose = cc_power_panel_dispose;
+
+ panel_class->get_help_uri = cc_power_panel_get_help_uri;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/power/cc-power-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, als_row);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, als_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, automatic_suspend_dialog);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, automatic_suspend_label);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, automatic_suspend_row);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, battery_listbox);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, battery_percentage_row);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, battery_percentage_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, battery_row_sizegroup);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, battery_section);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, blank_screen_row);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, device_listbox);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, device_section);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, dim_screen_row);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, dim_screen_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, general_section);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, level_sizegroup);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, power_button_row);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, power_profile_listbox);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, power_profile_info_listbox);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, power_profile_section);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, power_saver_low_battery_row);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, power_saver_low_battery_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, row_sizegroup);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, suspend_on_battery_delay_combo);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, suspend_on_battery_delay_label);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, suspend_on_battery_label);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, suspend_on_battery_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, suspend_on_ac_delay_combo);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, suspend_on_ac_label);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, suspend_on_ac_switch);
+
+ gtk_widget_class_bind_template_callback (widget_class, als_switch_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, automatic_suspend_label_mnemonic_activate_cb);
+ gtk_widget_class_bind_template_callback (widget_class, blank_screen_row_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, keynav_failed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, power_button_row_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, power_profiles_row_activated_cb);
+ gtk_widget_class_bind_template_callback (widget_class, automatic_suspend_row_activated_cb);
+}
+
+static void
+cc_power_panel_init (CcPowerPanel *self)
+{
+ guint i;
+
+ g_resources_register (cc_power_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+ load_custom_css (self, "/org/gnome/control-center/power/battery-levels.css");
+ load_custom_css (self, "/org/gnome/control-center/power/power-profiles.css");
+
+ self->chassis_type = get_chassis_type (cc_panel_get_cancellable (CC_PANEL (self)));
+
+ self->up_client = up_client_new ();
+
+ self->gsd_settings = g_settings_new ("org.gnome.settings-daemon.plugins.power");
+ self->session_settings = g_settings_new ("org.gnome.desktop.session");
+ self->interface_settings = g_settings_new ("org.gnome.desktop.interface");
+
+ gtk_list_box_set_sort_func (self->battery_listbox,
+ (GtkListBoxSortFunc)battery_sort_func, NULL, NULL);
+
+ gtk_list_box_set_sort_func (self->device_listbox,
+ (GtkListBoxSortFunc)battery_sort_func, NULL, NULL);
+
+ gtk_list_box_set_sort_func (self->power_profile_listbox,
+ perf_profile_list_box_sort,
+ NULL, NULL);
+ setup_power_profiles (self);
+
+ setup_power_saving (self);
+ g_settings_bind (self->gsd_settings, "power-saver-profile-on-low-battery",
+ self->power_saver_low_battery_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ setup_general_section (self);
+
+ /* populate batteries */
+ g_signal_connect_object (self->up_client, "device-added", G_CALLBACK (up_client_device_added), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->up_client, "device-removed", G_CALLBACK (up_client_device_removed), self, G_CONNECT_SWAPPED);
+
+ self->devices = up_client_get_devices2 (self->up_client);
+ for (i = 0; self->devices != NULL && i < self->devices->len; i++) {
+ UpDevice *device = g_ptr_array_index (self->devices, i);
+ g_signal_connect_object (G_OBJECT (device), "notify",
+ G_CALLBACK (up_client_changed), self, G_CONNECT_SWAPPED);
+ }
+ up_client_changed (self);
+}
diff --git a/panels/power/cc-power-panel.h b/panels/power/cc-power-panel.h
new file mode 100644
index 0000000..e8b922d
--- /dev/null
+++ b/panels/power/cc-power-panel.h
@@ -0,0 +1,29 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2010 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_POWER_PANEL (cc_power_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcPowerPanel, cc_power_panel, CC, POWER_PANEL, CcPanel)
+
+G_END_DECLS
diff --git a/panels/power/cc-power-panel.ui b/panels/power/cc-power-panel.ui
new file mode 100644
index 0000000..44c515b
--- /dev/null
+++ b/panels/power/cc-power-panel.ui
@@ -0,0 +1,364 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <object class="GtkListStore" id="time_liststore">
+ <columns>
+ <!-- column-name name -->
+ <column type="gchararray"/>
+ <!-- column-name value -->
+ <column type="gint"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes" context="automatic_suspend" comments="Translators: Option for &quot;Delay&quot; in &quot;Automatic suspend&quot; dialog.">15 minutes</col>
+ <col id="1">900</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" context="automatic_suspend" comments="Translators: Option for &quot;Delay&quot; in &quot;Automatic suspend&quot; dialog.">20 minutes</col>
+ <col id="1">1200</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" context="automatic_suspend" comments="Translators: Option for &quot;Delay&quot; in &quot;Automatic suspend&quot; dialog.">25 minutes</col>
+ <col id="1">1500</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" context="automatic_suspend" comments="Translators: Option for &quot;Delay&quot; in &quot;Automatic suspend&quot; dialog.">30 minutes</col>
+ <col id="1">1800</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" context="automatic_suspend" comments="Translators: Option for &quot;Delay&quot; in &quot;Automatic suspend&quot; dialog.">45 minutes</col>
+ <col id="1">2700</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" context="automatic_suspend" comments="Translators: Option for &quot;Delay&quot; in &quot;Automatic suspend&quot; dialog.">1 hour</col>
+ <col id="1">3600</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" context="automatic_suspend" comments="Translators: Option for &quot;Delay&quot; in &quot;Automatic suspend&quot; dialog.">80 minutes</col>
+ <col id="1">4800</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" context="automatic_suspend" comments="Translators: Option for &quot;Delay&quot; in &quot;Automatic suspend&quot; dialog.">90 minutes</col>
+ <col id="1">5400</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" context="automatic_suspend" comments="Translators: Option for &quot;Delay&quot; in &quot;Automatic suspend&quot; dialog.">100 minutes</col>
+ <col id="1">6000</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes" context="automatic_suspend" comments="Translators: Option for &quot;Delay&quot; in &quot;Automatic suspend&quot; dialog.">2 hours</col>
+ <col id="1">7200</col>
+ </row>
+ </data>
+ </object>
+ <template class="CcPowerPanel" parent="CcPanel">
+ <child type="content">
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup" id="battery_section">
+ <property name="title" translatable="yes">Battery</property>
+ <child>
+ <object class="GtkListBox" id="battery_listbox">
+ <property name="selection-mode">none</property>
+ <signal name="keynav-failed" handler="keynav_failed_cb" object="CcPowerPanel" swapped="yes"/>
+ <accessibility>
+ <relation name="labelled-by">battery_section</relation>
+ </accessibility>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup" id="device_section">
+ <property name="title" translatable="yes">Devices</property>
+ <child>
+ <object class="GtkListBox" id="device_listbox">
+ <property name="selection-mode">none</property>
+ <signal name="keynav-failed" handler="keynav_failed_cb" object="CcPowerPanel" swapped="yes"/>
+ <accessibility>
+ <relation name="labelled-by">device_section</relation>
+ </accessibility>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup" id="power_profile_section">
+ <property name="visible">False</property>
+ <property name="title" translatable="yes">Power Mode</property>
+ <property name="description" translatable="yes">Affects system performance and power usage.</property>
+ <child>
+ <object class="GtkListBox" id="power_profile_listbox">
+ <property name="selection-mode">none</property>
+ <signal name="keynav-failed" handler="keynav_failed_cb" object="CcPowerPanel" swapped="yes"/>
+ <signal name="row-activated" handler="power_profiles_row_activated_cb" object="CcPowerPanel" swapped="yes"/>
+ <accessibility>
+ <relation name="labelled-by">power_profile_section</relation>
+ </accessibility>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkListBox" id="power_profile_info_listbox">
+ <property name="visible">False</property>
+ <property name="selection-mode">none</property>
+ <property name="margin_top">12</property>
+ <signal name="keynav-failed" handler="keynav_failed_cb" object="CcPowerPanel" swapped="yes"/>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup" id="power_saving_section">
+ <property name="title" translatable="yes">Power Saving Options</property>
+ <child>
+ <object class="AdwActionRow" id="als_row">
+ <property name="title" translatable="yes">Automatic Screen Brightness</property>
+ <property name="subtitle" translatable="yes">Screen brightness adjusts to the surrounding light.</property>
+ <property name="activatable_widget">als_switch</property>
+ <child>
+ <object class="GtkSwitch" id="als_switch">
+ <property name="valign">center</property>
+ <signal name="notify::active" handler="als_switch_changed_cb" object="CcPowerPanel" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="dim_screen_row">
+ <property name="title" translatable="yes">Dim Screen</property>
+ <property name="subtitle" translatable="yes">Reduces the screen brightness when the computer is inactive.</property>
+ <property name="activatable_widget">dim_screen_switch</property>
+ <child>
+ <object class="GtkSwitch" id="dim_screen_switch">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwComboRow" id="blank_screen_row">
+ <property name="title" translatable="yes">Screen _Blank</property>
+ <property name="subtitle" translatable="yes">Turns the screen off after a period of inactivity.</property>
+ <property name="use_underline">True</property>
+ <signal name="notify::selected-item" handler="blank_screen_row_changed_cb" object="CcPowerPanel" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="power_saver_low_battery_row">
+ <property name="visible">False</property>
+ <property name="title" translatable="yes">Automatic Power Saver</property>
+ <property name="subtitle" translatable="yes">Enables power saver mode when battery is low.</property>
+ <property name="use_underline">True</property>
+ <property name="activatable_widget">power_saver_low_battery_switch</property>
+ <child>
+ <object class="GtkSwitch" id="power_saver_low_battery_switch">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="automatic_suspend_row">
+ <property name="visible">False</property>
+ <property name="title" translatable="yes">_Automatic Suspend</property>
+ <property name="subtitle" translatable="yes">Pauses the computer after a period of inactivity.</property>
+ <property name="use_underline">True</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="automatic_suspend_row_activated_cb" swapped="yes"/>
+ <child>
+ <object class="GtkLabel" id="automatic_suspend_label">
+ <property name="halign">end</property>
+ <signal name="mnemonic-activate" handler="automatic_suspend_label_mnemonic_activate_cb" object="CcPowerPanel" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="valign">center</property>
+ <property name="icon-name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup" id="general_section">
+ <child>
+ <object class="AdwComboRow" id="power_button_row">
+ <property name="visible">False</property>
+ <property name="title" translatable="yes">Po_wer Button Behavior</property>
+ <property name="use_underline">True</property>
+ <signal name="notify::selected-item" handler="power_button_row_changed_cb" object="CcPowerPanel" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="battery_percentage_row">
+ <property name="visible">False</property>
+ <property name="title" translatable="yes">Show Battery _Percentage</property>
+ <property name="use_underline">True</property>
+ <property name="activatable_widget">battery_percentage_switch</property>
+ <child>
+ <object class="GtkSwitch" id="battery_percentage_switch">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GtkSizeGroup" id="battery_row_sizegroup">
+ <property name="mode">vertical</property>
+ </object>
+ <object class="GtkSizeGroup" id="level_sizegroup">
+ <property name="mode">horizontal</property>
+ <widgets>
+ </widgets>
+ </object>
+ <object class="GtkSizeGroup" id="row_sizegroup">
+ <property name="mode">vertical</property>
+ <widgets>
+ <widget name="als_row"/>
+ <widget name="dim_screen_row"/>
+ <widget name="blank_screen_row"/>
+ <widget name="automatic_suspend_row"/>
+ <widget name="power_button_row"/>
+ <widget name="battery_percentage_row"/>
+ </widgets>
+ </object>
+
+ <object class="GtkDialog" id="automatic_suspend_dialog">
+ <property name="title" translatable="yes">Automatic Suspend</property>
+ <property name="resizable">False</property>
+ <property name="use_header_bar">1</property>
+ <property name="hide-on-close">True</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin_start">6</property>
+ <property name="margin_end">6</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">6</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="margin_start">12</property>
+ <property name="margin_end">6</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="row_spacing">12</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="suspend_on_ac_label">
+ <property name="margin_top">12</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Plugged In</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">suspend_on_ac_switch</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="suspend_on_battery_label">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">On _Battery Power</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">suspend_on_battery_switch</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="suspend_on_battery_switch">
+ <property name="halign">end</property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="suspend_on_battery_delay_combo">
+ <property name="entry_text_column">0</property>
+ <property name="id_column">1</property>
+ <property name="model">time_liststore</property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="suspend_on_battery_delay_label">
+ <property name="margin_start">20</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Delay</property>
+ <property name="mnemonic_widget">suspend_on_battery_delay_combo</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="suspend_on_ac_switch">
+ <property name="halign">end</property>
+ <property name="margin_top">12</property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="suspend_on_ac_delay_combo">
+ <property name="entry_text_column">0</property>
+ <property name="id_column">1</property>
+ <property name="model">time_liststore</property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="margin_start">20</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Delay</property>
+ <property name="mnemonic_widget">suspend_on_ac_delay_combo</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/panels/power/cc-power-profile-info-row.c b/panels/power/cc-power-profile-info-row.c
new file mode 100644
index 0000000..92bb788
--- /dev/null
+++ b/panels/power/cc-power-profile-info-row.c
@@ -0,0 +1,67 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-list-row.c
+ *
+ * Copyright 2020 Red Hat Inc.
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Bastien Nocera <hadess@hadess.net>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "cc-power-profile-info-row"
+
+#include <config.h>
+
+#include <glib/gi18n.h>
+#include "cc-power-profile-info-row.h"
+
+struct _CcPowerProfileInfoRow
+{
+ GtkListBoxRow parent_instance;
+
+ GtkLabel *title_label;
+};
+
+G_DEFINE_TYPE (CcPowerProfileInfoRow, cc_power_profile_info_row, GTK_TYPE_LIST_BOX_ROW)
+
+static void
+cc_power_profile_info_row_class_init (CcPowerProfileInfoRowClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/power/cc-power-profile-info-row.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcPowerProfileInfoRow, title_label);
+}
+
+static void
+cc_power_profile_info_row_init (CcPowerProfileInfoRow *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+CcPowerProfileInfoRow *
+cc_power_profile_info_row_new (const char *text)
+{
+ CcPowerProfileInfoRow *self;
+
+ self = g_object_new (CC_TYPE_POWER_PROFILE_INFO_ROW, NULL);
+ gtk_label_set_markup (self->title_label, text);
+
+ return self;
+}
diff --git a/panels/power/cc-power-profile-info-row.h b/panels/power/cc-power-profile-info-row.h
new file mode 100644
index 0000000..52d055a
--- /dev/null
+++ b/panels/power/cc-power-profile-info-row.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-list-row.h
+ *
+ * Copyright 2020 Red Hat Inc
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Bastien Nocera <hadess@hadess.net>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_POWER_PROFILE_INFO_ROW (cc_power_profile_info_row_get_type())
+G_DECLARE_FINAL_TYPE (CcPowerProfileInfoRow, cc_power_profile_info_row, CC, POWER_PROFILE_INFO_ROW, GtkListBoxRow)
+
+CcPowerProfileInfoRow *cc_power_profile_info_row_new (const char *text);
+
+G_END_DECLS
diff --git a/panels/power/cc-power-profile-info-row.ui b/panels/power/cc-power-profile-info-row.ui
new file mode 100644
index 0000000..4400244
--- /dev/null
+++ b/panels/power/cc-power-profile-info-row.ui
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcPowerProfileInfoRow" parent="GtkListBoxRow">
+ <property name="activatable">False</property>
+ <property name="selectable">False</property>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <property name="margin-start">4</property>
+ <property name="margin-end">8</property>
+ <property name="margin-top">8</property>
+ <property name="margin-bottom">8</property>
+ <property name="spacing">4</property>
+ <child>
+ <object class="GtkImage" id="icon_image">
+ <property name="margin-start">6</property>
+ <property name="margin-end">6</property>
+ <property name="icon-name">info-symbolic</property>
+ <property name="icon-size">large</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="title_label">
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="use-markup">True</property>
+ <property name="use-underline">True</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="margin-end">6</property>
+ <property name="wrap">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/power/cc-power-profile-row.c b/panels/power/cc-power-profile-row.c
new file mode 100644
index 0000000..dbb609f
--- /dev/null
+++ b/panels/power/cc-power-profile-row.c
@@ -0,0 +1,180 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-list-row.c
+ *
+ * Copyright 2020 Red Hat Inc.
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Bastien Nocera <hadess@hadess.net>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "cc-power-profile-row"
+
+#include <config.h>
+
+#include <glib/gi18n.h>
+#include "cc-power-profile-row.h"
+
+struct _CcPowerProfileRow
+{
+ GtkListBoxRow parent_instance;
+
+ GtkCheckButton *button;
+ GtkLabel *subtitle_label;
+ GtkLabel *title_label;
+
+ CcPowerProfile power_profile;
+};
+
+G_DEFINE_TYPE (CcPowerProfileRow, cc_power_profile_row, GTK_TYPE_LIST_BOX_ROW)
+
+enum {
+ BUTTON_TOGGLED,
+ N_SIGNALS
+};
+
+static guint signals[N_SIGNALS];
+
+static void
+cc_power_profile_row_button_toggled_cb (CcPowerProfileRow *self)
+{
+ g_signal_emit (self, signals[BUTTON_TOGGLED], 0);
+}
+
+static void
+cc_power_profile_row_class_init (CcPowerProfileRowClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/power/cc-power-profile-row.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcPowerProfileRow, button);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerProfileRow, subtitle_label);
+ gtk_widget_class_bind_template_child (widget_class, CcPowerProfileRow, title_label);
+
+ gtk_widget_class_bind_template_callback (widget_class, cc_power_profile_row_button_toggled_cb);
+
+ signals[BUTTON_TOGGLED] =
+ g_signal_new ("button-toggled",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ 0, NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 0);
+}
+
+static void
+cc_power_profile_row_init (CcPowerProfileRow *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+CcPowerProfile
+cc_power_profile_row_get_profile (CcPowerProfileRow *self)
+{
+ g_return_val_if_fail (CC_IS_POWER_PROFILE_ROW (self), -1);
+
+ return self->power_profile;
+}
+
+GtkCheckButton *
+cc_power_profile_row_get_radio_button (CcPowerProfileRow *self)
+{
+ g_return_val_if_fail (CC_IS_POWER_PROFILE_ROW (self), NULL);
+
+ return self->button;
+}
+
+void
+cc_power_profile_row_set_active (CcPowerProfileRow *self,
+ gboolean active)
+{
+ g_return_if_fail (CC_IS_POWER_PROFILE_ROW (self));
+
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->button), active);
+}
+
+gboolean
+cc_power_profile_row_get_active (CcPowerProfileRow *self)
+{
+ g_return_val_if_fail (CC_IS_POWER_PROFILE_ROW (self), FALSE);
+
+ return gtk_check_button_get_active (GTK_CHECK_BUTTON (self->button));
+}
+
+CcPowerProfileRow *
+cc_power_profile_row_new (CcPowerProfile power_profile)
+{
+ CcPowerProfileRow *self;
+ const char *text, *subtext;
+
+ self = g_object_new (CC_TYPE_POWER_PROFILE_ROW, NULL);
+
+ self->power_profile = power_profile;
+ switch (self->power_profile)
+ {
+ case CC_POWER_PROFILE_PERFORMANCE:
+ text = C_("Power profile", "Performance");
+ subtext = _("High performance and power usage.");
+ break;
+ case CC_POWER_PROFILE_BALANCED:
+ text = C_("Power profile", "Balanced");
+ subtext = _("Standard performance and power usage.");
+ break;
+ case CC_POWER_PROFILE_POWER_SAVER:
+ text = C_("Power profile", "Power Saver");
+ subtext = _("Reduced performance and power usage.");
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ gtk_label_set_markup (self->title_label, text);
+ gtk_label_set_markup (self->subtitle_label, subtext);
+
+ return self;
+}
+
+CcPowerProfile
+cc_power_profile_from_str (const char *profile)
+{
+ if (g_strcmp0 (profile, "power-saver") == 0)
+ return CC_POWER_PROFILE_POWER_SAVER;
+ if (g_strcmp0 (profile, "balanced") == 0)
+ return CC_POWER_PROFILE_BALANCED;
+ if (g_strcmp0 (profile, "performance") == 0)
+ return CC_POWER_PROFILE_PERFORMANCE;
+
+ g_assert_not_reached ();
+}
+
+const char *
+cc_power_profile_to_str (CcPowerProfile profile)
+{
+ switch (profile)
+ {
+ case CC_POWER_PROFILE_POWER_SAVER:
+ return "power-saver";
+ case CC_POWER_PROFILE_BALANCED:
+ return "balanced";
+ case CC_POWER_PROFILE_PERFORMANCE:
+ return "performance";
+ default:
+ g_assert_not_reached ();
+ }
+}
diff --git a/panels/power/cc-power-profile-row.h b/panels/power/cc-power-profile-row.h
new file mode 100644
index 0000000..a6406e9
--- /dev/null
+++ b/panels/power/cc-power-profile-row.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-list-row.h
+ *
+ * Copyright 2020 Red Hat Inc
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Bastien Nocera <hadess@hadess.net>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+typedef enum
+{
+ CC_POWER_PROFILE_PERFORMANCE = 0,
+ CC_POWER_PROFILE_BALANCED = 1,
+ CC_POWER_PROFILE_POWER_SAVER = 2,
+ NUM_CC_POWER_PROFILES
+} CcPowerProfile;
+
+#define CC_TYPE_POWER_PROFILE_ROW (cc_power_profile_row_get_type())
+G_DECLARE_FINAL_TYPE (CcPowerProfileRow, cc_power_profile_row, CC, POWER_PROFILE_ROW, GtkListBoxRow)
+
+CcPowerProfileRow *cc_power_profile_row_new (CcPowerProfile power_profile);
+CcPowerProfile cc_power_profile_row_get_profile (CcPowerProfileRow *row);
+GtkCheckButton *cc_power_profile_row_get_radio_button (CcPowerProfileRow *row);
+void cc_power_profile_row_set_active (CcPowerProfileRow *row, gboolean active);
+gboolean cc_power_profile_row_get_active (CcPowerProfileRow *row);
+
+CcPowerProfile cc_power_profile_from_str (const char *profile);
+const char *cc_power_profile_to_str (CcPowerProfile profile);
+
+G_END_DECLS
diff --git a/panels/power/cc-power-profile-row.ui b/panels/power/cc-power-profile-row.ui
new file mode 100644
index 0000000..6edcf7c
--- /dev/null
+++ b/panels/power/cc-power-profile-row.ui
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcPowerProfileRow" parent="GtkListBoxRow">
+ <property name="selectable">False</property>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="margin-top">6</property>
+ <property name="margin-bottom">6</property>
+ <child>
+ <object class="GtkCheckButton" id="button">
+ <property name="margin-start">6</property>
+ <property name="margin-end">18</property>
+ <accessibility>
+ <property name="label" translatable="yes">Active</property>
+ </accessibility>
+ <signal name="toggled" handler="cc_power_profile_row_button_toggled_cb" object="CcPowerProfileRow" swapped="yes"/>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ <property name="row-span">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="title_label">
+ <property name="halign">start</property>
+ <property name="ellipsize">end</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="use-markup">True</property>
+ <property name="use-underline">True</property>
+ <property name="xalign">0</property>
+ <property name="margin-end">6</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="subtitle_label">
+ <property name="ellipsize">end</property>
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="use-markup">True</property>
+ <property name="use-underline">True</property>
+ <property name="xalign">0</property>
+ <property name="margin-end">6</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ <property name="column-span">2</property>
+ </layout>
+ <attributes>
+ <attribute name="scale" value="0.9"/>
+ </attributes>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
+
diff --git a/panels/power/gnome-power-panel.desktop.in.in b/panels/power/gnome-power-panel.desktop.in.in
new file mode 100644
index 0000000..18a1cda
--- /dev/null
+++ b/panels/power/gnome-power-panel.desktop.in.in
@@ -0,0 +1,20 @@
+[Desktop Entry]
+Name=Power
+Comment=View your battery status and change power saving settings
+Exec=gnome-control-center power
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-power-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-DevicesSettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=power
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: Search terms to find the Power panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=Power;Sleep;Suspend;Hibernate;Battery;Brightness;Dim;Blank;Monitor;DPMS;Idle;Energy;
+# Notifications are emitted by gnome-settings-daemon
+X-GNOME-UsesNotifications=true
diff --git a/panels/power/icons/info-symbolic.svg b/panels/power/icons/info-symbolic.svg
new file mode 100644
index 0000000..65d5d5d
--- /dev/null
+++ b/panels/power/icons/info-symbolic.svg
@@ -0,0 +1 @@
+<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M7.906 1A7.002 7.002 0 0 0 1 8c0 3.867 3.133 7 7 7s7-3.133 7-7-3.133-7-7-7h-.094zM7.5 4h1c.277 0 .5.223.5.5v1c0 .277-.223.5-.5.5h-1a.498.498 0 0 1-.5-.5v-1c0-.277.223-.5.5-.5zM7 7h2v5H7zm0 0" fill="#2e3436"/></svg> \ No newline at end of file
diff --git a/panels/power/icons/meson.build b/panels/power/icons/meson.build
new file mode 100644
index 0000000..4cc814b
--- /dev/null
+++ b/panels/power/icons/meson.build
@@ -0,0 +1,10 @@
+install_data(
+ 'scalable/org.gnome.Settings-power-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
+
+# what an oddity. icons should install to the same location.
+install_data(
+ 'info-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'status')
+)
diff --git a/panels/power/icons/scalable/org.gnome.Settings-power-symbolic.svg b/panels/power/icons/scalable/org.gnome.Settings-power-symbolic.svg
new file mode 100644
index 0000000..72e54cb
--- /dev/null
+++ b/panels/power/icons/scalable/org.gnome.Settings-power-symbolic.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <path d="m 5 0 c -1 0 -1 1 -1 1 v 1 h -1 s -0.707031 -0.015625 -1.449219 0.355469 c -0.738281 0.371093 -1.550781 1.3125 -1.550781 2.644531 v 8 s -0.015625 0.707031 0.355469 1.449219 c 0.367187 0.738281 1.3125 1.550781 2.644531 1.550781 h 3 c 0.550781 0 1 -0.449219 1 -1 s -0.449219 -1 -1 -1 h -3 c -0.554688 0 -1 -0.445312 -1 -1 v -8 c 0 -0.554688 0.445312 -1 1 -1 h 6 c 0.554688 0 1 0.445312 1 1 h 2 c 0 -1.332031 -0.8125 -2.273438 -1.554688 -2.644531 c -0.738281 -0.371094 -1.445312 -0.355469 -1.445312 -0.355469 h -1 v -1 c 0 -1 -1 -1 -1 -1 z m 5 6 c -1.933594 0.277344 -2.722656 2.898438 -3 4 h -2 c -0.550781 0 -1 0.449219 -1 1 s 0.449219 1 1 1 h 2 c 0.277344 1.101562 1.066406 3.722656 3 4 h 2 s 1 0 1 -1 v -1 h 3 v -2 h -3 v -2 h 3 v -2 h -3 v -1 s 0 -1 -1 -1 z m 0 0" fill="#2e3434"/>
+</svg>
diff --git a/panels/power/meson.build b/panels/power/meson.build
new file mode 100644
index 0000000..1cafe2a
--- /dev/null
+++ b/panels/power/meson.build
@@ -0,0 +1,52 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+sources = files(
+ 'cc-battery-row.c',
+ 'cc-power-panel.c',
+ 'cc-power-profile-row.c',
+ 'cc-power-profile-info-row.c'
+)
+
+resource_data = files(
+ 'cc-battery-row.ui',
+ 'cc-power-panel.ui'
+)
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname,
+ dependencies: resource_data,
+ export: true
+)
+
+deps = common_deps + [
+ gnome_settings_dep,
+ upower_glib_dep
+]
+
+panels_libs += static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [ top_inc, common_inc ],
+ dependencies: deps,
+ c_args: cflags
+)
+
+subdir('icons')
diff --git a/panels/power/power-panel-scenario-tester.py b/panels/power/power-panel-scenario-tester.py
new file mode 100755
index 0000000..59860f7
--- /dev/null
+++ b/panels/power/power-panel-scenario-tester.py
@@ -0,0 +1,311 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2021 Red Hat Inc.
+#
+# Author: Bastien Nocera <hadess@hadess.net>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import dbus
+import dbusmock
+import sys
+import os
+import fcntl
+import gi
+import subprocess
+import time
+from collections import OrderedDict
+from dbusmock import DBusTestCase
+from dbus.mainloop.glib import DBusGMainLoop
+from consolemenu import *
+from consolemenu.items import *
+
+gi.require_version('UPowerGlib', '1.0')
+gi.require_version('UMockdev', '1.0')
+
+from gi.repository import Gio
+from gi.repository import GLib
+from gi.repository import UPowerGlib
+from gi.repository import UMockdev
+
+DBusGMainLoop(set_as_default=True)
+
+
+def set_nonblock(fd):
+ '''Set a file object to non-blocking'''
+ flags = fcntl.fcntl(fd, fcntl.F_GETFL)
+ fcntl.fcntl(fd, fcntl.F_SETFL, flags | os.O_NONBLOCK)
+
+def get_templates_dir():
+ return os.path.join(os.path.dirname(__file__), 'dbusmock-templates')
+
+def get_template_path(template_name):
+ return os.path.join(get_templates_dir(), template_name + '.py')
+
+class GccDBusTestCase(DBusTestCase):
+ @classmethod
+ def setUpClass(klass):
+ klass.mocks = OrderedDict()
+
+ # Start system bus
+ DBusTestCase.setUpClass()
+ klass.test_bus = Gio.TestDBus.new(Gio.TestDBusFlags.NONE)
+ klass.test_bus.up()
+ os.environ['DBUS_SYSTEM_BUS_ADDRESS'] = klass.test_bus.get_bus_address()
+
+ # Find upower
+ if os.environ.get('UNDER_JHBUILD', False):
+ jhbuild_prefix = os.environ['JHBUILD_PREFIX']
+ klass.upowerd_path = os.path.join(jhbuild_prefix, 'libexec', 'upowerd')
+ if not GLib.file_test(klass.upowerd_path, GLib.FileTest.IS_EXECUTABLE):
+ klass.upowerd_path = None
+
+ if not os.environ.get('UNDER_JHBUILD', False) or klass.upowerd_path == None:
+ klass.upowerd_path = None
+ with open('/usr/share/dbus-1/system-services/org.freedesktop.UPower.service') as f:
+ for line in f:
+ if line.startswith('Exec='):
+ klass.upowerd_path = line.split('=', 1)[1].strip()
+ break
+ assert klass.upowerd_path, 'could not determine daemon path from D-BUS .service file'
+
+ # Start mock udev
+ klass.testbed = UMockdev.Testbed.new()
+
+ # Start ppd and logind
+ klass.start_from_template('power_profiles_daemon')
+ klass.start_from_template('logind')
+
+ klass.system_bus = Gio.bus_get_sync(Gio.BusType.SYSTEM, None)
+
+ @classmethod
+ def tearDownClass(klass):
+ for (mock_server, mock_obj) in reversed(klass.mocks.values()):
+ mock_server.terminate()
+ mock_server.wait()
+
+ DBusTestCase.tearDownClass()
+
+ @classmethod
+ def start_from_template(klass, template, params={}):
+ mock_server, mock_obj = \
+ klass.spawn_server_template(template,
+ params,
+ stdout=subprocess.PIPE)
+ set_nonblock(mock_server.stdout)
+
+ mocks = (mock_server, mock_obj)
+ assert klass.mocks.setdefault(template, mocks) == mocks
+ return mocks
+
+ def get_upower_property(self, name):
+ '''Get property value from UPower D-Bus interface.'''
+
+ proxy = Gio.DBusProxy.new_sync(
+ self.system_bus, Gio.DBusProxyFlags.DO_NOT_AUTO_START, None, 'org.freedesktop.UPower',
+ '/org/freedesktop/UPower', 'org.freedesktop.DBus.Properties', None)
+ return proxy.Get('(ss)', 'org.freedesktop.UPower', name)
+
+ def __init__(self):
+ self.devices = {}
+ self.ppd = self.mocks['power_profiles_daemon'][1]
+
+ os.environ['UMOCKDEV_DIR'] = self.testbed.get_root_dir()
+ # See https://github.com/systemd/systemd/pull/21761
+ # os.environ['SYSTEMD_LOG_LEVEL'] = 'debug'
+ self.upowerd = subprocess.Popen([ self.upowerd_path ],
+ env=os.environ, stdout=None,
+ stderr=subprocess.STDOUT)
+
+ # wait until the daemon gets online
+ timeout = 100
+ while timeout > 0:
+ time.sleep(0.1)
+ timeout -= 1
+ try:
+ self.get_upower_property('DaemonVersion')
+ break
+ except GLib.GError:
+ pass
+ else:
+ self.fail('daemon did not start in 10 seconds')
+
+ # self.assertEqual(self.upowerd.poll(), None, 'daemon crashed')
+
+ def toggle_devices(self, device_types):
+ for _type in device_types:
+ if _type not in self.devices:
+ self.devices[_type] = self.add_device(_type)
+ # print('added ' + _type)
+ else:
+ # print('removing ' + _type)
+ devs = self.devices[_type]
+ devs.reverse()
+ for dev in devs:
+ self.testbed.uevent(dev, 'remove')
+ self.testbed.remove_device(dev)
+ del self.devices[_type]
+
+ # out = subprocess.check_output(['upower', '--dump'],
+ # universal_newlines=True)
+ # print(out)
+
+ def add_device(self, device):
+ if device == 'battery':
+ dev = self.testbed.add_device('power_supply', 'BAT0', None,
+ ['type', 'Battery',
+ 'present', '1',
+ 'status', 'Discharging',
+ 'energy_full', '60000000',
+ 'energy_full_design', '80000000',
+ 'energy_now', '48000000',
+ 'voltage_now', '12000000',
+ 'cycle_count', '250'], [])
+ return [ dev ]
+
+ elif device == '2nd-battery':
+ # Not charging or discharging
+ # No cycle count available
+ dev = self.testbed.add_device('power_supply', 'BAT1', None,
+ ['type', 'Battery',
+ 'present', '1',
+ 'status', 'Not charging',
+ 'energy_full', '30000000',
+ 'energy_full_design', '40000000',
+ 'energy_now', '20000000',
+ 'voltage_now', '12000000',
+ 'cycle_count', '-1'], [])
+ return [ dev ]
+
+ elif device == 'ac':
+ dev = self.testbed.add_device('power_supply', 'AC', None,
+ ['type', 'Mains', 'online', '0'], [])
+ return [ dev ]
+
+ elif device == 'keyboard':
+ dev = self.testbed.add_device('bluetooth',
+ 'usb2/bluetooth/hci0/hci0:1',
+ None,
+ [], [])
+ devs = [ dev ]
+
+ parent = dev
+ devs.append(self.testbed.add_device(
+ 'input',
+ 'input3/event4',
+ parent,
+ [], ['DEVNAME', 'input/event4', 'ID_INPUT_KEYBOARD', '1']))
+
+ devs.append(self.testbed.add_device(
+ 'power_supply',
+ 'power_supply/hid-00:22:33:44:55:66-battery',
+ parent,
+ ['type', 'Battery',
+ 'scope', 'Device',
+ 'present', '1',
+ 'online', '1',
+ 'status', 'Discharging',
+ 'capacity', '40',
+ 'model_name', 'Monster Typist'],
+ []))
+ return devs
+
+ elif device == 'mouse':
+ dev = self.testbed.add_device('hid',
+ '/devices/pci0000:00/0000:00:14.0/usb3/3-10/3-10:1.2/0003:046D:C52B.0009/0003:046D:4101.000A',
+ None,
+ [], [])
+ devs = [ dev ]
+
+ parent = dev
+ devs.append(self.testbed.add_device('input',
+ '/devices/pci0000:00/0000:00:14.0/usb3/3-10/3-10:1.2/0003:046D:C52B.0009/0003:046D:4101.000A/input/input22',
+ parent,
+ [], ['DEVNAME', 'input/mouse3', 'ID_INPUT_MOUSE', '1']))
+
+ devs.append(self.testbed.add_device('power_supply',
+ '/devices/pci0000:00/0000:00:14.0/usb3/3-10/3-10:1.2/0003:046D:C52B.0009/0003:046D:4101.000A/power_supply/hidpp_battery_3',
+ parent,
+ ['type', 'Battery',
+ 'scope', 'Device',
+ 'present', '1',
+ 'online', '1',
+ 'status', 'Discharging',
+ 'capacity', '30',
+ 'serial_number', '123456',
+ 'model_name', 'Fancy Mouse'],
+ []))
+ return devs
+
+ elif device == 'ups':
+ dev = self.testbed.add_device('usb', 'hiddev0', None, [],
+ ['DEVNAME', 'null',
+ 'UPOWER_VENDOR', 'APC',
+ 'UPOWER_BATTERY_TYPE', 'ups',
+ 'UPOWER_FAKE_DEVICE', '1',
+ 'UPOWER_FAKE_HID_CHARGING', '0',
+ 'UPOWER_FAKE_HID_PERCENTAGE', '70'])
+ return [ dev ]
+
+ print('Unhandled device')
+ return None
+
+ def cycle_degraded(self):
+ perf = self.ppd.Get('net.hadess.PowerProfiles', 'PerformanceDegraded')
+ if perf == '':
+ perf = 'lap-detected'
+ elif perf == 'lap-detected':
+ perf = 'high-operating-temperature'
+ elif perf == 'high-operating-temperature':
+ perf = ''
+ mock_iface = dbus.Interface(self.ppd, dbusmock.MOCK_IFACE)
+ mock_iface.UpdateProperties('net.hadess.PowerProfiles', {
+ 'PerformanceDegraded': dbus.String(perf, variant_level=1)
+ })
+
+ def start_menu(self):
+ menu = ConsoleMenu("Power Panel", "Scenario Tester", clear_screen = False)
+ function_item = FunctionItem("Toggle Keyboard", self.toggle_devices, [["keyboard"]])
+ menu.append_item(function_item)
+
+ function_item = FunctionItem("Toggle Mouse", self.toggle_devices, [["mouse"]])
+ menu.append_item(function_item)
+
+ function_item = FunctionItem("Toggle UPS", self.toggle_devices, [["ups"]])
+ menu.append_item(function_item)
+
+ function_item = FunctionItem("Toggle laptop battery", self.toggle_devices, [['ac', 'battery']])
+ menu.append_item(function_item)
+
+ function_item = FunctionItem("Toggle 2nd battery", self.toggle_devices, [['2nd-battery']])
+ menu.append_item(function_item)
+
+ function_item = FunctionItem("Cycle degraded performance", self.cycle_degraded, [])
+ menu.append_item(function_item)
+
+ menu.start(show_exit_option=False)
+
+ def wrap_call(self):
+ os.environ['GSETTINGS_BACKEND'] = 'memory'
+
+ wrapper = os.environ.get('META_DBUS_RUNNER_WRAPPER')
+ args = ['gnome-control-center', 'power']
+ if wrapper == 'gdb':
+ args = ['gdb', '-ex', 'r', '-ex', 'bt full', '--args'] + args
+ elif wrapper:
+ args = wrapper.split(' ') + args
+
+ p = subprocess.Popen(args, env=os.environ)
+ p.wait()
+
+if __name__ == '__main__':
+ if 'umockdev' not in os.environ.get('LD_PRELOAD', ''):
+ os.execvp('umockdev-wrapper', ['umockdev-wrapper'] + sys.argv)
+
+ GccDBusTestCase.setUpClass()
+ test_case = GccDBusTestCase()
+ test_case.start_menu()
+ try:
+ test_case.wrap_call()
+ finally:
+ GccDBusTestCase.tearDownClass()
diff --git a/panels/power/power-profiles.css b/panels/power/power-profiles.css
new file mode 100644
index 0000000..1c31493
--- /dev/null
+++ b/panels/power/power-profiles.css
@@ -0,0 +1,7 @@
+.power-profile.low-power {
+ color: @success_color;
+}
+
+.power-profile.performance {
+ color: @error_color;
+}
diff --git a/panels/power/power.gresource.xml b/panels/power/power.gresource.xml
new file mode 100644
index 0000000..5a33c8e
--- /dev/null
+++ b/panels/power/power.gresource.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/power">
+ <file preprocess="xml-stripblanks">cc-battery-row.ui</file>
+ <file preprocess="xml-stripblanks">cc-power-panel.ui</file>
+ <file preprocess="xml-stripblanks">cc-power-profile-row.ui</file>
+ <file preprocess="xml-stripblanks">cc-power-profile-info-row.ui</file>
+ <file>battery-levels.css</file>
+ <file>power-profiles.css</file>
+ </gresource>
+</gresources>
diff --git a/panels/printers/cc-printers-panel.c b/panels/printers/cc-printers-panel.c
new file mode 100644
index 0000000..34774a7
--- /dev/null
+++ b/panels/printers/cc-printers-panel.c
@@ -0,0 +1,1340 @@
+/*
+ * Copyright (C) 2010 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+
+#include "shell/cc-object-storage.h"
+
+#include "cc-printers-panel.h"
+#include "cc-printers-resources.h"
+#include "pp-printer.h"
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+#include <glib/gstdio.h>
+#include <polkit/polkit.h>
+#include <gdesktop-enums.h>
+
+#include <cups/cups.h>
+#include <cups/ppd.h>
+
+#include <math.h>
+
+#include "pp-new-printer-dialog.h"
+#include "pp-utils.h"
+#include "pp-cups.h"
+#include "pp-printer-entry.h"
+#include "pp-job.h"
+#include "pp-new-printer.h"
+
+#include "cc-permission-infobar.h"
+#include "cc-util.h"
+
+#define JOB_DEFAULT_PRIORITY 50
+#define RENEW_INTERVAL 500
+#define SUBSCRIPTION_DURATION 600
+
+#define CUPS_DBUS_NAME "org.cups.cupsd.Notifier"
+#define CUPS_DBUS_PATH "/org/cups/cupsd/Notifier"
+#define CUPS_DBUS_INTERFACE "org.cups.cupsd.Notifier"
+
+#define CUPS_STATUS_CHECK_INTERVAL 5
+
+#if (CUPS_VERSION_MAJOR > 1) || (CUPS_VERSION_MINOR > 5)
+#define HAVE_CUPS_1_6 1
+#endif
+
+#ifndef HAVE_CUPS_1_6
+#define ippGetState(ipp) ipp->state
+#define ippGetStatusCode(ipp) ipp->request.status.status_code
+#define ippGetString(attr, element, language) attr->values[element].string.text
+#endif
+
+struct _CcPrintersPanel
+{
+ CcPanel parent_instance;
+
+ GtkBuilder *builder;
+
+ PpCups *cups;
+
+ cups_dest_t *dests;
+ int num_dests;
+
+ GPermission *permission;
+ gboolean is_authorized;
+
+ GSettings *lockdown_settings;
+ CcPermissionInfobar *permission_infobar;
+
+ PpNewPrinterDialog *pp_new_printer_dialog;
+
+ GDBusProxy *cups_proxy;
+ GDBusConnection *cups_bus_connection;
+ gint subscription_id;
+ guint subscription_renewal_id;
+ guint cups_status_check_id;
+ guint dbus_subscription_id;
+ guint remove_printer_timeout_id;
+
+ GtkRevealer *notification;
+ PPDList *all_ppds_list;
+
+ gchar *new_printer_name;
+
+ gchar *renamed_printer_name;
+ gchar *old_printer_name;
+ gchar *deleted_printer_name;
+ GList *deleted_printers;
+ GObject *reference;
+
+ GHashTable *printer_entries;
+ gboolean entries_filled;
+ GVariant *action;
+
+ GtkSizeGroup *size_group;
+};
+
+CC_PANEL_REGISTER (CcPrintersPanel, cc_printers_panel)
+
+typedef struct
+{
+ gchar *printer_name;
+ GCancellable *cancellable;
+} SetPPDItem;
+
+enum {
+ PROP_0,
+ PROP_PARAMETERS
+};
+
+static void actualize_printers_list (CcPrintersPanel *self);
+static void update_sensitivity (gpointer user_data);
+static void detach_from_cups_notifier (gpointer data);
+static void free_dests (CcPrintersPanel *self);
+static void set_current_page (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data);
+
+static void
+execute_action (CcPrintersPanel *self,
+ GVariant *action)
+{
+ PpPrinterEntry *printer_entry;
+ const gchar *action_name;
+ const gchar *printer_name;
+ gint count;
+
+ count = g_variant_n_children (action);
+ if (count == 2)
+ {
+ g_autoptr(GVariant) action_variant = NULL;
+
+ g_variant_get_child (action, 0, "v", &action_variant);
+ action_name = g_variant_get_string (action_variant, NULL);
+
+ /* authenticate-jobs printer-name */
+ if (g_strcmp0 (action_name, "authenticate-jobs") == 0)
+ {
+ g_autoptr(GVariant) variant = NULL;
+
+ g_variant_get_child (action, 1, "v", &variant);
+ printer_name = g_variant_get_string (variant, NULL);
+
+ printer_entry = PP_PRINTER_ENTRY (g_hash_table_lookup (self->printer_entries, printer_name));
+ if (printer_entry != NULL)
+ pp_printer_entry_authenticate_jobs (printer_entry);
+ else
+ g_warning ("Could not find printer \"%s\"!", printer_name);
+ }
+ /* show-jobs printer-name */
+ else if (g_strcmp0 (action_name, "show-jobs") == 0)
+ {
+ g_autoptr(GVariant) variant = NULL;
+
+ g_variant_get_child (action, 1, "v", &variant);
+ printer_name = g_variant_get_string (variant, NULL);
+
+ printer_entry = PP_PRINTER_ENTRY (g_hash_table_lookup (self->printer_entries, printer_name));
+ if (printer_entry != NULL)
+ pp_printer_entry_show_jobs_dialog (printer_entry);
+ else
+ g_warning ("Could not find printer \"%s\"!", printer_name);
+ }
+ }
+}
+
+static void
+cc_printers_panel_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+cc_printers_panel_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcPrintersPanel *self = CC_PRINTERS_PANEL (object);
+ GVariant *parameters;
+
+ switch (property_id)
+ {
+ case PROP_PARAMETERS:
+ parameters = g_value_get_variant (value);
+ if (parameters != NULL && g_variant_n_children (parameters) > 0)
+ {
+ if (self->entries_filled)
+ {
+ execute_action (CC_PRINTERS_PANEL (object), parameters);
+ }
+ else
+ {
+ if (self->action != NULL)
+ g_variant_unref (self->action);
+ self->action = g_variant_ref (parameters);
+ }
+ }
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+cc_printers_panel_constructed (GObject *object)
+{
+ CcPrintersPanel *self = CC_PRINTERS_PANEL (object);
+ GtkWidget *widget;
+ CcShell *shell;
+
+ G_OBJECT_CLASS (cc_printers_panel_parent_class)->constructed (object);
+
+ shell = cc_panel_get_shell (CC_PANEL (self));
+
+ widget = (GtkWidget*)
+ gtk_builder_get_object (self->builder, "search-bar");
+ gtk_search_bar_set_key_capture_widget (GTK_SEARCH_BAR (widget),
+ GTK_WIDGET (shell));
+}
+
+static void
+printer_removed_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ PpPrinter *printer = PP_PRINTER (source_object);
+ g_autoptr(GError) error = NULL;
+
+ pp_printer_delete_finish (printer, result, &error);
+
+ if (user_data != NULL)
+ {
+ g_autoptr(GObject) reference = G_OBJECT (user_data);
+
+ if (g_object_get_data (reference, "self") != NULL)
+ {
+ CcPrintersPanel *self = CC_PRINTERS_PANEL (g_object_get_data (reference, "self"));
+ GList *iter;
+
+ for (iter = self->deleted_printers; iter != NULL; iter = iter->next)
+ {
+ if (g_strcmp0 (iter->data, pp_printer_get_name (printer)) == 0)
+ {
+ g_free (iter->data);
+ self->deleted_printers = g_list_delete_link (self->deleted_printers, iter);
+ break;
+ }
+ }
+ }
+ }
+
+ if (error != NULL)
+ g_warning ("Printer could not be deleted: %s", error->message);
+}
+
+static void
+cc_printers_panel_dispose (GObject *object)
+{
+ CcPrintersPanel *self = CC_PRINTERS_PANEL (object);
+
+ detach_from_cups_notifier (CC_PRINTERS_PANEL (object));
+
+ if (self->deleted_printer_name != NULL)
+ {
+ g_autoptr(PpPrinter) printer = pp_printer_new (self->deleted_printer_name);
+ pp_printer_delete_async (printer,
+ NULL,
+ printer_removed_cb,
+ NULL);
+ }
+
+ g_clear_object (&self->cups);
+ g_clear_pointer (&self->new_printer_name, g_free);
+ g_clear_pointer (&self->renamed_printer_name, g_free);
+ g_clear_pointer (&self->old_printer_name, g_free);
+ g_clear_object (&self->builder);
+ g_clear_object (&self->lockdown_settings);
+ g_clear_object (&self->permission);
+ g_clear_handle_id (&self->cups_status_check_id, g_source_remove);
+ g_clear_handle_id (&self->remove_printer_timeout_id, g_source_remove);
+ g_clear_pointer (&self->deleted_printer_name, g_free);
+ g_clear_pointer (&self->action, g_variant_unref);
+ g_clear_pointer (&self->printer_entries, g_hash_table_destroy);
+ g_clear_pointer (&self->all_ppds_list, ppd_list_free);
+ free_dests (self);
+ g_list_free_full (self->deleted_printers, g_free);
+ self->deleted_printers = NULL;
+ if (self->reference != NULL)
+ g_object_set_data (self->reference, "self", NULL);
+ g_clear_object (&self->reference);
+
+ G_OBJECT_CLASS (cc_printers_panel_parent_class)->dispose (object);
+}
+
+static const char *
+cc_printers_panel_get_help_uri (CcPanel *panel)
+{
+ return "help:gnome-help/printing";
+}
+
+static void
+cc_printers_panel_class_init (CcPrintersPanelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+
+ object_class->get_property = cc_printers_panel_get_property;
+ object_class->set_property = cc_printers_panel_set_property;
+ object_class->constructed = cc_printers_panel_constructed;
+ object_class->dispose = cc_printers_panel_dispose;
+
+ panel_class->get_help_uri = cc_printers_panel_get_help_uri;
+
+ g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters");
+}
+
+static void
+on_get_job_attributes_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcPrintersPanel *self = (CcPrintersPanel*) user_data;
+ const gchar *job_originating_user_name;
+ const gchar *job_printer_uri;
+ g_autoptr(GVariant) attributes = NULL;
+ g_autoptr(GError) error = NULL;
+
+ attributes = pp_job_get_attributes_finish (PP_JOB (source_object), res, &error);
+
+ if (attributes != NULL)
+ {
+ g_autoptr(GVariant) username = NULL;
+
+ if ((username = g_variant_lookup_value (attributes, "job-originating-user-name", G_VARIANT_TYPE ("as"))) != NULL)
+ {
+ g_autoptr(GVariant) printer_uri = NULL;
+
+ if ((printer_uri = g_variant_lookup_value (attributes, "job-printer-uri", G_VARIANT_TYPE ("as"))) != NULL)
+ {
+ job_originating_user_name = g_variant_get_string (g_variant_get_child_value (username, 0), NULL);
+ job_printer_uri = g_variant_get_string (g_variant_get_child_value (printer_uri, 0), NULL);
+
+ if (job_originating_user_name != NULL && job_printer_uri != NULL &&
+ g_strcmp0 (job_originating_user_name, cupsUser ()) == 0 &&
+ g_strrstr (job_printer_uri, "/") != 0 &&
+ self->dests != NULL)
+ {
+ PpPrinterEntry *printer_entry;
+ gchar *printer_name;
+
+ printer_name = g_strrstr (job_printer_uri, "/") + 1;
+ printer_entry = PP_PRINTER_ENTRY (g_hash_table_lookup (self->printer_entries, printer_name));
+
+ pp_printer_entry_update_jobs_count (printer_entry);
+ }
+ }
+ }
+ }
+}
+
+static void
+on_cups_notification (GDBusConnection *connection,
+ const char *sender_name,
+ const char *object_path,
+ const char *interface_name,
+ const char *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ CcPrintersPanel *self = (CcPrintersPanel*) user_data;
+ gboolean printer_is_accepting_jobs;
+ gchar *printer_name = NULL;
+ gchar *text = NULL;
+ gchar *printer_uri = NULL;
+ gchar *printer_state_reasons = NULL;
+ gchar *job_state_reasons = NULL;
+ gchar *job_name = NULL;
+ guint job_id;
+ gint printer_state;
+ gint job_state;
+ gint job_impressions_completed;
+ static gchar *requested_attrs[] = {
+ "job-printer-uri",
+ "job-originating-user-name",
+ NULL };
+
+ if (g_strcmp0 (signal_name, "PrinterAdded") != 0 &&
+ g_strcmp0 (signal_name, "PrinterDeleted") != 0 &&
+ g_strcmp0 (signal_name, "PrinterStateChanged") != 0 &&
+ g_strcmp0 (signal_name, "PrinterStopped") != 0 &&
+ g_strcmp0 (signal_name, "JobCreated") != 0 &&
+ g_strcmp0 (signal_name, "JobCompleted") != 0)
+ return;
+
+ if (g_variant_n_children (parameters) == 1)
+ g_variant_get (parameters, "(&s)", &text);
+ else if (g_variant_n_children (parameters) == 6)
+ {
+ g_variant_get (parameters, "(&s&s&su&sb)",
+ &text,
+ &printer_uri,
+ &printer_name,
+ &printer_state,
+ &printer_state_reasons,
+ &printer_is_accepting_jobs);
+ }
+ else if (g_variant_n_children (parameters) == 11)
+ {
+ g_variant_get (parameters, "(&s&s&su&sbuu&s&su)",
+ &text,
+ &printer_uri,
+ &printer_name,
+ &printer_state,
+ &printer_state_reasons,
+ &printer_is_accepting_jobs,
+ &job_id,
+ &job_state,
+ &job_state_reasons,
+ &job_name,
+ &job_impressions_completed);
+ }
+
+ if (g_strcmp0 (signal_name, "PrinterAdded") == 0 ||
+ g_strcmp0 (signal_name, "PrinterDeleted") == 0 ||
+ g_strcmp0 (signal_name, "PrinterStateChanged") == 0 ||
+ g_strcmp0 (signal_name, "PrinterStopped") == 0)
+ actualize_printers_list (self);
+ else if (g_strcmp0 (signal_name, "JobCreated") == 0 ||
+ g_strcmp0 (signal_name, "JobCompleted") == 0)
+ {
+ g_autoptr(PpJob) job = NULL;
+
+ job = pp_job_new (job_id, NULL, 0, JOB_DEFAULT_PRIORITY, NULL);
+ pp_job_get_attributes_async (job,
+ requested_attrs,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ on_get_job_attributes_cb,
+ self);
+ }
+}
+
+static gchar *subscription_events[] = {
+ "printer-added",
+ "printer-deleted",
+ "printer-stopped",
+ "printer-state-changed",
+ "job-created",
+ "job-completed",
+ NULL};
+
+static void
+renew_subscription_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ CcPrintersPanel *self = (CcPrintersPanel*) user_data;
+ gint subscription_id;
+
+ subscription_id = pp_cups_renew_subscription_finish (PP_CUPS (source_object), result);
+
+ if (subscription_id > 0)
+ self->subscription_id = subscription_id;
+}
+
+static gboolean
+renew_subscription (gpointer data)
+{
+ CcPrintersPanel *self = (CcPrintersPanel*) data;
+
+ pp_cups_renew_subscription_async (self->cups,
+ self->subscription_id,
+ subscription_events,
+ SUBSCRIPTION_DURATION,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ renew_subscription_cb,
+ data);
+
+ return G_SOURCE_CONTINUE;
+}
+
+static void
+attach_to_cups_notifier_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ CcPrintersPanel *self = (CcPrintersPanel*) user_data;
+ g_autoptr(GError) error = NULL;
+ gint subscription_id;
+
+ subscription_id = pp_cups_renew_subscription_finish (PP_CUPS (source_object), result);
+
+ if (subscription_id > 0)
+ {
+ self->subscription_id = subscription_id;
+
+ self->subscription_renewal_id =
+ g_timeout_add_seconds (RENEW_INTERVAL, renew_subscription, self);
+
+ self->cups_proxy = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ CUPS_DBUS_NAME,
+ CUPS_DBUS_PATH,
+ CUPS_DBUS_INTERFACE,
+ NULL,
+ &error);
+
+ if (!self->cups_proxy)
+ {
+ g_warning ("%s", error->message);
+ return;
+ }
+
+ self->cups_bus_connection = g_dbus_proxy_get_connection (self->cups_proxy);
+
+ self->dbus_subscription_id =
+ g_dbus_connection_signal_subscribe (self->cups_bus_connection,
+ NULL,
+ CUPS_DBUS_INTERFACE,
+ NULL,
+ CUPS_DBUS_PATH,
+ NULL,
+ 0,
+ on_cups_notification,
+ self,
+ NULL);
+ }
+}
+
+static void
+attach_to_cups_notifier (gpointer data)
+{
+ CcPrintersPanel *self = (CcPrintersPanel*) data;
+
+ pp_cups_renew_subscription_async (self->cups,
+ self->subscription_id,
+ subscription_events,
+ SUBSCRIPTION_DURATION,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ attach_to_cups_notifier_cb,
+ data);
+}
+
+static void
+subscription_cancel_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ pp_cups_cancel_subscription_finish (PP_CUPS (source_object), result);
+}
+
+static void
+detach_from_cups_notifier (gpointer data)
+{
+ CcPrintersPanel *self = (CcPrintersPanel*) data;
+
+ if (self->dbus_subscription_id != 0) {
+ g_dbus_connection_signal_unsubscribe (self->cups_bus_connection,
+ self->dbus_subscription_id);
+ self->dbus_subscription_id = 0;
+ }
+
+ pp_cups_cancel_subscription_async (self->cups,
+ self->subscription_id,
+ subscription_cancel_cb,
+ NULL);
+
+ self->subscription_id = 0;
+
+ if (self->subscription_renewal_id != 0) {
+ g_source_remove (self->subscription_renewal_id);
+ self->subscription_renewal_id = 0;
+ }
+
+ g_clear_object (&self->cups_proxy);
+}
+
+static void
+free_dests (CcPrintersPanel *self)
+{
+ if (self->num_dests > 0)
+ {
+ cupsFreeDests (self->num_dests, self->dests);
+ }
+ self->dests = NULL;
+ self->num_dests = 0;
+}
+
+static void
+on_printer_deletion_undone (CcPrintersPanel *self)
+{
+ GtkWidget *widget;
+
+ gtk_revealer_set_reveal_child (self->notification, FALSE);
+
+ g_clear_pointer (&self->deleted_printer_name, g_free);
+
+ widget = (GtkWidget*) gtk_builder_get_object (self->builder, "content");
+ gtk_list_box_invalidate_filter (GTK_LIST_BOX (widget));
+
+ g_clear_handle_id (&self->remove_printer_timeout_id, g_source_remove);
+
+ if (self->num_dests > 0)
+ {
+ widget = (GtkWidget *) gtk_builder_get_object (self->builder, "main-vbox");
+ gtk_stack_set_visible_child_name (GTK_STACK (widget), "printers-list");
+ }
+}
+
+static void
+on_notification_dismissed (CcPrintersPanel *self)
+{
+ g_clear_handle_id (&self->remove_printer_timeout_id, g_source_remove);
+
+ if (self->deleted_printer_name != NULL)
+ {
+ g_autoptr(PpPrinter) printer = NULL;
+
+ printer = pp_printer_new (self->deleted_printer_name);
+ /* The reference tells to the callback whether
+ printers panel was already destroyed so
+ it knows whether it can access the list
+ of deleted printers in it (see below).
+ */
+ pp_printer_delete_async (printer,
+ NULL,
+ printer_removed_cb,
+ g_object_ref (self->reference));
+
+ /* List of printers which were recently deleted but are still available
+ in CUPS due to async nature of the method (e.g. quick deletion
+ of several printers).
+ */
+ self->deleted_printers = g_list_prepend (self->deleted_printers, self->deleted_printer_name);
+ self->deleted_printer_name = NULL;
+ }
+
+ gtk_revealer_set_reveal_child (self->notification, FALSE);
+}
+
+static gboolean
+on_remove_printer_timeout (CcPrintersPanel *self)
+{
+ self->remove_printer_timeout_id = 0;
+
+ on_notification_dismissed (self);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+on_printer_deleted (CcPrintersPanel *self,
+ PpPrinterEntry *printer_entry)
+{
+ GtkLabel *label;
+ g_autofree gchar *notification_message = NULL;
+ GtkWidget *widget;
+
+ on_notification_dismissed (self);
+
+ /* Translators: %s is the printer name */
+ notification_message = g_strdup_printf (_("Printer “%s” has been deleted"),
+ pp_printer_entry_get_name (printer_entry));
+ label = (GtkLabel*)
+ gtk_builder_get_object (self->builder, "notification-label");
+ gtk_label_set_label (label, notification_message);
+
+ self->deleted_printer_name = g_strdup (pp_printer_entry_get_name (printer_entry));
+
+ widget = (GtkWidget*) gtk_builder_get_object (self->builder, "content");
+ gtk_list_box_invalidate_filter (GTK_LIST_BOX (widget));
+
+ gtk_revealer_set_reveal_child (self->notification, TRUE);
+
+ self->remove_printer_timeout_id = g_timeout_add_seconds (10, G_SOURCE_FUNC (on_remove_printer_timeout), self);
+
+ if (self->num_dests == 1 + g_list_length (self->deleted_printers))
+ pp_cups_connection_test_async (self->cups, NULL, set_current_page, self);
+}
+
+static void
+on_printer_renamed (CcPrintersPanel *self,
+ gchar *new_name,
+ PpPrinterEntry *printer_entry)
+{
+ self->old_printer_name = g_strdup (pp_printer_entry_get_name (printer_entry));
+ self->renamed_printer_name = g_strdup (new_name);
+}
+
+static void
+on_printer_changed (CcPrintersPanel *self)
+{
+ actualize_printers_list (self);
+}
+
+static void
+add_printer_entry (CcPrintersPanel *self,
+ cups_dest_t printer)
+{
+ PpPrinterEntry *printer_entry;
+ GtkWidget *content;
+ GSList *widgets, *l;
+
+ content = (GtkWidget*) gtk_builder_get_object (self->builder, "content");
+
+ printer_entry = pp_printer_entry_new (printer, self->is_authorized);
+ gtk_widget_show (GTK_WIDGET (printer_entry));
+
+ widgets = pp_printer_entry_get_size_group_widgets (printer_entry);
+ for (l = widgets; l != NULL; l = l->next)
+ gtk_size_group_add_widget (self->size_group, GTK_WIDGET (l->data));
+ g_slist_free (widgets);
+
+ g_signal_connect_object (printer_entry,
+ "printer-changed",
+ G_CALLBACK (on_printer_changed),
+ self,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (printer_entry,
+ "printer-delete",
+ G_CALLBACK (on_printer_deleted),
+ self,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (printer_entry,
+ "printer-renamed",
+ G_CALLBACK (on_printer_renamed),
+ self,
+ G_CONNECT_SWAPPED);
+
+ gtk_list_box_insert (GTK_LIST_BOX (content), GTK_WIDGET (printer_entry), -1);
+
+ g_hash_table_insert (self->printer_entries, g_strdup (printer.name), printer_entry);
+}
+
+static void
+set_current_page (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ CcPrintersPanel *self = (CcPrintersPanel *) user_data;
+ GtkWidget *widget;
+ gboolean success;
+
+ success = pp_cups_connection_test_finish (PP_CUPS (source_object), result, NULL);
+
+ widget = (GtkWidget*) gtk_builder_get_object (self->builder, "main-vbox");
+ if (success)
+ gtk_stack_set_visible_child_name (GTK_STACK (widget), "empty-state");
+ else
+ gtk_stack_set_visible_child_name (GTK_STACK (widget), "no-cups-page");
+
+ update_sensitivity (user_data);
+}
+
+static gboolean
+remove_nonexisting_entry (CcPrintersPanel *self,
+ PpPrinterEntry *entry)
+{
+ gboolean exists = FALSE;
+ gint i;
+
+ for (i = 0; i < self->num_dests; i++)
+ {
+ if (g_strcmp0 (self->dests[i].name, pp_printer_entry_get_name (entry)) == 0)
+ {
+ exists = TRUE;
+ break;
+ }
+ }
+
+ if (!exists)
+ g_hash_table_remove (self->printer_entries, pp_printer_entry_get_name (entry));
+
+ return !exists;
+}
+
+static void
+actualize_printers_list_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ CcPrintersPanel *self = (CcPrintersPanel*) user_data;
+ GtkWidget *widget;
+ PpCupsDests *cups_dests;
+ GtkWidget *child;
+ gboolean new_printer_available = FALSE;
+ g_autoptr(GError) error = NULL;
+ gpointer item;
+ int i;
+
+ cups_dests = pp_cups_get_dests_finish (PP_CUPS (source_object), result, &error);
+
+ if (cups_dests == NULL && error != NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ g_warning ("Could not get dests: %s", error->message);
+ }
+
+ return;
+ }
+
+ free_dests (self);
+ self->dests = cups_dests->dests;
+ self->num_dests = cups_dests->num_of_dests;
+ g_free (cups_dests);
+
+ widget = (GtkWidget*) gtk_builder_get_object (self->builder, "main-vbox");
+ if ((self->num_dests == 0 && self->new_printer_name == NULL) ||
+ (self->num_dests == 1 + g_list_length (self->deleted_printers) &&
+ self->deleted_printer_name != NULL))
+ pp_cups_connection_test_async (PP_CUPS (source_object), NULL, set_current_page, self);
+ else
+ gtk_stack_set_visible_child_name (GTK_STACK (widget), "printers-list");
+
+ widget = (GtkWidget*) gtk_builder_get_object (self->builder, "content");
+ child = gtk_widget_get_first_child (widget);
+ while (child)
+ {
+ GtkWidget *next = gtk_widget_get_next_sibling (child);
+
+ if (remove_nonexisting_entry (self, PP_PRINTER_ENTRY (child)))
+ gtk_list_box_remove (GTK_LIST_BOX (widget), child);
+
+ child = next;
+ }
+
+ for (i = 0; i < self->num_dests; i++)
+ {
+ new_printer_available = g_strcmp0 (self->dests[i].name, self->renamed_printer_name) == 0;
+ if (new_printer_available)
+ break;
+ }
+
+ for (i = 0; i < self->num_dests; i++)
+ {
+ if (new_printer_available && g_strcmp0 (self->dests[i].name, self->old_printer_name) == 0)
+ continue;
+
+ item = g_hash_table_lookup (self->printer_entries, self->dests[i].name);
+ if (item != NULL)
+ pp_printer_entry_update (PP_PRINTER_ENTRY (item), self->dests[i], self->is_authorized);
+ else
+ add_printer_entry (self, self->dests[i]);
+ }
+
+ if (!self->entries_filled)
+ {
+ if (self->action != NULL)
+ {
+ execute_action (self, self->action);
+ g_variant_unref (self->action);
+ self->action = NULL;
+ }
+
+ self->entries_filled = TRUE;
+ }
+
+ update_sensitivity (user_data);
+
+ if (self->new_printer_name != NULL)
+ {
+ GtkScrolledWindow *scrolled_window;
+ GtkAllocation allocation;
+ GtkAdjustment *adjustment;
+ GtkWidget *printer_entry;
+
+ /* Scroll the view to show the newly added printer-entry. */
+ scrolled_window = GTK_SCROLLED_WINDOW (gtk_builder_get_object (self->builder,
+ "scrolled-window"));
+ adjustment = gtk_scrolled_window_get_vadjustment (scrolled_window);
+
+ printer_entry = GTK_WIDGET (g_hash_table_lookup (self->printer_entries,
+ self->new_printer_name));
+ if (printer_entry != NULL)
+ {
+ gtk_widget_get_allocation (printer_entry, &allocation);
+ g_clear_pointer (&self->new_printer_name, g_free);
+
+ gtk_adjustment_set_value (adjustment,
+ allocation.y - gtk_widget_get_margin_top (printer_entry));
+ }
+ }
+}
+
+static void
+actualize_printers_list (CcPrintersPanel *self)
+{
+ pp_cups_get_dests_async (self->cups,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ actualize_printers_list_cb,
+ self);
+}
+
+static void
+printer_add_async_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcPrintersPanel *self = (CcPrintersPanel*) user_data;
+ gboolean success;
+ g_autoptr(GError) error = NULL;
+
+ success = pp_new_printer_add_finish (PP_NEW_PRINTER (source_object), res, &error);
+
+ if (!success)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ g_warning ("%s", error->message);
+
+ GtkWidget *message_dialog;
+
+ message_dialog = gtk_message_dialog_new (NULL,
+ 0,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ /* Translators: Addition of the new printer failed. */
+ _("Failed to add new printer."));
+ g_signal_connect (message_dialog,
+ "response",
+ G_CALLBACK (gtk_window_destroy),
+ NULL);
+ gtk_widget_show (message_dialog);
+ }
+ }
+
+ actualize_printers_list (self);
+}
+
+static void
+new_printer_dialog_response_cb (GtkDialog *_dialog,
+ gint response_id,
+ gpointer user_data)
+{
+ CcPrintersPanel *self = (CcPrintersPanel*) user_data;
+ PpNewPrinterDialog *pp_new_printer_dialog = PP_NEW_PRINTER_DIALOG (_dialog);
+ g_autoptr(PpNewPrinter) new_printer = NULL;
+
+ if (response_id == GTK_RESPONSE_OK)
+ {
+ new_printer = pp_new_printer_dialog_get_new_printer (pp_new_printer_dialog);
+ g_object_get(G_OBJECT (new_printer), "name", &self->new_printer_name, NULL);
+
+ actualize_printers_list (self);
+
+ pp_new_printer_add_async (new_printer,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ printer_add_async_cb,
+ self);
+ }
+
+ gtk_window_destroy (GTK_WINDOW (pp_new_printer_dialog));
+ self->pp_new_printer_dialog = NULL;
+}
+
+static void
+printer_add_cb (CcPrintersPanel *self)
+{
+ GtkNative *native;
+
+ native = gtk_widget_get_native (GTK_WIDGET (self));
+ self->pp_new_printer_dialog = pp_new_printer_dialog_new (self->all_ppds_list,
+ new_printer_dialog_response_cb,
+ self);
+
+ gtk_window_set_transient_for (GTK_WINDOW (self->pp_new_printer_dialog),
+ GTK_WINDOW (native));
+
+ gtk_widget_show (GTK_WIDGET (self->pp_new_printer_dialog));
+}
+
+static void
+update_sensitivity (gpointer user_data)
+{
+ CcPrintersPanel *self = (CcPrintersPanel*) user_data;
+ const char *cups_server = NULL;
+ GtkWidget *widget;
+ gboolean local_server = TRUE;
+ gboolean no_cups = FALSE;
+ gboolean empty_state = FALSE;
+
+ self->is_authorized =
+ self->permission &&
+ g_permission_get_allowed (G_PERMISSION (self->permission)) &&
+ self->lockdown_settings &&
+ !g_settings_get_boolean (self->lockdown_settings, "disable-print-setup");
+
+ widget = (GtkWidget*) gtk_builder_get_object (self->builder, "main-vbox");
+ if (g_strcmp0 (gtk_stack_get_visible_child_name (GTK_STACK (widget)), "no-cups-page") == 0)
+ no_cups = TRUE;
+ else if (g_strcmp0 (gtk_stack_get_visible_child_name (GTK_STACK (widget)), "empty-state") == 0)
+ empty_state = TRUE;
+
+ cups_server = cupsServer ();
+ if (cups_server &&
+ g_ascii_strncasecmp (cups_server, "localhost", 9) != 0 &&
+ g_ascii_strncasecmp (cups_server, "127.0.0.1", 9) != 0 &&
+ g_ascii_strncasecmp (cups_server, "::1", 3) != 0 &&
+ cups_server[0] != '/')
+ local_server = FALSE;
+
+ widget = (GtkWidget*) gtk_builder_get_object (self->builder, "search-button");
+ gtk_widget_set_visible (widget, !no_cups);
+
+ widget = (GtkWidget*) gtk_builder_get_object (self->builder, "search-bar");
+ gtk_widget_set_visible (widget, !no_cups);
+
+ widget = (GtkWidget*) gtk_builder_get_object (self->builder, "printer-add-button");
+ gtk_widget_set_visible (widget, !empty_state);
+ gtk_widget_set_sensitive (widget, local_server && self->is_authorized && !no_cups && !self->new_printer_name);
+
+ widget = (GtkWidget*) gtk_builder_get_object (self->builder, "printer-add-button2");
+ gtk_widget_set_sensitive (widget, local_server && self->is_authorized && !no_cups && !self->new_printer_name);
+}
+
+static void
+on_permission_changed (CcPrintersPanel *self)
+{
+ actualize_printers_list (self);
+ update_sensitivity (self);
+}
+
+static void
+on_lockdown_settings_changed (CcPrintersPanel *self,
+ const char *key)
+{
+ if (g_str_equal (key, "disable-print-setup") == FALSE)
+ return;
+
+#if 0
+ /* FIXME */
+ gtk_widget_set_sensitive (self->lock_button,
+ !g_settings_get_boolean (self->lockdown_settings, "disable-print-setup"));
+#endif
+
+ on_permission_changed (self);
+}
+
+static void
+cups_status_check_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ CcPrintersPanel *self = (CcPrintersPanel*) user_data;
+ gboolean success;
+
+ success = pp_cups_connection_test_finish (PP_CUPS (source_object), result, NULL);
+ if (success)
+ {
+ actualize_printers_list (self);
+ attach_to_cups_notifier (self);
+
+ g_source_remove (self->cups_status_check_id);
+ self->cups_status_check_id = 0;
+ }
+}
+
+static gboolean
+cups_status_check (gpointer user_data)
+{
+ CcPrintersPanel *self = (CcPrintersPanel*) user_data;
+
+ pp_cups_connection_test_async (self->cups, NULL, cups_status_check_cb, self);
+
+ return self->cups_status_check_id != 0;
+}
+
+static void
+connection_test_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ CcPrintersPanel *self;
+ gboolean success;
+ g_autoptr(GError) error = NULL;
+
+ success = pp_cups_connection_test_finish (PP_CUPS (source_object), result, &error);
+
+ if (error != NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ g_warning ("Could not test connection: %s", error->message);
+ }
+
+ return;
+ }
+
+ self = CC_PRINTERS_PANEL (user_data);
+
+ if (!success)
+ {
+ self->cups_status_check_id =
+ g_timeout_add_seconds (CUPS_STATUS_CHECK_INTERVAL, cups_status_check, self);
+ }
+}
+
+static void
+get_all_ppds_async_cb (PPDList *ppds,
+ gpointer user_data)
+{
+ CcPrintersPanel *self = (CcPrintersPanel*) user_data;
+
+ self->all_ppds_list = ppd_list_copy (ppds);
+
+ if (self->pp_new_printer_dialog)
+ pp_new_printer_dialog_set_ppd_list (self->pp_new_printer_dialog,
+ self->all_ppds_list);
+}
+
+static gboolean
+filter_function (GtkListBoxRow *row,
+ gpointer user_data)
+{
+ CcPrintersPanel *self = (CcPrintersPanel*) user_data;
+ PpPrinterEntry *entry = PP_PRINTER_ENTRY (row);
+ GtkWidget *search_entry;
+ gboolean retval;
+ g_autofree gchar *search = NULL;
+ g_autofree gchar *name = NULL;
+ g_autofree gchar *location = NULL;
+ GList *iter;
+ const gchar *search_text;
+
+ search_entry = (GtkWidget*)
+ gtk_builder_get_object (self->builder, "search-entry");
+ search_text = gtk_editable_get_text (GTK_EDITABLE (search_entry));
+
+ if (g_utf8_strlen (search_text, -1) == 0)
+ {
+ retval = TRUE;
+ }
+ else
+ {
+ name = cc_util_normalize_casefold_and_unaccent (pp_printer_entry_get_name (entry));
+ location = cc_util_normalize_casefold_and_unaccent (pp_printer_entry_get_location (entry));
+
+ search = cc_util_normalize_casefold_and_unaccent (search_text);
+
+ retval = strstr (name, search) != NULL;
+ if (location != NULL)
+ retval = retval || (strstr (location, search) != NULL);
+ }
+
+ if (self->deleted_printer_name != NULL &&
+ g_strcmp0 (self->deleted_printer_name, pp_printer_entry_get_name (entry)) == 0)
+ {
+ retval = FALSE;
+ }
+
+ if (self->deleted_printers != NULL)
+ {
+ for (iter = self->deleted_printers; iter != NULL; iter = iter->next)
+ {
+ if (g_strcmp0 (iter->data, pp_printer_entry_get_name (entry)) == 0)
+ {
+ retval = FALSE;
+ break;
+ }
+ }
+ }
+
+ return retval;
+}
+
+static gint
+sort_function (GtkListBoxRow *row1,
+ GtkListBoxRow *row2,
+ gpointer user_data)
+{
+ PpPrinterEntry *entry1 = PP_PRINTER_ENTRY (row1);
+ PpPrinterEntry *entry2 = PP_PRINTER_ENTRY (row2);
+
+ if (pp_printer_entry_get_name (entry1) != NULL)
+ {
+ if (pp_printer_entry_get_name (entry2) != NULL)
+ return g_ascii_strcasecmp (pp_printer_entry_get_name (entry1), pp_printer_entry_get_name (entry2));
+ else
+ return 1;
+ }
+ else
+ {
+ if (pp_printer_entry_get_name (entry2) != NULL)
+ return -1;
+ else
+ return 0;
+ }
+}
+
+static void
+cc_printers_panel_init (CcPrintersPanel *self)
+{
+ GtkWidget *top_widget;
+ GtkWidget *widget;
+ g_autoptr(GError) error = NULL;
+ const gchar *objects[] = { "overlay", "permission-infobar", "top-right-buttons", "printer-add-button", "search-button", NULL };
+ guint builder_result;
+
+ g_resources_register (cc_printers_get_resource ());
+
+ /* initialize main data structure */
+ self->builder = gtk_builder_new ();
+ self->reference = g_object_new (G_TYPE_OBJECT, NULL);
+
+ self->cups = pp_cups_new ();
+
+ self->printer_entries = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ NULL);
+
+ g_type_ensure (CC_TYPE_PERMISSION_INFOBAR);
+
+ g_object_set_data_full (self->reference, "self", self, NULL);
+
+ builder_result = gtk_builder_add_objects_from_resource (self->builder,
+ "/org/gnome/control-center/printers/printers.ui",
+ objects, &error);
+
+ if (builder_result == 0)
+ {
+ /* Translators: The XML file containing user interface can not be loaded */
+ g_warning (_("Could not load ui: %s"), error->message);
+ return;
+ }
+
+ self->notification = (GtkRevealer*)
+ gtk_builder_get_object (self->builder, "notification");
+
+ widget = (GtkWidget*)
+ gtk_builder_get_object (self->builder, "notification-undo-button");
+ g_signal_connect_object (widget, "clicked", G_CALLBACK (on_printer_deletion_undone), self, G_CONNECT_SWAPPED);
+
+ widget = (GtkWidget*)
+ gtk_builder_get_object (self->builder, "notification-dismiss-button");
+ g_signal_connect_object (widget, "clicked", G_CALLBACK (on_notification_dismissed), self, G_CONNECT_SWAPPED);
+
+ self->permission_infobar = (CcPermissionInfobar*)
+ gtk_builder_get_object (self->builder, "permission-infobar");
+
+ /* add the top level widget */
+ top_widget = (GtkWidget*)
+ gtk_builder_get_object (self->builder, "overlay");
+
+ /* connect signals */
+ widget = (GtkWidget*)
+ gtk_builder_get_object (self->builder, "printer-add-button");
+ g_signal_connect_object (widget, "clicked", G_CALLBACK (printer_add_cb), self, G_CONNECT_SWAPPED);
+
+ widget = (GtkWidget*)
+ gtk_builder_get_object (self->builder, "printer-add-button2");
+ g_signal_connect_object (widget, "clicked", G_CALLBACK (printer_add_cb), self, G_CONNECT_SWAPPED);
+
+ widget = (GtkWidget*)
+ gtk_builder_get_object (self->builder, "content");
+ gtk_list_box_set_filter_func (GTK_LIST_BOX (widget),
+ filter_function,
+ self,
+ NULL);
+ g_signal_connect_swapped (gtk_builder_get_object (self->builder, "search-entry"),
+ "search-changed",
+ G_CALLBACK (gtk_list_box_invalidate_filter),
+ widget);
+ gtk_list_box_set_sort_func (GTK_LIST_BOX (widget),
+ sort_function,
+ NULL,
+ NULL);
+
+ self->lockdown_settings = g_settings_new ("org.gnome.desktop.lockdown");
+ if (self->lockdown_settings)
+ g_signal_connect_object (self->lockdown_settings,
+ "changed",
+ G_CALLBACK (on_lockdown_settings_changed),
+ self,
+ G_CONNECT_SWAPPED | G_CONNECT_AFTER);
+
+ /* Add unlock button */
+ self->permission = (GPermission *)polkit_permission_new_sync (
+ "org.opensuse.cupspkhelper.mechanism.all-edit", NULL, NULL, NULL);
+ if (self->permission != NULL)
+ {
+ g_signal_connect_object (self->permission,
+ "notify",
+ G_CALLBACK (on_permission_changed),
+ self,
+ G_CONNECT_SWAPPED | G_CONNECT_AFTER);
+
+ cc_permission_infobar_set_permission (self->permission_infobar,
+ self->permission);
+ cc_permission_infobar_set_title (self->permission_infobar,
+ _("Unlock to Add Printers and Change Settings"));
+
+ on_permission_changed (self);
+ }
+ else
+ g_warning ("Your system does not have the cups-pk-helper's policy \
+\"org.opensuse.cupspkhelper.mechanism.all-edit\" installed. \
+Please check your installation");
+
+ self->size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
+ actualize_printers_list (self);
+ attach_to_cups_notifier (self);
+
+ get_all_ppds_async (cc_panel_get_cancellable (CC_PANEL (self)),
+ get_all_ppds_async_cb,
+ self);
+
+ pp_cups_connection_test_async (self->cups, cc_panel_get_cancellable (CC_PANEL (self)), connection_test_cb, self);
+ cc_panel_set_content (CC_PANEL (self), top_widget);
+
+ widget = (GtkWidget*)
+ gtk_builder_get_object (self->builder, "top-right-buttons");
+ adw_header_bar_pack_end (ADW_HEADER_BAR (cc_panel_get_titlebar (CC_PANEL (self))),
+ widget);
+}
diff --git a/panels/printers/cc-printers-panel.h b/panels/printers/cc-printers-panel.h
new file mode 100644
index 0000000..18e93a4
--- /dev/null
+++ b/panels/printers/cc-printers-panel.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2010 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_PRINTERS_PANEL (cc_printers_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcPrintersPanel, cc_printers_panel, CC, PRINTERS_PANEL, CcPanel)
+
+G_END_DECLS
diff --git a/panels/printers/gnome-printers-panel.desktop.in.in b/panels/printers/gnome-printers-panel.desktop.in.in
new file mode 100644
index 0000000..6ad952d
--- /dev/null
+++ b/panels/printers/gnome-printers-panel.desktop.in.in
@@ -0,0 +1,17 @@
+[Desktop Entry]
+Name=Printers
+Comment=Add printers, view printer jobs and decide how you want to print
+Exec=gnome-control-center printers
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-printers-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+# The X-GNOME-Settings-Panel is necessary to show in the main shell UI
+Categories=GNOME;GTK;Settings;HardwareSettings;X-GNOME-Settings-Panel;X-GNOME-DevicesSettings;
+OnlyShowIn=GNOME;Unity;
+# Translators: Search terms to find the Printers panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=Printer;Queue;Print;Paper;Ink;Toner;
+# Notifications are emitted by gnome-settings-daemon
+X-GNOME-UsesNotifications=true
diff --git a/panels/printers/icons/meson.build b/panels/printers/icons/meson.build
new file mode 100644
index 0000000..d44c8f5
--- /dev/null
+++ b/panels/printers/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-printers-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/printers/icons/scalable/org.gnome.Settings-printers-symbolic.svg b/panels/printers/icons/scalable/org.gnome.Settings-printers-symbolic.svg
new file mode 100644
index 0000000..bd21973
--- /dev/null
+++ b/panels/printers/icons/scalable/org.gnome.Settings-printers-symbolic.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <g fill="#2e3436">
+ <path d="m 4 2 v 1 h 8 v -1 c 0 -0.550781 -0.449219 -1 -1 -1 h -6 c -0.550781 0 -1 0.449219 -1 1 z m 0 0"/>
+ <path d="m 4 8 c -1.089844 0 -2 0.910156 -2 2 v 3 c 0 1.089844 0.910156 2 2 2 h 8 c 1.089844 0 2 -0.910156 2 -2 v -3 c 0 -1.089844 -0.910156 -2 -2 -2 z m 0 2 h 8 v 3 h -8 z m 0 0"/>
+ <path d="m 2 4 c -1.109375 0 -2 0.890625 -2 2 v 4 c 0 1.109375 0.890625 2 2 2 h 1 v -2 c 0 -0.554688 0.445312 -1 1 -1 h 8 c 0.554688 0 1 0.445312 1 1 v 2 h 1 c 1.109375 0 2 -0.890625 2 -2 v -4 c 0 -1.109375 -0.890625 -2 -2 -2 z m 0 0"/>
+ </g>
+</svg>
diff --git a/panels/printers/meson.build b/panels/printers/meson.build
new file mode 100644
index 0000000..3f50979
--- /dev/null
+++ b/panels/printers/meson.build
@@ -0,0 +1,76 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+sources = files(
+ 'cc-printers-panel.c',
+ 'pp-cups.c',
+ 'pp-details-dialog.c',
+ 'pp-host.c',
+ 'pp-ipp-option-widget.c',
+ 'pp-job.c',
+ 'pp-job-row.c',
+ 'pp-jobs-dialog.c',
+ 'pp-maintenance-command.c',
+ 'pp-new-printer-dialog.c',
+ 'pp-new-printer.c',
+ 'pp-options-dialog.c',
+ 'pp-ppd-option-widget.c',
+ 'pp-ppd-selection-dialog.c',
+ 'pp-print-device.c',
+ 'pp-printer-entry.c',
+ 'pp-printer.c',
+ 'pp-samba.c',
+ 'pp-utils.c'
+)
+
+resource_data = files(
+ 'new-printer-dialog.ui',
+ 'ppd-selection-dialog.ui',
+ 'pp-details-dialog.ui',
+ 'pp-job-row.ui',
+ 'pp-jobs-dialog.ui',
+ 'pp-options-dialog.ui',
+ 'printer-entry.ui',
+ 'printers.ui'
+)
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname,
+ dependencies: resource_data,
+ export: true
+)
+
+deps = common_deps + [
+ cups_dep,
+ m_dep,
+ polkit_gobject_dep,
+ dependency('smbclient')
+]
+
+printers_panel_lib = static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [top_inc, common_inc, shell_inc],
+ dependencies: deps,
+ c_args: cflags + cups_cflags,
+)
+panels_libs += [ printers_panel_lib ]
+
+subdir('icons')
diff --git a/panels/printers/new-printer-dialog.ui b/panels/printers/new-printer-dialog.ui
new file mode 100644
index 0000000..6c24ac1
--- /dev/null
+++ b/panels/printers/new-printer-dialog.ui
@@ -0,0 +1,378 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.14"/>
+ <object class="GtkListStore" id="devices_liststore">
+ <columns>
+ <!-- column-name device_gicon -->
+ <column type="GIcon"/>
+ <!-- column-name device_name -->
+ <column type="gchararray"/>
+ <!-- column-name device_display_name -->
+ <column type="gchararray"/>
+ <!-- column-name device_description -->
+ <column type="gchararray"/>
+ <!-- column-name server_needs_authentication -->
+ <column type="gboolean"/>
+ <!-- column-name device_visible -->
+ <column type="gboolean"/>
+ <!-- column-name device -->
+ <column type="PpPrintDevice"/>
+ </columns>
+ </object>
+ <object class="GtkTreeModelFilter" id="devices_model_filter">
+ <property name="child_model">devices_liststore</property>
+ </object>
+ <template class="PpNewPrinterDialog" parent="GtkDialog">
+ <property name="width_request">480</property>
+ <property name="height_request">490</property>
+ <property name="title" translatable="yes" comments="Translators: This is the title presented at top of the dialog.">Add Printer</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="use_header_bar">1</property>
+ <child internal-child="headerbar">
+ <object class="GtkHeaderBar" id="headerbar">
+ <property name="show-title-buttons">False</property>
+ <property name="title-widget">
+ <object class="AdwWindowTitle" id="header_title">
+ <property name="title" translatable="yes" comments="Translators: This is the title presented at top of the dialog.">Add Printer</property>
+ </object>
+ </property>
+ <child>
+ <object class="GtkStack" id="headerbar_topleft_buttons">
+ <property name="valign">center</property>
+
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">addprinter-page</property>
+ <property name="child">
+ <object class="GtkButton" id="new_printer_cancel_button">
+ <property name="label" translatable="yes">_Cancel</property>
+ <property name="use_underline">True</property>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">authentication-page</property>
+ <property name="child">
+ <object class="GtkButton" id="go_back_button">
+ <property name="halign">start</property>
+ <accessibility>
+ <property name="label" translatable="yes">Back</property>
+ </accessibility>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">go-previous-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ <child type="end">
+ <object class="GtkStack" id="headerbar_topright_buttons">
+ <property name="valign">center</property>
+
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">addprinter-page</property>
+ <property name="child">
+ <object class="GtkButton" id="new_printer_add_button">
+ <property name="label" translatable="yes">_Add</property>
+ <property name="sensitive">False</property>
+ <property name="use_underline">True</property>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">unlock_button</property>
+ <property name="child">
+ <object class="GtkButton" id="unlock_button">
+ <property name="label" translatable="yes" comments="Translators: This button opens authentication dialog for selected server.">_Unlock</property>
+ <property name="use_underline">True</property>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">authentication-page</property>
+ <property name="child">
+ <object class="GtkButton" id="authenticate_button">
+ <property name="label" translatable="yes" comments="Translators: This buttons submits the credentials for the selected server.">_Unlock</property>
+ <property name="use_underline">True</property>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="orientation">vertical</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkStack" id="dialog_stack">
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">addprinter-page</property>
+ <property name="child">
+ <object class="GtkBox" id="box2">
+ <property name="orientation">vertical</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="transition-type">none</property>
+ <style>
+ <class name="view"/>
+ </style>
+
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">standard-page</property>
+ <property name="child">
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <child>
+ <object class="GtkTreeView" id="devices_treeview">
+ <property name="model">devices_model_filter</property>
+ <property name="headers_visible">False</property>
+ <property name="enable-grid-lines">GTK_TREE_VIEW_GRID_LINES_HORIZONTAL</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview-selection"/>
+ </child>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">no-printers-page</property>
+ <property name="child">
+ <object class="GtkBox">
+ <property name="orientation">GTK_ORIENTATION_VERTICAL</property>
+ <property name="valign">GTK_ALIGN_CENTER</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkImage">
+ <property name="valign">GTK_ALIGN_START</property>
+ <property name="pixel_size">80</property>
+ <property name="icon_name">printer-symbolic</property>
+ <property name="opacity">0.6</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="no-devices-label">
+ <property name="sensitive">False</property>
+ <property name="label" translatable="yes" comments="Translators: No printers were detected">No Printers Found</property>
+ <property name="opacity">0.6</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">loading-page</property>
+ <property name="child">
+ <object class="GtkBox">
+ <style>
+ <class name="view"/>
+ </style>
+ <child>
+ <object class="GtkSpinner" id="spinner">
+ <property name="spinning">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="sensitive">False</property>
+ <property name="opacity">0.6</property>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparator" />
+ </child>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="margin-top">4</property>
+ <property name="margin-bottom">4</property>
+ <property name="margin-start">4</property>
+ <property name="margin-end">4</property>
+ <child>
+ <object class="GtkSearchEntry" id="search_entry">
+ <property name="has_tooltip">True</property>
+ <property name="placeholder_text" translatable="yes" comments="Translators: The entered text should contain network address of a printer or a text which will filter found devices (their names and locations)">Enter a network address or search for a printer</property>
+ <property name="margin_start">40</property>
+ <property name="margin_end">40</property>
+ <property name="hexpand">True</property>
+ <accessibility>
+ <property name="label" translatable="yes">Search</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">authentication-page</property>
+ <property name="child">
+ <object class="GtkGrid">
+ <property name="margin-top">20</property>
+ <property name="margin-bottom">20</property>
+ <property name="margin-start">20</property>
+ <property name="margin-end">20</property>
+ <property name="row_spacing">10</property>
+ <property name="column_spacing">15</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <style>
+ <class name="background"/>
+ </style>
+ <child>
+ <object class="GtkImage">
+ <property name="pixel_size">48</property>
+ <property name="icon_name">dialog-password-symbolic</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ <property name="row-span">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="authentication_title">
+ <property name="label" translatable="yes">Authentication Required</property>
+ <property name="xalign">0</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="authentication_text">
+ <property name="wrap">True</property>
+ <property name="max_width_chars">36</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Enter username and password to view printers on Print Server.</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Username</property>
+ <property name="mnemonic_widget">username_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="username_entry">
+ <property name="invisible_char">●</property>
+ <property name="activates_default">True</property>
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Password</property>
+ <property name="mnemonic_widget">password_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="password_entry">
+ <property name="visibility">False</property>
+ <property name="invisible_char">●</property>
+ <property name="activates_default">True</property>
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-6">new_printer_cancel_button</action-widget>
+ <action-widget response="-5">new_printer_add_button</action-widget>
+ </action-widgets>
+ </template>
+ <object class="GtkSizeGroup">
+ <widgets>
+ <widget name="new_printer_cancel_button"/>
+ <widget name="headerbar_topright_buttons"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/panels/printers/pp-cups.c b/panels/printers/pp-cups.c
new file mode 100644
index 0000000..9942579
--- /dev/null
+++ b/panels/printers/pp-cups.c
@@ -0,0 +1,313 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marek Kasik <mkasik@redhat.com>
+ */
+
+#include "config.h"
+
+#include "pp-cups.h"
+
+#if (CUPS_VERSION_MAJOR > 1) || (CUPS_VERSION_MINOR > 5)
+#define HAVE_CUPS_1_6 1
+#endif
+
+#ifndef HAVE_CUPS_1_6
+#define ippGetInteger(attr, element) attr->values[element].integer
+#define ippGetStatusCode(ipp) ipp->request.status.status_code
+#endif
+
+struct _PpCups
+{
+ GObject parent_instance;
+};
+
+G_DEFINE_TYPE (PpCups, pp_cups, G_TYPE_OBJECT);
+
+static void
+pp_cups_class_init (PpCupsClass *klass)
+{
+}
+
+static void
+pp_cups_init (PpCups *self)
+{
+}
+
+PpCups *
+pp_cups_new ()
+{
+ return g_object_new (PP_TYPE_CUPS, NULL);
+}
+
+static void
+pp_cups_dests_free (PpCupsDests *dests)
+{
+ cupsFreeDests (dests->num_of_dests, dests->dests);
+}
+
+static void
+_pp_cups_get_dests_thread (GTask *task,
+ gpointer *object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ PpCupsDests *dests;
+
+ dests = g_new0 (PpCupsDests, 1);
+ dests->num_of_dests = cupsGetDests (&dests->dests);
+
+ if (g_task_set_return_on_cancel (task, FALSE))
+ {
+ g_task_return_pointer (task, dests, (GDestroyNotify) pp_cups_dests_free);
+ }
+ else
+ {
+ pp_cups_dests_free (dests);
+ }
+}
+
+void
+pp_cups_get_dests_async (PpCups *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_return_on_cancel (task, TRUE);
+ g_task_run_in_thread (task, (GTaskThreadFunc) _pp_cups_get_dests_thread);
+}
+
+PpCupsDests *
+pp_cups_get_dests_finish (PpCups *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
+
+ return g_task_propagate_pointer (G_TASK (res), error);
+}
+
+static void
+connection_test_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ http_t *http;
+
+#ifdef HAVE_CUPS_HTTPCONNECT2
+ http = httpConnect2 (cupsServer (), ippPort (), NULL, AF_UNSPEC,
+ cupsEncryption (), 1, 30000, NULL);
+#else
+ http = httpConnectEncrypt (cupsServer (), ippPort (), cupsEncryption ());
+#endif
+ httpClose (http);
+
+ if (g_task_set_return_on_cancel (task, FALSE))
+ {
+ g_task_return_boolean (task, http != NULL);
+ }
+}
+
+void
+pp_cups_connection_test_async (PpCups *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_return_on_cancel (task, TRUE);
+ g_task_run_in_thread (task, connection_test_thread);
+}
+
+gboolean
+pp_cups_connection_test_finish (PpCups *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+/* Cancels subscription of given id */
+static void
+cancel_subscription_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ ipp_t *request;
+ ipp_t *response = NULL;
+ gint id = GPOINTER_TO_INT (task_data);
+
+ if (id >= 0)
+ {
+ request = ippNewRequest (IPP_CANCEL_SUBSCRIPTION);
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, "/");
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, cupsUser ());
+ ippAddInteger (request, IPP_TAG_OPERATION, IPP_TAG_INTEGER,
+ "notify-subscription-id", id);
+ response = cupsDoRequest (CUPS_HTTP_DEFAULT, request, "/");
+ }
+
+ g_task_return_boolean (task, response != NULL && ippGetStatusCode (response) <= IPP_OK);
+
+ ippDelete (response);
+}
+
+void
+pp_cups_cancel_subscription_async (PpCups *self,
+ gint subscription_id,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ task = g_task_new (self, NULL, callback, user_data);
+ g_task_set_task_data (task, GINT_TO_POINTER (subscription_id), NULL);
+ g_task_run_in_thread (task, cancel_subscription_thread);
+}
+
+gboolean
+pp_cups_cancel_subscription_finish (PpCups *self,
+ GAsyncResult *result)
+{
+ g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), NULL);
+}
+
+typedef struct {
+ gint id;
+ gchar **events;
+ int lease_duration;
+} CRSData;
+
+static void
+crs_data_free (CRSData *data)
+{
+ g_strfreev (data->events);
+ g_slice_free (CRSData, data);
+}
+
+static void
+renew_subscription_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ ipp_attribute_t *attr = NULL;
+ CRSData *subscription_data = task_data;
+ ipp_t *request;
+ ipp_t *response = NULL;
+ gint result = -1;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return;
+
+ if (subscription_data->id > 0)
+ {
+ request = ippNewRequest (IPP_RENEW_SUBSCRIPTION);
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, "/");
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, cupsUser ());
+ ippAddInteger (request, IPP_TAG_OPERATION, IPP_TAG_INTEGER,
+ "notify-subscription-id", subscription_data->id);
+ ippAddInteger (request, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
+ "notify-lease-duration", subscription_data->lease_duration);
+ response = cupsDoRequest (CUPS_HTTP_DEFAULT, request, "/");
+ if (response != NULL && ippGetStatusCode (response) <= IPP_OK_CONFLICT)
+ {
+ if ((attr = ippFindAttribute (response, "notify-lease-duration", IPP_TAG_INTEGER)) == NULL)
+ g_debug ("No notify-lease-duration in response!\n");
+ else if (ippGetInteger (attr, 0) == subscription_data->lease_duration)
+ result = subscription_data->id;
+ }
+ }
+
+ if (result < 0)
+ {
+ request = ippNewRequest (IPP_CREATE_PRINTER_SUBSCRIPTION);
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, "/");
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, cupsUser ());
+ ippAddStrings (request, IPP_TAG_SUBSCRIPTION, IPP_TAG_KEYWORD,
+ "notify-events", g_strv_length (subscription_data->events), NULL,
+ (const char * const *) subscription_data->events);
+ ippAddString (request, IPP_TAG_SUBSCRIPTION, IPP_TAG_KEYWORD,
+ "notify-pull-method", NULL, "ippget");
+ ippAddString (request, IPP_TAG_SUBSCRIPTION, IPP_TAG_URI,
+ "notify-recipient-uri", NULL, "dbus://");
+ ippAddInteger (request, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
+ "notify-lease-duration", subscription_data->lease_duration);
+ response = cupsDoRequest (CUPS_HTTP_DEFAULT, request, "/");
+
+ if (response != NULL && ippGetStatusCode (response) <= IPP_OK_CONFLICT)
+ {
+ if ((attr = ippFindAttribute (response, "notify-subscription-id", IPP_TAG_INTEGER)) == NULL)
+ g_debug ("No notify-subscription-id in response!\n");
+ else
+ result = ippGetInteger (attr, 0);
+ }
+ }
+
+ ippDelete (response);
+
+ g_task_return_int (task, result);
+}
+
+void
+pp_cups_renew_subscription_async (PpCups *self,
+ gint subscription_id,
+ gchar **events,
+ gint lease_duration,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ CRSData *subscription_data;
+ g_autoptr(GTask) task = NULL;
+
+ subscription_data = g_slice_new (CRSData);
+ subscription_data->id = subscription_id;
+ subscription_data->events = g_strdupv (events);
+ subscription_data->lease_duration = lease_duration;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_task_data (task, subscription_data, (GDestroyNotify) crs_data_free);
+ g_task_run_in_thread (task, renew_subscription_thread);
+}
+
+/* Returns id of renewed subscription or new id */
+gint
+pp_cups_renew_subscription_finish (PpCups *self,
+ GAsyncResult *result)
+{
+ g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
+
+ return g_task_propagate_int (G_TASK (result), NULL);
+}
diff --git a/panels/printers/pp-cups.h b/panels/printers/pp-cups.h
new file mode 100644
index 0000000..04063bb
--- /dev/null
+++ b/panels/printers/pp-cups.h
@@ -0,0 +1,76 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marek Kasik <mkasik@redhat.com>
+ */
+
+#pragma once
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include "pp-utils.h"
+
+G_BEGIN_DECLS
+
+#define PP_TYPE_CUPS (pp_cups_get_type ())
+G_DECLARE_FINAL_TYPE (PpCups, pp_cups, PP, CUPS, GObject)
+
+typedef struct{
+ cups_dest_t *dests;
+ gint num_of_dests;
+} PpCupsDests;
+
+PpCups *pp_cups_new (void);
+
+void pp_cups_get_dests_async (PpCups *cups,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+PpCupsDests *pp_cups_get_dests_finish (PpCups *cups,
+ GAsyncResult *result,
+ GError **error);
+
+void pp_cups_connection_test_async (PpCups *cups,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean pp_cups_connection_test_finish (PpCups *cups,
+ GAsyncResult *result,
+ GError **error);
+
+void pp_cups_cancel_subscription_async (PpCups *cups,
+ gint subscription_id,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean pp_cups_cancel_subscription_finish (PpCups *cups,
+ GAsyncResult *result);
+
+void pp_cups_renew_subscription_async (PpCups *cups,
+ gint subscription_id,
+ gchar **events,
+ gint lease_duration,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gint pp_cups_renew_subscription_finish (PpCups *cups,
+ GAsyncResult *result);
+
+G_END_DECLS
diff --git a/panels/printers/pp-details-dialog.c b/panels/printers/pp-details-dialog.c
new file mode 100644
index 0000000..6eeffb1
--- /dev/null
+++ b/panels/printers/pp-details-dialog.c
@@ -0,0 +1,399 @@
+/*
+ *
+ * Copyright 2016 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Felipe Borges <feborges@redhat.com>
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <gtk/gtk.h>
+
+#include <cups/cups.h>
+#include <cups/ppd.h>
+
+#include "pp-details-dialog.h"
+#include "pp-ppd-selection-dialog.h"
+#include "pp-printer.h"
+#include "pp-utils.h"
+
+struct _PpDetailsDialog {
+ GtkDialog parent_instance;
+
+ GtkLabel *dialog_title;
+ GtkBox *driver_buttons;
+ GtkBox *loading_box;
+ GtkLabel *printer_address_label;
+ GtkRevealer *print_name_hint_revealer;
+ GtkEntry *printer_location_entry;
+ GtkLabel *printer_model_label;
+ GtkStack *printer_model_stack;
+ GtkEntry *printer_name_entry;
+ GtkButton *search_for_drivers_button;
+
+ gchar *printer_name;
+ gchar *ppd_file_name;
+ PPDList *all_ppds_list;
+ GCancellable *cancellable;
+
+ /* Dialogs */
+ PpPPDSelectionDialog *pp_ppd_selection_dialog;
+};
+
+G_DEFINE_TYPE (PpDetailsDialog, pp_details_dialog, GTK_TYPE_DIALOG)
+
+static void
+printer_name_changed (PpDetailsDialog *self)
+{
+ const gchar *name;
+ g_autofree gchar *title = NULL;
+
+ name = pp_details_dialog_get_printer_name (self);
+
+ if (printer_name_is_valid (name)){
+ /* Translators: This is the title of the dialog. %s is the printer name. */
+ title = g_strdup_printf (_("%s Details"), name);
+ gtk_revealer_set_reveal_child (self->print_name_hint_revealer, FALSE);
+ gtk_label_set_label (self->dialog_title, title);
+ } else {
+ gtk_revealer_set_reveal_child (self->print_name_hint_revealer, TRUE);
+ }
+}
+
+static void set_ppd_cb (const gchar *printer_name, gboolean success, gpointer user_data);
+
+static void
+get_ppd_names_cb (PPDName **names,
+ const gchar *printer_name,
+ gboolean cancelled,
+ gpointer user_data)
+{
+ PpDetailsDialog *self = (PpDetailsDialog*) user_data;
+
+ if (!cancelled)
+ {
+ if (names != NULL)
+ {
+ gtk_label_set_text (self->printer_model_label, names[0]->ppd_display_name);
+ printer_set_ppd_async (printer_name,
+ names[0]->ppd_name,
+ self->cancellable,
+ set_ppd_cb,
+ self);
+ }
+ else
+ {
+ gtk_label_set_text (self->printer_model_label, _("No suitable driver found"));
+ }
+
+ gtk_stack_set_visible_child (self->printer_model_stack, GTK_WIDGET (self->printer_model_label));
+ }
+}
+
+static void
+search_for_drivers (PpDetailsDialog *self)
+{
+ gtk_stack_set_visible_child (self->printer_model_stack, GTK_WIDGET (self->loading_box));
+ gtk_widget_set_sensitive (GTK_WIDGET (self->search_for_drivers_button), FALSE);
+
+ get_ppd_names_async (self->printer_name,
+ 1,
+ self->cancellable,
+ get_ppd_names_cb,
+ self);
+}
+
+static void
+set_ppd_cb (const gchar *printer_name,
+ gboolean success,
+ gpointer user_data)
+{
+ PpDetailsDialog *self = (PpDetailsDialog*) user_data;
+
+ gtk_label_set_text (GTK_LABEL (self->printer_model_label), self->ppd_file_name);
+}
+
+static void
+ppd_selection_dialog_response_cb (GtkDialog *dialog,
+ gint response_id,
+ gpointer user_data)
+{
+ PpDetailsDialog *self = (PpDetailsDialog*) user_data;
+
+ if (response_id == GTK_RESPONSE_OK)
+ {
+ g_autofree gchar *ppd_name = NULL;
+
+ ppd_name = pp_ppd_selection_dialog_get_ppd_name (self->pp_ppd_selection_dialog);
+
+ if (self->printer_name && ppd_name)
+ {
+ printer_set_ppd_async (self->printer_name,
+ ppd_name,
+ self->cancellable,
+ set_ppd_cb,
+ self);
+
+ g_clear_pointer (&self->ppd_file_name, g_free);
+ self->ppd_file_name = g_strdup (ppd_name);
+ }
+ }
+
+ gtk_window_destroy (GTK_WINDOW (self->pp_ppd_selection_dialog));
+ self->pp_ppd_selection_dialog = NULL;
+}
+
+static void
+get_all_ppds_async_cb (PPDList *ppds,
+ gpointer user_data)
+{
+ PpDetailsDialog *self = user_data;
+
+ self->all_ppds_list = ppd_list_copy (ppds);
+
+ if (self->pp_ppd_selection_dialog)
+ pp_ppd_selection_dialog_set_ppd_list (self->pp_ppd_selection_dialog,
+ self->all_ppds_list);
+}
+
+static void
+select_ppd_in_dialog (PpDetailsDialog *self)
+{
+ g_autofree gchar *device_id = NULL;
+ g_autofree gchar *manufacturer = NULL;
+
+ g_clear_pointer (&self->ppd_file_name, g_free);
+ self->ppd_file_name = g_strdup (cupsGetPPD (self->printer_name));
+
+ if (!self->pp_ppd_selection_dialog)
+ {
+ device_id =
+ get_ppd_attribute (self->ppd_file_name,
+ "1284DeviceID");
+
+ if (device_id)
+ {
+ manufacturer = get_tag_value (device_id, "mfg");
+ if (!manufacturer)
+ manufacturer = get_tag_value (device_id, "manufacturer");
+ }
+
+ if (manufacturer == NULL)
+ {
+ manufacturer =
+ get_ppd_attribute (self->ppd_file_name,
+ "Manufacturer");
+ }
+
+ if (manufacturer == NULL)
+ {
+ manufacturer = g_strdup ("Raw");
+ }
+
+ if (self->all_ppds_list == NULL)
+ {
+ get_all_ppds_async (self->cancellable, get_all_ppds_async_cb, self);
+ }
+
+ self->pp_ppd_selection_dialog = pp_ppd_selection_dialog_new (
+ self->all_ppds_list,
+ manufacturer,
+ ppd_selection_dialog_response_cb,
+ self);
+
+ gtk_window_set_transient_for (GTK_WINDOW (self->pp_ppd_selection_dialog),
+ GTK_WINDOW (self));
+
+ gtk_widget_show (GTK_WIDGET (self->pp_ppd_selection_dialog));
+ }
+}
+
+static void
+ppd_file_select_response_cb (GtkDialog *dialog,
+ gint response_id,
+ gpointer user_data)
+{
+ PpDetailsDialog *self = PP_DETAILS_DIALOG (user_data);
+
+ if (response_id == GTK_RESPONSE_ACCEPT)
+ {
+ g_autoptr(GFile) file = NULL;
+ g_autofree gchar *ppd_filename = NULL;
+
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+ ppd_filename = g_file_get_path (file);
+
+ if (self->printer_name && ppd_filename)
+ {
+ printer_set_ppd_file_async (self->printer_name,
+ ppd_filename,
+ self->cancellable,
+ set_ppd_cb,
+ self);
+ }
+ }
+
+ gtk_window_destroy (GTK_WINDOW (dialog));
+}
+
+static void
+select_ppd_manually (PpDetailsDialog *self)
+{
+ GtkFileFilter *filter;
+ GtkWidget *dialog;
+
+ dialog = gtk_file_chooser_dialog_new (_("Select PPD File"),
+ GTK_WINDOW (self),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Open"), GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_set_name (filter,
+ _("PostScript Printer Description files (*.ppd, *.PPD, *.ppd.gz, *.PPD.gz, *.PPD.GZ)"));
+ gtk_file_filter_add_pattern (filter, "*.ppd");
+ gtk_file_filter_add_pattern (filter, "*.PPD");
+ gtk_file_filter_add_pattern (filter, "*.ppd.gz");
+ gtk_file_filter_add_pattern (filter, "*.PPD.gz");
+ gtk_file_filter_add_pattern (filter, "*.PPD.GZ");
+
+ gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter);
+
+ gtk_widget_show (dialog);
+
+ g_signal_connect (dialog, "response", G_CALLBACK (ppd_file_select_response_cb), self);
+}
+
+static void
+update_sensitivity (PpDetailsDialog *self,
+ gboolean sensitive)
+{
+ gtk_widget_set_sensitive (GTK_WIDGET (self->printer_name_entry), sensitive);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->printer_location_entry), sensitive);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->driver_buttons), sensitive);
+}
+
+static void
+pp_details_dialog_init (PpDetailsDialog *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->cancellable = g_cancellable_new ();
+}
+
+static void
+pp_details_dialog_dispose (GObject *object)
+{
+ PpDetailsDialog *self = PP_DETAILS_DIALOG (object);
+
+ g_clear_pointer (&self->printer_name, g_free);
+ g_clear_pointer (&self->ppd_file_name, g_free);
+
+ if (self->all_ppds_list != NULL)
+ {
+ ppd_list_free (self->all_ppds_list);
+ self->all_ppds_list = NULL;
+ }
+
+ g_cancellable_cancel (self->cancellable);
+ g_clear_object (&self->cancellable);
+
+ G_OBJECT_CLASS (pp_details_dialog_parent_class)->dispose (object);
+}
+
+static void
+pp_details_dialog_class_init (PpDetailsDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = pp_details_dialog_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/printers/pp-details-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, PpDetailsDialog, dialog_title);
+ gtk_widget_class_bind_template_child (widget_class, PpDetailsDialog, print_name_hint_revealer);
+ gtk_widget_class_bind_template_child (widget_class, PpDetailsDialog, driver_buttons);
+ gtk_widget_class_bind_template_child (widget_class, PpDetailsDialog, loading_box);
+ gtk_widget_class_bind_template_child (widget_class, PpDetailsDialog, printer_address_label);
+ gtk_widget_class_bind_template_child (widget_class, PpDetailsDialog, printer_location_entry);
+ gtk_widget_class_bind_template_child (widget_class, PpDetailsDialog, printer_model_label);
+ gtk_widget_class_bind_template_child (widget_class, PpDetailsDialog, printer_model_stack);
+ gtk_widget_class_bind_template_child (widget_class, PpDetailsDialog, printer_name_entry);
+ gtk_widget_class_bind_template_child (widget_class, PpDetailsDialog, search_for_drivers_button);
+
+ gtk_widget_class_bind_template_callback (widget_class, printer_name_changed);
+ gtk_widget_class_bind_template_callback (widget_class, search_for_drivers);
+ gtk_widget_class_bind_template_callback (widget_class, select_ppd_in_dialog);
+ gtk_widget_class_bind_template_callback (widget_class, select_ppd_manually);
+}
+
+PpDetailsDialog *
+pp_details_dialog_new (gchar *printer_name,
+ gchar *printer_location,
+ gchar *printer_address,
+ gchar *printer_make_and_model,
+ gboolean sensitive)
+{
+ PpDetailsDialog *self;
+ g_autofree gchar *title = NULL;
+ g_autofree gchar *printer_url = NULL;
+
+ self = g_object_new (PP_DETAILS_DIALOG_TYPE,
+ "use-header-bar", TRUE,
+ NULL);
+
+ self->printer_name = g_strdup (printer_name);
+ self->ppd_file_name = NULL;
+
+ /* Translators: This is the title of the dialog. %s is the printer name. */
+ title = g_strdup_printf (_("%s Details"), printer_name);
+ gtk_label_set_label (self->dialog_title, title);
+
+ printer_url = g_strdup_printf ("<a href=\"http://%s:%d\">%s</a>", printer_address, ippPort (), printer_address);
+ gtk_label_set_markup (GTK_LABEL (self->printer_address_label), printer_url);
+
+ gtk_editable_set_text (GTK_EDITABLE (self->printer_name_entry), printer_name);
+ gtk_editable_set_text (GTK_EDITABLE (self->printer_location_entry), printer_location);
+ gtk_label_set_text (GTK_LABEL (self->printer_model_label), printer_make_and_model);
+
+ update_sensitivity (self, sensitive);
+
+ return self;
+}
+
+const gchar *
+pp_details_dialog_get_printer_name (PpDetailsDialog *self)
+{
+ g_return_val_if_fail (PP_IS_DETAILS_DIALOG (self), NULL);
+ return gtk_editable_get_text (GTK_EDITABLE (self->printer_name_entry));
+}
+
+const gchar *
+pp_details_dialog_get_printer_location (PpDetailsDialog *self)
+{
+ g_return_val_if_fail (PP_IS_DETAILS_DIALOG (self), NULL);
+ return gtk_editable_get_text (GTK_EDITABLE (self->printer_location_entry));
+}
diff --git a/panels/printers/pp-details-dialog.h b/panels/printers/pp-details-dialog.h
new file mode 100644
index 0000000..8bb5a65
--- /dev/null
+++ b/panels/printers/pp-details-dialog.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2016 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Felipe Borges <feborges@redhat.com>
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include "pp-utils.h"
+
+G_BEGIN_DECLS
+
+#define PP_DETAILS_DIALOG_TYPE (pp_details_dialog_get_type ())
+G_DECLARE_FINAL_TYPE (PpDetailsDialog, pp_details_dialog, PP, DETAILS_DIALOG, GtkDialog)
+
+PpDetailsDialog *pp_details_dialog_new (gchar *printer_name,
+ gchar *printer_location,
+ gchar *printer_address,
+ gchar *printer_make_and_model,
+ gboolean sensitive);
+
+const gchar *pp_details_dialog_get_printer_name (PpDetailsDialog *dialog);
+
+const gchar *pp_details_dialog_get_printer_location (PpDetailsDialog *dialog);
+
+G_END_DECLS
diff --git a/panels/printers/pp-details-dialog.ui b/panels/printers/pp-details-dialog.ui
new file mode 100644
index 0000000..2dec9d4
--- /dev/null
+++ b/panels/printers/pp-details-dialog.ui
@@ -0,0 +1,235 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.18.3 -->
+<interface>
+ <requires lib="gtk+" version="3.12"/>
+ <template class="PpDetailsDialog" parent="GtkDialog">
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="use-header-bar">1</property>
+ <child internal-child="headerbar">
+ <object class="GtkHeaderBar">
+ <property name="show_title_buttons">True</property>
+ <child type="title">
+ <object class="GtkLabel" id="dialog_title">
+ <property name="wrap">True</property>
+ <property name="max_width_chars">30</property>
+ <property name="ellipsize">middle</property>
+ <property name="hexpand">true</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">20</property>
+ <property name="margin-bottom">20</property>
+ <property name="margin-start">20</property>
+ <property name="margin-end">20</property>
+ <property name="halign">center</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="row-spacing">10</property>
+ <property name="column-spacing">10</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Name</property>
+ <property name="halign">end</property>
+ <property name="mnemonic_widget">printer_name_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="printer_name_entry">
+ <property name="halign">fill</property>
+ <property name="width_request">320</property>
+ <signal name="changed" handler="printer_name_changed" object="PpDetailsDialog" swapped="yes"/>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkRevealer" id="print_name_hint_revealer">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="print_name_hint_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Printer names cannot contain SPACE, TAB, #, or /</property>
+ <property name="yalign">0</property>
+ <property name="xalign">0</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <attributes>
+ <attribute name="scale" value="0.83"/>
+ </attributes>
+ </object>
+ </child>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Location</property>
+ <property name="halign">end</property>
+ <property name="mnemonic_widget">printer_location_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="printer_location_entry">
+ <property name="width_request">320</property>
+ <property name="halign">fill</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Address</property>
+ <property name="halign">end</property>
+ <property name="mnemonic_widget">printer_address_label</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="printer_address_label">
+ <property name="label">192.168.0.1</property>
+ <property name="halign">start</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Driver</property>
+ <property name="halign">end</property>
+ <property name="mnemonic_widget">printer_model_label</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">4</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStack" id="printer_model_stack">
+ <property name="halign">start</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">4</property>
+ </layout>
+ <child>
+ <object class="GtkLabel" id="printer_model_label">
+ <property name="halign">start</property>
+ <property name="label">HP Inkjet Delux 9000</property>
+ <property name="selectable">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="loading_box">
+ <property name="halign">start</property>
+ <property name="spacing">5</property>
+ <child>
+ <object class="GtkSpinner">
+ <property name="spinning">True</property>
+ <property name="halign">start</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">Searching for preferred drivers…</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkBox" id="driver_buttons">
+ <property name="orientation">vertical</property>
+ <property name="spacing">10</property>
+ <property name="halign">start</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">5</property>
+ </layout>
+ <child>
+ <object class="GtkButton" id="search_for_drivers_button">
+ <property name="label" translatable="yes">Search for Drivers</property>
+ <property name="halign">fill</property>
+ <signal name="clicked" handler="search_for_drivers" object="PpDetailsDialog" swapped="yes"/>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkButton" id="select_from_database_button">
+ <property name="label" translatable="yes">Select from Database…</property>
+ <property name="halign">fill</property>
+ <signal name="clicked" handler="select_ppd_in_dialog" object="PpDetailsDialog" swapped="yes"/>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkButton" id="install_ppd_button">
+ <property name="label" translatable="yes">Install PPD File…</property>
+ <property name="halign">fill</property>
+ <signal name="clicked" handler="select_ppd_manually" object="PpDetailsDialog" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+
+ <object class="GtkSizeGroup">
+ <property name="mode">horizontal</property>
+ <widgets>
+ <widget name="search_for_drivers_button"/>
+ <widget name="select_from_database_button"/>
+ <widget name="install_ppd_button"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/panels/printers/pp-host.c b/panels/printers/pp-host.c
new file mode 100644
index 0000000..a31a606
--- /dev/null
+++ b/panels/printers/pp-host.c
@@ -0,0 +1,747 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marek Kasik <mkasik@redhat.com>
+ */
+
+#include "config.h"
+
+#include "pp-host.h"
+
+#include <glib/gi18n.h>
+
+#define BUFFER_LENGTH 1024
+
+typedef struct
+{
+ gchar *hostname;
+ gint port;
+} PpHostPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (PpHost, pp_host, G_TYPE_OBJECT);
+
+enum {
+ PROP_0 = 0,
+ PROP_HOSTNAME,
+ PROP_PORT,
+};
+
+enum {
+ AUTHENTICATION_REQUIRED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void
+pp_host_finalize (GObject *object)
+{
+ PpHost *self = PP_HOST (object);
+ PpHostPrivate *priv = pp_host_get_instance_private (self);
+
+ g_clear_pointer (&priv->hostname, g_free);
+
+ G_OBJECT_CLASS (pp_host_parent_class)->finalize (object);
+}
+
+static void
+pp_host_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *param_spec)
+{
+ PpHost *self = PP_HOST (object);
+ PpHostPrivate *priv = pp_host_get_instance_private (self);
+
+ switch (prop_id)
+ {
+ case PROP_HOSTNAME:
+ g_value_set_string (value, priv->hostname);
+ break;
+ case PROP_PORT:
+ g_value_set_int (value, priv->port);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
+ prop_id,
+ param_spec);
+ break;
+ }
+}
+
+static void
+pp_host_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *param_spec)
+{
+ PpHost *self = PP_HOST (object);
+ PpHostPrivate *priv = pp_host_get_instance_private (self);
+
+ switch (prop_id)
+ {
+ case PROP_HOSTNAME:
+ g_free (priv->hostname);
+ priv->hostname = g_value_dup_string (value);
+ break;
+ case PROP_PORT:
+ priv->port = g_value_get_int (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
+ prop_id,
+ param_spec);
+ break;
+ }
+}
+
+static void
+pp_host_class_init (PpHostClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->set_property = pp_host_set_property;
+ gobject_class->get_property = pp_host_get_property;
+ gobject_class->finalize = pp_host_finalize;
+
+ g_object_class_install_property (gobject_class, PROP_HOSTNAME,
+ g_param_spec_string ("hostname",
+ "Hostname",
+ "The hostname",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_PORT,
+ g_param_spec_int ("port",
+ "Port",
+ "The port",
+ -1, G_MAXINT32, PP_HOST_UNSET_PORT,
+ G_PARAM_READWRITE));
+
+ signals[AUTHENTICATION_REQUIRED] =
+ g_signal_new ("authentication-required",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+}
+
+static void
+pp_host_init (PpHost *self)
+{
+ PpHostPrivate *priv = pp_host_get_instance_private (self);
+ priv->port = PP_HOST_UNSET_PORT;
+}
+
+PpHost *
+pp_host_new (const gchar *hostname)
+{
+ return g_object_new (PP_TYPE_HOST,
+ "hostname", hostname,
+ NULL);
+}
+
+static gchar **
+line_split (gchar *line)
+{
+ gboolean escaped = FALSE;
+ gboolean quoted = FALSE;
+ gboolean in_word = FALSE;
+ gchar **words = NULL;
+ gchar **result = NULL;
+ g_autofree gchar *buffer = NULL;
+ gchar ch;
+ gint n = 0;
+ gint i, j = 0, k = 0;
+
+ if (line)
+ {
+ n = strlen (line);
+ words = g_new0 (gchar *, n + 1);
+ buffer = g_new0 (gchar, n + 1);
+
+ for (i = 0; i < n; i++)
+ {
+ ch = line[i];
+
+ if (escaped)
+ {
+ buffer[k++] = ch;
+ escaped = FALSE;
+ continue;
+ }
+
+ if (ch == '\\')
+ {
+ in_word = TRUE;
+ escaped = TRUE;
+ continue;
+ }
+
+ if (in_word)
+ {
+ if (quoted)
+ {
+ if (ch == '"')
+ quoted = FALSE;
+ else
+ buffer[k++] = ch;
+ }
+ else if (g_ascii_isspace (ch))
+ {
+ words[j++] = g_strdup (buffer);
+ memset (buffer, 0, n + 1);
+ k = 0;
+ in_word = FALSE;
+ }
+ else if (ch == '"')
+ quoted = TRUE;
+ else
+ buffer[k++] = ch;
+ }
+ else
+ {
+ if (ch == '"')
+ {
+ in_word = TRUE;
+ quoted = TRUE;
+ }
+ else if (!g_ascii_isspace (ch))
+ {
+ in_word = TRUE;
+ buffer[k++] = ch;
+ }
+ }
+ }
+ }
+
+ if (buffer && buffer[0] != '\0')
+ words[j++] = g_strdup (buffer);
+
+ result = g_strdupv (words);
+ g_strfreev (words);
+
+ return result;
+}
+
+static void
+_pp_host_get_snmp_devices_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ PpHost *self = source_object;
+ PpHostPrivate *priv = pp_host_get_instance_private (self);
+ g_autoptr(GPtrArray) devices = NULL;
+ g_autoptr(GError) error = NULL;
+ g_auto(GStrv) argv = NULL;
+ g_autofree gchar *stdout_string = NULL;
+ gint exit_status;
+
+ devices = g_ptr_array_new_with_free_func (g_object_unref);
+
+ argv = g_new0 (gchar *, 3);
+ argv[0] = g_strdup ("/usr/lib/cups/backend/snmp");
+ argv[1] = g_strdup (priv->hostname);
+
+ /* Use SNMP to get printer's informations */
+ g_spawn_sync (NULL,
+ argv,
+ NULL,
+ G_SPAWN_STDERR_TO_DEV_NULL,
+ NULL,
+ NULL,
+ &stdout_string,
+ NULL,
+ &exit_status,
+ &error);
+
+ if (exit_status == 0 && stdout_string)
+ {
+ g_auto(GStrv) printer_informations = NULL;
+ gint length;
+
+ printer_informations = line_split (stdout_string);
+ length = g_strv_length (printer_informations);
+
+ if (length >= 4)
+ {
+ g_autofree gchar *device_name = NULL;
+ gboolean is_network_device;
+ PpPrintDevice *device;
+
+ device_name = g_strdup (printer_informations[3]);
+ g_strcanon (device_name, ALLOWED_CHARACTERS, '-');
+ is_network_device = g_strcmp0 (printer_informations[0], "network") == 0;
+
+ device = g_object_new (PP_TYPE_PRINT_DEVICE,
+ "is-network-device", is_network_device,
+ "device-uri", printer_informations[1],
+ "device-make-and-model", printer_informations[2],
+ "device-info", printer_informations[3],
+ "acquisition-method", ACQUISITION_METHOD_SNMP,
+ "device-name", device_name,
+ NULL);
+
+ if (length >= 5 && printer_informations[4][0] != '\0')
+ g_object_set (device, "device-id", printer_informations[4], NULL);
+
+ if (length >= 6 && printer_informations[5][0] != '\0')
+ g_object_set (device, "device-location", printer_informations[5], NULL);
+
+ g_ptr_array_add (devices, device);
+ }
+ }
+
+ g_task_return_pointer (task, g_ptr_array_ref (devices), (GDestroyNotify) g_ptr_array_unref);
+}
+
+void
+pp_host_get_snmp_devices_async (PpHost *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_run_in_thread (task, _pp_host_get_snmp_devices_thread);
+}
+
+GPtrArray *
+pp_host_get_snmp_devices_finish (PpHost *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ return g_task_propagate_pointer (G_TASK (res), error);
+}
+
+static void
+_pp_host_get_remote_cups_devices_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ cups_dest_t *dests = NULL;
+ PpHost *self = (PpHost *) source_object;
+ PpHostPrivate *priv = pp_host_get_instance_private (self);
+ g_autoptr(GPtrArray) devices = NULL;
+ http_t *http;
+ gint num_of_devices = 0;
+ gint port;
+ gint i;
+
+ devices = g_ptr_array_new_with_free_func (g_object_unref);
+
+ if (priv->port == PP_HOST_UNSET_PORT)
+ port = PP_HOST_DEFAULT_IPP_PORT;
+ else
+ port = priv->port;
+
+ /* Connect to remote CUPS server and get its devices */
+#ifdef HAVE_CUPS_HTTPCONNECT2
+ http = httpConnect2 (priv->hostname, port, NULL, AF_UNSPEC,
+ HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL);
+#else
+ http = httpConnect (priv->hostname, port);
+#endif
+ if (http)
+ {
+ num_of_devices = cupsGetDests2 (http, &dests);
+ if (num_of_devices > 0)
+ {
+ for (i = 0; i < num_of_devices; i++)
+ {
+ g_autofree gchar *device_uri = NULL;
+ const char *device_location;
+ PpPrintDevice *device;
+
+ device_uri = g_strdup_printf ("ipp://%s:%d/printers/%s",
+ priv->hostname,
+ port,
+ dests[i].name);
+
+ device_location = cupsGetOption ("printer-location",
+ dests[i].num_options,
+ dests[i].options);
+
+ device = g_object_new (PP_TYPE_PRINT_DEVICE,
+ "is-network-device", TRUE,
+ "device-uri", device_uri,
+ "device-name", dests[i].name,
+ "device-location", device_location,
+ "host-name", priv->hostname,
+ "host-port", port,
+ "acquisition-method", ACQUISITION_METHOD_REMOTE_CUPS_SERVER,
+ NULL);
+ g_ptr_array_add (devices, device);
+ }
+ }
+
+ httpClose (http);
+ }
+
+ g_task_return_pointer (task, g_ptr_array_ref (devices), (GDestroyNotify) g_ptr_array_unref);
+}
+
+void
+pp_host_get_remote_cups_devices_async (PpHost *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_run_in_thread (task, _pp_host_get_remote_cups_devices_thread);
+}
+
+GPtrArray *
+pp_host_get_remote_cups_devices_finish (PpHost *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ return g_task_propagate_pointer (G_TASK (res), error);
+}
+
+typedef struct
+{
+ PpHost *host;
+ gint port;
+} JetDirectData;
+
+static void
+jetdirect_data_free (JetDirectData *data)
+{
+ if (data != NULL)
+ {
+ g_clear_object (&data->host);
+ g_free (data);
+ }
+}
+
+static void
+jetdirect_connection_test_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GSocketConnection) connection = NULL;
+ PpHostPrivate *priv;
+ JetDirectData *data;
+ g_autoptr(GPtrArray) devices = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GTask) task = G_TASK (user_data);
+
+ data = g_task_get_task_data (task);
+ priv = pp_host_get_instance_private (data->host);
+
+ devices = g_ptr_array_new_with_free_func (g_object_unref);
+
+ connection = g_socket_client_connect_to_host_finish (G_SOCKET_CLIENT (source_object),
+ res,
+ &error);
+
+ if (connection != NULL)
+ {
+ g_autofree gchar *device_uri = NULL;
+ PpPrintDevice *device;
+
+ g_io_stream_close (G_IO_STREAM (connection), NULL, NULL);
+
+ device_uri = g_strdup_printf ("socket://%s:%d",
+ priv->hostname,
+ data->port);
+
+ device = g_object_new (PP_TYPE_PRINT_DEVICE,
+ "is-network-device", TRUE,
+ "device-uri", device_uri,
+ /* Translators: The found device is a JetDirect printer */
+ "device-name", _("JetDirect Printer"),
+ "host-name", priv->hostname,
+ "host-port", data->port,
+ "acquisition-method", ACQUISITION_METHOD_JETDIRECT,
+ NULL);
+ g_ptr_array_add (devices, device);
+ }
+
+ g_task_return_pointer (task, g_ptr_array_ref (devices), (GDestroyNotify) g_ptr_array_unref);
+}
+
+/* Test whether given host has an AppSocket/HP JetDirect printer connected.
+ See http://en.wikipedia.org/wiki/JetDirect
+ http://www.cups.org/documentation.php/network.html */
+void
+pp_host_get_jetdirect_devices_async (PpHost *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ PpHostPrivate *priv = pp_host_get_instance_private (self);
+ JetDirectData *data;
+ g_autoptr(GTask) task = NULL;
+ g_autofree gchar *address = NULL;
+
+ data = g_new0 (JetDirectData, 1);
+ data->host = g_object_ref (self);
+
+ if (priv->port == PP_HOST_UNSET_PORT)
+ data->port = PP_HOST_DEFAULT_JETDIRECT_PORT;
+ else
+ data->port = priv->port;
+
+ task = g_task_new (G_OBJECT (self), cancellable, callback, user_data);
+ g_task_set_task_data (task, data, (GDestroyNotify) jetdirect_data_free);
+
+ address = g_strdup_printf ("%s:%d", priv->hostname, data->port);
+ if (address != NULL && address[0] != '/')
+ {
+ g_autoptr(GSocketClient) client = NULL;
+
+ client = g_socket_client_new ();
+
+ g_socket_client_connect_to_host_async (client,
+ address,
+ data->port,
+ cancellable,
+ jetdirect_connection_test_cb,
+ g_steal_pointer (&task));
+ }
+ else
+ {
+ GPtrArray *devices = g_ptr_array_new_with_free_func (g_object_unref);
+ g_task_return_pointer (task, devices, (GDestroyNotify) g_ptr_array_unref);
+ }
+}
+
+GPtrArray *
+pp_host_get_jetdirect_devices_finish (PpHost *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ return g_task_propagate_pointer (G_TASK (res), error);
+}
+
+static gboolean
+test_lpd_queue (GSocketClient *client,
+ gchar *address,
+ gint port,
+ GCancellable *cancellable,
+ gchar *queue_name)
+{
+ g_autoptr(GSocketConnection) connection = NULL;
+ gboolean result = FALSE;
+ g_autoptr(GError) error = NULL;
+
+ connection = g_socket_client_connect_to_host (client,
+ address,
+ port,
+ cancellable,
+ &error);
+
+ if (connection != NULL)
+ {
+ if (G_IS_TCP_CONNECTION (connection))
+ {
+ GOutputStream *output;
+ GInputStream *input;
+ gssize bytes_read, bytes_written;
+ gchar buffer[BUFFER_LENGTH];
+ gint length;
+
+ output = g_io_stream_get_output_stream (G_IO_STREAM (connection));
+ input = g_io_stream_get_input_stream (G_IO_STREAM (connection));
+
+ /* This LPD command is explained in RFC 1179, section 5.2 */
+ length = g_snprintf (buffer, BUFFER_LENGTH, "\2%s\n", queue_name);
+
+ bytes_written = g_output_stream_write (output,
+ buffer,
+ length,
+ NULL,
+ &error);
+
+ if (bytes_written != -1)
+ {
+ bytes_read = g_input_stream_read (input,
+ buffer,
+ BUFFER_LENGTH,
+ NULL,
+ &error);
+
+ if (bytes_read != -1)
+ {
+ if (bytes_read > 0 && buffer[0] == 0)
+ {
+ /* This LPD command is explained in RFC 1179, section 6.1 */
+ length = g_snprintf (buffer, BUFFER_LENGTH, "\1\n");
+
+ bytes_written = g_output_stream_write (output,
+ buffer,
+ length,
+ NULL,
+ &error);
+
+ result = TRUE;
+ }
+ }
+ }
+ }
+
+ g_io_stream_close (G_IO_STREAM (connection), NULL, NULL);
+ }
+
+ return result;
+}
+
+static void
+_pp_host_get_lpd_devices_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ g_autoptr(GSocketConnection) connection = NULL;
+ PpHost *self = source_object;
+ PpHostPrivate *priv = pp_host_get_instance_private (self);
+ g_autoptr(GPtrArray) devices = NULL;
+ g_autoptr(GSocketClient) client = NULL;
+ g_autoptr(GError) error = NULL;
+ GList *candidates = NULL;
+ GList *iter;
+ gchar *found_queue = NULL;
+ gchar *candidate;
+ g_autofree gchar *address = NULL;
+ gint port;
+ gint i;
+
+ if (priv->port == PP_HOST_UNSET_PORT)
+ port = PP_HOST_DEFAULT_LPD_PORT;
+ else
+ port = priv->port;
+
+ devices = g_ptr_array_new_with_free_func (g_object_unref);
+
+ address = g_strdup_printf ("%s:%d", priv->hostname, port);
+ if (address == NULL || address[0] == '/')
+ {
+ g_task_return_pointer (task, g_ptr_array_ref (devices), (GDestroyNotify) g_ptr_array_unref);
+ return;
+ }
+
+ client = g_socket_client_new ();
+
+ connection = g_socket_client_connect_to_host (client,
+ address,
+ port,
+ cancellable,
+ &error);
+
+ if (connection != NULL)
+ {
+ g_io_stream_close (G_IO_STREAM (connection), NULL, NULL);
+
+ /* Most of this list is taken from system-config-printer */
+ candidates = g_list_append (candidates, g_strdup ("PASSTHRU"));
+ candidates = g_list_append (candidates, g_strdup ("AUTO"));
+ candidates = g_list_append (candidates, g_strdup ("BINPS"));
+ candidates = g_list_append (candidates, g_strdup ("RAW"));
+ candidates = g_list_append (candidates, g_strdup ("TEXT"));
+ candidates = g_list_append (candidates, g_strdup ("ps"));
+ candidates = g_list_append (candidates, g_strdup ("lp"));
+ candidates = g_list_append (candidates, g_strdup ("PORT1"));
+
+ for (i = 0; i < 8; i++)
+ {
+ candidates = g_list_append (candidates, g_strdup_printf ("LPT%d", i));
+ candidates = g_list_append (candidates, g_strdup_printf ("LPT%d_PASSTHRU", i));
+ candidates = g_list_append (candidates, g_strdup_printf ("COM%d", i));
+ candidates = g_list_append (candidates, g_strdup_printf ("COM%d_PASSTHRU", i));
+ }
+
+ for (i = 0; i < 50; i++)
+ candidates = g_list_append (candidates, g_strdup_printf ("pr%d", i));
+
+ for (iter = candidates; iter != NULL; iter = iter->next)
+ {
+ candidate = (gchar *) iter->data;
+
+ if (test_lpd_queue (client,
+ address,
+ port,
+ cancellable,
+ candidate))
+ {
+ found_queue = g_strdup (candidate);
+ break;
+ }
+ }
+
+ if (found_queue != NULL)
+ {
+ g_autofree gchar *device_uri = NULL;
+ PpPrintDevice *device;
+
+ device_uri = g_strdup_printf ("lpd://%s:%d/%s",
+ priv->hostname,
+ port,
+ found_queue);
+
+ device = g_object_new (PP_TYPE_PRINT_DEVICE,
+ "is-network-device", TRUE,
+ "device-uri", device_uri,
+ /* Translators: The found device is a Line Printer Daemon printer */
+ "device-name", _("LPD Printer"),
+ "host-name", priv->hostname,
+ "host-port", port,
+ "acquisition-method", ACQUISITION_METHOD_LPD,
+ NULL);
+ g_ptr_array_add (devices, device);
+ }
+
+ g_list_free_full (candidates, g_free);
+ }
+
+ g_task_return_pointer (task, g_ptr_array_ref (devices), (GDestroyNotify) g_ptr_array_unref);
+}
+
+void
+pp_host_get_lpd_devices_async (PpHost *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ task = g_task_new (G_OBJECT (self), cancellable, callback, user_data);
+ g_task_run_in_thread (task, _pp_host_get_lpd_devices_thread);
+}
+
+GPtrArray *
+pp_host_get_lpd_devices_finish (PpHost *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ return g_task_propagate_pointer (G_TASK (res), error);
+}
diff --git a/panels/printers/pp-host.h b/panels/printers/pp-host.h
new file mode 100644
index 0000000..3e29217
--- /dev/null
+++ b/panels/printers/pp-host.h
@@ -0,0 +1,80 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marek Kasik <mkasik@redhat.com>
+ */
+
+#pragma once
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include "pp-utils.h"
+
+G_BEGIN_DECLS
+
+#define PP_TYPE_HOST (pp_host_get_type ())
+G_DECLARE_DERIVABLE_TYPE (PpHost, pp_host, PP, HOST, GObject)
+
+struct _PpHostClass
+{
+ GObjectClass parent_class;
+};
+
+#define PP_HOST_UNSET_PORT -1
+#define PP_HOST_DEFAULT_IPP_PORT 631
+#define PP_HOST_DEFAULT_JETDIRECT_PORT 9100
+#define PP_HOST_DEFAULT_LPD_PORT 515
+
+PpHost *pp_host_new (const gchar *hostname);
+
+void pp_host_get_snmp_devices_async (PpHost *host,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GPtrArray *pp_host_get_snmp_devices_finish (PpHost *host,
+ GAsyncResult *result,
+ GError **error);
+
+void pp_host_get_remote_cups_devices_async (PpHost *host,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GPtrArray *pp_host_get_remote_cups_devices_finish (PpHost *host,
+ GAsyncResult *result,
+ GError **error);
+
+void pp_host_get_jetdirect_devices_async (PpHost *host,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GPtrArray *pp_host_get_jetdirect_devices_finish (PpHost *host,
+ GAsyncResult *result,
+ GError **error);
+
+void pp_host_get_lpd_devices_async (PpHost *host,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GPtrArray *pp_host_get_lpd_devices_finish (PpHost *host,
+ GAsyncResult *result,
+ GError **error);
+
+G_END_DECLS
diff --git a/panels/printers/pp-ipp-option-widget.c b/panels/printers/pp-ipp-option-widget.c
new file mode 100644
index 0000000..ea27ad7
--- /dev/null
+++ b/panels/printers/pp-ipp-option-widget.c
@@ -0,0 +1,524 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marek Kasik <mkasik@redhat.com>
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <glib/gi18n-lib.h>
+
+#include "pp-ipp-option-widget.h"
+#include "pp-utils.h"
+
+static void pp_ipp_option_widget_finalize (GObject *object);
+
+static gboolean construct_widget (PpIPPOptionWidget *self);
+static void update_widget (PpIPPOptionWidget *self);
+static void update_widget_real (PpIPPOptionWidget *self);
+
+struct _PpIPPOptionWidget
+{
+ GtkBox parent_instance;
+
+ GtkWidget *switch_button;
+ GtkWidget *spin_button;
+ GtkWidget *dropdown;
+
+ IPPAttribute *option_supported;
+ IPPAttribute *option_default;
+
+ gchar *printer_name;
+ gchar *option_name;
+
+ GHashTable *ipp_attribute;
+
+ GCancellable *cancellable;
+};
+
+G_DEFINE_TYPE (PpIPPOptionWidget, pp_ipp_option_widget, GTK_TYPE_BOX)
+
+static const struct {
+ const char *keyword;
+ const char *choice;
+ const char *translation;
+} ipp_choice_translations[] = {
+ /* Translators: this is an option of "Two Sided" */
+ { "sides", "one-sided", N_("One Sided") },
+ /* Translators: this is an option of "Two Sided" */
+ { "sides", "two-sided-long-edge", N_("Long Edge (Standard)") },
+ /* Translators: this is an option of "Two Sided" */
+ { "sides", "two-sided-short-edge", N_("Short Edge (Flip)") },
+ /* Translators: this is an option of "Orientation" */
+ { "orientation-requested", "3", N_("Portrait") },
+ /* Translators: this is an option of "Orientation" */
+ { "orientation-requested", "4", N_("Landscape") },
+ /* Translators: this is an option of "Orientation" */
+ { "orientation-requested", "5", N_("Reverse landscape") },
+ /* Translators: this is an option of "Orientation" */
+ { "orientation-requested", "6", N_("Reverse portrait") },
+};
+
+static const gchar *
+ipp_choice_translate (const gchar *option,
+ const gchar *choice)
+{
+ gint i;
+
+ for (i = 0; i < G_N_ELEMENTS (ipp_choice_translations); i++)
+ {
+ if (g_strcmp0 (ipp_choice_translations[i].keyword, option) == 0 &&
+ g_strcmp0 (ipp_choice_translations[i].choice, choice) == 0)
+ {
+ return _(ipp_choice_translations[i].translation);
+ }
+ }
+
+ return choice;
+}
+
+static void
+pp_ipp_option_widget_class_init (PpIPPOptionWidgetClass *class)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (class);
+
+ object_class->finalize = pp_ipp_option_widget_finalize;
+}
+
+static void
+pp_ipp_option_widget_init (PpIPPOptionWidget *self)
+{
+ gtk_orientable_set_orientation (GTK_ORIENTABLE (self),
+ GTK_ORIENTATION_HORIZONTAL);
+}
+
+static void
+pp_ipp_option_widget_finalize (GObject *object)
+{
+ PpIPPOptionWidget *self = PP_IPP_OPTION_WIDGET (object);
+
+ g_cancellable_cancel (self->cancellable);
+
+ g_clear_pointer (&self->option_name, g_free);
+ g_clear_pointer (&self->printer_name, g_free);
+ g_clear_pointer (&self->option_supported, ipp_attribute_free);
+ g_clear_pointer (&self->option_default, ipp_attribute_free);
+ g_clear_pointer (&self->ipp_attribute, g_hash_table_unref);
+ g_clear_object (&self->cancellable);
+
+ G_OBJECT_CLASS (pp_ipp_option_widget_parent_class)->finalize (object);
+}
+
+GtkWidget *
+pp_ipp_option_widget_new (IPPAttribute *attr_supported,
+ IPPAttribute *attr_default,
+ const gchar *option_name,
+ const gchar *printer)
+{
+ PpIPPOptionWidget *self = NULL;
+
+ if (attr_supported && option_name && printer)
+ {
+ self = g_object_new (PP_TYPE_IPP_OPTION_WIDGET, NULL);
+
+ self->printer_name = g_strdup (printer);
+ self->option_name = g_strdup (option_name);
+ self->option_supported = ipp_attribute_copy (attr_supported);
+ self->option_default = ipp_attribute_copy (attr_default);
+
+ if (construct_widget (self))
+ {
+ update_widget_real (self);
+ }
+ else
+ {
+ g_object_ref_sink (self);
+ g_object_unref (self);
+ self = NULL;
+ }
+ }
+
+ return (GtkWidget *) self;
+}
+
+static GtkWidget *
+dropdown_new (void)
+{
+ GtkStringList *store = NULL;
+ GtkWidget *dropdown;
+
+ store = gtk_string_list_new (NULL);
+
+ dropdown = gtk_drop_down_new (G_LIST_MODEL (store), NULL);
+
+ return dropdown;
+}
+
+static void
+dropdown_append (GtkWidget *dropdown,
+ const gchar *display_text)
+{
+ GtkStringList *store;
+
+ store = GTK_STRING_LIST (gtk_drop_down_get_model (GTK_DROP_DOWN (dropdown)));
+
+ gtk_string_list_append (store, display_text);
+}
+
+static void
+dropdown_set (GtkWidget *dropdown,
+ IPPAttribute *option,
+ const gchar *value)
+{
+ g_autofree gchar *attribute_value = NULL;
+
+ for (guint i = 0; i < option->num_of_values; i++)
+ {
+ if (option->attribute_type == IPP_ATTRIBUTE_TYPE_INTEGER)
+ attribute_value = g_strdup_printf ("%d", option->attribute_values[i].integer_value);
+ else
+ attribute_value = g_strdup (option->attribute_values[i].string_value);
+
+ if (g_strcmp0 (attribute_value, value) == 0)
+ {
+ gtk_drop_down_set_selected (GTK_DROP_DOWN (dropdown), i);
+ break;
+ }
+ }
+}
+
+static char *
+dropdown_get (GtkWidget *dropdown,
+ IPPAttribute *option)
+{
+ guint selected_item;
+ gchar *value = NULL;
+
+ selected_item = gtk_drop_down_get_selected (GTK_DROP_DOWN (dropdown));
+
+ if (selected_item != GTK_INVALID_LIST_POSITION)
+ {
+ if (option->attribute_type == IPP_ATTRIBUTE_TYPE_INTEGER)
+ value = g_strdup_printf ("%d", option->attribute_values[selected_item].integer_value);
+ else
+ value = option->attribute_values[selected_item].string_value;
+ }
+
+ return value;
+}
+
+static void
+printer_add_option_async_cb (gboolean success,
+ gpointer user_data)
+{
+ PpIPPOptionWidget *self = user_data;
+
+ update_widget (user_data);
+ g_clear_object (&self->cancellable);
+}
+
+static void
+switch_changed_cb (PpIPPOptionWidget *self)
+{
+ gchar **values;
+
+ values = g_new0 (gchar *, 2);
+
+ if (gtk_switch_get_active (GTK_SWITCH (self->switch_button)))
+ values[0] = g_strdup ("True");
+ else
+ values[0] = g_strdup ("False");
+
+ g_cancellable_cancel (self->cancellable);
+ g_clear_object (&self->cancellable);
+
+ self->cancellable = g_cancellable_new ();
+ printer_add_option_async (self->printer_name,
+ self->option_name,
+ values,
+ TRUE,
+ self->cancellable,
+ printer_add_option_async_cb,
+ self);
+
+ g_strfreev (values);
+}
+
+static void
+dropdown_changed_cb (PpIPPOptionWidget *self)
+{
+ gchar **values;
+
+ values = g_new0 (gchar *, 2);
+ values[0] = g_strdup (dropdown_get (self->dropdown, self->option_supported));
+
+ g_cancellable_cancel (self->cancellable);
+ g_clear_object (&self->cancellable);
+
+ self->cancellable = g_cancellable_new ();
+ printer_add_option_async (self->printer_name,
+ self->option_name,
+ values,
+ TRUE,
+ self->cancellable,
+ printer_add_option_async_cb,
+ self);
+
+ g_strfreev (values);
+}
+
+static void
+spin_button_changed_cb (PpIPPOptionWidget *self)
+{
+ gchar **values;
+
+ values = g_new0 (gchar *, 2);
+ values[0] = g_strdup_printf ("%d", gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (self->spin_button)));
+
+ g_cancellable_cancel (self->cancellable);
+ g_clear_object (&self->cancellable);
+
+ self->cancellable = g_cancellable_new ();
+ printer_add_option_async (self->printer_name,
+ self->option_name,
+ values,
+ TRUE,
+ self->cancellable,
+ printer_add_option_async_cb,
+ self);
+
+ g_strfreev (values);
+}
+
+static gboolean
+construct_widget (PpIPPOptionWidget *self)
+{
+ gboolean trivial_option = FALSE;
+ gboolean result = FALSE;
+ gint i;
+
+ if (self->option_supported)
+ {
+ switch (self->option_supported->attribute_type)
+ {
+ case IPP_ATTRIBUTE_TYPE_INTEGER:
+ if (self->option_supported->num_of_values <= 1)
+ trivial_option = TRUE;
+ break;
+
+ case IPP_ATTRIBUTE_TYPE_STRING:
+ if (self->option_supported->num_of_values <= 1)
+ trivial_option = TRUE;
+ break;
+
+ case IPP_ATTRIBUTE_TYPE_RANGE:
+ if (self->option_supported->attribute_values[0].lower_range ==
+ self->option_supported->attribute_values[0].upper_range)
+ trivial_option = TRUE;
+ break;
+ }
+
+ if (!trivial_option)
+ {
+ switch (self->option_supported->attribute_type)
+ {
+ case IPP_ATTRIBUTE_TYPE_BOOLEAN:
+ self->switch_button = gtk_switch_new ();
+
+ gtk_box_append (GTK_BOX (self), self->switch_button);
+ g_signal_connect_object (self->switch_button, "notify::active", G_CALLBACK (switch_changed_cb), self, G_CONNECT_SWAPPED);
+ break;
+
+ case IPP_ATTRIBUTE_TYPE_INTEGER:
+ self->dropdown = dropdown_new ();
+
+ for (i = 0; i < self->option_supported->num_of_values; i++)
+ {
+ g_autofree gchar *value = NULL;
+
+ value = g_strdup_printf ("%d", self->option_supported->attribute_values[i].integer_value);
+ dropdown_append (self->dropdown,
+ ipp_choice_translate (self->option_name,
+ value));
+ }
+
+ gtk_box_append (GTK_BOX (self), self->dropdown);
+ g_signal_connect_object (self->dropdown, "notify::selected", G_CALLBACK (dropdown_changed_cb), self, G_CONNECT_SWAPPED);
+ break;
+
+ case IPP_ATTRIBUTE_TYPE_STRING:
+ self->dropdown = dropdown_new ();
+
+ for (i = 0; i < self->option_supported->num_of_values; i++)
+ dropdown_append (self->dropdown,
+ ipp_choice_translate (self->option_name,
+ self->option_supported->attribute_values[i].string_value));
+
+ gtk_box_append (GTK_BOX (self), self->dropdown);
+ g_signal_connect_object (self->dropdown, "notify::selected", G_CALLBACK (dropdown_changed_cb), self, G_CONNECT_SWAPPED);
+ break;
+
+ case IPP_ATTRIBUTE_TYPE_RANGE:
+ self->spin_button = gtk_spin_button_new_with_range (
+ self->option_supported->attribute_values[0].lower_range,
+ self->option_supported->attribute_values[0].upper_range,
+ 1);
+
+ gtk_box_append (GTK_BOX (self), self->spin_button);
+ g_signal_connect_object (self->spin_button, "value-changed", G_CALLBACK (spin_button_changed_cb), self, G_CONNECT_SWAPPED);
+ break;
+
+ default:
+ break;
+ }
+
+ result = TRUE;
+ }
+ }
+
+ return result;
+}
+
+static void
+update_widget_real (PpIPPOptionWidget *self)
+{
+ IPPAttribute *attr = NULL;
+
+ if (self->option_default)
+ {
+ attr = ipp_attribute_copy (self->option_default);
+
+ ipp_attribute_free (self->option_default);
+ self->option_default = NULL;
+ }
+ else if (self->ipp_attribute)
+ {
+ g_autofree gchar *attr_name = g_strdup_printf ("%s-default", self->option_name);
+ attr = ipp_attribute_copy (g_hash_table_lookup (self->ipp_attribute, attr_name));
+
+ g_hash_table_unref (self->ipp_attribute);
+ self->ipp_attribute = NULL;
+ }
+
+ switch (self->option_supported->attribute_type)
+ {
+ case IPP_ATTRIBUTE_TYPE_BOOLEAN:
+ g_signal_handlers_block_by_func (self->switch_button, switch_changed_cb, self);
+
+ if (attr && attr->num_of_values > 0 &&
+ attr->attribute_type == IPP_ATTRIBUTE_TYPE_BOOLEAN)
+ {
+ gtk_switch_set_active (GTK_SWITCH (self->switch_button),
+ attr->attribute_values[0].boolean_value);
+ }
+
+ g_signal_handlers_unblock_by_func (self->switch_button, switch_changed_cb, self);
+ break;
+
+ case IPP_ATTRIBUTE_TYPE_INTEGER:
+ g_signal_handlers_block_by_func (self->dropdown, dropdown_changed_cb, self);
+
+ if (attr && attr->num_of_values > 0 &&
+ attr->attribute_type == IPP_ATTRIBUTE_TYPE_INTEGER)
+ {
+ g_autofree gchar *value = g_strdup_printf ("%d", attr->attribute_values[0].integer_value);
+ dropdown_set (self->dropdown, self->option_supported, value);
+ }
+ else
+ {
+ g_autofree gchar *value = g_strdup_printf ("%d", self->option_supported->attribute_values[0].integer_value);
+ dropdown_set (self->dropdown, self->option_supported, value);
+ }
+
+ g_signal_handlers_unblock_by_func (self->dropdown, dropdown_changed_cb, self);
+ break;
+
+ case IPP_ATTRIBUTE_TYPE_STRING:
+ g_signal_handlers_block_by_func (self->dropdown, dropdown_changed_cb, self);
+
+ if (attr && attr->num_of_values > 0 &&
+ attr->attribute_type == IPP_ATTRIBUTE_TYPE_STRING)
+ {
+ dropdown_set (self->dropdown, self->option_supported, attr->attribute_values[0].string_value);
+ }
+ else
+ {
+ dropdown_set (self->dropdown, self->option_supported, self->option_supported->attribute_values[0].string_value);
+ }
+
+ g_signal_handlers_unblock_by_func (self->dropdown, dropdown_changed_cb, self);
+ break;
+
+ case IPP_ATTRIBUTE_TYPE_RANGE:
+ g_signal_handlers_block_by_func (self->spin_button, spin_button_changed_cb, self);
+
+ if (attr && attr->num_of_values > 0 &&
+ attr->attribute_type == IPP_ATTRIBUTE_TYPE_INTEGER)
+ {
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (self->spin_button),
+ attr->attribute_values[0].integer_value);
+ }
+ else
+ {
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (self->spin_button),
+ self->option_supported->attribute_values[0].lower_range);
+ }
+
+ g_signal_handlers_unblock_by_func (self->spin_button, spin_button_changed_cb, self);
+ break;
+
+ default:
+ break;
+ }
+
+ ipp_attribute_free (attr);
+}
+
+static void
+get_ipp_attributes_cb (GHashTable *table,
+ gpointer user_data)
+{
+ PpIPPOptionWidget *self = user_data;
+
+ if (self->ipp_attribute)
+ g_hash_table_unref (self->ipp_attribute);
+
+ self->ipp_attribute = g_hash_table_ref (table);
+
+ update_widget_real (self);
+}
+
+static void
+update_widget (PpIPPOptionWidget *self)
+{
+ gchar **attributes_names;
+
+ attributes_names = g_new0 (gchar *, 2);
+ attributes_names[0] = g_strdup_printf ("%s-default", self->option_name);
+
+ get_ipp_attributes_async (self->printer_name,
+ attributes_names,
+ get_ipp_attributes_cb,
+ self);
+
+ g_strfreev (attributes_names);
+}
diff --git a/panels/printers/pp-ipp-option-widget.h b/panels/printers/pp-ipp-option-widget.h
new file mode 100644
index 0000000..a5d0b84
--- /dev/null
+++ b/panels/printers/pp-ipp-option-widget.h
@@ -0,0 +1,39 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marek Kasik <mkasik@redhat.com>
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <cups/cups.h>
+#include <cups/ppd.h>
+
+#include "pp-utils.h"
+
+G_BEGIN_DECLS
+
+#define PP_TYPE_IPP_OPTION_WIDGET (pp_ipp_option_widget_get_type ())
+G_DECLARE_FINAL_TYPE (PpIPPOptionWidget, pp_ipp_option_widget, PP, IPP_OPTION_WIDGET, GtkBox)
+
+GtkWidget *pp_ipp_option_widget_new (IPPAttribute *attr_supported,
+ IPPAttribute *attr_default,
+ const gchar *option_name,
+ const gchar *printer);
+
+G_END_DECLS
diff --git a/panels/printers/pp-job-row.c b/panels/printers/pp-job-row.c
new file mode 100644
index 0000000..6b1fe27
--- /dev/null
+++ b/panels/printers/pp-job-row.c
@@ -0,0 +1,190 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2020 Canonical Ltd.
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+
+#include "pp-job-row.h"
+#include "cc-printers-resources.h"
+
+struct _PpJobRow
+{
+ GtkListBoxRow parent;
+
+ GtkButton *pause_button;
+ GtkButton *priority_button;
+ GtkLabel *state_label;
+ GtkLabel *title_label;
+
+ PpJob *job;
+};
+
+G_DEFINE_TYPE (PpJobRow, pp_job_row, GTK_TYPE_LIST_BOX_ROW)
+
+enum {
+ PRIORITY_CHANGED,
+ LAST_SIGNAL,
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void
+update_pause_button (PpJobRow *self, gboolean paused)
+{
+ gtk_button_set_icon_name (self->pause_button,
+ paused ? "media-playback-start-symbolic" : "media-playback-pause-symbolic");
+ gtk_accessible_update_property (GTK_ACCESSIBLE (self->pause_button),
+ GTK_ACCESSIBLE_PROPERTY_LABEL,
+ paused ? _("Resume") : _("Pause"),
+ -1);
+}
+
+static void
+pause_cb (PpJobRow *self)
+{
+ pp_job_set_hold_until_async (self->job, pp_job_get_state (self->job) == IPP_JOB_HELD ? "no-hold" : "indefinite");
+ update_pause_button (self,
+ pp_job_get_state (self->job) == IPP_JOB_HELD);
+ }
+
+static void
+stop_cb (PpJobRow *self)
+{
+ pp_job_cancel_purge_async (self->job, FALSE);
+}
+
+static void
+priority_cb (PpJobRow *self)
+{
+ g_signal_emit_by_name (self, "priority-changed");
+}
+
+static void
+pp_job_row_dispose (GObject *object)
+{
+ PpJobRow *self = PP_JOB_ROW (object);
+
+ g_clear_object (&self->job);
+
+ G_OBJECT_CLASS (pp_job_row_parent_class)->dispose (object);
+}
+
+static void
+pp_job_row_class_init (PpJobRowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = pp_job_row_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/printers/pp-job-row.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, PpJobRow, pause_button);
+ gtk_widget_class_bind_template_child (widget_class, PpJobRow, priority_button);
+ gtk_widget_class_bind_template_child (widget_class, PpJobRow, state_label);
+ gtk_widget_class_bind_template_child (widget_class, PpJobRow, title_label);
+
+ gtk_widget_class_bind_template_callback (widget_class, pause_cb);
+ gtk_widget_class_bind_template_callback (widget_class, stop_cb);
+ gtk_widget_class_bind_template_callback (widget_class, priority_cb);
+
+ signals[PRIORITY_CHANGED] =
+ g_signal_new ("priority-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+}
+
+static void
+pp_job_row_init (PpJobRow *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+PpJob *
+pp_job_row_get_job (PpJobRow *self)
+{
+ return self->job;
+}
+
+PpJobRow *
+pp_job_row_new (PpJob *job)
+{
+ PpJobRow *self;
+ gboolean status;
+ g_autofree gchar *state_string = NULL;
+
+ self = g_object_new (PP_TYPE_JOB_ROW, NULL);
+
+ self->job = g_object_ref (job);
+
+ switch (pp_job_get_state (job))
+ {
+ case IPP_JOB_PENDING:
+ /* Translators: Job's state (job is waiting to be printed) */
+ state_string = g_strdup (C_("print job", "Pending"));
+ break;
+ case IPP_JOB_HELD:
+ if (pp_job_get_auth_info_required (job) == NULL)
+ {
+ /* Translators: Job's state (job is held for printing) */
+ state_string = g_strdup (C_("print job", "Paused"));
+ }
+ else
+ {
+ /* Translators: Job's state (job needs authentication to proceed further) */
+ state_string = g_strdup_printf ("<span foreground=\"#ff0000\">%s</span>", C_("print job", "Authentication required"));
+ }
+ break;
+ case IPP_JOB_PROCESSING:
+ /* Translators: Job's state (job is currently printing) */
+ state_string = g_strdup (C_("print job", "Processing"));
+ break;
+ case IPP_JOB_STOPPED:
+ /* Translators: Job's state (job has been stopped) */
+ state_string = g_strdup (C_("print job", "Stopped"));
+ break;
+ case IPP_JOB_CANCELED:
+ /* Translators: Job's state (job has been canceled) */
+ state_string = g_strdup (C_("print job", "Canceled"));
+ break;
+ case IPP_JOB_ABORTED:
+ /* Translators: Job's state (job has aborted due to error) */
+ state_string = g_strdup (C_("print job", "Aborted"));
+ break;
+ case IPP_JOB_COMPLETED:
+ /* Translators: Job's state (job has completed successfully) */
+ state_string = g_strdup (C_("print job", "Completed"));
+ break;
+ }
+ gtk_label_set_text (self->title_label, pp_job_get_title (job));
+ gtk_label_set_markup (self->state_label, state_string);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->pause_button), pp_job_get_auth_info_required (job) == NULL);
+ status = pp_job_priority_get_sensitive (job);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->priority_button), status);
+ if (status)
+ /* Translators: Clicking this button prioritizes printing of this print job */
+ gtk_widget_set_tooltip_text (GTK_WIDGET (self->priority_button), _("Move this job to the top of the queue"));
+ update_pause_button (self,
+ pp_job_get_state (self->job) == IPP_JOB_HELD);
+ return self;
+}
diff --git a/panels/printers/pp-job-row.h b/panels/printers/pp-job-row.h
new file mode 100644
index 0000000..088d7ff
--- /dev/null
+++ b/panels/printers/pp-job-row.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2020 Canonical Ltd.
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "pp-job.h"
+
+G_BEGIN_DECLS
+
+#define PP_TYPE_JOB_ROW (pp_job_row_get_type())
+G_DECLARE_FINAL_TYPE (PpJobRow, pp_job_row, PP, JOB_ROW, GtkListBoxRow)
+
+PpJobRow* pp_job_row_new (PpJob *job);
+
+PpJob* pp_job_row_get_job (PpJobRow *self);
+
+G_END_DECLS
diff --git a/panels/printers/pp-job-row.ui b/panels/printers/pp-job-row.ui
new file mode 100644
index 0000000..0db47d7
--- /dev/null
+++ b/panels/printers/pp-job-row.ui
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="PpJobRow" parent="GtkListBoxRow">
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">6</property>
+ <property name="margin-bottom">6</property>
+ <property name="margin-start">6</property>
+ <property name="margin-end">6</property>
+ <child>
+ <object class="GtkLabel" id="title_label">
+ <property name="ellipsize">end</property>
+ <property name="max-width-chars">40</property>
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <property name="margin-start">10</property>
+ <property name="margin-end">10</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="state_label">
+ <property name="halign">end</property>
+ <property name="margin-start">74</property>
+ <property name="margin-end">74</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="priority_button">
+ <property name="margin-start">4</property>
+ <property name="margin-end">4</property>
+ <property name="icon-name">go-top-symbolic</property>
+ <signal name="clicked" handler="priority_cb" object="PpJobRow" swapped="yes" />
+ <style>
+ <class name="image-button"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="pause_button">
+ <property name="margin-start">4</property>
+ <property name="margin-end">4</property>
+ <signal name="clicked" handler="pause_cb" object="PpJobRow" swapped="yes" />
+ <style>
+ <class name="image-button"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="margin-start">4</property>
+ <property name="margin-end">4</property>
+ <property name="icon-name">edit-delete-symbolic</property>
+ <signal name="clicked" handler="stop_cb" object="PpJobRow" swapped="yes" />
+ <style>
+ <class name="image-button"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/printers/pp-job.c b/panels/printers/pp-job.c
new file mode 100644
index 0000000..68ceb6b
--- /dev/null
+++ b/panels/printers/pp-job.c
@@ -0,0 +1,485 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2015 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Felipe Borges <feborges@redhat.com>
+ */
+
+#include "pp-job.h"
+
+#include <gio/gio.h>
+#include <cups/cups.h>
+
+#if (CUPS_VERSION_MAJOR > 1) || (CUPS_VERSION_MINOR > 5)
+#define HAVE_CUPS_1_6 1
+#endif
+
+#ifndef HAVE_CUPS_1_6
+#define ippGetBoolean(attr, element) attr->values[element].boolean
+#define ippGetCount(attr) attr->num_values
+#define ippGetInteger(attr, element) attr->values[element].integer
+#define ippGetString(attr, element, language) attr->values[element].string.text
+#define ippGetValueTag(attr) attr->value_tag
+static int
+ippGetRange (ipp_attribute_t *attr,
+ int element,
+ int *upper)
+{
+ *upper = attr->values[element].range.upper;
+ return (attr->values[element].range.lower);
+}
+#endif
+
+struct _PpJob
+{
+ GObject parent_instance;
+
+ gint id;
+ gchar *title;
+ gint state;
+ gint priority;
+ gboolean sensitive;
+
+ GStrv auth_info_required;
+};
+
+G_DEFINE_TYPE (PpJob, pp_job, G_TYPE_OBJECT)
+
+static void
+pp_job_cancel_purge_async_dbus_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GVariant) output = NULL;
+
+ output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ res,
+ NULL);
+}
+
+PpJob *
+pp_job_new (gint id, const gchar *title, gint state, gint priority, GStrv auth_info_required)
+{
+ PpJob *job = g_object_new (pp_job_get_type (), NULL);
+
+ job->id = id;
+ job->title = g_strdup (title);
+ job->state = state;
+ job->priority = priority;
+ job->sensitive = FALSE;
+ job->auth_info_required = g_strdupv (auth_info_required);
+
+ return job;
+}
+
+const gchar *
+pp_job_get_title (PpJob *self)
+{
+ g_return_val_if_fail (PP_IS_JOB(self), NULL);
+ return self->title;
+}
+
+gint
+pp_job_get_state (PpJob *self)
+{
+ g_return_val_if_fail (PP_IS_JOB(self), -1);
+ return self->state;
+}
+
+void
+pp_job_priority_set_sensitive (PpJob *self,
+ gboolean sensitive)
+{
+ self->sensitive = sensitive;
+}
+
+gboolean
+pp_job_priority_get_sensitive (PpJob *self)
+{
+ g_return_val_if_fail (PP_IS_JOB (self), FALSE);
+ return self->sensitive;
+}
+
+gint
+pp_job_get_priority (PpJob *self)
+{
+ g_return_val_if_fail (PP_IS_JOB (self), -1);
+ return self->priority;
+}
+
+void
+pp_job_set_priority (PpJob *self,
+ gint priority)
+{
+ self->priority = priority;
+}
+
+GStrv
+pp_job_get_auth_info_required (PpJob *self)
+{
+ g_return_val_if_fail (PP_IS_JOB(self), NULL);
+ return self->auth_info_required;
+}
+
+void
+pp_job_cancel_purge_async (PpJob *self,
+ gboolean job_purge)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+ g_autoptr(GError) error = NULL;
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!bus)
+ {
+ g_warning ("Failed to get session bus: %s", error->message);
+ return;
+ }
+
+ g_dbus_connection_call (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "JobCancelPurge",
+ g_variant_new ("(ib)",
+ self->id,
+ job_purge),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ pp_job_cancel_purge_async_dbus_cb,
+ NULL);
+}
+
+static void
+pp_job_set_hold_until_async_dbus_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GVariant) output = NULL;
+
+ output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ res,
+ NULL);
+}
+
+void
+pp_job_set_hold_until_async (PpJob *self,
+ const gchar *job_hold_until)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+ g_autoptr(GError) error = NULL;
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!bus)
+ {
+ g_warning ("Failed to get session bus: %s", error->message);
+ return;
+ }
+
+ g_dbus_connection_call (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "JobSetHoldUntil",
+ g_variant_new ("(is)",
+ self->id,
+ job_hold_until),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ pp_job_set_hold_until_async_dbus_cb,
+ NULL);
+}
+
+static void
+pp_job_init (PpJob *obj)
+{
+}
+
+static void
+pp_job_finalize (GObject *object)
+{
+ PpJob *self = PP_JOB (object);
+
+ g_clear_pointer (&self->title, g_free);
+ g_clear_pointer (&self->auth_info_required, g_strfreev);
+
+ G_OBJECT_CLASS (pp_job_parent_class)->finalize (object);
+}
+
+static void
+pp_job_class_init (PpJobClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ object_class->finalize = pp_job_finalize;
+}
+
+static void
+_pp_job_get_attributes_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ PpJob *self = PP_JOB (source_object);
+ ipp_attribute_t *attr = NULL;
+ GVariantBuilder builder;
+ GVariant *attributes = NULL;
+ gchar **attributes_names = task_data;
+ ipp_t *request;
+ ipp_t *response = NULL;
+ g_autofree gchar *job_uri = NULL;
+ gint i, j, length = 0, n_attrs = 0;
+
+ job_uri = g_strdup_printf ("ipp://localhost/jobs/%d", self->id);
+
+ if (attributes_names != NULL)
+ {
+ length = g_strv_length (attributes_names);
+
+ request = ippNewRequest (IPP_GET_JOB_ATTRIBUTES);
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "job-uri", NULL, job_uri);
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, cupsUser ());
+ ippAddStrings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", length, NULL, (const char **) attributes_names);
+ response = cupsDoRequest (CUPS_HTTP_DEFAULT, request, "/");
+ }
+
+ if (response != NULL)
+ {
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+
+ for (j = 0; j < length; j++)
+ {
+ attr = ippFindAttribute (response, attributes_names[j], IPP_TAG_ZERO);
+ n_attrs = ippGetCount (attr);
+ if (attr != NULL && n_attrs > 0 && ippGetValueTag (attr) != IPP_TAG_NOVALUE)
+ {
+ const GVariantType *type = NULL;
+ GVariant **values;
+ GVariant *range[2];
+ gint range_uppervalue;
+
+ values = g_new (GVariant*, n_attrs);
+
+ switch (ippGetValueTag (attr))
+ {
+ case IPP_TAG_INTEGER:
+ case IPP_TAG_ENUM:
+ type = G_VARIANT_TYPE_INT32;
+
+ for (i = 0; i < n_attrs; i++)
+ values[i] = g_variant_new_int32 (ippGetInteger (attr, i));
+ break;
+
+ case IPP_TAG_NAME:
+ case IPP_TAG_STRING:
+ case IPP_TAG_TEXT:
+ case IPP_TAG_URI:
+ case IPP_TAG_KEYWORD:
+ case IPP_TAG_URISCHEME:
+ type = G_VARIANT_TYPE_STRING;
+
+ for (i = 0; i < n_attrs; i++)
+ values[i] = g_variant_new_string (ippGetString (attr, i, NULL));
+ break;
+
+ case IPP_TAG_RANGE:
+ type = G_VARIANT_TYPE_TUPLE;
+
+ for (i = 0; i < n_attrs; i++)
+ {
+ range[0] = g_variant_new_int32 (ippGetRange (attr, i, &(range_uppervalue)));
+ range[1] = g_variant_new_int32 (range_uppervalue);
+
+ values[i] = g_variant_new_tuple (range, 2);
+ }
+ break;
+
+ case IPP_TAG_BOOLEAN:
+ type = G_VARIANT_TYPE_BOOLEAN;
+
+ for (i = 0; i < n_attrs; i++)
+ values[i] = g_variant_new_boolean (ippGetBoolean (attr, i));
+ break;
+
+ default:
+ /* do nothing (switch w/ enumeration type) */
+ break;
+ }
+
+ if (type != NULL)
+ {
+ g_variant_builder_add (&builder, "{sv}",
+ attributes_names[j],
+ g_variant_new_array (type, values, n_attrs));
+ }
+
+ g_free (values);
+ }
+ }
+
+ attributes = g_variant_builder_end (&builder);
+ }
+
+ g_task_return_pointer (task, attributes, (GDestroyNotify) g_variant_unref);
+}
+
+void
+pp_job_get_attributes_async (PpJob *self,
+ gchar **attributes_names,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_task_data (task, g_strdupv (attributes_names), (GDestroyNotify) g_strfreev);
+ g_task_run_in_thread (task, _pp_job_get_attributes_thread);
+}
+
+GVariant *
+pp_job_get_attributes_finish (PpJob *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (result, self), NULL);
+
+ return g_task_propagate_pointer (G_TASK (result), error);
+}
+
+static void
+_pp_job_authenticate_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ PpJob *self = source_object;
+ gboolean result = FALSE;
+ gchar **auth_info = task_data;
+ ipp_t *request;
+ ipp_t *response = NULL;
+ gint length;
+
+ if (auth_info != NULL)
+ {
+ g_autofree gchar *job_uri = g_strdup_printf ("ipp://localhost/jobs/%d", self->id);
+
+ length = g_strv_length (auth_info);
+
+ request = ippNewRequest (IPP_OP_CUPS_AUTHENTICATE_JOB);
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "job-uri", NULL, job_uri);
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, cupsUser ());
+ ippAddStrings (request, IPP_TAG_OPERATION, IPP_TAG_TEXT,
+ "auth-info", length, NULL, (const char **) auth_info);
+ response = cupsDoRequest (CUPS_HTTP_DEFAULT, request, "/");
+
+ result = response != NULL && ippGetStatusCode (response) <= IPP_OK;
+
+ if (response != NULL)
+ ippDelete (response);
+ }
+
+ g_task_return_boolean (task, result);
+}
+
+void
+pp_job_authenticate_async (PpJob *self,
+ gchar **auth_info,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_task_data (task, g_strdupv (auth_info), (GDestroyNotify) g_strfreev);
+ g_task_run_in_thread (task, _pp_job_authenticate_thread);
+}
+
+gboolean
+pp_job_authenticate_finish (PpJob *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+static void
+pp_job_set_priority_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ PpJob *self = source_object;
+ gint priority = GPOINTER_TO_INT (task_data);
+ ipp_t *request;
+ gboolean result = TRUE;
+ g_autofree gchar *uri = NULL;
+
+ request = ippNewRequest (IPP_SET_JOB_ATTRIBUTES);
+ uri = g_strdup_printf ("ipp://localhost/jobs/%d", self->id);
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "job-uri", NULL, uri);
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, cupsUser ());
+
+ ippAddInteger (request, IPP_TAG_JOB, IPP_TAG_INTEGER,
+ "job-priority", priority);
+
+ ippDelete (cupsDoRequest (CUPS_HTTP_DEFAULT, request, "/"));
+
+ if (cupsLastError () > IPP_OK_CONFLICT)
+ {
+ g_warning ("Failed to set job priority: %s", cupsLastErrorString ());
+ result = FALSE;
+ }
+
+ g_task_return_boolean (task, result);
+}
+
+void
+pp_job_set_priority_async (PpJob *self,
+ gint priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_task_data (task, GINT_TO_POINTER (priority), NULL);
+ g_task_run_in_thread (task, pp_job_set_priority_thread);
+}
+
+gboolean
+pp_job_set_priority_finish (PpJob *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
diff --git a/panels/printers/pp-job.h b/panels/printers/pp-job.h
new file mode 100644
index 0000000..b5d7348
--- /dev/null
+++ b/panels/printers/pp-job.h
@@ -0,0 +1,90 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2015 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Felipe Borges <feborges@redhat.com>
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <glib-object.h>
+
+#include "pp-utils.h"
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (PpJob, pp_job, PP, JOB, GObject)
+
+PpJob *pp_job_new (gint id,
+ const gchar *title,
+ gint state,
+ gint priority,
+ GStrv auth_info_required);
+
+const gchar *pp_job_get_title (PpJob *job);
+
+gint pp_job_get_state (PpJob *job);
+
+gboolean pp_job_priority_get_sensitive (PpJob *job);
+
+void pp_job_priority_set_sensitive (PpJob *job,
+ gboolean sensitive);
+
+gint pp_job_get_priority (PpJob *job);
+
+void pp_job_set_priority (PpJob *job,
+ gint priority);
+
+GStrv pp_job_get_auth_info_required (PpJob *job);
+
+void pp_job_set_hold_until_async (PpJob *job,
+ const gchar *job_hold_until);
+
+void pp_job_cancel_purge_async (PpJob *job,
+ gboolean job_purge);
+
+void pp_job_get_attributes_async (PpJob *job,
+ gchar **attributes_names,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GVariant *pp_job_get_attributes_finish (PpJob *job,
+ GAsyncResult *result,
+ GError **error);
+
+void pp_job_authenticate_async (PpJob *job,
+ gchar **auth_info,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean pp_job_authenticate_finish (PpJob *job,
+ GAsyncResult *result,
+ GError **error);
+
+void pp_job_set_priority_async (PpJob *job,
+ gint priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean pp_job_set_priority_finish (PpJob *job,
+ GAsyncResult *result,
+ GError **error);
+
+G_END_DECLS
diff --git a/panels/printers/pp-jobs-dialog.c b/panels/printers/pp-jobs-dialog.c
new file mode 100644
index 0000000..6a9b704
--- /dev/null
+++ b/panels/printers/pp-jobs-dialog.c
@@ -0,0 +1,539 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marek Kasik <mkasik@redhat.com>
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <gtk/gtk.h>
+#include <gdesktop-enums.h>
+
+#include <cups/cups.h>
+
+#include "pp-jobs-dialog.h"
+#include "pp-utils.h"
+#include "pp-job.h"
+#include "pp-job-row.h"
+#include "pp-cups.h"
+#include "pp-printer.h"
+
+#define EMPTY_TEXT "\xe2\x80\x94"
+
+#define CLOCK_SCHEMA "org.gnome.desktop.interface"
+#define CLOCK_FORMAT_KEY "clock-format"
+
+struct _PpJobsDialog {
+ GtkDialog parent_instance;
+
+ GtkButton *authenticate_button;
+ GtkMenuButton *authenticate_jobs_button;
+ GtkLabel *authenticate_jobs_label;
+ GtkInfoBar *authentication_infobar;
+ GtkLabel *authentication_label;
+ GtkEntry *domain_entry;
+ GtkLabel *domain_label;
+ GtkButton *jobs_clear_all_button;
+ GtkListBox *jobs_listbox;
+ GtkScrolledWindow *list_jobs_page;
+ GtkBox *no_jobs_page;
+ GtkEntry *password_entry;
+ GtkLabel *password_label;
+ GtkStack *stack;
+ GListStore *store;
+ GtkEntry *username_entry;
+ GtkLabel *username_label;
+
+ gchar *printer_name;
+
+ gchar **actual_auth_info_required;
+ gboolean jobs_filled;
+ gboolean pop_up_authentication_popup;
+ gint max_priority;
+
+ GCancellable *get_jobs_cancellable;
+};
+
+G_DEFINE_TYPE (PpJobsDialog, pp_jobs_dialog, GTK_TYPE_DIALOG)
+
+static gboolean
+is_info_required (PpJobsDialog *self,
+ const gchar *info)
+{
+ gint i;
+
+ if (self->actual_auth_info_required == NULL)
+ return FALSE;
+
+ for (i = 0; self->actual_auth_info_required[i] != NULL; i++)
+ if (g_strcmp0 (self->actual_auth_info_required[i], info) == 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+static gboolean
+is_domain_required (PpJobsDialog *self)
+{
+ return is_info_required (self, "domain");
+}
+
+static gboolean
+is_username_required (PpJobsDialog *self)
+{
+ return is_info_required (self, "username");
+}
+
+static gboolean
+is_password_required (PpJobsDialog *self)
+{
+ return is_info_required (self, "password");
+}
+
+static gboolean
+auth_popup_filled (PpJobsDialog *self)
+{
+ gboolean domain_required;
+ gboolean username_required;
+ gboolean password_required;
+ guint16 domain_length;
+ guint16 username_length;
+ guint16 password_length;
+
+ domain_required = is_domain_required (self);
+ username_required = is_username_required (self);
+ password_required = is_password_required (self);
+
+ domain_length = gtk_entry_get_text_length (self->domain_entry);
+ username_length = gtk_entry_get_text_length (self->username_entry);
+ password_length = gtk_entry_get_text_length (self->password_entry);
+
+ return (!domain_required || domain_length > 0) &&
+ (!username_required || username_length > 0) &&
+ (!password_required || password_length > 0);
+}
+
+static void
+auth_entries_changed (PpJobsDialog *self)
+{
+ gtk_widget_set_sensitive (GTK_WIDGET (self->authenticate_button), auth_popup_filled (self));
+}
+
+static void
+auth_entries_activated (PpJobsDialog *self)
+{
+ if (auth_popup_filled (self))
+ g_signal_emit_by_name (self->authenticate_button, "activate");
+}
+
+static void
+authenticate_popover_update (PpJobsDialog *self)
+{
+ gboolean domain_required;
+ gboolean username_required;
+ gboolean password_required;
+
+ domain_required = is_domain_required (self);
+ username_required = is_username_required (self);
+ password_required = is_password_required (self);
+
+ gtk_widget_set_visible (GTK_WIDGET (self->domain_label), domain_required);
+ gtk_widget_set_visible (GTK_WIDGET (self->domain_entry), domain_required);
+ if (domain_required)
+ gtk_editable_set_text (GTK_EDITABLE (self->domain_entry), "");
+
+ gtk_widget_set_visible (GTK_WIDGET (self->username_label), username_required);
+ gtk_widget_set_visible (GTK_WIDGET (self->username_entry), username_required);
+ if (username_required)
+ gtk_editable_set_text (GTK_EDITABLE (self->username_entry), cupsUser ());
+
+ gtk_widget_set_visible (GTK_WIDGET (self->password_label), password_required);
+ gtk_widget_set_visible (GTK_WIDGET (self->password_entry), password_required);
+ if (password_required)
+ gtk_editable_set_text (GTK_EDITABLE (self->password_entry), "");
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->authenticate_button), FALSE);
+}
+
+static void
+pp_job_update_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ PpJobsDialog *self = user_data;
+ gboolean result;
+ g_autoptr(GError) error = NULL;
+ PpJob *job = PP_JOB (source_object);
+
+ result = pp_job_set_priority_finish (job, res, &error);
+ if (result)
+ {
+ pp_jobs_dialog_update (self);
+ }
+ else if (error != NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ g_warning ("Could not set job priority: %s", error->message);
+ }
+ }
+}
+
+static void
+on_priority_changed (PpJobRow *job_row,
+ PpJobsDialog *self)
+{
+ PpJob *job;
+
+ job = pp_job_row_get_job (job_row);
+ pp_job_set_priority_async (job, ++self->max_priority, NULL, pp_job_update_cb, self);
+}
+
+static GtkWidget *
+create_listbox_row (gpointer item,
+ gpointer user_data)
+{
+ PpJobRow *job_row;
+
+ job_row = pp_job_row_new (PP_JOB (item));
+
+ g_signal_connect (job_row,
+ "priority-changed",
+ G_CALLBACK (on_priority_changed),
+ user_data);
+
+ return GTK_WIDGET (job_row);
+}
+
+static void
+pop_up_authentication_popup (PpJobsDialog *self)
+{
+ if (self->actual_auth_info_required != NULL)
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->authenticate_jobs_button), TRUE);
+}
+
+static void
+update_jobs_list_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ PpJobsDialog *self = user_data;
+ PpPrinter *printer = PP_PRINTER (source_object);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) jobs;
+ PpJob *job;
+ gint num_of_auth_jobs = 0;
+ gint job_priority;
+ guint state;
+ guint i;
+ gint current_max_value = 1;
+ gint first_unprocessed_job = -1;
+
+ g_list_store_remove_all (self->store);
+
+ jobs = pp_printer_get_jobs_finish (printer, result, &error);
+ if (error != NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ g_warning ("Could not get jobs: %s", error->message);
+ }
+
+ return;
+ }
+
+ if (jobs->len > 0)
+ {
+ gtk_widget_set_sensitive (GTK_WIDGET (self->jobs_clear_all_button), TRUE);
+ gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->list_jobs_page));
+ }
+ else
+ {
+ gtk_widget_set_sensitive (GTK_WIDGET (self->jobs_clear_all_button), FALSE);
+ gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->no_jobs_page));
+ }
+
+ for (i = 0; i < jobs->len; i++)
+ {
+ job = PP_JOB (g_ptr_array_index (jobs, i));
+ state = pp_job_get_state (job);
+
+ if (state == IPP_JOB_PENDING || state == IPP_JOB_HELD)
+ {
+ if (first_unprocessed_job == -1)
+ {
+ first_unprocessed_job = i;
+ break;
+ }
+ }
+ }
+
+ for (i = 0; i < jobs->len; i++)
+ {
+ job = PP_JOB (g_ptr_array_index (jobs, i));
+ job_priority = pp_job_get_priority (job);
+ pp_job_priority_set_sensitive (job, (pp_job_get_state (job) == IPP_JOB_PENDING ||
+ pp_job_get_state (job) == IPP_JOB_HELD) &&
+ i > first_unprocessed_job);
+
+ if (job_priority >= current_max_value && job_priority != 100)
+ current_max_value = job_priority;
+
+ g_list_store_append (self->store, g_object_ref (job));
+
+ if (pp_job_get_auth_info_required (job) != NULL)
+ {
+ num_of_auth_jobs++;
+
+ if (self->actual_auth_info_required == NULL)
+ self->actual_auth_info_required = g_strdupv (pp_job_get_auth_info_required (job));
+ }
+ }
+ self->max_priority = current_max_value;
+ if (num_of_auth_jobs > 0)
+ {
+ g_autofree gchar *text = NULL;
+
+ /* Translators: This label shows how many jobs of this printer needs to be authenticated to be printed. */
+ text = g_strdup_printf (ngettext ("%u Job Requires Authentication", "%u Jobs Require Authentication", num_of_auth_jobs), num_of_auth_jobs);
+ gtk_label_set_text (self->authenticate_jobs_label, text);
+
+ gtk_widget_show (GTK_WIDGET (self->authentication_infobar));
+ }
+ else
+ {
+ gtk_widget_hide (GTK_WIDGET (self->authentication_infobar));
+ }
+
+ authenticate_popover_update (self);
+
+ g_clear_object (&self->get_jobs_cancellable);
+
+ if (!self->jobs_filled)
+ {
+ if (self->pop_up_authentication_popup)
+ {
+ pop_up_authentication_popup (self);
+ self->pop_up_authentication_popup = FALSE;
+ }
+
+ self->jobs_filled = TRUE;
+ }
+}
+
+static void
+update_jobs_list (PpJobsDialog *self)
+{
+ g_autoptr(PpPrinter) printer = NULL;
+
+ if (self->printer_name != NULL)
+ {
+ g_cancellable_cancel (self->get_jobs_cancellable);
+ g_clear_object (&self->get_jobs_cancellable);
+
+ self->get_jobs_cancellable = g_cancellable_new ();
+
+ printer = pp_printer_new (self->printer_name);
+ pp_printer_get_jobs_async (printer,
+ TRUE,
+ CUPS_WHICHJOBS_ACTIVE,
+ self->get_jobs_cancellable,
+ update_jobs_list_cb,
+ self);
+ }
+}
+
+static void
+on_clear_all_button_clicked (PpJobsDialog *self)
+{
+ guint num_items;
+ guint i;
+
+ num_items = g_list_model_get_n_items (G_LIST_MODEL (self->store));
+
+ for (i = 0; i < num_items; i++)
+ {
+ PpJob *job = PP_JOB (g_list_model_get_item (G_LIST_MODEL (self->store), i));
+
+ pp_job_cancel_purge_async (job, FALSE);
+ }
+}
+
+static void
+pp_job_authenticate_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ PpJobsDialog *self = user_data;
+ gboolean result;
+ g_autoptr(GError) error = NULL;
+ PpJob *job = PP_JOB (source_object);
+
+ result = pp_job_authenticate_finish (job, res, &error);
+ if (result)
+ {
+ pp_jobs_dialog_update (self);
+ }
+ else if (error != NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ g_warning ("Could not authenticate job: %s", error->message);
+ }
+ }
+}
+
+static void
+authenticate_button_clicked (PpJobsDialog *self)
+{
+ PpJob *job;
+ gchar **auth_info;
+ guint num_items;
+ gint i;
+
+ auth_info = g_new0 (gchar *, g_strv_length (self->actual_auth_info_required) + 1);
+ for (i = 0; self->actual_auth_info_required[i] != NULL; i++)
+ {
+ if (g_strcmp0 (self->actual_auth_info_required[i], "domain") == 0)
+ auth_info[i] = g_strdup (gtk_editable_get_text (GTK_EDITABLE (self->domain_entry)));
+ else if (g_strcmp0 (self->actual_auth_info_required[i], "username") == 0)
+ auth_info[i] = g_strdup (gtk_editable_get_text (GTK_EDITABLE (self->username_entry)));
+ else if (g_strcmp0 (self->actual_auth_info_required[i], "password") == 0)
+ auth_info[i] = g_strdup (gtk_editable_get_text (GTK_EDITABLE (self->password_entry)));
+ }
+
+ num_items = g_list_model_get_n_items (G_LIST_MODEL (self->store));
+ for (i = 0; i < num_items; i++)
+ {
+ job = PP_JOB (g_list_model_get_item (G_LIST_MODEL (self->store), i));
+
+ if (pp_job_get_auth_info_required (job) != NULL)
+ {
+ pp_job_authenticate_async (job, auth_info, NULL, pp_job_authenticate_cb, self);
+ }
+ }
+
+ g_strfreev (auth_info);
+}
+
+PpJobsDialog *
+pp_jobs_dialog_new (const gchar *printer_name)
+{
+ PpJobsDialog *self;
+ g_autofree gchar *text = NULL;
+ g_autofree gchar *title = NULL;
+
+ self = g_object_new (PP_TYPE_JOBS_DIALOG,
+ "use-header-bar", 1,
+ NULL);
+
+ self->printer_name = g_strdup (printer_name);
+ self->actual_auth_info_required = NULL;
+ self->jobs_filled = FALSE;
+ self->pop_up_authentication_popup = FALSE;
+
+ /* Translators: This is the printer name for which we are showing the active jobs */
+ title = g_strdup_printf (C_("Printer jobs dialog title", "%s — Active Jobs"), printer_name);
+ gtk_window_set_title (GTK_WINDOW (self), title);
+
+ /* Translators: The printer needs authentication info to print. */
+ text = g_strdup_printf (_("Enter credentials to print from %s."), printer_name);
+ gtk_label_set_text (self->authentication_label, text);
+
+ self->store = g_list_store_new (pp_job_get_type ());
+ gtk_list_box_bind_model (self->jobs_listbox, G_LIST_MODEL (self->store),
+ create_listbox_row, self, NULL);
+
+ update_jobs_list (self);
+
+ return self;
+}
+
+void
+pp_jobs_dialog_update (PpJobsDialog *self)
+{
+ update_jobs_list (self);
+}
+
+void
+pp_jobs_dialog_authenticate_jobs (PpJobsDialog *self)
+{
+ if (self->jobs_filled)
+ pop_up_authentication_popup (self);
+ else
+ self->pop_up_authentication_popup = TRUE;
+}
+
+static void
+pp_jobs_dialog_init (PpJobsDialog *dialog)
+{
+ gtk_widget_init_template (GTK_WIDGET (dialog));
+}
+
+static void
+pp_jobs_dialog_dispose (GObject *object)
+{
+ PpJobsDialog *self = PP_JOBS_DIALOG (object);
+
+ g_cancellable_cancel (self->get_jobs_cancellable);
+ g_clear_object (&self->get_jobs_cancellable);
+ g_clear_pointer (&self->actual_auth_info_required, g_strfreev);
+ g_clear_pointer (&self->printer_name, g_free);
+
+ G_OBJECT_CLASS (pp_jobs_dialog_parent_class)->dispose (object);
+}
+
+static void
+pp_jobs_dialog_class_init (PpJobsDialogClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/printers/pp-jobs-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, PpJobsDialog, authenticate_button);
+ gtk_widget_class_bind_template_child (widget_class, PpJobsDialog, authenticate_jobs_button);
+ gtk_widget_class_bind_template_child (widget_class, PpJobsDialog, authenticate_jobs_label);
+ gtk_widget_class_bind_template_child (widget_class, PpJobsDialog, authentication_infobar);
+ gtk_widget_class_bind_template_child (widget_class, PpJobsDialog, authentication_label);
+ gtk_widget_class_bind_template_child (widget_class, PpJobsDialog, domain_entry);
+ gtk_widget_class_bind_template_child (widget_class, PpJobsDialog, domain_label);
+ gtk_widget_class_bind_template_child (widget_class, PpJobsDialog, jobs_clear_all_button);
+ gtk_widget_class_bind_template_child (widget_class, PpJobsDialog, jobs_listbox);
+ gtk_widget_class_bind_template_child (widget_class, PpJobsDialog, list_jobs_page);
+ gtk_widget_class_bind_template_child (widget_class, PpJobsDialog, no_jobs_page);
+ gtk_widget_class_bind_template_child (widget_class, PpJobsDialog, password_entry);
+ gtk_widget_class_bind_template_child (widget_class, PpJobsDialog, password_label);
+ gtk_widget_class_bind_template_child (widget_class, PpJobsDialog, stack);
+ gtk_widget_class_bind_template_child (widget_class, PpJobsDialog, username_entry);
+ gtk_widget_class_bind_template_child (widget_class, PpJobsDialog, username_label);
+
+ gtk_widget_class_bind_template_callback (widget_class, authenticate_button_clicked);
+ gtk_widget_class_bind_template_callback (widget_class, on_clear_all_button_clicked);
+ gtk_widget_class_bind_template_callback (widget_class, auth_entries_activated);
+ gtk_widget_class_bind_template_callback (widget_class, auth_entries_changed);
+
+ object_class->dispose = pp_jobs_dialog_dispose;
+
+ gtk_widget_class_add_binding_action (widget_class, GDK_KEY_Escape, 0, "window.close", NULL);
+}
diff --git a/panels/printers/pp-jobs-dialog.h b/panels/printers/pp-jobs-dialog.h
new file mode 100644
index 0000000..c61354b
--- /dev/null
+++ b/panels/printers/pp-jobs-dialog.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marek Kasik <mkasik@redhat.com>
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include "pp-utils.h"
+
+G_BEGIN_DECLS
+
+#define PP_TYPE_JOBS_DIALOG (pp_jobs_dialog_get_type ())
+G_DECLARE_FINAL_TYPE (PpJobsDialog, pp_jobs_dialog, PP, JOBS_DIALOG, GtkDialog)
+
+PpJobsDialog *pp_jobs_dialog_new (const gchar *printer_name);
+void pp_jobs_dialog_update (PpJobsDialog *dialog);
+void pp_jobs_dialog_authenticate_jobs (PpJobsDialog *dialog);
+
+G_END_DECLS
diff --git a/panels/printers/pp-jobs-dialog.ui b/panels/printers/pp-jobs-dialog.ui
new file mode 100644
index 0000000..0a4f0d2
--- /dev/null
+++ b/panels/printers/pp-jobs-dialog.ui
@@ -0,0 +1,234 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.2 -->
+<interface>
+ <requires lib="gtk+" version="3.22"/>
+ <object class="GtkPopover" id="authentication_popover">
+ <property name="halign">start</property>
+ <property name="valign">start</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin_start">30</property>
+ <property name="margin_end">30</property>
+ <property name="margin_top">20</property>
+ <property name="margin_bottom">20</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">20</property>
+ <child>
+ <object class="GtkLabel" id="authentication_label">
+ <property name="margin_top">5</property>
+ <property name="margin_bottom">5</property>
+ <property name="label" translatable="no">Enter credentials to print from %s.</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkGrid">
+ <property name="row_spacing">10</property>
+ <property name="column_spacing">15</property>
+ <child>
+ <object class="GtkLabel" id="domain_label">
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" comments="Translators: This is a windows domain used with SMB protocol.">Domain</property>
+ <property name="xalign">1</property>
+ <property name="mnemonic_widget">domain_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="username_label">
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" comments="Translators: This is a username on a print server.">Username</property>
+ <property name="xalign">1</property>
+ <property name="mnemonic_widget">username_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="password_label">
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" comments="Translators: This is a password needed for printing.">Password</property>
+ <property name="xalign">1</property>
+ <property name="mnemonic_widget">password_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="domain_entry">
+ <property name="hexpand">True</property>
+ <signal name="changed" handler="auth_entries_changed" swapped="yes"/>
+ <signal name="activate" handler="auth_entries_activated" swapped="yes"/>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="username_entry">
+ <property name="hexpand">True</property>
+ <signal name="changed" handler="auth_entries_changed" swapped="yes"/>
+ <signal name="activate" handler="auth_entries_activated" swapped="yes"/>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="password_entry">
+ <property name="hexpand">True</property>
+ <property name="visibility">False</property>
+ <property name="invisible_char">*</property>
+ <property name="input_purpose">password</property>
+ <signal name="changed" handler="auth_entries_changed" swapped="yes"/>
+ <signal name="activate" handler="auth_entries_activated" swapped="yes"/>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="authenticate_button">
+ <property name="label" translatable="yes" comments="Translators: This button authenticates all print jobs and send them for printing.">A_uthenticate</property>
+ <property name="use_underline">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">end</property>
+ <signal name="clicked" handler="authenticate_button_clicked" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <object class="GtkSizeGroup">
+ <widgets>
+ <widget name="domain_label"/>
+ <widget name="username_label"/>
+ <widget name="password_label"/>
+ </widgets>
+ </object>
+ <template class="PpJobsDialog" parent="GtkDialog">
+ <property name="width_request">720</property>
+ <property name="height_request">500</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="destroy_with_parent">True</property>
+ <child internal-child="headerbar">
+ <object class="GtkHeaderBar">
+ <property name="show_title_buttons">True</property>
+ <child>
+ <object class="GtkButton" id="jobs_clear_all_button">
+ <property name="label" translatable="yes" comments="Translators: this action removes (purges) all the listed jobs from the list.">Clear All</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ <property name="valign">center</property>
+ <signal name="clicked" handler="on_clear_all_button_clicked" swapped="yes"/>
+ <style>
+ <class name="destructive-action"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <style>
+ <class name="view"/>
+ </style>
+ <child>
+ <object class="GtkInfoBar" id="authentication_infobar">
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">16</property>
+ <property name="margin-start">12</property>
+ <child>
+ <object class="GtkLabel" id="authenticate_jobs_label">
+ <property name="halign">start</property>
+ <property name="hexpand">False</property>
+ <property name="wrap">True</property>
+ <property name="label" translatable="no">2 Jobs Require Authentication</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">2</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkMenuButton" id="authenticate_jobs_button">
+ <property name="label" translatable="yes" comments="Translators: This button pop up authentication dialog for print jobs which need credentials.">_Authenticate</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="halign">end</property>
+ <property name="valign">GTK_ALIGN_CENTER</property>
+ <property name="popover">authentication_popover</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStack" id="stack">
+ <child>
+ <object class="GtkScrolledWindow" id="list_jobs_page">
+ <property name="vexpand">True</property>
+ <property name="hscrollbar-policy">never</property>
+ <child>
+ <object class="GtkListBox" id="jobs_listbox">
+ <property name="halign">fill</property>
+ <property name="valign">fill</property>
+ <property name="selection-mode">none</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="no_jobs_page">
+ <property name="spacing">10</property>
+ <property name="orientation">vertical</property>
+ <property name="valign">center</property>
+ <child>
+ <object class="GtkImage">
+ <property name="valign">start</property>
+ <property name="pixel_size">64</property>
+ <property name="icon_name">printer-symbolic</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes" comments="Translators: this label describes the dialog empty state, with no jobs listed.">No Active Printer Jobs</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/printers/pp-maintenance-command.c b/panels/printers/pp-maintenance-command.c
new file mode 100644
index 0000000..fd843d0
--- /dev/null
+++ b/panels/printers/pp-maintenance-command.c
@@ -0,0 +1,390 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marek Kasik <mkasik@redhat.com>
+ */
+
+#include <glib/gstdio.h>
+
+#include "pp-maintenance-command.h"
+
+#include "pp-utils.h"
+
+#if (CUPS_VERSION_MAJOR > 1) || (CUPS_VERSION_MINOR > 5)
+#define HAVE_CUPS_1_6 1
+#endif
+
+#ifndef HAVE_CUPS_1_6
+#define ippGetCount(attr) attr->num_values
+#define ippGetValueTag(attr) attr->value_tag
+#define ippGetStatusCode(ipp) ipp->request.status.status_code
+#define ippGetString(attr, element, language) attr->values[element].string.text
+#endif
+
+struct _PpMaintenanceCommand
+{
+ GObject parent_instance;
+
+ gchar *printer_name;
+ gchar *command;
+ gchar *parameters;
+ gchar *title;
+};
+
+G_DEFINE_TYPE (PpMaintenanceCommand, pp_maintenance_command, G_TYPE_OBJECT);
+
+enum {
+ PROP_0 = 0,
+ PROP_PRINTER_NAME,
+ PROP_COMMAND,
+ PROP_PARAMETERS,
+ PROP_TITLE
+};
+
+static void
+pp_maintenance_command_finalize (GObject *object)
+{
+ PpMaintenanceCommand *self = PP_MAINTENANCE_COMMAND (object);
+
+ g_clear_pointer (&self->printer_name, g_free);
+ g_clear_pointer (&self->command, g_free);
+ g_clear_pointer (&self->parameters, g_free);
+ g_clear_pointer (&self->title, g_free);
+
+ G_OBJECT_CLASS (pp_maintenance_command_parent_class)->finalize (object);
+}
+
+static void
+pp_maintenance_command_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *param_spec)
+{
+ PpMaintenanceCommand *self = PP_MAINTENANCE_COMMAND (object);
+
+ switch (prop_id)
+ {
+ case PROP_PRINTER_NAME:
+ g_value_set_string (value, self->printer_name);
+ break;
+ case PROP_COMMAND:
+ g_value_set_string (value, self->command);
+ break;
+ case PROP_PARAMETERS:
+ g_value_set_string (value, self->parameters);
+ break;
+ case PROP_TITLE:
+ g_value_set_string (value, self->title);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
+ prop_id,
+ param_spec);
+ break;
+ }
+}
+
+static void
+pp_maintenance_command_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *param_spec)
+{
+ PpMaintenanceCommand *self = PP_MAINTENANCE_COMMAND (object);
+
+ switch (prop_id)
+ {
+ case PROP_PRINTER_NAME:
+ g_free (self->printer_name);
+ self->printer_name = g_value_dup_string (value);
+ break;
+ case PROP_COMMAND:
+ g_free (self->command);
+ self->command = g_value_dup_string (value);
+ break;
+ case PROP_PARAMETERS:
+ g_free (self->parameters);
+ self->parameters = g_value_dup_string (value);
+ break;
+ case PROP_TITLE:
+ g_free (self->title);
+ self->title = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
+ prop_id,
+ param_spec);
+ break;
+ }
+}
+
+static void
+pp_maintenance_command_class_init (PpMaintenanceCommandClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->set_property = pp_maintenance_command_set_property;
+ gobject_class->get_property = pp_maintenance_command_get_property;
+ gobject_class->finalize = pp_maintenance_command_finalize;
+
+ g_object_class_install_property (gobject_class, PROP_PRINTER_NAME,
+ g_param_spec_string ("printer-name",
+ "Printer name",
+ "Name of the printer",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_COMMAND,
+ g_param_spec_string ("command",
+ "Maintenance command",
+ "Command to execute",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_PARAMETERS,
+ g_param_spec_string ("parameters",
+ "Optional parameters",
+ "Optional parameters for the maintenance command",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_TITLE,
+ g_param_spec_string ("title",
+ "Command title",
+ "Title of the job by which the command will be executed",
+ NULL,
+ G_PARAM_READWRITE));
+}
+
+static void
+pp_maintenance_command_init (PpMaintenanceCommand *self)
+{
+}
+
+PpMaintenanceCommand *
+pp_maintenance_command_new (const gchar *printer_name,
+ const gchar *command,
+ const gchar *parameters,
+ const gchar *title)
+{
+ return g_object_new (PP_TYPE_MAINTENANCE_COMMAND,
+ "printer-name", printer_name,
+ "command", command,
+ "parameters", parameters,
+ "title", title,
+ NULL);
+}
+
+static gboolean _pp_maintenance_command_is_supported (const gchar *printer_name,
+ const gchar *command);
+
+static void
+_pp_maintenance_command_execute_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ PpMaintenanceCommand *self = PP_MAINTENANCE_COMMAND (source_object);
+ gboolean success = FALSE;
+ GError *error = NULL;
+
+ if (_pp_maintenance_command_is_supported (self->printer_name, self->command))
+ {
+ ipp_t *request;
+ ipp_t *response = NULL;
+ g_autofree gchar *printer_uri = NULL;
+ g_autofree gchar *file_name = NULL;
+ int fd = -1;
+
+ printer_uri = g_strdup_printf ("ipp://localhost/printers/%s",
+ self->printer_name);
+
+ request = ippNewRequest (IPP_PRINT_JOB);
+
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, printer_uri);
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "job-name", NULL, self->title);
+ ippAddString (request, IPP_TAG_JOB, IPP_TAG_MIMETYPE,
+ "document-format", NULL, "application/vnd.cups-command");
+
+ fd = g_file_open_tmp ("ccXXXXXX", &file_name, &error);
+
+ if (fd != -1)
+ {
+ FILE *file;
+
+ file = fdopen (fd, "w");
+ fprintf (file, "#CUPS-COMMAND\n");
+ fprintf (file, "%s", self->command);
+ if (self->parameters)
+ fprintf (file, " %s", self->parameters);
+ fprintf (file, "\n");
+ fclose (file);
+
+ response = cupsDoFileRequest (CUPS_HTTP_DEFAULT, request, "/", file_name);
+ g_unlink (file_name);
+
+ if (response != NULL)
+ {
+ if (ippGetStatusCode (response) <= IPP_OK_CONFLICT)
+ {
+ success = TRUE;
+ }
+
+ ippDelete (response);
+ }
+ }
+ }
+ else
+ {
+ success = TRUE;
+ }
+
+ if (!success)
+ {
+ g_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Execution of maintenance command failed.");
+ }
+
+ g_task_return_boolean (task, success);
+}
+
+void
+pp_maintenance_command_execute_async (PpMaintenanceCommand *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_check_cancellable (task, TRUE);
+ g_task_run_in_thread (task, _pp_maintenance_command_execute_thread);
+}
+
+gboolean
+pp_maintenance_command_execute_finish (PpMaintenanceCommand *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+static gboolean
+_pp_maintenance_command_is_supported (const gchar *printer_name,
+ const gchar *command)
+{
+ ipp_attribute_t *attr = NULL;
+ gboolean is_supported = FALSE;
+ ipp_t *request;
+ ipp_t *response = NULL;
+ g_autofree gchar *printer_uri = NULL;
+ GPtrArray *available_commands = NULL;
+ int i;
+
+ printer_uri = g_strdup_printf ("ipp://localhost/printers/%s",
+ printer_name);
+
+ request = ippNewRequest (IPP_GET_PRINTER_ATTRIBUTES);
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, printer_uri);
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", NULL, "printer-commands");
+ response = cupsDoRequest (CUPS_HTTP_DEFAULT, request, "/");
+ if (response != NULL)
+ {
+ if (ippGetStatusCode (response) <= IPP_OK_CONFLICT)
+ {
+ int commands_count;
+
+ attr = ippFindAttribute (response, "printer-commands", IPP_TAG_ZERO);
+ commands_count = attr != NULL ? ippGetCount (attr) : 0;
+ if (commands_count > 0 &&
+ ippGetValueTag (attr) != IPP_TAG_NOVALUE &&
+ (ippGetValueTag (attr) == IPP_TAG_KEYWORD))
+ {
+ available_commands = g_ptr_array_new_full (commands_count, g_free);
+ for (i = 0; i < commands_count; ++i)
+ {
+ /* Array gains ownership of the lower-cased string */
+ g_ptr_array_add (available_commands, g_ascii_strdown (ippGetString (attr, i, NULL), -1));
+ }
+ }
+ }
+
+ ippDelete (response);
+ }
+
+ if (available_commands != NULL)
+ {
+ g_autofree gchar *command_lowercase = g_ascii_strdown (command, -1);
+ for (i = 0; i < available_commands->len; ++i)
+ {
+ const gchar *available_command = g_ptr_array_index (available_commands, i);
+ if (g_strcmp0 (available_command, command_lowercase) == 0)
+ {
+ is_supported = TRUE;
+ break;
+ }
+ }
+
+ g_ptr_array_free (available_commands, TRUE);
+ }
+
+ return is_supported;
+}
+
+static void
+_pp_maintenance_command_is_supported_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ PpMaintenanceCommand *self = PP_MAINTENANCE_COMMAND (source_object);
+ gboolean success = FALSE;
+
+ success = _pp_maintenance_command_is_supported (self->printer_name, self->command);
+ g_task_return_boolean (task, success);
+}
+
+void
+pp_maintenance_command_is_supported_async (PpMaintenanceCommand *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_check_cancellable (task, TRUE);
+ g_task_run_in_thread (task, _pp_maintenance_command_is_supported_thread);
+}
+
+gboolean
+pp_maintenance_command_is_supported_finish (PpMaintenanceCommand *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
diff --git a/panels/printers/pp-maintenance-command.h b/panels/printers/pp-maintenance-command.h
new file mode 100644
index 0000000..b5bacfe
--- /dev/null
+++ b/panels/printers/pp-maintenance-command.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marek Kasik <mkasik@redhat.com>
+ */
+
+#pragma once
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define PP_TYPE_MAINTENANCE_COMMAND (pp_maintenance_command_get_type ())
+G_DECLARE_FINAL_TYPE (PpMaintenanceCommand, pp_maintenance_command, PP, MAINTENANCE_COMMAND, GObject)
+
+PpMaintenanceCommand *pp_maintenance_command_new (const gchar *printer_name,
+ const gchar *command,
+ const gchar *parameters,
+ const gchar *title);
+
+void pp_maintenance_command_execute_async (PpMaintenanceCommand *command,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean pp_maintenance_command_execute_finish (PpMaintenanceCommand *command,
+ GAsyncResult *result,
+ GError **error);
+void pp_maintenance_command_is_supported_async (PpMaintenanceCommand *command,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean pp_maintenance_command_is_supported_finish (PpMaintenanceCommand *command,
+ GAsyncResult *result,
+ GError **error);
+G_END_DECLS
diff --git a/panels/printers/pp-new-printer-dialog.c b/panels/printers/pp-new-printer-dialog.c
new file mode 100644
index 0000000..a3c0e48
--- /dev/null
+++ b/panels/printers/pp-new-printer-dialog.c
@@ -0,0 +1,1929 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2009-2010 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <adwaita.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <gdk/x11/gdkx.h>
+#include <gtk/gtk.h>
+
+#include "pp-new-printer-dialog.h"
+#include "pp-cups.h"
+#include "pp-host.h"
+#include "pp-new-printer.h"
+#include "pp-ppd-selection-dialog.h"
+#include "pp-samba.h"
+#include "pp-utils.h"
+
+#if (CUPS_VERSION_MAJOR > 1) || (CUPS_VERSION_MINOR > 5)
+#define HAVE_CUPS_1_6 1
+#endif
+
+#ifndef HAVE_CUPS_1_6
+#define ippGetState(ipp) ipp->state
+#endif
+
+/*
+ * Additional delay to the default 150ms delay in GtkSearchEntry
+ * resulting in total delay of 500ms.
+ */
+#define HOST_SEARCH_DELAY (500 - 150)
+
+#define AUTHENTICATION_PAGE "authentication-page"
+#define ADDPRINTER_PAGE "addprinter-page"
+
+static void set_device (PpNewPrinterDialog *self,
+ PpPrintDevice *device,
+ GtkTreeIter *iter);
+static void replace_device (PpNewPrinterDialog *self,
+ PpPrintDevice *old_device,
+ PpPrintDevice *new_device);
+static void populate_devices_list (PpNewPrinterDialog *self);
+static void search_entry_activated_cb (PpNewPrinterDialog *self);
+static void search_entry_changed_cb (PpNewPrinterDialog *self);
+static void new_printer_dialog_response_cb (PpNewPrinterDialog *self,
+ gint response_id);
+static void update_dialog_state (PpNewPrinterDialog *self);
+static void add_devices_to_list (PpNewPrinterDialog *self,
+ GPtrArray *devices);
+static void remove_device_from_list (PpNewPrinterDialog *self,
+ const gchar *device_name);
+
+enum
+{
+ DEVICE_GICON_COLUMN = 0,
+ DEVICE_NAME_COLUMN,
+ DEVICE_DISPLAY_NAME_COLUMN,
+ DEVICE_DESCRIPTION_COLUMN,
+ SERVER_NEEDS_AUTHENTICATION_COLUMN,
+ DEVICE_VISIBLE_COLUMN,
+ DEVICE_COLUMN,
+ DEVICE_N_COLUMNS
+};
+
+struct _PpNewPrinterDialog
+{
+ GtkDialog parent_instance;
+
+ GPtrArray *local_cups_devices;
+
+ GtkListStore *devices_liststore;
+ GtkTreeModelFilter *devices_model_filter;
+
+ /* headerbar */
+ GtkHeaderBar *headerbar;
+ AdwWindowTitle *header_title;
+
+ /* headerbar topleft buttons */
+ GtkStack *headerbar_topleft_buttons;
+ GtkButton *go_back_button;
+
+ /* headerbar topright buttons */
+ GtkStack *headerbar_topright_buttons;
+ GtkButton *new_printer_add_button;
+ GtkButton *unlock_button;
+ GtkButton *authenticate_button;
+ /* end headerbar */
+
+ /* dialogstack */
+ GtkStack *dialog_stack;
+ GtkStack *stack;
+
+ /* scrolledwindow1 */
+ GtkScrolledWindow *scrolledwindow1;
+ GtkTreeView *devices_treeview;
+
+ GtkEntry *search_entry;
+
+ /* authentication page */
+ GtkLabel *authentication_title;
+ GtkLabel *authentication_text;
+ GtkEntry *username_entry;
+ GtkEntry *password_entry;
+ /* end dialog stack */
+
+ UserResponseCallback user_callback;
+ gpointer user_data;
+
+ cups_dest_t *dests;
+ gint num_of_dests;
+
+ GCancellable *cancellable;
+ GCancellable *remote_host_cancellable;
+
+ gboolean cups_searching;
+ gboolean samba_authenticated_searching;
+ gboolean samba_searching;
+
+ PpPPDSelectionDialog *ppd_selection_dialog;
+
+ PpPrintDevice *new_device;
+
+ PPDList *list;
+
+ GIcon *local_printer_icon;
+ GIcon *remote_printer_icon;
+ GIcon *authenticated_server_icon;
+
+ PpHost *snmp_host;
+ PpHost *socket_host;
+ PpHost *lpd_host;
+ PpHost *remote_cups_host;
+ PpSamba *samba_host;
+ guint host_search_timeout_id;
+};
+
+G_DEFINE_TYPE (PpNewPrinterDialog, pp_new_printer_dialog, GTK_TYPE_DIALOG)
+
+typedef struct
+{
+ gchar *server_name;
+ gpointer dialog;
+} AuthSMBData;
+
+static void
+get_authenticated_samba_devices_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ AuthSMBData *data = user_data;
+ PpNewPrinterDialog *self = PP_NEW_PRINTER_DIALOG (data->dialog);
+ g_autoptr(GPtrArray) devices = NULL;
+ gboolean cancelled = FALSE;
+ g_autoptr(GError) error = NULL;
+
+ devices = pp_samba_get_devices_finish (PP_SAMBA (source_object), res, &error);
+
+ if (devices != NULL)
+ {
+ self->samba_authenticated_searching = FALSE;
+
+ for (guint i = 0; i < devices->len; i++)
+ {
+ PpPrintDevice *device = g_ptr_array_index (devices, i);
+
+ if (pp_print_device_is_authenticated_server (device))
+ {
+ cancelled = TRUE;
+ break;
+ }
+ }
+
+ if (!cancelled)
+ {
+ if (devices != NULL)
+ {
+ add_devices_to_list (self, devices);
+
+ if (devices->len > 0)
+ {
+ gtk_editable_set_text (GTK_EDITABLE (self->search_entry),
+ pp_print_device_get_device_location (g_ptr_array_index (devices, 0)));
+ search_entry_activated_cb (self);
+ }
+ }
+ }
+
+ update_dialog_state (self);
+ }
+ else
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ g_warning ("%s", error->message);
+
+ self->samba_authenticated_searching = FALSE;
+ update_dialog_state (self);
+ }
+ }
+
+ g_free (data->server_name);
+ g_free (data);
+}
+
+static void
+go_to_page (PpNewPrinterDialog *self,
+ const gchar *page)
+{
+ gtk_stack_set_visible_child_name (self->dialog_stack, page);
+ gtk_stack_set_visible_child_name (self->headerbar_topright_buttons, page);
+ gtk_stack_set_visible_child_name (self->headerbar_topleft_buttons, page);
+}
+
+static void
+on_authenticate (PpNewPrinterDialog *self)
+{
+ gchar *hostname = NULL;
+ gchar *username = NULL;
+ gchar *password = NULL;
+
+ username = g_strdup (gtk_editable_get_text (GTK_EDITABLE (self->username_entry)));
+ password = g_strdup (gtk_editable_get_text (GTK_EDITABLE (self->password_entry)));
+
+ if ((username == NULL) || (username[0] == '\0') ||
+ (password == NULL) || (password[0] == '\0'))
+ {
+ g_clear_pointer (&username, g_free);
+ g_clear_pointer (&password, g_free);
+ return;
+ }
+
+ pp_samba_set_auth_info (PP_SAMBA (self->samba_host), username, password);
+
+ adw_window_title_set_title (self->header_title, _("Add Printer"));
+ go_to_page (self, ADDPRINTER_PAGE);
+
+ g_object_get (PP_HOST (self->samba_host), "hostname", &hostname, NULL);
+ remove_device_from_list (self, hostname);
+}
+
+static void
+on_authentication_required (PpNewPrinterDialog *self)
+{
+ g_autofree gchar *hostname = NULL;
+ g_autofree gchar *title = NULL;
+ g_autofree gchar *text = NULL;
+
+ adw_window_title_set_subtitle (self->header_title, NULL);
+ adw_window_title_set_title (self->header_title, _("Unlock Print Server"));
+
+ g_object_get (self->samba_host, "hostname", &hostname, NULL);
+ /* Translators: Samba server needs authentication of the user to show list of its printers. */
+ title = g_strdup_printf (_("Unlock %s."), hostname);
+ gtk_label_set_text (self->authentication_title, title);
+
+ /* Translators: Samba server needs authentication of the user to show list of its printers. */
+ text = g_strdup_printf (_("Enter username and password to view printers on %s."), hostname);
+ gtk_label_set_text (self->authentication_text, text);
+
+ go_to_page (self, AUTHENTICATION_PAGE);
+
+ g_signal_connect_object (self->authenticate_button, "clicked", G_CALLBACK (on_authenticate), self, G_CONNECT_SWAPPED);
+}
+
+static void
+auth_entries_changed (PpNewPrinterDialog *self)
+{
+ gboolean can_authenticate = FALSE;
+ gchar *username = NULL;
+ gchar *password = NULL;
+
+ username = g_strdup (gtk_editable_get_text (GTK_EDITABLE (self->username_entry)));
+ password = g_strdup (gtk_editable_get_text (GTK_EDITABLE (self->password_entry)));
+
+ can_authenticate = (username != NULL && username[0] != '\0' &&
+ password != NULL && password[0] != '\0');
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->authenticate_button), can_authenticate);
+
+ g_clear_pointer (&username, g_free);
+ g_clear_pointer (&password, g_free);
+}
+
+static void
+on_go_back_button_clicked (PpNewPrinterDialog *self)
+{
+ pp_samba_set_auth_info (self->samba_host, NULL, NULL);
+ g_clear_object (&self->samba_host);
+
+ go_to_page (self, ADDPRINTER_PAGE);
+ adw_window_title_set_title (self->header_title, _("Add Printer"));
+ gtk_widget_set_sensitive (GTK_WIDGET (self->new_printer_add_button), FALSE);
+
+ gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (self->devices_treeview));
+}
+
+static void
+authenticate_samba_server (PpNewPrinterDialog *self)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ AuthSMBData *data;
+ gchar *server_name = NULL;
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->unlock_button), FALSE);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->authenticate_button), FALSE);
+ gtk_widget_grab_focus (GTK_WIDGET (self->username_entry));
+
+ if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (self->devices_treeview), &model, &iter))
+ {
+ gtk_tree_model_get (model, &iter,
+ DEVICE_NAME_COLUMN, &server_name,
+ -1);
+
+ if (server_name != NULL)
+ {
+ g_clear_object (&self->samba_host);
+
+ self->samba_host = pp_samba_new (server_name);
+ g_signal_connect_object (self->samba_host,
+ "authentication-required",
+ G_CALLBACK (on_authentication_required),
+ self, G_CONNECT_SWAPPED);
+
+ self->samba_authenticated_searching = TRUE;
+ update_dialog_state (self);
+
+ data = g_new (AuthSMBData, 1);
+ data->server_name = server_name;
+ data->dialog = self;
+
+ pp_samba_get_devices_async (self->samba_host,
+ TRUE,
+ self->cancellable,
+ get_authenticated_samba_devices_cb,
+ data);
+ }
+ }
+}
+
+static void
+device_selection_changed_cb (PpNewPrinterDialog *self)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gboolean authentication_needed;
+ gboolean selected;
+
+ selected = gtk_tree_selection_get_selected (gtk_tree_view_get_selection (self->devices_treeview),
+ &model,
+ &iter);
+
+ if (selected)
+ {
+ gtk_tree_model_get (model, &iter,
+ SERVER_NEEDS_AUTHENTICATION_COLUMN, &authentication_needed,
+ -1);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->new_printer_add_button), selected);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->unlock_button), authentication_needed);
+
+ if (authentication_needed)
+ gtk_stack_set_visible_child_name (self->headerbar_topright_buttons, "unlock_button");
+ else
+ gtk_stack_set_visible_child_name (self->headerbar_topright_buttons, ADDPRINTER_PAGE);
+ }
+}
+
+static void
+remove_device_from_list (PpNewPrinterDialog *self,
+ const gchar *device_name)
+{
+ GtkTreeIter iter;
+ gboolean cont;
+
+ cont = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->devices_liststore), &iter);
+ while (cont)
+ {
+ g_autoptr(PpPrintDevice) device = NULL;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (self->devices_liststore), &iter,
+ DEVICE_COLUMN, &device,
+ -1);
+
+ if (g_strcmp0 (pp_print_device_get_device_name (device), device_name) == 0)
+ {
+ gtk_list_store_remove (self->devices_liststore, &iter);
+ break;
+ }
+
+ cont = gtk_tree_model_iter_next (GTK_TREE_MODEL (self->devices_liststore), &iter);
+ }
+
+ update_dialog_state (self);
+}
+
+static gboolean
+prepend_original_name (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ g_autoptr(PpPrintDevice) device = NULL;
+ GList **list = data;
+
+ gtk_tree_model_get (model, iter,
+ DEVICE_COLUMN, &device,
+ -1);
+
+ *list = g_list_prepend (*list, g_strdup (pp_print_device_get_device_original_name (device)));
+
+ return FALSE;
+}
+
+static void
+add_device_to_list (PpNewPrinterDialog *self,
+ PpPrintDevice *device)
+{
+ GList *original_names_list = NULL;
+ gint acquisition_method;
+
+ if (device)
+ {
+ if (pp_print_device_get_host_name (device) == NULL)
+ {
+ g_autofree gchar *host_name = guess_device_hostname (device);
+ g_object_set (device, "host-name", host_name, NULL);
+ }
+
+ acquisition_method = pp_print_device_get_acquisition_method (device);
+ if (pp_print_device_get_device_id (device) ||
+ pp_print_device_get_device_ppd (device) ||
+ (pp_print_device_get_host_name (device) &&
+ acquisition_method == ACQUISITION_METHOD_REMOTE_CUPS_SERVER) ||
+ acquisition_method == ACQUISITION_METHOD_SAMBA_HOST ||
+ acquisition_method == ACQUISITION_METHOD_SAMBA ||
+ (pp_print_device_get_device_uri (device) &&
+ (acquisition_method == ACQUISITION_METHOD_JETDIRECT ||
+ acquisition_method == ACQUISITION_METHOD_LPD)))
+ {
+ g_autofree gchar *canonicalized_name = NULL;
+
+ g_object_set (device,
+ "device-original-name", pp_print_device_get_device_name (device),
+ NULL);
+
+ gtk_tree_model_foreach (GTK_TREE_MODEL (self->devices_liststore),
+ prepend_original_name,
+ &original_names_list);
+
+ original_names_list = g_list_reverse (original_names_list);
+
+ canonicalized_name = canonicalize_device_name (original_names_list,
+ self->local_cups_devices,
+ self->dests,
+ self->num_of_dests,
+ device);
+
+ g_list_free_full (original_names_list, g_free);
+
+ g_object_set (device,
+ "display-name", canonicalized_name,
+ "device-name", canonicalized_name,
+ NULL);
+
+ if (pp_print_device_get_acquisition_method (device) == ACQUISITION_METHOD_DEFAULT_CUPS_SERVER)
+ g_ptr_array_add (self->local_cups_devices, g_object_ref (device));
+ else
+ set_device (self, device, NULL);
+ }
+ else if (pp_print_device_is_authenticated_server (device) &&
+ pp_print_device_get_host_name (device) != NULL)
+ {
+ g_autoptr(PpPrintDevice) store_device = NULL;
+
+ store_device = g_object_new (PP_TYPE_PRINT_DEVICE,
+ "device-name", pp_print_device_get_host_name (device),
+ "host-name", pp_print_device_get_host_name (device),
+ "is-authenticated-server", pp_print_device_is_authenticated_server (device),
+ NULL);
+
+ set_device (self, store_device, NULL);
+ }
+ }
+}
+
+static void
+add_devices_to_list (PpNewPrinterDialog *self,
+ GPtrArray *devices)
+{
+ for (guint i = 0; i < devices->len; i++)
+ add_device_to_list (self, g_ptr_array_index (devices, i));
+}
+
+static PpPrintDevice *
+device_in_list (gchar *device_uri,
+ GPtrArray *device_list)
+{
+ for (guint i = 0; i < device_list->len; i++)
+ {
+ PpPrintDevice *device = g_ptr_array_index (device_list, i);
+ /* GroupPhysicalDevices returns uris without port numbers */
+ if (pp_print_device_get_device_uri (device) != NULL &&
+ g_str_has_prefix (pp_print_device_get_device_uri (device), device_uri))
+ return g_object_ref (device);
+ }
+
+ return NULL;
+}
+
+static PpPrintDevice *
+device_in_liststore (gchar *device_uri,
+ GtkListStore *device_liststore)
+{
+ GtkTreeIter iter;
+ gboolean cont;
+
+ cont = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (device_liststore), &iter);
+ while (cont)
+ {
+ g_autoptr(PpPrintDevice) device = NULL;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (device_liststore), &iter,
+ DEVICE_COLUMN, &device,
+ -1);
+
+ /* GroupPhysicalDevices returns uris without port numbers */
+ if (pp_print_device_get_device_uri (device) != NULL &&
+ g_str_has_prefix (pp_print_device_get_device_uri (device), device_uri))
+ {
+ return g_steal_pointer(&device);
+ }
+
+ cont = gtk_tree_model_iter_next (GTK_TREE_MODEL (device_liststore), &iter);
+ }
+
+ return NULL;
+}
+
+static void
+update_dialog_state (PpNewPrinterDialog *self)
+{
+ GtkTreeIter iter;
+ gboolean searching;
+
+ searching = self->cups_searching ||
+ self->remote_cups_host != NULL ||
+ self->snmp_host != NULL ||
+ self->socket_host != NULL ||
+ self->lpd_host != NULL ||
+ self->samba_host != NULL ||
+ self->samba_authenticated_searching ||
+ self->samba_searching;
+
+ if (searching)
+ {
+ adw_window_title_set_subtitle (self->header_title, _("Searching for Printers"));
+ }
+ else
+ {
+ adw_window_title_set_subtitle (self->header_title, NULL);
+ }
+
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->devices_liststore), &iter))
+ gtk_stack_set_visible_child_name (self->stack, "standard-page");
+ else
+ gtk_stack_set_visible_child_name (self->stack, searching ? "loading-page" : "no-printers-page");
+}
+
+static void
+group_physical_devices_cb (gchar ***device_uris,
+ gpointer user_data)
+{
+ PpNewPrinterDialog *self = user_data;
+ gint i, j;
+
+ if (device_uris != NULL)
+ {
+ for (i = 0; device_uris[i] != NULL; i++)
+ {
+ /* Is there any device in this sublist? */
+ if (device_uris[i][0] != NULL)
+ {
+ g_autoptr(PpPrintDevice) device = NULL;
+
+ for (j = 0; device_uris[i][j] != NULL; j++)
+ {
+ device = device_in_liststore (device_uris[i][j], self->devices_liststore);
+ if (device != NULL)
+ break;
+ }
+
+ /* Is this sublist represented in the current list of devices? */
+ if (device != NULL)
+ {
+ /* Is there better device in the sublist? */
+ if (j != 0)
+ {
+ g_autoptr(PpPrintDevice) better_device = NULL;
+
+ better_device = device_in_list (device_uris[i][0], self->local_cups_devices);
+ replace_device (self, device, better_device);
+ }
+ }
+ else
+ {
+ device = device_in_list (device_uris[i][0], self->local_cups_devices);
+ if (device != NULL)
+ set_device (self, device, NULL);
+ }
+ }
+ }
+
+ for (i = 0; device_uris[i] != NULL; i++)
+ g_strfreev (device_uris[i]);
+
+ g_free (device_uris);
+ }
+ else
+ {
+ for (i = 0; i < self->local_cups_devices->len; i++)
+ set_device (self, g_ptr_array_index (self->local_cups_devices, i), NULL);
+ g_ptr_array_set_size (self->local_cups_devices, 0);
+ }
+
+ update_dialog_state (self);
+}
+
+static void
+group_physical_devices_dbus_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GVariant) output = NULL;
+ g_autoptr(GError) error = NULL;
+ gchar ***result = NULL;
+ gint i;
+
+ output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ res,
+ &error);
+
+ if (output)
+ {
+ g_autoptr(GVariant) array = NULL;
+
+ g_variant_get (output, "(@aas)", &array);
+
+ if (array)
+ {
+ g_autoptr(GVariantIter) iter = NULL;
+ GStrv device_uris;
+
+ result = g_new0 (gchar **, g_variant_n_children (array) + 1);
+ g_variant_get (array, "aas", &iter);
+ i = 0;
+ while (g_variant_iter_next (iter, "^as", &device_uris))
+ {
+ result[i] = device_uris;
+ i++;
+ }
+ }
+ }
+ else if (error &&
+ error->domain == G_DBUS_ERROR &&
+ (error->code == G_DBUS_ERROR_SERVICE_UNKNOWN ||
+ error->code == G_DBUS_ERROR_UNKNOWN_METHOD))
+ {
+ g_warning ("Install system-config-printer which provides \
+DBus method \"GroupPhysicalDevices\" to group duplicates in device list.");
+ }
+ else
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("%s", error->message);
+ }
+
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ group_physical_devices_cb (result, user_data);
+}
+
+static void
+get_cups_devices_cb (GPtrArray *devices,
+ gboolean finished,
+ gboolean cancelled,
+ gpointer user_data)
+{
+ PpNewPrinterDialog *self = user_data;
+ g_autoptr(GDBusConnection) bus = NULL;
+ GVariantBuilder device_list;
+ GVariantBuilder device_hash;
+ PpPrintDevice **all_devices;
+ const gchar *device_class;
+ GtkTreeIter iter;
+ gboolean cont;
+ g_autoptr(GError) error = NULL;
+ gint length, i;
+
+
+ if (!cancelled)
+ {
+ if (finished)
+ {
+ self->cups_searching = FALSE;
+ }
+
+ if (devices != NULL)
+ {
+ add_devices_to_list (self, devices);
+
+ length = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (self->devices_liststore), NULL) + self->local_cups_devices->len;
+ if (length > 0)
+ {
+ all_devices = g_new0 (PpPrintDevice *, length);
+
+ i = 0;
+ cont = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->devices_liststore), &iter);
+ while (cont)
+ {
+ g_autoptr(PpPrintDevice) device = NULL;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (self->devices_liststore), &iter,
+ DEVICE_COLUMN, &device,
+ -1);
+
+ all_devices[i] = g_object_new (PP_TYPE_PRINT_DEVICE,
+ "device-id", pp_print_device_get_device_id (device),
+ "device-make-and-model", pp_print_device_get_device_make_and_model (device),
+ "is-network-device", pp_print_device_is_network_device (device),
+ "device-uri", pp_print_device_get_device_uri (device),
+ NULL);
+ i++;
+
+ cont = gtk_tree_model_iter_next (GTK_TREE_MODEL (self->devices_liststore), &iter);
+ }
+
+ for (guint j = 0; j < self->local_cups_devices->len; j++)
+ {
+ PpPrintDevice *pp_device = g_ptr_array_index (self->local_cups_devices, j);
+ all_devices[i] = g_object_new (PP_TYPE_PRINT_DEVICE,
+ "device-id", pp_print_device_get_device_id (pp_device),
+ "device-make-and-model", pp_print_device_get_device_make_and_model (pp_device),
+ "is-network-device", pp_print_device_is_network_device (pp_device),
+ "device-uri", pp_print_device_get_device_uri (pp_device),
+ NULL);
+ i++;
+ }
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
+ if (bus)
+ {
+ g_variant_builder_init (&device_list, G_VARIANT_TYPE ("a{sv}"));
+
+ for (i = 0; i < length; i++)
+ {
+ if (pp_print_device_get_device_uri (all_devices[i]))
+ {
+ g_variant_builder_init (&device_hash, G_VARIANT_TYPE ("a{ss}"));
+
+ if (pp_print_device_get_device_id (all_devices[i]))
+ g_variant_builder_add (&device_hash,
+ "{ss}",
+ "device-id",
+ pp_print_device_get_device_id (all_devices[i]));
+
+ if (pp_print_device_get_device_make_and_model (all_devices[i]))
+ g_variant_builder_add (&device_hash,
+ "{ss}",
+ "device-make-and-model",
+ pp_print_device_get_device_make_and_model (all_devices[i]));
+
+ if (pp_print_device_is_network_device (all_devices[i]))
+ device_class = "network";
+ else
+ device_class = "direct";
+
+ g_variant_builder_add (&device_hash,
+ "{ss}",
+ "device-class",
+ device_class);
+
+ g_variant_builder_add (&device_list,
+ "{sv}",
+ pp_print_device_get_device_uri (all_devices[i]),
+ g_variant_builder_end (&device_hash));
+ }
+ }
+
+ g_dbus_connection_call (bus,
+ SCP_BUS,
+ SCP_PATH,
+ SCP_IFACE,
+ "GroupPhysicalDevices",
+ g_variant_new ("(v)", g_variant_builder_end (&device_list)),
+ G_VARIANT_TYPE ("(aas)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ self->cancellable,
+ group_physical_devices_dbus_cb,
+ self);
+ }
+ else
+ {
+ g_warning ("Failed to get system bus: %s", error->message);
+ group_physical_devices_cb (NULL, user_data);
+ }
+
+ for (i = 0; i < length; i++)
+ g_object_unref (all_devices[i]);
+ g_free (all_devices);
+ }
+ else
+ {
+ update_dialog_state (self);
+ }
+ }
+ else
+ {
+ update_dialog_state (self);
+ }
+ }
+}
+
+static void
+get_snmp_devices_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ PpNewPrinterDialog *self = user_data;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) devices = NULL;
+
+ devices = pp_host_get_snmp_devices_finish (PP_HOST (source_object), res, &error);
+
+ if (devices != NULL)
+ {
+ g_clear_object(&self->snmp_host);
+
+ add_devices_to_list (self, devices);
+
+ update_dialog_state (self);
+ }
+ else
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ g_warning ("%s", error->message);
+
+ g_clear_object(&self->snmp_host);
+
+ update_dialog_state (self);
+ }
+ }
+}
+
+static void
+get_remote_cups_devices_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ PpNewPrinterDialog *self = user_data;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) devices = NULL;
+
+ devices = pp_host_get_remote_cups_devices_finish (PP_HOST (source_object), res, &error);
+
+ if (devices != NULL)
+ {
+ g_clear_object(&self->remote_cups_host);
+
+ add_devices_to_list (self, devices);
+
+ update_dialog_state (self);
+ }
+ else
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ g_warning ("%s", error->message);
+
+ g_clear_object(&self->remote_cups_host);
+
+ update_dialog_state (self);
+ }
+ }
+}
+
+static void
+get_samba_host_devices_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ PpNewPrinterDialog *self = user_data;
+ g_autoptr(GPtrArray) devices = NULL;
+ g_autoptr(GError) error = NULL;
+
+ devices = pp_samba_get_devices_finish (PP_SAMBA (source_object), res, &error);
+
+ if (devices != NULL)
+ {
+ g_clear_object(&self->samba_host);
+
+ add_devices_to_list (self, devices);
+
+ update_dialog_state (self);
+ }
+ else
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ g_warning ("%s", error->message);
+
+ g_clear_object(&self->samba_host);
+
+ update_dialog_state (self);
+ }
+ }
+}
+
+static void
+get_samba_devices_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ PpNewPrinterDialog *self = user_data;
+ g_autoptr(GPtrArray) devices = NULL;
+ g_autoptr(GError) error = NULL;
+
+ devices = pp_samba_get_devices_finish (PP_SAMBA (source_object), res, &error);
+
+ if (devices != NULL)
+ {
+ self->samba_searching = FALSE;
+
+ add_devices_to_list (self, devices);
+
+ update_dialog_state (self);
+ }
+ else
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ g_warning ("%s", error->message);
+
+ self->samba_searching = FALSE;
+
+ update_dialog_state (self);
+ }
+ }
+}
+
+static void
+get_jetdirect_devices_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ PpNewPrinterDialog *self = user_data;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) devices = NULL;
+
+ devices = pp_host_get_jetdirect_devices_finish (PP_HOST (source_object), res, &error);
+
+ if (devices != NULL)
+ {
+ g_clear_object(&self->socket_host);
+
+ add_devices_to_list (self, devices);
+
+ update_dialog_state (self);
+ }
+ else
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ g_warning ("%s", error->message);
+
+ g_clear_object(&self->socket_host);
+
+ update_dialog_state (self);
+ }
+ }
+}
+
+static void
+get_lpd_devices_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ PpNewPrinterDialog *self = user_data;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) devices = NULL;
+
+ devices = pp_host_get_lpd_devices_finish (PP_HOST (source_object), res, &error);
+
+ if (devices != NULL)
+ {
+ g_clear_object(&self->lpd_host);
+
+ add_devices_to_list (self, devices);
+
+ update_dialog_state (self);
+ }
+ else
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ g_warning ("%s", error->message);
+
+ g_clear_object(&self->lpd_host);
+
+ update_dialog_state (self);
+ }
+ }
+}
+
+static void
+get_cups_devices (PpNewPrinterDialog *self)
+{
+ self->cups_searching = TRUE;
+ update_dialog_state (self);
+
+ get_cups_devices_async (self->cancellable,
+ get_cups_devices_cb,
+ self);
+}
+
+static gboolean
+parse_uri (const gchar *uri,
+ gchar **scheme,
+ gchar **host,
+ gint *port)
+{
+ const gchar *tmp = NULL;
+ g_autofree gchar *resulting_host = NULL;
+ gchar *position;
+
+ *port = PP_HOST_UNSET_PORT;
+
+ position = g_strrstr (uri, "://");
+ if (position != NULL)
+ {
+ *scheme = g_strndup (uri, position - uri);
+ tmp = position + 3;
+ }
+ else
+ {
+ tmp = uri;
+ }
+
+ if (g_strrstr (tmp, "@"))
+ tmp = g_strrstr (tmp, "@") + 1;
+
+ if ((position = g_strrstr (tmp, "/")))
+ {
+ *position = '\0';
+ resulting_host = g_strdup (tmp);
+ *position = '/';
+ }
+ else
+ {
+ resulting_host = g_strdup (tmp);
+ }
+
+ if ((position = g_strrstr (resulting_host, ":")))
+ {
+ *position = '\0';
+ *port = atoi (position + 1);
+ }
+
+ *host = g_uri_unescape_string (resulting_host,
+ G_URI_RESERVED_CHARS_GENERIC_DELIMITERS
+ G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS);
+
+ return TRUE;
+}
+
+typedef struct
+{
+ PpNewPrinterDialog *dialog;
+ gchar *host_scheme;
+ gchar *host_name;
+ gint host_port;
+} THostSearchData;
+
+static void
+search_for_remote_printers_free (THostSearchData *data)
+{
+ g_free (data->host_scheme);
+ g_free (data->host_name);
+ g_free (data);
+}
+
+static gboolean
+search_for_remote_printers (THostSearchData *data)
+{
+ PpNewPrinterDialog *self = data->dialog;
+
+ g_cancellable_cancel (self->remote_host_cancellable);
+ g_clear_object (&self->remote_host_cancellable);
+
+ self->remote_host_cancellable = g_cancellable_new ();
+
+ self->remote_cups_host = pp_host_new (data->host_name);
+ self->snmp_host = pp_host_new (data->host_name);
+ self->socket_host = pp_host_new (data->host_name);
+ self->lpd_host = pp_host_new (data->host_name);
+
+ if (data->host_port != PP_HOST_UNSET_PORT)
+ {
+ g_object_set (self->remote_cups_host, "port", data->host_port, NULL);
+ g_object_set (self->snmp_host, "port", data->host_port, NULL);
+
+ /* Accept port different from the default one only if user specifies
+ * scheme (for socket and lpd printers).
+ */
+ if (data->host_scheme != NULL &&
+ g_ascii_strcasecmp (data->host_scheme, "socket") == 0)
+ g_object_set (self->socket_host, "port", data->host_port, NULL);
+
+ if (data->host_scheme != NULL &&
+ g_ascii_strcasecmp (data->host_scheme, "lpd") == 0)
+ g_object_set (self->lpd_host, "port", data->host_port, NULL);
+ }
+
+ self->samba_host = pp_samba_new (data->host_name);
+
+ update_dialog_state (data->dialog);
+
+ pp_host_get_remote_cups_devices_async (self->remote_cups_host,
+ self->remote_host_cancellable,
+ get_remote_cups_devices_cb,
+ data->dialog);
+
+ pp_host_get_snmp_devices_async (self->snmp_host,
+ self->remote_host_cancellable,
+ get_snmp_devices_cb,
+ data->dialog);
+
+ pp_host_get_jetdirect_devices_async (self->socket_host,
+ self->remote_host_cancellable,
+ get_jetdirect_devices_cb,
+ data->dialog);
+
+ pp_host_get_lpd_devices_async (self->lpd_host,
+ self->remote_host_cancellable,
+ get_lpd_devices_cb,
+ data->dialog);
+
+ pp_samba_get_devices_async (self->samba_host,
+ FALSE,
+ self->remote_host_cancellable,
+ get_samba_host_devices_cb,
+ data->dialog);
+
+ self->host_search_timeout_id = 0;
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+search_address (const gchar *text,
+ PpNewPrinterDialog *self,
+ gboolean delay_search)
+{
+ GtkTreeIter iter;
+ gboolean found = FALSE;
+ gboolean subfound;
+ gboolean next_set;
+ gboolean cont;
+ g_autofree gchar *lowercase_text = NULL;
+ gchar **words;
+ gint words_length = 0;
+ gint i;
+ gint acquisition_method;
+
+ lowercase_text = g_ascii_strdown (text, -1);
+ words = g_strsplit_set (lowercase_text, " ", -1);
+
+ if (words)
+ {
+ words_length = g_strv_length (words);
+
+ cont = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->devices_liststore), &iter);
+ while (cont)
+ {
+ g_autoptr(PpPrintDevice) device = NULL;
+ g_autofree gchar *lowercase_name = NULL;
+ g_autofree gchar *lowercase_location = NULL;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (self->devices_liststore), &iter,
+ DEVICE_COLUMN, &device,
+ -1);
+
+ lowercase_name = g_ascii_strdown (pp_print_device_get_device_name (device), -1);
+ if (pp_print_device_get_device_location (device))
+ lowercase_location = g_ascii_strdown (pp_print_device_get_device_location (device), -1);
+ else
+ lowercase_location = NULL;
+
+ subfound = TRUE;
+ for (i = 0; words[i]; i++)
+ {
+ if (!g_strrstr (lowercase_name, words[i]) &&
+ (!lowercase_location || !g_strrstr (lowercase_location, words[i])))
+ subfound = FALSE;
+ }
+
+ if (subfound)
+ found = TRUE;
+
+ gtk_list_store_set (GTK_LIST_STORE (self->devices_liststore), &iter,
+ DEVICE_VISIBLE_COLUMN, subfound,
+ -1);
+
+ cont = gtk_tree_model_iter_next (GTK_TREE_MODEL (self->devices_liststore), &iter);
+ }
+
+ g_strfreev (words);
+ }
+
+ /*
+ * The given word is probably an address since it was not found among
+ * already present devices.
+ */
+ if (!found && words_length == 1)
+ {
+ cont = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->devices_liststore), &iter);
+ while (cont)
+ {
+ g_autoptr(PpPrintDevice) device = NULL;
+
+ next_set = FALSE;
+ gtk_tree_model_get (GTK_TREE_MODEL (self->devices_liststore), &iter,
+ DEVICE_COLUMN, &device,
+ -1);
+
+ gtk_list_store_set (GTK_LIST_STORE (self->devices_liststore), &iter,
+ DEVICE_VISIBLE_COLUMN, TRUE,
+ -1);
+
+ acquisition_method = pp_print_device_get_acquisition_method (device);
+ if (acquisition_method == ACQUISITION_METHOD_REMOTE_CUPS_SERVER ||
+ acquisition_method == ACQUISITION_METHOD_SNMP ||
+ acquisition_method == ACQUISITION_METHOD_JETDIRECT ||
+ acquisition_method == ACQUISITION_METHOD_LPD ||
+ acquisition_method == ACQUISITION_METHOD_SAMBA_HOST)
+ {
+ if (!gtk_list_store_remove (self->devices_liststore, &iter))
+ break;
+ else
+ next_set = TRUE;
+ }
+
+ if (!next_set)
+ cont = gtk_tree_model_iter_next (GTK_TREE_MODEL (self->devices_liststore), &iter);
+ }
+
+ if (text && text[0] != '\0')
+ {
+ g_autoptr(GSocketConnectable) conn = NULL;
+ g_autofree gchar *test_uri = NULL;
+ g_autofree gchar *test_port = NULL;
+ gchar *scheme = NULL;
+ gchar *host = NULL;
+ gint port;
+
+ parse_uri (text, &scheme, &host, &port);
+
+ if (host != NULL)
+ {
+ if (port >= 0)
+ test_port = g_strdup_printf (":%d", port);
+ else
+ test_port = g_strdup ("");
+
+ test_uri = g_strdup_printf ("%s://%s%s",
+ scheme != NULL && scheme[0] != '\0' ? scheme : "none",
+ host,
+ test_port);
+
+ conn = g_network_address_parse_uri (test_uri, 0, NULL);
+ if (conn != NULL)
+ {
+ THostSearchData *search_data;
+
+ search_data = g_new (THostSearchData, 1);
+ search_data->host_scheme = scheme;
+ search_data->host_name = host;
+ search_data->host_port = port;
+ search_data->dialog = self;
+
+ if (self->host_search_timeout_id != 0)
+ {
+ g_source_remove (self->host_search_timeout_id);
+ self->host_search_timeout_id = 0;
+ }
+
+ if (delay_search)
+ {
+ self->host_search_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
+ HOST_SEARCH_DELAY,
+ (GSourceFunc) search_for_remote_printers,
+ search_data,
+ (GDestroyNotify) search_for_remote_printers_free);
+ }
+ else
+ {
+ search_for_remote_printers (search_data);
+ search_for_remote_printers_free (search_data);
+ }
+ }
+ }
+ }
+ }
+}
+
+static void
+search_entry_activated_cb (PpNewPrinterDialog *self)
+{
+ search_address (gtk_editable_get_text (GTK_EDITABLE (self->search_entry)),
+ self,
+ FALSE);
+}
+
+static void
+search_entry_changed_cb (PpNewPrinterDialog *self)
+{
+ search_address (gtk_editable_get_text (GTK_EDITABLE (self->search_entry)),
+ self,
+ TRUE);
+}
+
+static gchar *
+get_local_scheme_description_from_uri (gchar *device_uri)
+{
+ gchar *description = NULL;
+
+ if (device_uri != NULL)
+ {
+ if (g_str_has_prefix (device_uri, "usb") ||
+ g_str_has_prefix (device_uri, "hp:/usb/") ||
+ g_str_has_prefix (device_uri, "hpfax:/usb/"))
+ {
+ /* Translators: The found device is a printer connected via USB */
+ description = g_strdup (_("USB"));
+ }
+ else if (g_str_has_prefix (device_uri, "serial"))
+ {
+ /* Translators: The found device is a printer connected via serial port */
+ description = g_strdup (_("Serial Port"));
+ }
+ else if (g_str_has_prefix (device_uri, "parallel") ||
+ g_str_has_prefix (device_uri, "hp:/par/") ||
+ g_str_has_prefix (device_uri, "hpfax:/par/"))
+ {
+ /* Translators: The found device is a printer connected via parallel port */
+ description = g_strdup (_("Parallel Port"));
+ }
+ else if (g_str_has_prefix (device_uri, "bluetooth"))
+ {
+ /* Translators: The found device is a printer connected via Bluetooth */
+ description = g_strdup (_("Bluetooth"));
+ }
+ }
+
+ return description;
+}
+
+static void
+set_device (PpNewPrinterDialog *self,
+ PpPrintDevice *device,
+ GtkTreeIter *iter)
+{
+ GtkTreeIter titer;
+ gint acquisition_method;
+
+ if (device != NULL)
+ {
+ acquisition_method = pp_print_device_get_acquisition_method (device);
+ if (pp_print_device_get_display_name (device) &&
+ (pp_print_device_get_device_id (device) ||
+ pp_print_device_get_device_ppd (device) ||
+ (pp_print_device_get_host_name (device) &&
+ acquisition_method == ACQUISITION_METHOD_REMOTE_CUPS_SERVER) ||
+ (pp_print_device_get_device_uri (device) &&
+ (acquisition_method == ACQUISITION_METHOD_JETDIRECT ||
+ acquisition_method == ACQUISITION_METHOD_LPD)) ||
+ acquisition_method == ACQUISITION_METHOD_SAMBA_HOST ||
+ acquisition_method == ACQUISITION_METHOD_SAMBA))
+ {
+ g_autofree gchar *description = NULL;
+
+ description = get_local_scheme_description_from_uri (pp_print_device_get_device_uri (device));
+ if (description == NULL)
+ {
+ if (pp_print_device_get_device_location (device) != NULL && pp_print_device_get_device_location (device)[0] != '\0')
+ {
+ /* Translators: Location of found network printer (e.g. Kitchen, Reception) */
+ description = g_strdup_printf (_("Location: %s"), pp_print_device_get_device_location (device));
+ }
+ else if (pp_print_device_get_host_name (device) != NULL && pp_print_device_get_host_name (device)[0] != '\0')
+ {
+ /* Translators: Network address of found printer */
+ description = g_strdup_printf (_("Address: %s"), pp_print_device_get_host_name (device));
+ }
+ }
+
+ if (iter == NULL)
+ gtk_list_store_append (self->devices_liststore, &titer);
+
+ gtk_list_store_set (self->devices_liststore, iter == NULL ? &titer : iter,
+ DEVICE_GICON_COLUMN, pp_print_device_is_network_device (device) ? self->remote_printer_icon : self->local_printer_icon,
+ DEVICE_NAME_COLUMN, pp_print_device_get_device_name (device),
+ DEVICE_DISPLAY_NAME_COLUMN, pp_print_device_get_display_name (device),
+ DEVICE_DESCRIPTION_COLUMN, description,
+ DEVICE_VISIBLE_COLUMN, TRUE,
+ DEVICE_COLUMN, device,
+ -1);
+ }
+ else if (pp_print_device_is_authenticated_server (device) &&
+ pp_print_device_get_host_name (device) != NULL)
+ {
+ if (iter == NULL)
+ gtk_list_store_append (self->devices_liststore, &titer);
+
+ gtk_list_store_set (self->devices_liststore, iter == NULL ? &titer : iter,
+ DEVICE_GICON_COLUMN, self->authenticated_server_icon,
+ DEVICE_NAME_COLUMN, pp_print_device_get_host_name (device),
+ DEVICE_DISPLAY_NAME_COLUMN, pp_print_device_get_host_name (device),
+ /* Translators: This item is a server which needs authentication to show its printers */
+ DEVICE_DESCRIPTION_COLUMN, _("Server requires authentication"),
+ SERVER_NEEDS_AUTHENTICATION_COLUMN, TRUE,
+ DEVICE_VISIBLE_COLUMN, TRUE,
+ DEVICE_COLUMN, device,
+ -1);
+ }
+ }
+}
+
+static void
+replace_device (PpNewPrinterDialog *self,
+ PpPrintDevice *old_device,
+ PpPrintDevice *new_device)
+{
+ GtkTreeIter iter;
+ gboolean cont;
+
+ if (old_device != NULL && new_device != NULL)
+ {
+ cont = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->devices_liststore), &iter);
+ while (cont)
+ {
+ g_autoptr(PpPrintDevice) device = NULL;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (self->devices_liststore), &iter,
+ DEVICE_COLUMN, &device,
+ -1);
+
+ if (old_device == device)
+ {
+ set_device (self, new_device, &iter);
+ break;
+ }
+
+ cont = gtk_tree_model_iter_next (GTK_TREE_MODEL (self->devices_liststore), &iter);
+ }
+ }
+}
+
+static void
+cups_get_dests_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ PpNewPrinterDialog *self = user_data;
+ PpCupsDests *dests;
+ g_autoptr(GError) error = NULL;
+
+ dests = pp_cups_get_dests_finish (PP_CUPS (source_object), res, &error);
+
+ if (dests)
+ {
+ self->dests = dests->dests;
+ self->num_of_dests = dests->num_of_dests;
+
+ get_cups_devices (self);
+ }
+ else
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ g_warning ("%s", error->message);
+
+ get_cups_devices (self);
+ }
+ }
+}
+
+static void
+row_activated_cb (PpNewPrinterDialog *self)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gboolean authentication_needed;
+ gboolean selected;
+
+ selected = gtk_tree_selection_get_selected (gtk_tree_view_get_selection (self->devices_treeview),
+ &model,
+ &iter);
+
+ if (selected)
+ {
+ gtk_tree_model_get (model, &iter, SERVER_NEEDS_AUTHENTICATION_COLUMN, &authentication_needed, -1);
+
+ if (authentication_needed)
+ {
+ authenticate_samba_server (self);
+ }
+ else
+ {
+ gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_OK);
+ }
+ }
+}
+
+static void
+cell_data_func (GtkTreeViewColumn *tree_column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ PpNewPrinterDialog *self = user_data;
+ gboolean selected = FALSE;
+ g_autofree gchar *name = NULL;
+ g_autofree gchar *description = NULL;
+
+ selected = gtk_tree_selection_iter_is_selected (gtk_tree_view_get_selection (self->devices_treeview), iter);
+
+ gtk_tree_model_get (tree_model, iter,
+ DEVICE_DISPLAY_NAME_COLUMN, &name,
+ DEVICE_DESCRIPTION_COLUMN, &description,
+ -1);
+
+ if (name != NULL)
+ {
+ g_autofree gchar *text = NULL;
+
+ if (description != NULL)
+ {
+ if (selected)
+ text = g_markup_printf_escaped ("<b>%s</b>\n<small>%s</small>",
+ name,
+ description);
+ else
+ text = g_markup_printf_escaped ("<b>%s</b>\n<small><span foreground=\"#555555\">%s</span></small>",
+ name,
+ description);
+ }
+ else
+ {
+ text = g_markup_printf_escaped ("<b>%s</b>\n ",
+ name);
+ }
+
+ g_object_set (G_OBJECT (cell),
+ "markup", text,
+ NULL);
+ }
+}
+
+static void
+populate_devices_list (PpNewPrinterDialog *self)
+{
+ GtkTreeViewColumn *column;
+ g_autoptr(PpSamba) samba = NULL;
+ g_autoptr(GEmblem) emblem = NULL;
+ g_autoptr(PpCups) cups = NULL;
+ g_autoptr(GIcon) icon = NULL;
+ g_autoptr(GIcon) emblem_icon = NULL;
+ GtkCellRenderer *text_renderer;
+ GtkCellRenderer *icon_renderer;
+
+ g_signal_connect_object (gtk_tree_view_get_selection (self->devices_treeview),
+ "changed", G_CALLBACK (device_selection_changed_cb), self, G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self->devices_treeview,
+ "row-activated", G_CALLBACK (row_activated_cb), self, G_CONNECT_SWAPPED);
+
+ self->local_printer_icon = g_themed_icon_new ("printer");
+ self->remote_printer_icon = g_themed_icon_new ("printer-network");
+
+ icon = g_themed_icon_new ("network-server");
+ emblem_icon = g_themed_icon_new ("changes-prevent");
+ emblem = g_emblem_new (emblem_icon);
+
+ self->authenticated_server_icon = g_emblemed_icon_new (icon, emblem);
+
+ icon_renderer = gtk_cell_renderer_pixbuf_new ();
+ g_object_set (icon_renderer, "icon-size", GTK_ICON_SIZE_LARGE, NULL);
+ gtk_cell_renderer_set_alignment (icon_renderer, 1.0, 0.5);
+ gtk_cell_renderer_set_padding (icon_renderer, 4, 4);
+ column = gtk_tree_view_column_new_with_attributes ("Icon", icon_renderer,
+ "gicon", DEVICE_GICON_COLUMN, NULL);
+ gtk_tree_view_column_set_max_width (column, -1);
+ gtk_tree_view_column_set_min_width (column, 80);
+ gtk_tree_view_append_column (self->devices_treeview, column);
+
+
+ text_renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes ("Devices", text_renderer,
+ NULL);
+ gtk_tree_view_column_set_cell_data_func (column, text_renderer, cell_data_func,
+ self, NULL);
+ gtk_tree_view_append_column (self->devices_treeview, column);
+
+ gtk_tree_model_filter_set_visible_column (self->devices_model_filter, DEVICE_VISIBLE_COLUMN);
+
+ cups = pp_cups_new ();
+ pp_cups_get_dests_async (cups, self->cancellable, cups_get_dests_cb, self);
+
+ self->samba_searching = TRUE;
+ update_dialog_state (self);
+
+ samba = pp_samba_new (NULL);
+ pp_samba_get_devices_async (samba, FALSE, self->cancellable, get_samba_devices_cb, self);
+}
+
+static void
+ppd_selection_cb (GtkDialog *_dialog,
+ gint response_id,
+ gpointer user_data)
+{
+ PpNewPrinterDialog *self = user_data;
+ GList *original_names_list = NULL;
+ g_autofree gchar *ppd_name = NULL;
+ g_autofree gchar *ppd_display_name = NULL;
+ gint acquisition_method;
+
+ if (response_id == GTK_RESPONSE_OK) {
+ ppd_name = pp_ppd_selection_dialog_get_ppd_name (self->ppd_selection_dialog);
+ ppd_display_name = pp_ppd_selection_dialog_get_ppd_display_name (self->ppd_selection_dialog);
+ }
+
+ if (ppd_name)
+ {
+ g_object_set (self->new_device, "device-ppd", ppd_name, NULL);
+
+ acquisition_method = pp_print_device_get_acquisition_method (self->new_device);
+ if ((acquisition_method == ACQUISITION_METHOD_JETDIRECT ||
+ acquisition_method == ACQUISITION_METHOD_LPD) &&
+ ppd_display_name != NULL)
+ {
+ g_autofree gchar *printer_name = NULL;
+
+ g_object_set (self->new_device,
+ "device-name", ppd_display_name,
+ "device-original-name", ppd_display_name,
+ NULL);
+
+ gtk_tree_model_foreach (GTK_TREE_MODEL (self->devices_liststore),
+ prepend_original_name,
+ &original_names_list);
+
+ original_names_list = g_list_reverse (original_names_list);
+
+ printer_name = canonicalize_device_name (original_names_list,
+ self->local_cups_devices,
+ self->dests,
+ self->num_of_dests,
+ self->new_device);
+
+ g_list_free_full (original_names_list, g_free);
+
+ g_object_set (self->new_device,
+ "device-name", printer_name,
+ "device-original-name", printer_name,
+ NULL);
+ }
+ }
+
+ /* This is needed here since parent dialog is destroyed first. */
+ gtk_window_set_transient_for (GTK_WINDOW (self->ppd_selection_dialog), NULL);
+
+ self->user_callback (GTK_DIALOG (self), response_id, self->user_data);
+}
+
+static void
+new_printer_dialog_response_cb (PpNewPrinterDialog *self,
+ gint response_id)
+{
+ g_autoptr(PpPrintDevice) device = NULL;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gint acquisition_method;
+
+ if (response_id == GTK_RESPONSE_OK)
+ {
+ g_cancellable_cancel (self->cancellable);
+ g_clear_object (&self->cancellable);
+
+ if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (self->devices_treeview), &model, &iter))
+ {
+ gtk_tree_model_get (model, &iter,
+ DEVICE_COLUMN, &device,
+ -1);
+ }
+
+ if (device)
+ {
+ acquisition_method = pp_print_device_get_acquisition_method (device);
+ if (acquisition_method == ACQUISITION_METHOD_SAMBA ||
+ acquisition_method == ACQUISITION_METHOD_SAMBA_HOST ||
+ acquisition_method == ACQUISITION_METHOD_JETDIRECT ||
+ acquisition_method == ACQUISITION_METHOD_LPD)
+ {
+ self->new_device = pp_print_device_copy (device);
+ self->ppd_selection_dialog =
+ pp_ppd_selection_dialog_new (self->list,
+ NULL,
+ ppd_selection_cb,
+ self);
+
+ gtk_window_set_transient_for (GTK_WINDOW (self->ppd_selection_dialog),
+ GTK_WINDOW (self));
+
+ /* New device will be set at return from ppd selection */
+ gtk_widget_show (GTK_WIDGET (self->ppd_selection_dialog));
+ }
+ else
+ {
+ self->new_device = pp_print_device_copy (device);
+ self->user_callback (GTK_DIALOG (self), GTK_RESPONSE_OK, self->user_data);
+ }
+ }
+ }
+ else
+ {
+ self->user_callback (GTK_DIALOG (self), GTK_RESPONSE_CANCEL, self->user_data);
+ }
+}
+
+PpNewPrinterDialog *
+pp_new_printer_dialog_new (PPDList *ppd_list,
+ UserResponseCallback user_callback,
+ gpointer user_data)
+{
+ PpNewPrinterDialog *self;
+
+ self = g_object_new (pp_new_printer_dialog_get_type (), NULL);
+
+ self->user_callback = user_callback;
+ self->user_data = user_data;
+
+ self->list = ppd_list_copy (ppd_list);
+
+ self->local_cups_devices = g_ptr_array_new_with_free_func (g_object_unref);
+
+ /* GCancellable for cancelling of async operations */
+ self->cancellable = g_cancellable_new ();
+
+ g_signal_connect_object (self, "response", G_CALLBACK (new_printer_dialog_response_cb), self, G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self->search_entry, "activate", G_CALLBACK (search_entry_activated_cb), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->search_entry, "search-changed", G_CALLBACK (search_entry_changed_cb), self, G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self->unlock_button, "clicked", G_CALLBACK (authenticate_samba_server), self, G_CONNECT_SWAPPED);
+
+ /* Authentication form widgets */
+ g_signal_connect_object (self->username_entry, "changed", G_CALLBACK (auth_entries_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->password_entry, "changed", G_CALLBACK (auth_entries_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->go_back_button, "clicked", G_CALLBACK (on_go_back_button_clicked), self, G_CONNECT_SWAPPED);
+
+ /* Set titlebar */
+ gtk_window_set_titlebar(GTK_WINDOW (self), GTK_WIDGET (self->headerbar));
+
+ /* Fill with data */
+ populate_devices_list (self);
+
+ return self;
+}
+
+static void
+pp_new_printer_dialog_dispose (GObject *object)
+{
+ PpNewPrinterDialog *self = PP_NEW_PRINTER_DIALOG (object);
+
+ g_cancellable_cancel (self->remote_host_cancellable);
+ g_cancellable_cancel (self->cancellable);
+
+ g_clear_handle_id (&self->host_search_timeout_id, g_source_remove);
+ g_clear_object (&self->remote_host_cancellable);
+ g_clear_object (&self->cancellable);
+ g_clear_pointer (&self->list, ppd_list_free);
+ g_clear_pointer (&self->local_cups_devices, g_ptr_array_unref);
+ g_clear_object (&self->new_device);
+ g_clear_object (&self->local_printer_icon);
+ g_clear_object (&self->remote_printer_icon);
+ g_clear_object (&self->authenticated_server_icon);
+ g_clear_object (&self->snmp_host);
+ g_clear_object (&self->socket_host);
+ g_clear_object (&self->lpd_host);
+ g_clear_object (&self->remote_cups_host);
+ g_clear_object (&self->samba_host);
+
+ if (self->ppd_selection_dialog != NULL)
+ {
+ gtk_window_destroy (GTK_WINDOW (self->ppd_selection_dialog));
+ self->ppd_selection_dialog = NULL;
+ }
+
+ if (self->num_of_dests > 0)
+ {
+ cupsFreeDests (self->num_of_dests, self->dests);
+ self->num_of_dests = 0;
+ self->dests = NULL;
+ }
+
+ G_OBJECT_CLASS (pp_new_printer_dialog_parent_class)->dispose (object);
+}
+
+void
+pp_new_printer_dialog_class_init (PpNewPrinterDialogClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_ensure (PP_TYPE_PRINT_DEVICE);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/printers/new-printer-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, PpNewPrinterDialog, devices_liststore);
+ gtk_widget_class_bind_template_child (widget_class, PpNewPrinterDialog, devices_model_filter);
+
+ /* headerbar */
+ gtk_widget_class_bind_template_child (widget_class, PpNewPrinterDialog, headerbar);
+ gtk_widget_class_bind_template_child (widget_class, PpNewPrinterDialog, header_title);
+
+ /* headerbar topleft buttons */
+ gtk_widget_class_bind_template_child (widget_class, PpNewPrinterDialog, headerbar_topleft_buttons);
+ gtk_widget_class_bind_template_child (widget_class, PpNewPrinterDialog, go_back_button);
+
+ /* headerbar topright buttons */
+ gtk_widget_class_bind_template_child (widget_class, PpNewPrinterDialog, headerbar_topright_buttons);
+ gtk_widget_class_bind_template_child (widget_class, PpNewPrinterDialog, new_printer_add_button);
+ gtk_widget_class_bind_template_child (widget_class, PpNewPrinterDialog, unlock_button);
+ gtk_widget_class_bind_template_child (widget_class, PpNewPrinterDialog, authenticate_button);
+
+ /* dialogstack */
+ gtk_widget_class_bind_template_child (widget_class, PpNewPrinterDialog, dialog_stack);
+ gtk_widget_class_bind_template_child (widget_class, PpNewPrinterDialog, stack);
+
+ /* scrolledwindow1 */
+ gtk_widget_class_bind_template_child (widget_class, PpNewPrinterDialog, scrolledwindow1);
+ gtk_widget_class_bind_template_child (widget_class, PpNewPrinterDialog, devices_treeview);
+
+ gtk_widget_class_bind_template_child (widget_class, PpNewPrinterDialog, search_entry);
+
+ /* authentication page */
+ gtk_widget_class_bind_template_child (widget_class, PpNewPrinterDialog, authentication_title);
+ gtk_widget_class_bind_template_child (widget_class, PpNewPrinterDialog, authentication_text);
+ gtk_widget_class_bind_template_child (widget_class, PpNewPrinterDialog, username_entry);
+ gtk_widget_class_bind_template_child (widget_class, PpNewPrinterDialog, password_entry);
+
+ object_class->dispose = pp_new_printer_dialog_dispose;
+}
+
+
+void
+pp_new_printer_dialog_init (PpNewPrinterDialog *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+void
+pp_new_printer_dialog_set_ppd_list (PpNewPrinterDialog *self,
+ PPDList *list)
+{
+ self->list = ppd_list_copy (list);
+
+ if (self->ppd_selection_dialog)
+ pp_ppd_selection_dialog_set_ppd_list (self->ppd_selection_dialog, self->list);
+}
+
+PpNewPrinter *
+pp_new_printer_dialog_get_new_printer (PpNewPrinterDialog *self)
+{
+ PpNewPrinter *new_printer = NULL;
+
+ new_printer = pp_new_printer_new ();
+ g_object_set (new_printer,
+ "name", pp_print_device_get_device_name (self->new_device),
+ "original-name", pp_print_device_get_device_original_name (self->new_device),
+ "device-uri", pp_print_device_get_device_uri (self->new_device),
+ "device-id", pp_print_device_get_device_id (self->new_device),
+ "ppd-name", pp_print_device_get_device_ppd (self->new_device),
+ "ppd-file-name", pp_print_device_get_device_ppd (self->new_device),
+ "info", pp_print_device_get_device_info (self->new_device),
+ "location", pp_print_device_get_device_location (self->new_device),
+ "make-and-model", pp_print_device_get_device_make_and_model (self->new_device),
+ "host-name", pp_print_device_get_host_name (self->new_device),
+ "host-port", pp_print_device_get_host_port (self->new_device),
+ "is-network-device", pp_print_device_is_network_device (self->new_device),
+ "window-id", 0,
+ NULL);
+
+ return new_printer;
+}
diff --git a/panels/printers/pp-new-printer-dialog.h b/panels/printers/pp-new-printer-dialog.h
new file mode 100644
index 0000000..78ac68d
--- /dev/null
+++ b/panels/printers/pp-new-printer-dialog.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2009-2010 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include "pp-new-printer.h"
+#include "pp-utils.h"
+
+G_BEGIN_DECLS
+
+#define PP_TYPE_NEW_PRINTER_DIALOG (pp_new_printer_dialog_get_type ())
+G_DECLARE_FINAL_TYPE (PpNewPrinterDialog, pp_new_printer_dialog, PP, NEW_PRINTER_DIALOG, GtkDialog)
+
+PpNewPrinterDialog *pp_new_printer_dialog_new (PPDList *ppd_list,
+ UserResponseCallback user_callback,
+ gpointer user_data);
+void pp_new_printer_dialog_set_ppd_list (PpNewPrinterDialog *dialog,
+ PPDList *list);
+PpNewPrinter *pp_new_printer_dialog_get_new_printer (PpNewPrinterDialog *dialog);
+
+G_END_DECLS
diff --git a/panels/printers/pp-new-printer.c b/panels/printers/pp-new-printer.c
new file mode 100644
index 0000000..072a760
--- /dev/null
+++ b/panels/printers/pp-new-printer.c
@@ -0,0 +1,1300 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marek Kasik <mkasik@redhat.com>
+ */
+
+#include "pp-new-printer.h"
+
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+
+#include "pp-utils.h"
+#include "pp-maintenance-command.h"
+
+#define PACKAGE_KIT_BUS "org.freedesktop.PackageKit"
+#define PACKAGE_KIT_PATH "/org/freedesktop/PackageKit"
+#define PACKAGE_KIT_MODIFY_IFACE "org.freedesktop.PackageKit.Modify"
+#define PACKAGE_KIT_QUERY_IFACE "org.freedesktop.PackageKit.Query"
+
+#define DBUS_TIMEOUT 120000
+#define DBUS_TIMEOUT_LONG 600000
+
+#if (CUPS_VERSION_MAJOR > 1) || (CUPS_VERSION_MINOR > 5)
+#define HAVE_CUPS_1_6 1
+#endif
+
+#ifndef HAVE_CUPS_1_6
+#define ippGetState(ipp) ipp->state
+#endif
+
+struct _PpNewPrinter
+{
+ GObject parent_instance;
+
+ gchar *name;
+ gchar *original_name;
+ gchar *device_uri;
+ gchar *device_id;
+ gchar *ppd_name;
+ gchar *ppd_file_name;
+ gchar *info;
+ gchar *location;
+ gchar *make_and_model;
+ gchar *host_name;
+ gint host_port;
+ gboolean is_network_device;
+ guint window_id;
+ gboolean unlink_ppd_file;
+
+ GTask *task;
+ GCancellable *cancellable;
+};
+
+G_DEFINE_TYPE (PpNewPrinter, pp_new_printer, G_TYPE_OBJECT);
+
+enum {
+ PROP_0 = 0,
+ PROP_NAME,
+ PROP_ORIGINAL_NAME,
+ PROP_DEVICE_URI,
+ PROP_DEVICE_ID,
+ PROP_PPD_NAME,
+ PROP_PPD_FILE_NAME,
+ PROP_INFO,
+ PROP_LOCATION,
+ PROP_MAKE_AND_MODEL,
+ PROP_HOST_NAME,
+ PROP_HOST_PORT,
+ PROP_IS_NETWORK_DEVICE,
+ PROP_WINDOW_ID
+};
+
+static void
+pp_new_printer_finalize (GObject *object)
+{
+ PpNewPrinter *self = PP_NEW_PRINTER (object);
+
+ if (self->unlink_ppd_file && self->ppd_file_name)
+ g_unlink (self->ppd_file_name);
+
+ g_clear_pointer (&self->name, g_free);
+ g_clear_pointer (&self->original_name, g_free);
+ g_clear_pointer (&self->device_uri, g_free);
+ g_clear_pointer (&self->device_id, g_free);
+ g_clear_pointer (&self->ppd_name, g_free);
+ g_clear_pointer (&self->ppd_file_name, g_free);
+ g_clear_pointer (&self->info, g_free);
+ g_clear_pointer (&self->location, g_free);
+ g_clear_pointer (&self->make_and_model, g_free);
+ g_clear_pointer (&self->host_name, g_free);
+ g_clear_object (&self->task);
+ g_clear_object (&self->cancellable);
+
+ G_OBJECT_CLASS (pp_new_printer_parent_class)->finalize (object);
+}
+
+static void
+pp_new_printer_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *param_spec)
+{
+ PpNewPrinter *self = PP_NEW_PRINTER (object);
+
+ switch (prop_id)
+ {
+ case PROP_NAME:
+ g_value_set_string (value, self->name);
+ break;
+ case PROP_ORIGINAL_NAME:
+ g_value_set_string (value, self->original_name);
+ break;
+ case PROP_DEVICE_URI:
+ g_value_set_string (value, self->device_uri);
+ break;
+ case PROP_DEVICE_ID:
+ g_value_set_string (value, self->device_id);
+ break;
+ case PROP_PPD_NAME:
+ g_value_set_string (value, self->ppd_name);
+ break;
+ case PROP_PPD_FILE_NAME:
+ g_value_set_string (value, self->ppd_file_name);
+ break;
+ case PROP_INFO:
+ g_value_set_string (value, self->info);
+ break;
+ case PROP_LOCATION:
+ g_value_set_string (value, self->location);
+ break;
+ case PROP_MAKE_AND_MODEL:
+ g_value_set_string (value, self->make_and_model);
+ break;
+ case PROP_HOST_NAME:
+ g_value_set_string (value, self->host_name);
+ break;
+ case PROP_HOST_PORT:
+ g_value_set_int (value, self->host_port);
+ break;
+ case PROP_IS_NETWORK_DEVICE:
+ g_value_set_boolean (value, self->is_network_device);
+ break;
+ case PROP_WINDOW_ID:
+ g_value_set_uint (value, self->window_id);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
+ prop_id,
+ param_spec);
+ break;
+ }
+}
+
+static void
+pp_new_printer_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *param_spec)
+{
+ PpNewPrinter *self = PP_NEW_PRINTER (object);
+
+ switch (prop_id)
+ {
+ case PROP_NAME:
+ g_free (self->name);
+ self->name = g_value_dup_string (value);
+ break;
+ case PROP_ORIGINAL_NAME:
+ g_free (self->original_name);
+ self->original_name = g_value_dup_string (value);
+ break;
+ case PROP_DEVICE_URI:
+ g_free (self->device_uri);
+ self->device_uri = g_value_dup_string (value);
+ break;
+ case PROP_DEVICE_ID:
+ g_free (self->device_id);
+ self->device_id = g_value_dup_string (value);
+ break;
+ case PROP_PPD_NAME:
+ g_free (self->ppd_name);
+ self->ppd_name = g_value_dup_string (value);
+ break;
+ case PROP_PPD_FILE_NAME:
+ g_free (self->ppd_file_name);
+ self->ppd_file_name = g_value_dup_string (value);
+ break;
+ case PROP_INFO:
+ g_free (self->info);
+ self->info = g_value_dup_string (value);
+ break;
+ case PROP_LOCATION:
+ g_free (self->location);
+ self->location = g_value_dup_string (value);
+ break;
+ case PROP_MAKE_AND_MODEL:
+ g_free (self->make_and_model);
+ self->make_and_model = g_value_dup_string (value);
+ break;
+ case PROP_HOST_NAME:
+ g_free (self->host_name);
+ self->host_name = g_value_dup_string (value);
+ break;
+ case PROP_HOST_PORT:
+ self->host_port = g_value_get_int (value);
+ break;
+ case PROP_IS_NETWORK_DEVICE:
+ self->is_network_device = g_value_get_boolean (value);
+ break;
+ case PROP_WINDOW_ID:
+ self->window_id = g_value_get_uint (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
+ prop_id,
+ param_spec);
+ break;
+ }
+}
+
+static void
+pp_new_printer_class_init (PpNewPrinterClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->set_property = pp_new_printer_set_property;
+ gobject_class->get_property = pp_new_printer_get_property;
+
+ gobject_class->finalize = pp_new_printer_finalize;
+
+ g_object_class_install_property (gobject_class, PROP_NAME,
+ g_param_spec_string ("name",
+ "Name",
+ "The new printer's name",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_ORIGINAL_NAME,
+ g_param_spec_string ("original-name",
+ "Original name",
+ "Original name of the new printer",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_DEVICE_URI,
+ g_param_spec_string ("device-uri",
+ "Device URI",
+ "The new printer's device URI",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_DEVICE_ID,
+ g_param_spec_string ("device-id",
+ "DeviceID",
+ "The new printer's DeviceID",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_PPD_NAME,
+ g_param_spec_string ("ppd-name",
+ "PPD name",
+ "Name of PPD for the new printer",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_PPD_FILE_NAME,
+ g_param_spec_string ("ppd-file-name",
+ "PPD file name",
+ "PPD file for the new printer",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_INFO,
+ g_param_spec_string ("info",
+ "Printer info",
+ "The new printer's info",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_LOCATION,
+ g_param_spec_string ("location",
+ "Printer location",
+ "The new printer's location",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_MAKE_AND_MODEL,
+ g_param_spec_string ("make-and-model",
+ "Printer make and model",
+ "The new printer's make and model",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_HOST_NAME,
+ g_param_spec_string ("host-name",
+ "Hostname",
+ "The new printer's hostname",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_HOST_PORT,
+ g_param_spec_int ("host-port",
+ "Host port",
+ "The port of the host",
+ 0, G_MAXINT32, 631,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_IS_NETWORK_DEVICE,
+ g_param_spec_boolean ("is-network-device",
+ "Network device",
+ "Whether the new printer is a network device",
+ FALSE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_WINDOW_ID,
+ g_param_spec_uint ("window-id",
+ "WindowID",
+ "Window ID of parent window",
+ 0, G_MAXUINT, 0,
+ G_PARAM_READWRITE));
+}
+
+static void
+pp_new_printer_init (PpNewPrinter *self)
+{
+}
+
+PpNewPrinter *
+pp_new_printer_new ()
+{
+ return g_object_new (PP_TYPE_NEW_PRINTER, NULL);
+}
+
+static void printer_configure_async (PpNewPrinter *self);
+
+static void
+_pp_new_printer_add_async_cb (gboolean success,
+ PpNewPrinter *self)
+{
+ if (!success)
+ {
+ g_task_return_new_error (self->task,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Installation of the new printer failed.");
+ return;
+ }
+
+ g_task_return_boolean (self->task, success);
+}
+
+static void
+printer_add_real_async_cb (cups_dest_t *destination,
+ gpointer user_data)
+{
+ PpNewPrinter *self = user_data;
+ gboolean success = FALSE;
+
+ if (destination)
+ {
+ success = TRUE;
+ cupsFreeDests (1, destination);
+ }
+
+ if (success)
+ {
+ printer_configure_async (self);
+ }
+ else
+ {
+ _pp_new_printer_add_async_cb (FALSE, self);
+ }
+}
+
+static void
+printer_add_real_async_dbus_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ PpNewPrinter *self = user_data;
+ g_autoptr(GVariant) output = NULL;
+ g_autoptr(GError) error = NULL;
+
+ output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ res,
+ &error);
+
+ if (output)
+ {
+ const gchar *ret_error;
+
+ g_variant_get (output, "(&s)", &ret_error);
+ if (ret_error[0] != '\0')
+ {
+ g_warning ("cups-pk-helper: addition of printer %s failed: %s", self->name, ret_error);
+ }
+ }
+ else
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("%s", error->message);
+ }
+
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ get_named_dest_async (self->name,
+ printer_add_real_async_cb,
+ self);
+ }
+}
+
+static void
+printer_add_real_async (PpNewPrinter *self)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+ g_autoptr(GError) error = NULL;
+
+ if (!self->ppd_name && !self->ppd_file_name)
+ {
+ _pp_new_printer_add_async_cb (FALSE, self);
+ return;
+ }
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!bus)
+ {
+ g_warning ("Failed to get system bus: %s", error->message);
+ _pp_new_printer_add_async_cb (FALSE, self);
+ return;
+ }
+
+ g_dbus_connection_call (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ self->ppd_name ? "PrinterAdd" : "PrinterAddWithPpdFile",
+ g_variant_new ("(sssss)",
+ self->name,
+ self->device_uri,
+ self->ppd_name ? self->ppd_name : self->ppd_file_name,
+ self->info ? self->info : "",
+ self->location ? self->location : ""),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_TIMEOUT,
+ NULL,
+ printer_add_real_async_dbus_cb,
+ self);
+}
+
+static PPDName *
+get_ppd_item_from_output (GVariant *output)
+{
+ g_autoptr(GVariant) array = NULL;
+ gint j;
+ static const char * const match_levels[] = {
+ "exact-cmd",
+ "exact",
+ "close",
+ "generic",
+ "none"};
+
+ if (output == NULL)
+ return NULL;
+
+ g_variant_get (output, "(@a(ss))", &array);
+ for (j = 0; j < G_N_ELEMENTS (match_levels); j++)
+ {
+ g_autoptr(GVariantIter) iter = NULL;
+ const gchar *driver, *match;
+
+ g_variant_get (array, "a(ss)", &iter);
+ while (g_variant_iter_next (iter, "(&s&s)", &driver, &match))
+ {
+ PPDName *ppd_item;
+
+ if (!g_str_equal (match, match_levels[j]))
+ continue;
+
+ ppd_item = g_new0 (PPDName, 1);
+ ppd_item->ppd_name = g_strdup (driver);
+
+ if (g_strcmp0 (match, "exact-cmd") == 0)
+ ppd_item->ppd_match_level = PPD_EXACT_CMD_MATCH;
+ else if (g_strcmp0 (match, "exact") == 0)
+ ppd_item->ppd_match_level = PPD_EXACT_MATCH;
+ else if (g_strcmp0 (match, "close") == 0)
+ ppd_item->ppd_match_level = PPD_CLOSE_MATCH;
+ else if (g_strcmp0 (match, "generic") == 0)
+ ppd_item->ppd_match_level = PPD_GENERIC_MATCH;
+ else if (g_strcmp0 (match, "none") == 0)
+ ppd_item->ppd_match_level = PPD_NO_MATCH;
+
+ return ppd_item;
+ }
+ }
+
+ return NULL;
+}
+
+
+static void
+printer_add_async_scb3 (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ PpNewPrinter *self = user_data;
+ g_autoptr(GVariant) output = NULL;
+ PPDName *ppd_item = NULL;
+ g_autoptr(GError) error = NULL;
+
+ output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ res,
+ &error);
+
+ if (output)
+ {
+ ppd_item = get_ppd_item_from_output (output);
+ }
+ else
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("%s", error->message);
+ }
+
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) &&
+ ppd_item && ppd_item->ppd_name)
+ {
+ self->ppd_name = g_strdup (ppd_item->ppd_name);
+ printer_add_real_async (self);
+ }
+ else
+ {
+ _pp_new_printer_add_async_cb (FALSE, self);
+ }
+
+ if (ppd_item)
+ {
+ g_free (ppd_item->ppd_name);
+ g_free (ppd_item);
+ }
+}
+
+static void
+install_printer_drivers_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ PpNewPrinter *self = user_data;
+ g_autoptr(GVariant) output = NULL;
+ g_autoptr(GError) error = NULL;
+
+ output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ res,
+ &error);
+
+ if (output == NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("%s", error->message);
+ }
+
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ g_autoptr(GDBusConnection) bus = NULL;
+ g_autoptr(GError) bus_error = NULL;
+
+ /* Try whether CUPS has a driver for the new printer */
+ bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &bus_error);
+ if (bus)
+ {
+ g_dbus_connection_call (bus,
+ SCP_BUS,
+ SCP_PATH,
+ SCP_IFACE,
+ "GetBestDrivers",
+ g_variant_new ("(sss)",
+ self->device_id,
+ self->make_and_model ? self->make_and_model : "",
+ self->device_uri ? self->device_uri : ""),
+ G_VARIANT_TYPE ("(a(ss))"),
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_TIMEOUT_LONG,
+ self->cancellable,
+ printer_add_async_scb3,
+ self);
+ }
+ else
+ {
+ g_warning ("Failed to get system bus: %s", bus_error->message);
+ _pp_new_printer_add_async_cb (FALSE, self);
+ }
+ }
+}
+
+static void
+printer_add_async_scb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ PpNewPrinter *self = user_data;
+ g_autoptr(GDBusConnection) bus = NULL;
+ GVariantBuilder array_builder;
+ g_autoptr(GVariant) output = NULL;
+ gboolean cancelled = FALSE;
+ PPDName *ppd_item = NULL;
+ g_autoptr(GError) error = NULL;
+
+ output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ res,
+ &error);
+
+ if (output)
+ {
+ ppd_item = get_ppd_item_from_output (output);
+ }
+ else
+ {
+ cancelled = g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
+
+ if (!cancelled)
+ g_warning ("%s", error->message);
+ }
+
+ if (!cancelled)
+ {
+ if (ppd_item == NULL || ppd_item->ppd_match_level < PPD_EXACT_MATCH)
+ {
+ g_autoptr(GError) bus_error = NULL;
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &bus_error);
+ if (bus)
+ {
+ g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("as"));
+ g_variant_builder_add (&array_builder, "s", self->device_id);
+
+ g_dbus_connection_call (bus,
+ PACKAGE_KIT_BUS,
+ PACKAGE_KIT_PATH,
+ PACKAGE_KIT_MODIFY_IFACE,
+ "InstallPrinterDrivers",
+ g_variant_new ("(uass)",
+ self->window_id,
+ &array_builder,
+ "hide-finished"),
+ G_VARIANT_TYPE ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_TIMEOUT_LONG,
+ NULL,
+ install_printer_drivers_cb,
+ self);
+ }
+ else
+ {
+ g_warning ("Failed to get session bus: %s", bus_error->message);
+ _pp_new_printer_add_async_cb (FALSE, self);
+ }
+ }
+ else if (ppd_item && ppd_item->ppd_name)
+ {
+ self->ppd_name = g_strdup (ppd_item->ppd_name);
+ printer_add_real_async (self);
+ }
+ else
+ {
+ _pp_new_printer_add_async_cb (FALSE, self);
+ }
+ }
+
+ if (ppd_item)
+ {
+ g_free (ppd_item->ppd_name);
+ g_free (ppd_item);
+ }
+}
+
+static void
+printer_add_async_scb4 (const gchar *ppd_filename,
+ gpointer user_data)
+{
+ PpNewPrinter *self = user_data;
+
+ self->ppd_file_name = g_strdup (ppd_filename);
+ if (self->ppd_file_name)
+ {
+ self->unlink_ppd_file = TRUE;
+ printer_add_real_async (self);
+ }
+ else
+ {
+ _pp_new_printer_add_async_cb (FALSE, self);
+ }
+}
+
+static GList *
+glist_uniq (GList *list)
+{
+ GList *result = NULL;
+ GList *iter = NULL;
+ GList *tmp = NULL;
+
+ for (iter = list; iter; iter = iter->next)
+ {
+ if (tmp == NULL ||
+ g_strcmp0 ((gchar *) tmp->data, (gchar *) iter->data) != 0)
+ {
+ tmp = iter;
+ result = g_list_append (result, g_strdup (iter->data));
+ }
+ }
+
+ g_list_free_full (list, g_free);
+
+ return result;
+}
+
+typedef struct
+{
+ PpNewPrinter *new_printer;
+ GCancellable *cancellable;
+ gboolean set_accept_jobs_finished;
+ gboolean set_enabled_finished;
+ gboolean autoconfigure_finished;
+ gboolean set_media_size_finished;
+ gboolean install_missing_executables_finished;
+} PCData;
+
+static void
+printer_configure_async_finish (PCData *data)
+{
+ PpNewPrinter *self = data->new_printer;
+
+ if (data->set_accept_jobs_finished &&
+ data->set_enabled_finished &&
+ (data->autoconfigure_finished || self->is_network_device) &&
+ data->set_media_size_finished &&
+ data->install_missing_executables_finished)
+ {
+ _pp_new_printer_add_async_cb (TRUE, data->new_printer);
+
+ g_clear_object (&data->cancellable);
+ g_free (data);
+ }
+}
+
+static void
+pao_cb (gboolean success,
+ gpointer user_data)
+{
+ PCData *data = (PCData *) user_data;
+
+ data->set_media_size_finished = TRUE;
+ printer_configure_async_finish (data);
+}
+
+static void
+printer_set_accepting_jobs_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GVariant) output = NULL;
+ PCData *data = (PCData *) user_data;
+ g_autoptr(GError) error = NULL;
+
+ output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ res,
+ &error);
+
+ if (output == NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("%s", error->message);
+ }
+
+ data->set_accept_jobs_finished = TRUE;
+ printer_configure_async_finish (data);
+}
+
+static void
+printer_set_enabled_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GVariant) output = NULL;
+ PCData *data = (PCData *) user_data;
+ g_autoptr(GError) error = NULL;
+
+ output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ res,
+ &error);
+
+ if (output == NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("%s", error->message);
+ }
+
+ data->set_enabled_finished = TRUE;
+ printer_configure_async_finish (data);
+}
+
+typedef struct
+{
+ GList *executables;
+ GList *packages;
+ guint window_id;
+ gchar *ppd_file_name;
+ GCancellable *cancellable;
+ gpointer user_data;
+} IMEData;
+
+static void
+install_missing_executables_cb (IMEData *data)
+{
+ PCData *pc_data = (PCData *) data->user_data;
+
+ pc_data->install_missing_executables_finished = TRUE;
+ printer_configure_async_finish (pc_data);
+
+ if (data->ppd_file_name)
+ {
+ g_unlink (data->ppd_file_name);
+ g_clear_pointer (&data->ppd_file_name, g_free);
+ }
+
+ if (data->executables)
+ {
+ g_list_free_full (data->executables, g_free);
+ data->executables = NULL;
+ }
+
+ if (data->packages)
+ {
+ g_list_free_full (data->packages, g_free);
+ data->packages = NULL;
+ }
+
+ if (data->cancellable)
+ g_clear_object (&data->cancellable);
+
+ g_free (data);
+}
+
+static void
+install_package_names_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GVariant) output = NULL;
+ IMEData *data = (IMEData *) user_data;
+ g_autoptr(GError) error = NULL;
+
+ output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ res,
+ &error);
+
+ if (output == NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("%s", error->message);
+ }
+
+ install_missing_executables_cb (data);
+}
+
+
+static void
+search_files_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GVariant) output = NULL;
+ IMEData *data = (IMEData *) user_data;
+ g_autoptr(GError) error = NULL;
+ GList *item;
+
+ output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ res,
+ &error);
+ if (output)
+ {
+ gboolean installed;
+ gchar *package;
+
+ g_variant_get (output,
+ "(bs)",
+ &installed,
+ &package);
+
+ if (!installed)
+ data->packages = g_list_append (data->packages, g_strdup (package));
+ }
+ else
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("%s", error->message);
+ }
+
+ if (data->executables)
+ {
+ item = data->executables;
+ g_dbus_connection_call (G_DBUS_CONNECTION (source_object),
+ PACKAGE_KIT_BUS,
+ PACKAGE_KIT_PATH,
+ PACKAGE_KIT_QUERY_IFACE,
+ "SearchFile",
+ g_variant_new ("(ss)",
+ (gchar *) item->data,
+ ""),
+ G_VARIANT_TYPE ("(bs)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_TIMEOUT_LONG,
+ data->cancellable,
+ search_files_cb,
+ data);
+
+ data->executables = g_list_remove_link (data->executables, item);
+ g_list_free_full (item, g_free);
+ }
+ else
+ {
+ GVariantBuilder array_builder;
+ GList *pkg_iter;
+
+ data->packages = g_list_sort (data->packages, (GCompareFunc) g_strcmp0);
+ data->packages = glist_uniq (data->packages);
+
+ if (data->packages)
+ {
+ g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("as"));
+
+ for (pkg_iter = data->packages; pkg_iter; pkg_iter = pkg_iter->next)
+ g_variant_builder_add (&array_builder,
+ "s",
+ (gchar *) pkg_iter->data);
+
+ g_dbus_connection_call (G_DBUS_CONNECTION (source_object),
+ PACKAGE_KIT_BUS,
+ PACKAGE_KIT_PATH,
+ PACKAGE_KIT_MODIFY_IFACE,
+ "InstallPackageNames",
+ g_variant_new ("(uass)",
+ data->window_id,
+ &array_builder,
+ "hide-finished"),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_TIMEOUT_LONG,
+ data->cancellable,
+ install_package_names_cb,
+ data);
+
+ g_list_free_full (data->packages, g_free);
+ data->packages = NULL;
+ }
+ else
+ {
+ install_missing_executables_cb (data);
+ }
+ }
+}
+
+static void
+get_missing_executables_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GVariant) output = NULL;
+ IMEData *data = (IMEData *) user_data;
+ g_autoptr(GError) error = NULL;
+ GList *executables = NULL;
+ GList *item;
+
+ if (data->ppd_file_name)
+ {
+ g_unlink (data->ppd_file_name);
+ g_clear_pointer (&data->ppd_file_name, g_free);
+ }
+
+ output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ res,
+ &error);
+
+ if (output)
+ {
+ g_autoptr(GVariant) array = NULL;
+ g_autoptr(GVariantIter) iter = NULL;
+ const gchar *executable;
+
+ g_variant_get (output, "(@as)", &array);
+
+ g_variant_get (array, "as", &iter);
+ while (g_variant_iter_next (iter, "&s", &executable))
+ executables = g_list_append (executables, g_strdup (executable));
+ }
+ else if (error->domain == G_DBUS_ERROR &&
+ (error->code == G_DBUS_ERROR_SERVICE_UNKNOWN ||
+ error->code == G_DBUS_ERROR_UNKNOWN_METHOD))
+ {
+ g_warning ("Install system-config-printer which provides \
+DBus method \"MissingExecutables\" to find missing executables and filters.");
+ }
+ else
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("%s", error->message);
+ }
+
+ executables = g_list_sort (executables, (GCompareFunc) g_strcmp0);
+ executables = glist_uniq (executables);
+
+ if (executables)
+ {
+ data->executables = executables;
+
+ item = data->executables;
+ g_dbus_connection_call (g_object_ref (G_DBUS_CONNECTION (source_object)),
+ PACKAGE_KIT_BUS,
+ PACKAGE_KIT_PATH,
+ PACKAGE_KIT_QUERY_IFACE,
+ "SearchFile",
+ g_variant_new ("(ss)",
+ (gchar *) item->data,
+ ""),
+ G_VARIANT_TYPE ("(bs)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_TIMEOUT_LONG,
+ data->cancellable,
+ search_files_cb,
+ data);
+
+ data->executables = g_list_remove_link (data->executables, item);
+ g_list_free_full (item, g_free);
+ }
+ else
+ {
+ install_missing_executables_cb (data);
+ }
+}
+
+static void
+printer_get_ppd_cb (const gchar *ppd_filename,
+ gpointer user_data)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+ IMEData *data = (IMEData *) user_data;
+ g_autoptr(GError) error = NULL;
+
+ data->ppd_file_name = g_strdup (ppd_filename);
+ if (data->ppd_file_name)
+ {
+ bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
+ if (!bus)
+ {
+ g_warning ("%s", error->message);
+ }
+ else
+ {
+ g_dbus_connection_call (bus,
+ SCP_BUS,
+ SCP_PATH,
+ SCP_IFACE,
+ "MissingExecutables",
+ g_variant_new ("(s)", data->ppd_file_name),
+ G_VARIANT_TYPE ("(as)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_TIMEOUT,
+ data->cancellable,
+ get_missing_executables_cb,
+ data);
+ return;
+ }
+ }
+
+ install_missing_executables_cb (data);
+}
+
+static void
+pp_maintenance_command_execute_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+ PCData *data;
+ gboolean result;
+
+ result = pp_maintenance_command_execute_finish (PP_MAINTENANCE_COMMAND (source_object), res, &error);
+
+ if (result)
+ {
+ data = (PCData *) user_data;
+
+ data->autoconfigure_finished = TRUE;
+ printer_configure_async_finish (data);
+ }
+ else
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ data = (PCData *) user_data;
+
+ g_warning ("%s", error->message);
+
+ data->autoconfigure_finished = TRUE;
+ printer_configure_async_finish (data);
+ }
+ }
+}
+
+static void
+printer_configure_async (PpNewPrinter *self)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+ PCData *data;
+ IMEData *ime_data;
+ gchar **values;
+ g_autoptr(GError) error = NULL;
+
+ data = g_new0 (PCData, 1);
+ data->new_printer = self;
+ data->set_accept_jobs_finished = FALSE;
+ data->set_enabled_finished = FALSE;
+ data->autoconfigure_finished = FALSE;
+ data->set_media_size_finished = FALSE;
+ data->install_missing_executables_finished = FALSE;
+
+ /* Enable printer and make it accept jobs */
+ if (self->name)
+ {
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (bus)
+ {
+ g_dbus_connection_call (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "PrinterSetAcceptJobs",
+ g_variant_new ("(sbs)",
+ self->name,
+ TRUE,
+ ""),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ printer_set_accepting_jobs_cb,
+ data);
+
+ g_dbus_connection_call (g_object_ref (bus),
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "PrinterSetEnabled",
+ g_variant_new ("(sb)",
+ self->name,
+ TRUE),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ printer_set_enabled_cb,
+ data);
+ }
+ else
+ {
+ g_warning ("Failed to get system bus: %s", error->message);
+ data->set_accept_jobs_finished = TRUE;
+ data->set_enabled_finished = TRUE;
+ }
+ }
+ else
+ {
+ data->set_accept_jobs_finished = TRUE;
+ data->set_enabled_finished = TRUE;
+ }
+
+ /* Run autoconfiguration of printer */
+ if (!self->is_network_device)
+ {
+ g_autoptr(PpMaintenanceCommand) command = NULL;
+
+ command = pp_maintenance_command_new (self->name,
+ "autoconfigure",
+ NULL,
+ /* Translators: Name of job which makes printer to autoconfigure itself */
+ _("Automatic configuration"));
+
+ pp_maintenance_command_execute_async (command,
+ NULL,
+ pp_maintenance_command_execute_cb,
+ data);
+ }
+
+ /* Set media size for printer */
+ values = g_new0 (gchar *, 2);
+ values[0] = g_strdup (get_page_size_from_locale ());
+
+ printer_add_option_async (self->name, "PageSize", values, FALSE, NULL, pao_cb, data);
+
+ g_strfreev (values);
+
+ /* Install missing executables for printer */
+ ime_data = g_new0 (IMEData, 1);
+ ime_data->window_id = self->window_id;
+ if (data->cancellable)
+ ime_data->cancellable = g_object_ref (data->cancellable);
+ ime_data->user_data = data;
+
+ printer_get_ppd_async (self->name,
+ NULL,
+ 0,
+ printer_get_ppd_cb,
+ ime_data);
+}
+
+void
+pp_new_printer_add_async (PpNewPrinter *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ self->task = g_task_new (self, cancellable, callback, user_data);
+ self->cancellable = g_object_ref (cancellable);
+
+ if (self->ppd_name || self->ppd_file_name)
+ {
+ /* We have everything we need */
+ printer_add_real_async (self);
+ }
+ else if (self->device_id)
+ {
+ g_autoptr(GDBusConnection) bus = NULL;
+ g_autoptr(GError) error = NULL;
+
+ /* Try whether CUPS has a driver for the new printer */
+ bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
+ if (bus)
+ {
+ g_dbus_connection_call (bus,
+ SCP_BUS,
+ SCP_PATH,
+ SCP_IFACE,
+ "GetBestDrivers",
+ g_variant_new ("(sss)",
+ self->device_id,
+ self->make_and_model ? self->make_and_model : "",
+ self->device_uri ? self->device_uri : ""),
+ G_VARIANT_TYPE ("(a(ss))"),
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_TIMEOUT_LONG,
+ cancellable,
+ printer_add_async_scb,
+ self);
+ }
+ else
+ {
+ g_warning ("Failed to get system bus: %s", error->message);
+ _pp_new_printer_add_async_cb (FALSE, self);
+ }
+ }
+ else if (self->original_name && self->host_name)
+ {
+ /* Try to get PPD from remote CUPS */
+ printer_get_ppd_async (self->original_name,
+ self->host_name,
+ self->host_port,
+ printer_add_async_scb4,
+ self);
+ }
+ else
+ {
+ _pp_new_printer_add_async_cb (FALSE, self);
+ }
+}
+
+gboolean
+pp_new_printer_add_finish (PpNewPrinter *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
diff --git a/panels/printers/pp-new-printer.h b/panels/printers/pp-new-printer.h
new file mode 100644
index 0000000..207bac4
--- /dev/null
+++ b/panels/printers/pp-new-printer.h
@@ -0,0 +1,42 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marek Kasik <mkasik@redhat.com>
+ */
+
+#pragma once
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define PP_TYPE_NEW_PRINTER (pp_new_printer_get_type ())
+G_DECLARE_FINAL_TYPE (PpNewPrinter, pp_new_printer, PP, NEW_PRINTER, GObject)
+
+PpNewPrinter *pp_new_printer_new (void);
+
+void pp_new_printer_add_async (PpNewPrinter *host,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean pp_new_printer_add_finish (PpNewPrinter *host,
+ GAsyncResult *result,
+ GError **error);
+
+G_END_DECLS
diff --git a/panels/printers/pp-options-dialog.c b/panels/printers/pp-options-dialog.c
new file mode 100644
index 0000000..36e9bb2
--- /dev/null
+++ b/panels/printers/pp-options-dialog.c
@@ -0,0 +1,940 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marek Kasik <mkasik@redhat.com>
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <gtk/gtk.h>
+
+#include <cups/cups.h>
+#include <cups/ppd.h>
+
+#include "pp-options-dialog.h"
+#include "pp-maintenance-command.h"
+#include "pp-ppd-option-widget.h"
+#include "pp-ipp-option-widget.h"
+#include "pp-utils.h"
+#include "pp-printer.h"
+
+struct _PpOptionsDialog {
+ GtkDialog parent_instance;
+
+ GtkTreeSelection *categories_selection;
+ GtkTreeView *categories_treeview;
+ GtkBox *main_box;
+ GtkNotebook *notebook;
+ GtkSpinner *spinner;
+ GtkStack *stack;
+
+ gchar *printer_name;
+
+ gchar *ppd_filename;
+ gboolean ppd_filename_set;
+
+ cups_dest_t *destination;
+ gboolean destination_set;
+
+ GHashTable *ipp_attributes;
+ gboolean ipp_attributes_set;
+
+ gboolean sensitive;
+};
+
+G_DEFINE_TYPE (PpOptionsDialog, pp_options_dialog, GTK_TYPE_DIALOG)
+
+enum
+{
+ CATEGORY_IDS_COLUMN = 0,
+ CATEGORY_NAMES_COLUMN
+};
+
+/* These lists come from Gtk+ */
+/* TODO: Only "Resolution" currently has a context to disambiguate it from
+ * the display settings. All of these should have contexts, but it
+ * was late in the release cycle and this partial solution was
+ * preferable. See:
+ * https://gitlab.gnome.org/GNOME/gnome-control-center/merge_requests/414#note_446778
+ */
+static const struct {
+ const char *keyword;
+ const char *translation_context;
+ const char *translation;
+} ppd_option_translations[] = {
+ { "Duplex", NULL, N_("Two Sided") },
+ { "MediaType", NULL, N_("Paper Type") },
+ { "InputSlot", NULL, N_("Paper Source") },
+ { "OutputBin", NULL, N_("Output Tray") },
+ { "Resolution", "printing option", NC_("printing option", "Resolution") },
+ { "PreFilter", NULL, N_("GhostScript pre-filtering") },
+};
+
+/* keep sorted when changing */
+static const char *allowed_page_setup_options[] = {
+ "InputSlot",
+ "MediaType",
+ "OutputBin",
+ "PageSize",
+};
+
+/* keep sorted when changing */
+static const char *allowed_color_options[] = {
+ "BRColorEnhancement",
+ "BRColorMatching",
+ "BRColorMatching",
+ "BRColorMode",
+ "BRGammaValue",
+ "BRImprovedGray",
+ "BlackSubstitution",
+ "ColorModel",
+ "HPCMYKInks",
+ "HPCSGraphics",
+ "HPCSImages",
+ "HPCSText",
+ "HPColorSmart",
+ "RPSBlackMode",
+ "RPSBlackOverPrint",
+ "Rcmyksimulation",
+};
+
+/* keep sorted when changing */
+static const char *allowed_color_groups[] = {
+ "Color",
+ "Color1",
+ "Color2",
+ "ColorBalance",
+ "ColorPage",
+ "ColorSettings1",
+ "ColorSettings2",
+ "ColorSettings3",
+ "ColorSettings4",
+ "EPColorSettings",
+ "FPColorWise1",
+ "FPColorWise2",
+ "FPColorWise3",
+ "FPColorWise4",
+ "FPColorWise5",
+ "HPCMYKInksPanel",
+ "HPColorOptions",
+ "HPColorOptionsPanel",
+ "HPColorQualityOptionsPanel",
+ "ManualColor",
+};
+
+/* keep sorted when changing */
+static const char *allowed_image_quality_options[] = {
+ "BRDocument",
+ "BRHalfTonePattern",
+ "BRNormalPrt",
+ "BRPrintQuality",
+ "BitsPerPixel",
+ "Darkness",
+ "Dithering",
+ "EconoMode",
+ "Economode",
+ "HPEconoMode",
+ "HPEdgeControl",
+ "HPGraphicsHalftone",
+ "HPHalftone",
+ "HPImagingOptions",
+ "HPLJDensity",
+ "HPPhotoHalftone",
+ "HPPrintQualityOptions",
+ "HPResolutionOptions",
+ "OutputMode",
+ "REt",
+ "RPSBitsPerPixel",
+ "RPSDitherType",
+ "Resolution",
+ "ScreenLock",
+ "Smoothing",
+ "TonerSaveMode",
+ "UCRGCRForImage",
+};
+
+/* keep sorted when changing */
+static const char *allowed_image_quality_groups[] = {
+ "EPQualitySettings",
+ "FPImageQuality1",
+ "FPImageQuality2",
+ "FPImageQuality3",
+ "ImageQualityPage",
+ "Quality",
+};
+
+/* keep sorted when changing */
+static const char * allowed_finishing_options[] = {
+ "BindColor",
+ "BindEdge",
+ "BindType",
+ "BindWhen",
+ "Booklet",
+ "FoldType",
+ "FoldWhen",
+ "HPStaplerOptions",
+ "Jog",
+ "Slipsheet",
+ "Sorter",
+ "StapleLocation",
+ "StapleOrientation",
+ "StapleWhen",
+ "StapleX",
+ "StapleY",
+};
+
+/* keep sorted when changing */
+static const char *allowed_job_groups[] = {
+ "JobHandling",
+ "JobLog",
+};
+
+/* keep sorted when changing */
+static const char *allowed_finishing_groups[] = {
+ "Booklet",
+ "BookletCover",
+ "BookletModeOptions",
+ "FPFinishing1",
+ "FPFinishing2",
+ "FPFinishing3",
+ "FPFinishing4",
+ "Finishing",
+ "FinishingOptions",
+ "FinishingPage",
+ "HPBookletPanel",
+ "HPFinishing",
+ "HPFinishingOptions",
+ "HPFinishingPanel",
+};
+
+/* keep sorted when changing */
+static const char *allowed_installable_options_groups[] = {
+ "InstallableOptions",
+};
+
+/* keep sorted when changing */
+static const char *allowed_page_setup_groups[] = {
+ "HPMarginAndLayout",
+ "OutputControl",
+ "PaperHandling",
+ "Paper",
+ "Source",
+};
+
+/* keep sorted when changing */
+static const char *disallowed_ppd_options[] = {
+ "Collate",
+ "Copies",
+ "Duplex",
+ "HPManualDuplexOrientation",
+ "HPManualDuplexSwitch",
+ "OutputOrder",
+ "PageRegion"
+};
+
+static int
+strptr_cmp (const void *a,
+ const void *b)
+{
+ char **aa = (char **)a;
+ char **bb = (char **)b;
+ return strcmp (*aa, *bb);
+}
+
+static gboolean
+string_in_table (gchar *str,
+ const gchar *table[],
+ gint table_len)
+{
+ return bsearch (&str, table, table_len, sizeof (char *), (void *)strptr_cmp) != NULL;
+}
+
+#define STRING_IN_TABLE(_str, _table) (string_in_table (_str, _table, G_N_ELEMENTS (_table)))
+
+static const gchar *
+ppd_option_name_translate (ppd_option_t *option)
+{
+ gint i;
+
+ for (i = 0; i < G_N_ELEMENTS (ppd_option_translations); i++)
+ {
+ if (g_strcmp0 (ppd_option_translations[i].keyword, option->keyword) == 0)
+ {
+ if (ppd_option_translations[i].translation_context)
+ return g_dpgettext2(NULL, ppd_option_translations[i].translation_context, ppd_option_translations[i].translation);
+ else
+ return _(ppd_option_translations[i].translation);
+ }
+ }
+
+ return option->text;
+}
+
+static gint
+grid_get_height (GtkWidget *grid)
+{
+ GtkWidget *child;
+ gint height = 0;
+ gint row = 0;
+ gint max = 0;
+
+ for (child = gtk_widget_get_first_child (grid);
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ {
+ gtk_grid_query_child (GTK_GRID (grid),
+ child,
+ NULL, &row,
+ NULL, &height);
+
+ if (height + row > max)
+ max = height + row;
+ }
+
+ return max;
+}
+
+static gboolean
+grid_is_empty (GtkWidget *grid)
+{
+ return gtk_widget_get_first_child (grid) == NULL;
+}
+
+static GtkWidget *
+ipp_option_add (IPPAttribute *attr_supported,
+ IPPAttribute *attr_default,
+ const gchar *option_name,
+ const gchar *option_display_name,
+ const gchar *printer_name,
+ GtkWidget *grid,
+ gboolean sensitive)
+{
+ GtkStyleContext *context;
+ GtkWidget *widget;
+ GtkWidget *label;
+ gint position;
+
+ widget = (GtkWidget *) pp_ipp_option_widget_new (attr_supported,
+ attr_default,
+ option_name,
+ printer_name);
+ if (widget)
+ {
+ gtk_widget_show (widget);
+ gtk_widget_set_sensitive (widget, sensitive);
+ position = grid_get_height (grid);
+
+ label = gtk_label_new (option_display_name);
+ gtk_widget_show (GTK_WIDGET (label));
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
+ context = gtk_widget_get_style_context (label);
+ gtk_style_context_add_class (context, "dim-label");
+ gtk_widget_set_halign (label, GTK_ALIGN_END);
+ gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
+ gtk_widget_set_margin_start (label, 10);
+ gtk_grid_attach (GTK_GRID (grid), label, 0, position, 1, 1);
+
+ gtk_widget_set_margin_start (widget, 20);
+ gtk_grid_attach (GTK_GRID (grid), widget, 1, position, 1, 1);
+ }
+
+ return widget;
+}
+
+static GtkWidget *
+ppd_option_add (ppd_option_t option,
+ const gchar *printer_name,
+ GtkWidget *grid,
+ gboolean sensitive)
+{
+ GtkStyleContext *context;
+ GtkWidget *widget;
+ GtkWidget *label;
+ gint position;
+
+ widget = (GtkWidget *) pp_ppd_option_widget_new (&option, printer_name);
+ if (widget)
+ {
+ gtk_widget_show (widget);
+ gtk_widget_set_sensitive (widget, sensitive);
+ position = grid_get_height (grid);
+
+ label = gtk_label_new (ppd_option_name_translate (&option));
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
+ context = gtk_widget_get_style_context (label);
+ gtk_style_context_add_class (context, "dim-label");
+ gtk_widget_set_halign (label, GTK_ALIGN_END);
+ gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
+ gtk_widget_set_margin_start (label, 10);
+ gtk_grid_attach (GTK_GRID (grid), label, 0, position, 1, 1);
+
+ gtk_widget_set_margin_start (widget, 20);
+ gtk_grid_attach (GTK_GRID (grid), widget, 1, position, 1, 1);
+ }
+
+ return widget;
+}
+
+static GtkWidget *
+tab_grid_new ()
+{
+ GtkWidget *grid;
+
+ grid = gtk_grid_new ();
+ gtk_widget_set_margin_start (grid, 20);
+ gtk_widget_set_margin_end (grid, 20);
+ gtk_widget_set_margin_top (grid, 20);
+ gtk_widget_set_margin_bottom (grid, 20);
+ gtk_grid_set_row_spacing (GTK_GRID (grid), 15);
+
+ return grid;
+}
+
+static void
+tab_add (PpOptionsDialog *self,
+ const gchar *tab_name,
+ GtkWidget *grid)
+{
+ GtkListStore *store;
+ GtkTreeIter iter;
+ GtkWidget *scrolled_window;
+ gboolean unref_store = FALSE;
+ gint id;
+
+ if (!grid_is_empty (grid))
+ {
+ scrolled_window = gtk_scrolled_window_new ();
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+ GTK_POLICY_NEVER,
+ GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolled_window), grid);
+
+ id = gtk_notebook_append_page (self->notebook,
+ scrolled_window,
+ NULL);
+
+ if (id >= 0)
+ {
+ store = GTK_LIST_STORE (gtk_tree_view_get_model (self->categories_treeview));
+ if (!store)
+ {
+ store = gtk_list_store_new (2, G_TYPE_INT, G_TYPE_STRING);
+ unref_store = TRUE;
+ }
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ CATEGORY_IDS_COLUMN, id,
+ CATEGORY_NAMES_COLUMN, tab_name,
+ -1);
+
+ if (unref_store)
+ {
+ gtk_tree_view_set_model (self->categories_treeview, GTK_TREE_MODEL (store));
+ g_object_unref (store);
+ }
+ }
+ }
+ else
+ {
+ g_object_ref_sink (grid);
+ g_object_unref (grid);
+ }
+}
+
+static void
+category_selection_changed_cb (PpOptionsDialog *self)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gint id = -1;
+
+ if (gtk_tree_selection_get_selected (self->categories_selection, &model, &iter))
+ {
+ gtk_tree_model_get (model, &iter,
+ CATEGORY_IDS_COLUMN, &id,
+ -1);
+ }
+
+ if (id >= 0)
+ {
+ gtk_notebook_set_current_page (self->notebook, id);
+ }
+}
+
+static void
+populate_options_real (PpOptionsDialog *self)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ ppd_file_t *ppd_file;
+ GtkWidget *grid;
+ GtkWidget *general_tab_grid = tab_grid_new ();
+ GtkWidget *page_setup_tab_grid = tab_grid_new ();
+ GtkWidget *installable_options_tab_grid = tab_grid_new ();
+ GtkWidget *job_tab_grid = tab_grid_new ();
+ GtkWidget *image_quality_tab_grid = tab_grid_new ();
+ GtkWidget *color_tab_grid = tab_grid_new ();
+ GtkWidget *finishing_tab_grid = tab_grid_new ();
+ GtkWidget *advanced_tab_grid = tab_grid_new ();
+ gint i, j;
+
+ gtk_spinner_stop (self->spinner);
+
+ gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->main_box));
+
+ if (self->ipp_attributes)
+ {
+ /* Add number-up option to Page Setup tab */
+ ipp_option_add (g_hash_table_lookup (self->ipp_attributes,
+ "number-up-supported"),
+ g_hash_table_lookup (self->ipp_attributes,
+ "number-up-default"),
+ "number-up",
+ /* Translators: This option sets number of pages printed on one sheet */
+ _("Pages per side"),
+ self->printer_name,
+ page_setup_tab_grid,
+ self->sensitive);
+
+ /* Add sides option to Page Setup tab */
+ ipp_option_add (g_hash_table_lookup (self->ipp_attributes,
+ "sides-supported"),
+ g_hash_table_lookup (self->ipp_attributes,
+ "sides-default"),
+ "sides",
+ /* Translators: This option sets whether to print on both sides of paper */
+ _("Two-sided"),
+ self->printer_name,
+ page_setup_tab_grid,
+ self->sensitive);
+
+ /* Add orientation-requested option to Page Setup tab */
+ ipp_option_add (g_hash_table_lookup (self->ipp_attributes,
+ "orientation-requested-supported"),
+ g_hash_table_lookup (self->ipp_attributes,
+ "orientation-requested-default"),
+ "orientation-requested",
+ /* Translators: This option sets orientation of print (portrait, landscape...) */
+ _("Orientation"),
+ self->printer_name,
+ page_setup_tab_grid,
+ self->sensitive);
+ }
+
+ if (self->destination && self->ppd_filename)
+ {
+ ppd_file = ppdOpenFile (self->ppd_filename);
+ ppdLocalize (ppd_file);
+
+ if (ppd_file)
+ {
+ ppdMarkDefaults (ppd_file);
+ cupsMarkOptions (ppd_file,
+ self->destination->num_options,
+ self->destination->options);
+
+ for (i = 0; i < ppd_file->num_groups; i++)
+ {
+ for (j = 0; j < ppd_file->groups[i].num_options; j++)
+ {
+ grid = NULL;
+
+ if (STRING_IN_TABLE (ppd_file->groups[i].name,
+ allowed_color_groups))
+ grid = color_tab_grid;
+ else if (STRING_IN_TABLE (ppd_file->groups[i].name,
+ allowed_image_quality_groups))
+ grid = image_quality_tab_grid;
+ else if (STRING_IN_TABLE (ppd_file->groups[i].name,
+ allowed_job_groups))
+ grid = job_tab_grid;
+ else if (STRING_IN_TABLE (ppd_file->groups[i].name,
+ allowed_finishing_groups))
+ grid = finishing_tab_grid;
+ else if (STRING_IN_TABLE (ppd_file->groups[i].name,
+ allowed_installable_options_groups))
+ grid = installable_options_tab_grid;
+ else if (STRING_IN_TABLE (ppd_file->groups[i].name,
+ allowed_page_setup_groups))
+ grid = page_setup_tab_grid;
+
+ if (!STRING_IN_TABLE (ppd_file->groups[i].options[j].keyword,
+ disallowed_ppd_options))
+ {
+ if (!grid && STRING_IN_TABLE (ppd_file->groups[i].options[j].keyword,
+ allowed_color_options))
+ grid = color_tab_grid;
+ else if (!grid && STRING_IN_TABLE (ppd_file->groups[i].options[j].keyword,
+ allowed_image_quality_options))
+ grid = image_quality_tab_grid;
+ else if (!grid && STRING_IN_TABLE (ppd_file->groups[i].options[j].keyword,
+ allowed_finishing_options))
+ grid = finishing_tab_grid;
+ else if (!grid && STRING_IN_TABLE (ppd_file->groups[i].options[j].keyword,
+ allowed_page_setup_options))
+ grid = page_setup_tab_grid;
+
+ if (!grid)
+ grid = advanced_tab_grid;
+
+ ppd_option_add (ppd_file->groups[i].options[j],
+ self->printer_name,
+ grid,
+ self->sensitive);
+ }
+ }
+ }
+
+ ppdClose (ppd_file);
+ }
+ }
+
+ self->ppd_filename_set = FALSE;
+ if (self->ppd_filename)
+ {
+ g_unlink (self->ppd_filename);
+ g_free (self->ppd_filename);
+ self->ppd_filename = NULL;
+ }
+
+ self->destination_set = FALSE;
+ if (self->destination)
+ {
+ cupsFreeDests (1, self->destination);
+ self->destination = NULL;
+ }
+
+ self->ipp_attributes_set = FALSE;
+ if (self->ipp_attributes)
+ {
+ g_hash_table_unref (self->ipp_attributes);
+ self->ipp_attributes = NULL;
+ }
+
+ /* Translators: "General" tab contains general printer options */
+ tab_add (self, C_("Printer Option Group", "General"), general_tab_grid);
+
+ /* Translators: "Page Setup" tab contains settings related to pages (page size, paper source, etc.) */
+ tab_add (self, C_("Printer Option Group", "Page Setup"), page_setup_tab_grid);
+
+ /* Translators: "Installable Options" tab contains settings of presence of installed options (amount of RAM, duplex unit, etc.) */
+ tab_add (self, C_("Printer Option Group", "Installable Options"), installable_options_tab_grid);
+
+ /* Translators: "Job" tab contains settings for jobs */
+ tab_add (self, C_("Printer Option Group", "Job"), job_tab_grid);
+
+ /* Translators: "Image Quality" tab contains settings for quality of output print (e.g. resolution) */
+ tab_add (self, C_("Printer Option Group", "Image Quality"), image_quality_tab_grid);
+
+ /* Translators: "Color" tab contains color settings (e.g. color printing) */
+ tab_add (self, C_("Printer Option Group", "Color"), color_tab_grid);
+
+ /* Translators: "Finishing" tab contains finishing settings (e.g. booklet printing) */
+ tab_add (self, C_("Printer Option Group", "Finishing"), finishing_tab_grid);
+
+ /* Translators: "Advanced" tab contains all others settings */
+ tab_add (self, C_("Printer Option Group", "Advanced"), advanced_tab_grid);
+
+ /* Select the first option group */
+ if ((model = gtk_tree_view_get_model (self->categories_treeview)) != NULL &&
+ gtk_tree_model_get_iter_first (model, &iter))
+ gtk_tree_selection_select_iter (self->categories_selection, &iter);
+}
+
+static void
+printer_get_ppd_cb (const gchar *ppd_filename,
+ gpointer user_data)
+{
+ PpOptionsDialog *self = (PpOptionsDialog *) user_data;
+
+ if (self->ppd_filename)
+ {
+ g_unlink (self->ppd_filename);
+ g_free (self->ppd_filename);
+ }
+
+ self->ppd_filename = g_strdup (ppd_filename);
+ self->ppd_filename_set = TRUE;
+
+ if (self->destination_set &&
+ self->ipp_attributes_set)
+ {
+ populate_options_real (self);
+ }
+}
+
+static void
+get_named_dest_cb (cups_dest_t *dest,
+ gpointer user_data)
+{
+ PpOptionsDialog *self = (PpOptionsDialog *) user_data;
+
+ if (self->destination)
+ cupsFreeDests (1, self->destination);
+
+ self->destination = dest;
+ self->destination_set = TRUE;
+
+ if (self->ppd_filename_set &&
+ self->ipp_attributes_set)
+ {
+ populate_options_real (self);
+ }
+}
+
+static void
+get_ipp_attributes_cb (GHashTable *table,
+ gpointer user_data)
+{
+ PpOptionsDialog *self = (PpOptionsDialog *) user_data;
+
+ if (self->ipp_attributes)
+ g_hash_table_unref (self->ipp_attributes);
+
+ self->ipp_attributes = g_hash_table_ref (table);
+ self->ipp_attributes_set = TRUE;
+
+ if (self->ppd_filename_set &&
+ self->destination_set)
+ {
+ populate_options_real (self);
+ }
+}
+
+static void
+populate_options (PpOptionsDialog *self)
+{
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+ /*
+ * Options which we need to obtain through an IPP request
+ * to be able to fill the options dialog.
+ * *-supported - possible values of the option
+ * *-default - actual value of the option
+ */
+ const gchar *attributes[] =
+ { "number-up-supported",
+ "number-up-default",
+ "sides-supported",
+ "sides-default",
+ "orientation-requested-supported",
+ "orientation-requested-default",
+ NULL};
+
+ gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->spinner));
+
+ renderer = gtk_cell_renderer_text_new ();
+
+ column = gtk_tree_view_column_new_with_attributes ("Categories", renderer,
+ "text", CATEGORY_NAMES_COLUMN, NULL);
+ gtk_tree_view_column_set_expand (column, TRUE);
+ gtk_tree_view_append_column (self->categories_treeview, column);
+
+ gtk_spinner_start (self->spinner);
+
+ printer_get_ppd_async (self->printer_name,
+ NULL,
+ 0,
+ printer_get_ppd_cb,
+ self);
+
+ get_named_dest_async (self->printer_name,
+ get_named_dest_cb,
+ self);
+
+ get_ipp_attributes_async (self->printer_name,
+ (gchar **) attributes,
+ get_ipp_attributes_cb,
+ self);
+}
+
+static void
+pp_maintenance_command_execute_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ pp_maintenance_command_execute_finish (PP_MAINTENANCE_COMMAND(source_object), res, NULL);
+}
+
+static gchar *
+get_testprint_filename (const gchar *datadir)
+{
+ const gchar *testprint[] = { "/data/testprint",
+ "/data/testprint.ps",
+ NULL };
+ gchar *filename = NULL;
+ gint i;
+
+ for (i = 0; testprint[i] != NULL; i++)
+ {
+ filename = g_strconcat (datadir, testprint[i], NULL);
+ if (g_access (filename, R_OK) == 0)
+ break;
+
+ g_clear_pointer (&filename, g_free);
+ }
+
+ return filename;
+}
+
+static void
+print_test_page_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ pp_printer_print_file_finish (PP_PRINTER (source_object),
+ result, NULL);
+}
+
+static void
+test_page_cb (PpOptionsDialog *self)
+{
+ gint i;
+
+ if (self->printer_name)
+ {
+ const gchar *const dirs[] = { "/usr/share/cups",
+ "/usr/local/share/cups",
+ NULL };
+ const gchar *datadir = NULL;
+ g_autofree gchar *filename = NULL;
+
+ datadir = getenv ("CUPS_DATADIR");
+ if (datadir != NULL)
+ {
+ filename = get_testprint_filename (datadir);
+ }
+ else
+ {
+ for (i = 0; dirs[i] != NULL && filename == NULL; i++)
+ filename = get_testprint_filename (dirs[i]);
+ }
+
+ if (filename != NULL)
+ {
+ g_autoptr(PpPrinter) printer = NULL;
+
+ printer = pp_printer_new (self->printer_name);
+ pp_printer_print_file_async (printer,
+ filename,
+ /* Translators: Name of job which makes printer to print test page */
+ _("Test Page"),
+ NULL,
+ print_test_page_cb,
+ NULL);
+ }
+ else
+ {
+ g_autoptr(PpMaintenanceCommand) command = NULL;
+
+ command = pp_maintenance_command_new (self->printer_name,
+ "PrintSelfTestPage",
+ NULL,
+ /* Translators: Name of job which makes printer to print test page */
+ _("Test page"));
+
+ pp_maintenance_command_execute_async (command, NULL, pp_maintenance_command_execute_cb, NULL);
+ }
+ }
+}
+
+PpOptionsDialog *
+pp_options_dialog_new (gchar *printer_name,
+ gboolean sensitive)
+{
+ PpOptionsDialog *self;
+
+ self = g_object_new (pp_options_dialog_get_type (),
+ "use-header-bar", 1,
+ NULL);
+
+ self->printer_name = g_strdup (printer_name);
+
+ self->sensitive = sensitive;
+
+ gtk_window_set_title (GTK_WINDOW (self), printer_name);
+
+ populate_options (self);
+
+ return self;
+}
+
+static void
+pp_options_dialog_dispose (GObject *object)
+{
+ PpOptionsDialog *self = PP_OPTIONS_DIALOG (object);
+
+ g_free (self->printer_name);
+ self->printer_name = NULL;
+
+ if (self->ppd_filename)
+ {
+ g_unlink (self->ppd_filename);
+ g_free (self->ppd_filename);
+ self->ppd_filename = NULL;
+ }
+
+ if (self->destination)
+ {
+ cupsFreeDests (1, self->destination);
+ self->destination = NULL;
+ }
+
+ if (self->ipp_attributes)
+ {
+ g_hash_table_unref (self->ipp_attributes);
+ self->ipp_attributes = NULL;
+ }
+
+ G_OBJECT_CLASS (pp_options_dialog_parent_class)->dispose (object);
+}
+
+void
+pp_options_dialog_class_init (PpOptionsDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = pp_options_dialog_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/printers/pp-options-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, PpOptionsDialog, categories_selection);
+ gtk_widget_class_bind_template_child (widget_class, PpOptionsDialog, categories_treeview);
+ gtk_widget_class_bind_template_child (widget_class, PpOptionsDialog, main_box);
+ gtk_widget_class_bind_template_child (widget_class, PpOptionsDialog, notebook);
+ gtk_widget_class_bind_template_child (widget_class, PpOptionsDialog, spinner);
+ gtk_widget_class_bind_template_child (widget_class, PpOptionsDialog, stack);
+
+ gtk_widget_class_bind_template_callback (widget_class, category_selection_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, test_page_cb);
+}
+
+void
+pp_options_dialog_init (PpOptionsDialog *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
diff --git a/panels/printers/pp-options-dialog.h b/panels/printers/pp-options-dialog.h
new file mode 100644
index 0000000..9c881eb
--- /dev/null
+++ b/panels/printers/pp-options-dialog.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marek Kasik <mkasik@redhat.com>
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include "pp-utils.h"
+
+G_BEGIN_DECLS
+
+#define PP_TYPE_OPTIONS_DIALOG (pp_options_dialog_get_type ())
+G_DECLARE_FINAL_TYPE (PpOptionsDialog, pp_options_dialog, PP, OPTIONS_DIALOG, GtkDialog)
+
+PpOptionsDialog *pp_options_dialog_new (gchar *printer_name,
+ gboolean sensitive);
+
+G_END_DECLS
diff --git a/panels/printers/pp-options-dialog.ui b/panels/printers/pp-options-dialog.ui
new file mode 100644
index 0000000..49e6fb9
--- /dev/null
+++ b/panels/printers/pp-options-dialog.ui
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.18.3 -->
+<interface>
+ <requires lib="gtk+" version="3.12"/>
+ <template class="PpOptionsDialog" parent="GtkDialog">
+ <property name="width_request">500</property>
+ <property name="height_request">400</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <child internal-child="headerbar">
+ <object class="GtkHeaderBar">
+ <child>
+ <object class="GtkButton">
+ <property name="label" translatable="yes" comments="Translators: This button triggers the printing of a test page.">Test Page</property>
+ <signal name="clicked" handler="test_page_cb" object="PpOptionsDialog" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="hhomogeneous">True</property>
+ <property name="vhomogeneous">True</property>
+ <child>
+ <object class="GtkBox" id="main_box">
+ <property name="orientation">vertical</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkBox">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="width_request">120</property>
+ <property name="hscrollbar_policy">never</property>
+ <child>
+ <object class="GtkTreeView" id="categories_treeview">
+ <property name="headers_visible">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="categories_selection">
+ <signal name="changed" handler="category_selection_changed_cb" object="PpOptionsDialog" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkNotebook" id="notebook">
+ <property name="tab_pos">left</property>
+ <property name="show_tabs">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSpinner" id="spinner">
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="width_request">24</property>
+ <property name="height_request">24</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/printers/pp-ppd-option-widget.c b/panels/printers/pp-ppd-option-widget.c
new file mode 100644
index 0000000..0375b16
--- /dev/null
+++ b/panels/printers/pp-ppd-option-widget.c
@@ -0,0 +1,535 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marek Kasik <mkasik@redhat.com>
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <glib/gi18n-lib.h>
+#include <glib/gstdio.h>
+
+#include "pp-ppd-option-widget.h"
+#include "pp-utils.h"
+
+static void pp_ppd_option_widget_finalize (GObject *object);
+
+static gboolean construct_widget (PpPPDOptionWidget *self);
+static void update_widget (PpPPDOptionWidget *self);
+static void update_widget_real (PpPPDOptionWidget *self);
+
+struct _PpPPDOptionWidget
+{
+ GtkBox parent_instance;
+
+ GtkWidget *switch_button;
+ GtkWidget *dropdown;
+ GtkWidget *image;
+ GtkWidget *box;
+
+ ppd_option_t *option;
+
+ gchar *printer_name;
+ gchar *option_name;
+
+ cups_dest_t *destination;
+ gboolean destination_set;
+
+ gchar *ppd_filename;
+ gboolean ppd_filename_set;
+
+ GCancellable *cancellable;
+};
+
+G_DEFINE_TYPE (PpPPDOptionWidget, pp_ppd_option_widget, GTK_TYPE_BOX)
+
+/* This list comes from Gtk+ */
+static const struct {
+ const char *keyword;
+ const char *choice;
+ const char *translation;
+} ppd_choice_translations[] = {
+ { "Duplex", "None", N_("One Sided") },
+ /* Translators: this is an option of "Two Sided" */
+ { "Duplex", "DuplexNoTumble", N_("Long Edge (Standard)") },
+ /* Translators: this is an option of "Two Sided" */
+ { "Duplex", "DuplexTumble", N_("Short Edge (Flip)") },
+ /* Translators: this is an option of "Paper Source" */
+ { "InputSlot", "Auto", N_("Auto Select") },
+ /* Translators: this is an option of "Paper Source" */
+ { "InputSlot", "AutoSelect", N_("Auto Select") },
+ /* Translators: this is an option of "Paper Source" */
+ { "InputSlot", "Default", N_("Printer Default") },
+ /* Translators: this is an option of "Paper Source" */
+ { "InputSlot", "None", N_("Printer Default") },
+ /* Translators: this is an option of "Paper Source" */
+ { "InputSlot", "PrinterDefault", N_("Printer Default") },
+ /* Translators: this is an option of "Paper Source" */
+ { "InputSlot", "Unspecified", N_("Auto Select") },
+ /* Translators: this is an option of "Resolution" */
+ { "Resolution", "default", N_("Printer Default") },
+ /* Translators: this is an option of "GhostScript" */
+ { "PreFilter", "EmbedFonts", N_("Embed GhostScript fonts only") },
+ /* Translators: this is an option of "GhostScript" */
+ { "PreFilter", "Level1", N_("Convert to PS level 1") },
+ /* Translators: this is an option of "GhostScript" */
+ { "PreFilter", "Level2", N_("Convert to PS level 2") },
+ /* Translators: this is an option of "GhostScript" */
+ { "PreFilter", "No", N_("No pre-filtering") },
+};
+
+static ppd_option_t *
+cups_option_copy (ppd_option_t *option)
+{
+ ppd_option_t *result;
+ gint i;
+
+ result = g_new0 (ppd_option_t, 1);
+
+ *result = *option;
+
+ result->choices = g_new (ppd_choice_t, result->num_choices);
+ for (i = 0; i < result->num_choices; i++)
+ {
+ result->choices[i] = option->choices[i];
+ result->choices[i].code = g_strdup (option->choices[i].code);
+ result->choices[i].option = result;
+ }
+
+ return result;
+}
+
+static void
+cups_option_free (ppd_option_t *option)
+{
+ gint i;
+
+ if (option)
+ {
+ for (i = 0; i < option->num_choices; i++)
+ g_free (option->choices[i].code);
+
+ g_free (option->choices);
+ g_free (option);
+ }
+}
+
+static void
+pp_ppd_option_widget_class_init (PpPPDOptionWidgetClass *class)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (class);
+
+ object_class->finalize = pp_ppd_option_widget_finalize;
+}
+
+static void
+pp_ppd_option_widget_init (PpPPDOptionWidget *self)
+{
+ gtk_orientable_set_orientation (GTK_ORIENTABLE (self),
+ GTK_ORIENTATION_HORIZONTAL);
+}
+
+static void
+pp_ppd_option_widget_finalize (GObject *object)
+{
+ PpPPDOptionWidget *self = PP_PPD_OPTION_WIDGET (object);
+
+ g_cancellable_cancel (self->cancellable);
+ if (self->ppd_filename)
+ g_unlink (self->ppd_filename);
+
+ g_clear_pointer (&self->option, cups_option_free);
+ g_clear_pointer (&self->printer_name, g_free);
+ g_clear_pointer (&self->option_name, g_free);
+ if (self->destination)
+ {
+ cupsFreeDests (1, self->destination);
+ self->destination = NULL;
+ }
+ g_clear_pointer (&self->ppd_filename, g_free);
+ g_clear_object (&self->cancellable);
+
+ G_OBJECT_CLASS (pp_ppd_option_widget_parent_class)->finalize (object);
+}
+
+static const gchar *
+ppd_choice_translate (ppd_choice_t *choice)
+{
+ const gchar *keyword = choice->option->keyword;
+ gint i;
+
+ for (i = 0; i < G_N_ELEMENTS (ppd_choice_translations); i++)
+ {
+ if (g_strcmp0 (ppd_choice_translations[i].keyword, keyword) == 0 &&
+ g_strcmp0 (ppd_choice_translations[i].choice, choice->choice) == 0)
+ {
+ return _(ppd_choice_translations[i].translation);
+ }
+ }
+
+ return choice->text;
+}
+
+GtkWidget *
+pp_ppd_option_widget_new (ppd_option_t *option,
+ const gchar *printer_name)
+{
+ PpPPDOptionWidget *self = NULL;
+
+ if (option && printer_name)
+ {
+ self = g_object_new (PP_TYPE_PPD_OPTION_WIDGET, NULL);
+
+ self->printer_name = g_strdup (printer_name);
+ self->option = cups_option_copy (option);
+ self->option_name = g_strdup (option->keyword);
+
+ if (construct_widget (self))
+ {
+ update_widget_real (self);
+ }
+ else
+ {
+ g_object_ref_sink (self);
+ g_object_unref (self);
+ self = NULL;
+ }
+ }
+
+ return (GtkWidget *) self;
+}
+
+static GtkWidget *
+dropdown_new (void)
+{
+ GtkStringList *store = NULL;
+ GtkWidget *dropdown;
+
+ store = gtk_string_list_new (NULL);
+
+ dropdown = gtk_drop_down_new (G_LIST_MODEL (store), NULL);
+
+ return dropdown;
+}
+
+static void
+dropdown_append (GtkWidget *dropdown,
+ const gchar *display_text)
+{
+ GtkStringList *store;
+
+ store = GTK_STRING_LIST (gtk_drop_down_get_model (GTK_DROP_DOWN (dropdown)));
+
+ gtk_string_list_append (store, display_text);
+}
+
+static void
+dropdown_set (GtkWidget *dropdown,
+ ppd_option_t *option,
+ const gchar *value)
+{
+ for (guint i = 0; i < option->num_choices; i++)
+ {
+ if (g_strcmp0 (option->choices[i].choice, value) == 0)
+ {
+ gtk_drop_down_set_selected (GTK_DROP_DOWN (dropdown), i);
+ break;
+ }
+ }
+}
+
+static char *
+dropdown_get (GtkWidget *dropdown,
+ ppd_option_t *option)
+{
+ guint selected_item;
+ gchar *value = NULL;
+
+ selected_item = gtk_drop_down_get_selected (GTK_DROP_DOWN (dropdown));
+
+ if (selected_item != GTK_INVALID_LIST_POSITION)
+ {
+ value = option->choices[selected_item].choice;
+ }
+
+ return value;
+}
+
+static void
+printer_add_option_async_cb (gboolean success,
+ gpointer user_data)
+{
+ PpPPDOptionWidget *self = user_data;
+
+ update_widget (user_data);
+ g_clear_object (&self->cancellable);
+}
+
+static void
+switch_changed_cb (PpPPDOptionWidget *self)
+{
+ gchar **values;
+
+ values = g_new0 (gchar *, 2);
+
+ if (gtk_switch_get_active (GTK_SWITCH (self->switch_button)))
+ values[0] = g_strdup ("True");
+ else
+ values[0] = g_strdup ("False");
+
+ g_cancellable_cancel (self->cancellable);
+ g_clear_object (&self->cancellable);
+
+ self->cancellable = g_cancellable_new ();
+ printer_add_option_async (self->printer_name,
+ self->option_name,
+ values,
+ FALSE,
+ self->cancellable,
+ printer_add_option_async_cb,
+ self);
+
+ g_strfreev (values);
+}
+
+static void
+dropdown_changed_cb (PpPPDOptionWidget *self)
+{
+ gchar **values;
+
+ values = g_new0 (gchar *, 2);
+ values[0] = g_strdup (dropdown_get (self->dropdown, self->option));
+
+ g_cancellable_cancel (self->cancellable);
+ g_clear_object (&self->cancellable);
+
+ self->cancellable = g_cancellable_new ();
+ printer_add_option_async (self->printer_name,
+ self->option_name,
+ values,
+ FALSE,
+ self->cancellable,
+ printer_add_option_async_cb,
+ self);
+
+ g_strfreev (values);
+}
+
+static gboolean
+construct_widget (PpPPDOptionWidget *self)
+{
+ gint i;
+
+ /* Don't show options which has only one choice */
+ if (self->option && self->option->num_choices > 1)
+ {
+ switch (self->option->ui)
+ {
+ case PPD_UI_BOOLEAN:
+ self->switch_button = gtk_switch_new ();
+
+ g_signal_connect_object (self->switch_button, "notify::active", G_CALLBACK (switch_changed_cb), self, G_CONNECT_SWAPPED);
+ gtk_box_append (GTK_BOX (self), self->switch_button);
+ break;
+
+ case PPD_UI_PICKONE:
+ self->dropdown = dropdown_new ();
+
+ for (i = 0; i < self->option->num_choices; i++)
+ {
+ dropdown_append (self->dropdown,
+ ppd_choice_translate (&self->option->choices[i]));
+ }
+
+ gtk_box_append (GTK_BOX (self), self->dropdown);
+ g_signal_connect_object (self->dropdown, "notify::selected", G_CALLBACK (dropdown_changed_cb), self, G_CONNECT_SWAPPED);
+ break;
+
+ case PPD_UI_PICKMANY:
+ self->dropdown = dropdown_new ();
+
+ for (i = 0; i < self->option->num_choices; i++)
+ {
+ dropdown_append (self->dropdown,
+ ppd_choice_translate (&self->option->choices[i]));
+ }
+
+ gtk_box_append (GTK_BOX (self), self->dropdown);
+ g_signal_connect_object (self->dropdown, "notify::selected", G_CALLBACK (dropdown_changed_cb), self, G_CONNECT_SWAPPED);
+ break;
+
+ default:
+ break;
+ }
+
+ self->image = gtk_image_new_from_icon_name ("dialog-warning-symbolic");
+ if (!self->image)
+ self->image = gtk_image_new_from_icon_name ("dialog-warning");
+ gtk_box_append (GTK_BOX (self), self->image);
+
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+static void
+update_widget_real (PpPPDOptionWidget *self)
+{
+ ppd_option_t *option = NULL, *iter;
+ ppd_file_t *ppd_file;
+ gint i;
+
+ if (self->ppd_filename_set && self->ppd_filename)
+ {
+ ppd_file = ppdOpenFile (self->ppd_filename);
+ ppdLocalize (ppd_file);
+
+ if (ppd_file)
+ {
+ ppdMarkDefaults (ppd_file);
+
+ for (iter = ppdFirstOption(ppd_file); iter; iter = ppdNextOption(ppd_file))
+ {
+ if (g_str_equal (iter->keyword, self->option_name))
+ {
+ g_clear_pointer (&self->option, cups_option_free);
+ self->option = cups_option_copy (iter);
+ break;
+ }
+ }
+
+ ppdClose (ppd_file);
+ }
+
+ g_unlink (self->ppd_filename);
+ g_free (self->ppd_filename);
+ self->ppd_filename = NULL;
+ }
+
+ option = self->option;
+
+ if (option)
+ {
+ g_autofree gchar *value = NULL;
+
+ for (i = 0; i < option->num_choices; i++)
+ if (option->choices[i].marked)
+ value = g_strdup (option->choices[i].choice);
+
+ if (value == NULL)
+ value = g_strdup (option->defchoice);
+
+ if (value)
+ {
+ switch (option->ui)
+ {
+ case PPD_UI_BOOLEAN:
+ g_signal_handlers_block_by_func (self->switch_button, switch_changed_cb, self);
+ if (g_ascii_strcasecmp (value, "True") == 0)
+ gtk_switch_set_active (GTK_SWITCH (self->switch_button), TRUE);
+ else
+ gtk_switch_set_active (GTK_SWITCH (self->switch_button), FALSE);
+ g_signal_handlers_unblock_by_func (self->switch_button, switch_changed_cb, self);
+ break;
+
+ case PPD_UI_PICKONE:
+ g_signal_handlers_block_by_func (self->dropdown, dropdown_changed_cb, self);
+ dropdown_set (self->dropdown, option, value);
+ g_signal_handlers_unblock_by_func (self->dropdown, dropdown_changed_cb, self);
+ break;
+
+ case PPD_UI_PICKMANY:
+ g_signal_handlers_block_by_func (self->dropdown, dropdown_changed_cb, self);
+ dropdown_set (self->dropdown, option, value);
+ g_signal_handlers_unblock_by_func (self->dropdown, dropdown_changed_cb, self);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (option->conflicted)
+ gtk_widget_show (self->image);
+ else
+ gtk_widget_hide (self->image);
+ }
+}
+
+static void
+get_named_dest_cb (cups_dest_t *dest,
+ gpointer user_data)
+{
+ PpPPDOptionWidget *self = user_data;
+
+ if (self->destination)
+ cupsFreeDests (1, self->destination);
+
+ self->destination = dest;
+ self->destination_set = TRUE;
+
+ if (self->ppd_filename_set)
+ {
+ update_widget_real (self);
+ }
+}
+
+static void
+printer_get_ppd_cb (const gchar *ppd_filename,
+ gpointer user_data)
+{
+ PpPPDOptionWidget *self = user_data;
+
+ if (self->ppd_filename)
+ {
+ g_unlink (self->ppd_filename);
+ g_free (self->ppd_filename);
+ }
+
+ self->ppd_filename = g_strdup (ppd_filename);
+ self->ppd_filename_set = TRUE;
+
+ if (self->destination_set)
+ {
+ update_widget_real (self);
+ }
+}
+
+static void
+update_widget (PpPPDOptionWidget *self)
+{
+ self->ppd_filename_set = FALSE;
+ self->destination_set = FALSE;
+
+ get_named_dest_async (self->printer_name,
+ get_named_dest_cb,
+ self);
+
+ printer_get_ppd_async (self->printer_name,
+ NULL,
+ 0,
+ printer_get_ppd_cb,
+ self);
+}
diff --git a/panels/printers/pp-ppd-option-widget.h b/panels/printers/pp-ppd-option-widget.h
new file mode 100644
index 0000000..b558e51
--- /dev/null
+++ b/panels/printers/pp-ppd-option-widget.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marek Kasik <mkasik@redhat.com>
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <cups/cups.h>
+#include <cups/ppd.h>
+
+G_BEGIN_DECLS
+
+#define PP_TYPE_PPD_OPTION_WIDGET (pp_ppd_option_widget_get_type ())
+G_DECLARE_FINAL_TYPE (PpPPDOptionWidget, pp_ppd_option_widget, PP, PPD_OPTION_WIDGET, GtkBox)
+
+GtkWidget *pp_ppd_option_widget_new (ppd_option_t *source,
+ const gchar *printer_name);
+
+G_END_DECLS
diff --git a/panels/printers/pp-ppd-selection-dialog.c b/panels/printers/pp-ppd-selection-dialog.c
new file mode 100644
index 0000000..13f7274
--- /dev/null
+++ b/panels/printers/pp-ppd-selection-dialog.c
@@ -0,0 +1,378 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marek Kasik <mkasik@redhat.com>
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <gtk/gtk.h>
+
+#include "pp-ppd-selection-dialog.h"
+
+enum
+{
+ PPD_NAMES_COLUMN = 0,
+ PPD_DISPLAY_NAMES_COLUMN
+};
+
+enum
+{
+ PPD_MANUFACTURERS_NAMES_COLUMN = 0,
+ PPD_MANUFACTURERS_DISPLAY_NAMES_COLUMN
+};
+
+
+struct _PpPPDSelectionDialog {
+ GtkDialog parent_instance;
+
+ GtkButton *ppd_selection_select_button;
+ GtkSpinner *ppd_spinner;
+ GtkLabel *progress_label;
+ GtkTreeView *ppd_selection_manufacturers_treeview;
+ GtkTreeView *ppd_selection_models_treeview;
+
+ UserResponseCallback user_callback;
+ gpointer user_data;
+
+ gchar *ppd_name;
+ gchar *ppd_display_name;
+ gchar *manufacturer;
+
+ PPDList *list;
+};
+
+G_DEFINE_TYPE (PpPPDSelectionDialog, pp_ppd_selection_dialog, GTK_TYPE_DIALOG)
+
+static void
+manufacturer_selection_changed_cb (PpPPDSelectionDialog *self)
+{
+ GtkTreeView *treeview;
+ g_autoptr(GtkListStore) store = NULL;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkTreeView *models_treeview;
+ gchar *manufacturer_name = NULL;
+ gint i, index;
+
+ treeview = self->ppd_selection_manufacturers_treeview;
+ if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (treeview), &model, &iter))
+ {
+ gtk_tree_model_get (model, &iter,
+ PPD_MANUFACTURERS_NAMES_COLUMN, &manufacturer_name,
+ -1);
+ }
+
+ if (manufacturer_name)
+ {
+ index = -1;
+ for (i = 0; i < self->list->num_of_manufacturers; i++)
+ {
+ if (g_strcmp0 (manufacturer_name,
+ self->list->manufacturers[i]->manufacturer_name) == 0)
+ {
+ index = i;
+ break;
+ }
+ }
+
+ if (index >= 0)
+ {
+ models_treeview = self->ppd_selection_models_treeview;
+
+ store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
+
+ for (i = 0; i < self->list->manufacturers[index]->num_of_ppds; i++)
+ {
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ PPD_NAMES_COLUMN, self->list->manufacturers[index]->ppds[i]->ppd_name,
+ PPD_DISPLAY_NAMES_COLUMN, self->list->manufacturers[index]->ppds[i]->ppd_display_name,
+ -1);
+ }
+
+ gtk_tree_view_set_model (models_treeview, GTK_TREE_MODEL (store));
+ gtk_tree_view_columns_autosize (models_treeview);
+ }
+
+ g_free (manufacturer_name);
+ }
+}
+
+static void
+model_selection_changed_cb (PpPPDSelectionDialog *self)
+{
+ GtkTreeView *treeview;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkButton *ppd_select_button;
+ gchar *model_name = NULL;
+
+ treeview = self->ppd_selection_models_treeview;
+ if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (treeview), &model, &iter))
+ {
+ gtk_tree_model_get (model, &iter,
+ PPD_NAMES_COLUMN, &model_name,
+ -1);
+ }
+
+ ppd_select_button = self->ppd_selection_select_button;
+
+ if (model_name)
+ {
+ gtk_widget_set_sensitive (GTK_WIDGET (ppd_select_button), TRUE);
+ g_free (model_name);
+ }
+ else
+ {
+ gtk_widget_set_sensitive (GTK_WIDGET (ppd_select_button), FALSE);
+ }
+}
+
+static void
+fill_ppds_list (PpPPDSelectionDialog *self)
+{
+ GtkTreeSelection *selection;
+ g_autoptr(GtkListStore) store = NULL;
+ GtkTreePath *path;
+ GtkTreeView *treeview;
+ GtkTreeIter iter;
+ GtkTreeIter *preselect_iter = NULL;
+ gint i;
+
+ gtk_widget_hide (GTK_WIDGET (self->ppd_spinner));
+ gtk_spinner_stop (self->ppd_spinner);
+
+ gtk_widget_hide (GTK_WIDGET (self->progress_label));
+
+ treeview = self->ppd_selection_manufacturers_treeview;
+
+ if (self->list)
+ {
+ store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
+
+ for (i = 0; i < self->list->num_of_manufacturers; i++)
+ {
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ PPD_MANUFACTURERS_NAMES_COLUMN, self->list->manufacturers[i]->manufacturer_name,
+ PPD_MANUFACTURERS_DISPLAY_NAMES_COLUMN, self->list->manufacturers[i]->manufacturer_display_name,
+ -1);
+
+ if (g_strcmp0 (self->manufacturer,
+ self->list->manufacturers[i]->manufacturer_display_name) == 0)
+ {
+ preselect_iter = gtk_tree_iter_copy (&iter);
+ }
+ }
+
+ gtk_tree_view_set_model (treeview, GTK_TREE_MODEL (store));
+
+ if (preselect_iter &&
+ (selection = gtk_tree_view_get_selection (treeview)) != NULL)
+ {
+ gtk_tree_selection_select_iter (selection, preselect_iter);
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), preselect_iter);
+ gtk_tree_view_scroll_to_cell (treeview, path, NULL, TRUE, 0.5, 0.0);
+ gtk_tree_path_free (path);
+ gtk_tree_iter_free (preselect_iter);
+ }
+ }
+}
+
+static void
+populate_dialog (PpPPDSelectionDialog *self)
+{
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+ GtkTreeView *manufacturers_treeview;
+ GtkTreeView *models_treeview;
+ GtkWidget *header;
+
+ manufacturers_treeview = self->ppd_selection_manufacturers_treeview;
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_renderer_set_padding (renderer, 10, 0);
+
+ /* Translators: Name of column showing printer manufacturers */
+ column = gtk_tree_view_column_new_with_attributes (_("Manufacturer"), renderer,
+ "text", PPD_MANUFACTURERS_DISPLAY_NAMES_COLUMN, NULL);
+ gtk_tree_view_column_set_expand (column, TRUE);
+ header = gtk_label_new (gtk_tree_view_column_get_title (column));
+ gtk_widget_set_margin_start (header, 10);
+ gtk_tree_view_column_set_widget (column, header);
+ gtk_widget_show (header);
+ gtk_tree_view_append_column (manufacturers_treeview, column);
+
+
+ models_treeview = self->ppd_selection_models_treeview;
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_renderer_set_padding (renderer, 10, 0);
+
+ /* Translators: Name of column showing printer drivers */
+ column = gtk_tree_view_column_new_with_attributes (_("Driver"), renderer,
+ "text", PPD_DISPLAY_NAMES_COLUMN,
+ NULL);
+ gtk_tree_view_column_set_expand (column, TRUE);
+ header = gtk_label_new (gtk_tree_view_column_get_title (column));
+ gtk_widget_set_margin_start (header, 10);
+ gtk_tree_view_column_set_widget (column, header);
+ gtk_widget_show (header);
+ gtk_tree_view_append_column (models_treeview, column);
+
+
+ g_signal_connect_object (gtk_tree_view_get_selection (models_treeview),
+ "changed", G_CALLBACK (model_selection_changed_cb), self, G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (gtk_tree_view_get_selection (manufacturers_treeview),
+ "changed", G_CALLBACK (manufacturer_selection_changed_cb), self, G_CONNECT_SWAPPED);
+
+ if (!self->list)
+ {
+ gtk_widget_show (GTK_WIDGET (self->ppd_spinner));
+ gtk_spinner_start (self->ppd_spinner);
+
+ gtk_widget_show (GTK_WIDGET (self->progress_label));
+ }
+ else
+ {
+ fill_ppds_list (self);
+ }
+}
+
+static void
+ppd_selection_dialog_response_cb (PpPPDSelectionDialog *self,
+ gint response_id)
+{
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreeView *models_treeview;
+ GtkTreeIter iter;
+
+ if (response_id == GTK_RESPONSE_OK)
+ {
+ models_treeview = self->ppd_selection_models_treeview;
+
+ if (models_treeview)
+ {
+ selection = gtk_tree_view_get_selection (models_treeview);
+
+ if (selection)
+ {
+ if (gtk_tree_selection_get_selected (selection, &model, &iter))
+ {
+ gtk_tree_model_get (model, &iter,
+ PPD_NAMES_COLUMN, &self->ppd_name,
+ PPD_DISPLAY_NAMES_COLUMN, &self->ppd_display_name,
+ -1);
+ }
+ }
+ }
+ }
+
+ self->user_callback (GTK_DIALOG (self), response_id, self->user_data);
+}
+
+PpPPDSelectionDialog *
+pp_ppd_selection_dialog_new (PPDList *ppd_list,
+ const gchar *manufacturer,
+ UserResponseCallback user_callback,
+ gpointer user_data)
+{
+ PpPPDSelectionDialog *self;
+
+ self = g_object_new (pp_ppd_selection_dialog_get_type (), NULL);
+
+ self->user_callback = user_callback;
+ self->user_data = user_data;
+
+ self->list = ppd_list_copy (ppd_list);
+
+ self->manufacturer = get_standard_manufacturers_name (manufacturer);
+
+ /* connect signal */
+ g_signal_connect_object (self, "response", G_CALLBACK (ppd_selection_dialog_response_cb), self, G_CONNECT_SWAPPED);
+
+ gtk_spinner_start (self->ppd_spinner);
+
+ populate_dialog (self);
+
+ return self;
+}
+
+static void
+pp_ppd_selection_dialog_dispose (GObject *object)
+{
+ PpPPDSelectionDialog *self = PP_PPD_SELECTION_DIALOG (object);
+
+ g_clear_pointer (&self->ppd_name, g_free);
+ g_clear_pointer (&self->ppd_display_name, g_free);
+ g_clear_pointer (&self->manufacturer, g_free);
+
+ G_OBJECT_CLASS (pp_ppd_selection_dialog_parent_class)->dispose (object);
+}
+
+void
+pp_ppd_selection_dialog_class_init (PpPPDSelectionDialogClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/printers/ppd-selection-dialog.ui");
+ gtk_widget_class_bind_template_child (widget_class, PpPPDSelectionDialog, ppd_selection_select_button);
+ gtk_widget_class_bind_template_child (widget_class, PpPPDSelectionDialog, ppd_spinner);
+ gtk_widget_class_bind_template_child (widget_class, PpPPDSelectionDialog, progress_label);
+ gtk_widget_class_bind_template_child (widget_class, PpPPDSelectionDialog, ppd_selection_manufacturers_treeview);
+ gtk_widget_class_bind_template_child (widget_class, PpPPDSelectionDialog, ppd_selection_models_treeview);
+
+ object_class->dispose = pp_ppd_selection_dialog_dispose;
+}
+
+void
+pp_ppd_selection_dialog_init (PpPPDSelectionDialog *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+gchar *
+pp_ppd_selection_dialog_get_ppd_name (PpPPDSelectionDialog *self)
+{
+ return g_strdup (self->ppd_name);
+}
+
+gchar *
+pp_ppd_selection_dialog_get_ppd_display_name (PpPPDSelectionDialog *self)
+{
+ return g_strdup (self->ppd_display_name);
+}
+
+void
+pp_ppd_selection_dialog_set_ppd_list (PpPPDSelectionDialog *self,
+ PPDList *list)
+{
+ self->list = list;
+ fill_ppds_list (self);
+}
diff --git a/panels/printers/pp-ppd-selection-dialog.h b/panels/printers/pp-ppd-selection-dialog.h
new file mode 100644
index 0000000..5b4ee22
--- /dev/null
+++ b/panels/printers/pp-ppd-selection-dialog.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marek Kasik <mkasik@redhat.com>
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include "pp-utils.h"
+
+G_BEGIN_DECLS
+
+#define PP_TYPE_PPD_SELECTION_DIALOG (pp_ppd_selection_dialog_get_type ())
+G_DECLARE_FINAL_TYPE (PpPPDSelectionDialog, pp_ppd_selection_dialog, PP, PPD_SELECTION_DIALOG, GtkDialog)
+
+PpPPDSelectionDialog *pp_ppd_selection_dialog_new (PPDList *ppd_list,
+ const gchar *manufacturer,
+ UserResponseCallback user_callback,
+ gpointer user_data);
+gchar *pp_ppd_selection_dialog_get_ppd_name (PpPPDSelectionDialog *dialog);
+gchar *pp_ppd_selection_dialog_get_ppd_display_name (PpPPDSelectionDialog *dialog);
+void pp_ppd_selection_dialog_set_ppd_list (PpPPDSelectionDialog *dialog,
+ PPDList *list);
+
+G_END_DECLS
diff --git a/panels/printers/pp-print-device.c b/panels/printers/pp-print-device.c
new file mode 100644
index 0000000..3ab0b07
--- /dev/null
+++ b/panels/printers/pp-print-device.c
@@ -0,0 +1,450 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2015 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marek Kasik <mkasik@redhat.com>
+ */
+
+#include "pp-print-device.h"
+
+struct _PpPrintDevice
+{
+ GObject parent_instance;
+
+ gchar *device_name;
+ gchar *display_name;
+ gchar *device_original_name;
+ gchar *device_make_and_model;
+ gchar *device_location;
+ gchar *device_info;
+ gchar *device_uri;
+ gchar *device_id;
+ gchar *device_ppd;
+ gchar *host_name;
+ gint host_port;
+ gboolean is_authenticated_server;
+ gint acquisition_method;
+ gboolean is_network_device;
+};
+
+G_DEFINE_TYPE (PpPrintDevice, pp_print_device, G_TYPE_OBJECT);
+
+enum
+{
+ PROP_0 = 0,
+ PROP_DEVICE_NAME,
+ PROP_DISPLAY_NAME,
+ PROP_DEVICE_ORIGINAL_NAME,
+ PROP_DEVICE_MAKE_AND_MODEL,
+ PROP_DEVICE_LOCATION,
+ PROP_DEVICE_INFO,
+ PROP_DEVICE_URI,
+ PROP_DEVICE_ID,
+ PROP_DEVICE_PPD,
+ PROP_HOST_NAME,
+ PROP_HOST_PORT,
+ PROP_IS_AUTHENTICATED_SERVER,
+ PROP_ACQUISITION_METHOD,
+ PROP_IS_NETWORK_DEVICE
+};
+
+static void
+pp_print_device_finalize (GObject *object)
+{
+ PpPrintDevice *self = PP_PRINT_DEVICE (object);
+
+ g_clear_pointer (&self->device_name, g_free);
+ g_clear_pointer (&self->display_name, g_free);
+ g_clear_pointer (&self->device_original_name, g_free);
+ g_clear_pointer (&self->device_make_and_model, g_free);
+ g_clear_pointer (&self->device_location, g_free);
+ g_clear_pointer (&self->device_info, g_free);
+ g_clear_pointer (&self->device_uri, g_free);
+ g_clear_pointer (&self->device_id, g_free);
+ g_clear_pointer (&self->device_ppd, g_free);
+ g_clear_pointer (&self->host_name, g_free);
+
+ G_OBJECT_CLASS (pp_print_device_parent_class)->finalize (object);
+}
+
+static void
+pp_print_device_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *param_spec)
+{
+ PpPrintDevice *self = PP_PRINT_DEVICE (object);
+
+ switch (prop_id)
+ {
+ case PROP_DEVICE_NAME:
+ g_value_set_string (value, self->device_name);
+ break;
+ case PROP_DISPLAY_NAME:
+ g_value_set_string (value, self->display_name);
+ break;
+ case PROP_DEVICE_ORIGINAL_NAME:
+ g_value_set_string (value, self->device_original_name);
+ break;
+ case PROP_DEVICE_MAKE_AND_MODEL:
+ g_value_set_string (value, self->device_make_and_model);
+ break;
+ case PROP_DEVICE_LOCATION:
+ g_value_set_string (value, self->device_location);
+ break;
+ case PROP_DEVICE_INFO:
+ g_value_set_string (value, self->device_info);
+ break;
+ case PROP_DEVICE_URI:
+ g_value_set_string (value, self->device_uri);
+ break;
+ case PROP_DEVICE_ID:
+ g_value_set_string (value, self->device_id);
+ break;
+ case PROP_DEVICE_PPD:
+ g_value_set_string (value, self->device_ppd);
+ break;
+ case PROP_HOST_NAME:
+ g_value_set_string (value, self->host_name);
+ break;
+ case PROP_HOST_PORT:
+ g_value_set_int (value, self->host_port);
+ break;
+ case PROP_IS_AUTHENTICATED_SERVER:
+ g_value_set_boolean (value, self->is_authenticated_server);
+ break;
+ case PROP_ACQUISITION_METHOD:
+ g_value_set_int (value, self->acquisition_method);
+ break;
+ case PROP_IS_NETWORK_DEVICE:
+ g_value_set_boolean (value, self->is_network_device);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
+ prop_id,
+ param_spec);
+ break;
+ }
+}
+
+static void
+pp_print_device_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *param_spec)
+{
+ PpPrintDevice *self = PP_PRINT_DEVICE (object);
+
+ switch (prop_id)
+ {
+ case PROP_DEVICE_NAME:
+ g_free (self->device_name);
+ self->device_name = g_value_dup_string (value);
+ break;
+ case PROP_DISPLAY_NAME:
+ g_free (self->display_name);
+ self->display_name = g_value_dup_string (value);
+ break;
+ case PROP_DEVICE_ORIGINAL_NAME:
+ g_free (self->device_original_name);
+ self->device_original_name = g_value_dup_string (value);
+ break;
+ case PROP_DEVICE_MAKE_AND_MODEL:
+ g_free (self->device_make_and_model);
+ self->device_make_and_model = g_value_dup_string (value);
+ break;
+ case PROP_DEVICE_LOCATION:
+ g_free (self->device_location);
+ self->device_location = g_value_dup_string (value);
+ break;
+ case PROP_DEVICE_INFO:
+ g_free (self->device_info);
+ self->device_info = g_value_dup_string (value);
+ break;
+ case PROP_DEVICE_URI:
+ g_free (self->device_uri);
+ self->device_uri = g_value_dup_string (value);
+ break;
+ case PROP_DEVICE_ID:
+ g_free (self->device_id);
+ self->device_id = g_value_dup_string (value);
+ break;
+ case PROP_DEVICE_PPD:
+ g_free (self->device_ppd);
+ self->device_ppd = g_value_dup_string (value);
+ break;
+ case PROP_HOST_NAME:
+ g_free (self->host_name);
+ self->host_name = g_value_dup_string (value);
+ break;
+ case PROP_HOST_PORT:
+ self->host_port = g_value_get_int (value);
+ break;
+ case PROP_IS_AUTHENTICATED_SERVER:
+ self->is_authenticated_server = g_value_get_boolean (value);
+ break;
+ case PROP_ACQUISITION_METHOD:
+ self->acquisition_method = g_value_get_int (value);
+ break;
+ case PROP_IS_NETWORK_DEVICE:
+ self->is_network_device = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
+ prop_id,
+ param_spec);
+ break;
+ }
+}
+
+static void
+pp_print_device_class_init (PpPrintDeviceClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->set_property = pp_print_device_set_property;
+ gobject_class->get_property = pp_print_device_get_property;
+
+ gobject_class->finalize = pp_print_device_finalize;
+
+ g_object_class_install_property (gobject_class,
+ PROP_DEVICE_NAME,
+ g_param_spec_string ("device-name",
+ "Device name",
+ "Name of the device",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_DISPLAY_NAME,
+ g_param_spec_string ("display-name",
+ "Display name",
+ "Name of the device formatted for users",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_DEVICE_ORIGINAL_NAME,
+ g_param_spec_string ("device-original-name",
+ "Device original name",
+ "Original name of the device",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_DEVICE_MAKE_AND_MODEL,
+ g_param_spec_string ("device-make-and-model",
+ "Device make and model",
+ "Make and model of the device",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_DEVICE_LOCATION,
+ g_param_spec_string ("device-location",
+ "Device location",
+ "Locaton of the device",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_DEVICE_INFO,
+ g_param_spec_string ("device-info",
+ "Device info",
+ "Information about the device",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_DEVICE_URI,
+ g_param_spec_string ("device-uri",
+ "Device URI",
+ "URI of the device",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_DEVICE_ID,
+ g_param_spec_string ("device-id",
+ "DeviceID",
+ "DeviceID of the device",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_DEVICE_PPD,
+ g_param_spec_string ("device-ppd",
+ "Device PPD",
+ "Name of the PPD of the device",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_HOST_NAME,
+ g_param_spec_string ("host-name",
+ "Host name",
+ "Hostname of the device",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_HOST_PORT,
+ g_param_spec_int ("host-port",
+ "Host port",
+ "The port of the host",
+ 0, G_MAXINT32, 0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_IS_AUTHENTICATED_SERVER,
+ g_param_spec_boolean ("is-authenticated-server",
+ "Is authenticated server",
+ "Whether the device is a server which needs authentication",
+ FALSE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_ACQUISITION_METHOD,
+ g_param_spec_int ("acquisition-method",
+ "Acquisition method",
+ "Acquisition method of the device",
+ 0, G_MAXINT32, 0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_IS_NETWORK_DEVICE,
+ g_param_spec_boolean ("is-network-device",
+ "Network device",
+ "Whether the device is a network device",
+ FALSE,
+ G_PARAM_READWRITE));
+}
+
+static void
+pp_print_device_init (PpPrintDevice *self)
+{
+}
+
+PpPrintDevice *
+pp_print_device_new ()
+{
+ return g_object_new (PP_TYPE_PRINT_DEVICE, NULL);
+}
+
+gchar *
+pp_print_device_get_device_name (PpPrintDevice *self)
+{
+ return self->device_name;
+}
+
+gchar *
+pp_print_device_get_display_name (PpPrintDevice *self)
+{
+ return self->display_name;
+}
+
+gchar *
+pp_print_device_get_device_original_name (PpPrintDevice *self)
+{
+ return self->device_original_name;
+}
+
+gchar *
+pp_print_device_get_device_make_and_model (PpPrintDevice *self)
+{
+ return self->device_make_and_model;
+}
+
+gchar *
+pp_print_device_get_device_location (PpPrintDevice *self)
+{
+ return self->device_location;
+}
+
+gchar *
+pp_print_device_get_device_info (PpPrintDevice *self)
+{
+ return self->device_info;
+}
+
+gchar *
+pp_print_device_get_device_uri (PpPrintDevice *self)
+{
+ return self->device_uri;
+}
+
+gchar *
+pp_print_device_get_device_id (PpPrintDevice *self)
+{
+ return self->device_id;
+}
+
+gchar *
+pp_print_device_get_device_ppd (PpPrintDevice *self)
+{
+ return self->device_ppd;
+}
+
+gchar *
+pp_print_device_get_host_name (PpPrintDevice *self)
+{
+ return self->host_name;
+}
+
+gint
+pp_print_device_get_host_port (PpPrintDevice *self)
+{
+ return self->host_port;
+}
+
+gboolean
+pp_print_device_is_authenticated_server (PpPrintDevice *self)
+{
+ return self->is_authenticated_server;
+}
+
+gint
+pp_print_device_get_acquisition_method (PpPrintDevice *self)
+{
+ return self->acquisition_method;
+}
+
+gboolean
+pp_print_device_is_network_device (PpPrintDevice *self)
+{
+ return self->is_network_device;
+}
+
+PpPrintDevice *
+pp_print_device_copy (PpPrintDevice *self)
+{
+ return g_object_new (PP_TYPE_PRINT_DEVICE,
+ "device-name", pp_print_device_get_device_name (self),
+ "display-name", pp_print_device_get_display_name (self),
+ "device-original-name", pp_print_device_get_device_original_name (self),
+ "device-make-and-model", pp_print_device_get_device_make_and_model (self),
+ "device-location", pp_print_device_get_device_location (self),
+ "device-info", pp_print_device_get_device_info (self),
+ "device-uri", pp_print_device_get_device_uri (self),
+ "device-id", pp_print_device_get_device_id (self),
+ "device-ppd", pp_print_device_get_device_ppd (self),
+ "host-name", pp_print_device_get_host_name (self),
+ "host-port", pp_print_device_get_host_port (self),
+ "is-authenticated-server", pp_print_device_is_authenticated_server (self),
+ "acquisition-method", pp_print_device_get_acquisition_method (self),
+ "is-network-device", pp_print_device_is_network_device (self),
+ NULL);
+}
diff --git a/panels/printers/pp-print-device.h b/panels/printers/pp-print-device.h
new file mode 100644
index 0000000..a271254
--- /dev/null
+++ b/panels/printers/pp-print-device.h
@@ -0,0 +1,48 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2015 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marek Kasik <mkasik@redhat.com>
+ */
+
+#pragma once
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define PP_TYPE_PRINT_DEVICE (pp_print_device_get_type ())
+G_DECLARE_FINAL_TYPE (PpPrintDevice, pp_print_device, PP, PRINT_DEVICE, GObject)
+
+PpPrintDevice *pp_print_device_new (void);
+PpPrintDevice *pp_print_device_copy (PpPrintDevice *device);
+gchar *pp_print_device_get_device_name (PpPrintDevice *device);
+gchar *pp_print_device_get_display_name (PpPrintDevice *device);
+gchar *pp_print_device_get_device_original_name (PpPrintDevice *device);
+gchar *pp_print_device_get_device_make_and_model (PpPrintDevice *device);
+gchar *pp_print_device_get_device_location (PpPrintDevice *device);
+gchar *pp_print_device_get_device_info (PpPrintDevice *device);
+gchar *pp_print_device_get_device_uri (PpPrintDevice *device);
+gchar *pp_print_device_get_device_id (PpPrintDevice *device);
+gchar *pp_print_device_get_device_ppd (PpPrintDevice *device);
+gchar *pp_print_device_get_host_name (PpPrintDevice *device);
+gint pp_print_device_get_host_port (PpPrintDevice *device);
+gboolean pp_print_device_is_authenticated_server (PpPrintDevice *device);
+gint pp_print_device_get_acquisition_method (PpPrintDevice *device);
+gboolean pp_print_device_is_network_device (PpPrintDevice *device);
+
+G_END_DECLS
diff --git a/panels/printers/pp-printer-entry.c b/panels/printers/pp-printer-entry.c
new file mode 100644
index 0000000..ba87004
--- /dev/null
+++ b/panels/printers/pp-printer-entry.c
@@ -0,0 +1,1022 @@
+/*
+ * Copyright 2017 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Felipe Borges <felipeborges@gnome.org>
+ */
+
+#include <config.h>
+
+#include "pp-printer-entry.h"
+#include <gtk/gtk.h>
+#include <glib/gi18n-lib.h>
+#include <glib/gstdio.h>
+
+#include "pp-details-dialog.h"
+#include "pp-maintenance-command.h"
+#include "pp-options-dialog.h"
+#include "pp-jobs-dialog.h"
+#include "pp-printer.h"
+#include "pp-utils.h"
+
+#define SUPPLY_BAR_HEIGHT 8
+
+typedef struct
+{
+ gchar *marker_names;
+ gchar *marker_levels;
+ gchar *marker_colors;
+ gchar *marker_types;
+} InkLevelData;
+
+struct _PpPrinterEntry
+{
+ GtkListBoxRow parent;
+
+ gchar *printer_name;
+ gboolean is_accepting_jobs;
+ gchar *printer_make_and_model;
+ gchar *printer_location;
+ gchar *printer_hostname;
+ gboolean is_authorized;
+ gint printer_state;
+ InkLevelData *inklevel;
+
+ /* Maintenance commands */
+ PpMaintenanceCommand *clean_command;
+ GCancellable *check_clean_heads_cancellable;
+
+ /* Widgets */
+ GtkImage *printer_icon;
+ GtkLabel *printer_status;
+ GtkLabel *printer_name_label;
+ GtkLabel *printer_model_label;
+ GtkLabel *printer_model;
+ GtkLabel *printer_location_label;
+ GtkLabel *printer_location_address_label;
+ GtkLabel *printer_inklevel_label;
+ GtkFrame *supply_frame;
+ GtkDrawingArea *supply_drawing_area;
+ GtkWidget *show_jobs_dialog_button;
+ GtkWidget *clean_heads_menuitem;
+ GtkCheckButton *printer_default_checkbutton;
+ GtkWidget *remove_printer_menuitem;
+ GtkBox *printer_error;
+ GtkLabel *error_status;
+
+ /* Dialogs */
+ PpJobsDialog *pp_jobs_dialog;
+
+ GCancellable *get_jobs_cancellable;
+};
+
+struct _PpPrinterEntryClass
+{
+ GtkListBoxRowClass parent_class;
+
+ void (*printer_changed) (PpPrinterEntry *printer_entry);
+ void (*printer_delete) (PpPrinterEntry *printer_entry);
+ void (*printer_renamed) (PpPrinterEntry *printer_entry, const gchar *new_name);
+};
+
+G_DEFINE_TYPE (PpPrinterEntry, pp_printer_entry, GTK_TYPE_LIST_BOX_ROW)
+
+enum {
+ IS_DEFAULT_PRINTER,
+ PRINTER_DELETE,
+ PRINTER_RENAMED,
+ LAST_SIGNAL,
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static InkLevelData *
+ink_level_data_new (void)
+{
+ return g_slice_new0 (InkLevelData);
+}
+
+static void
+ink_level_data_free (InkLevelData *data)
+{
+ g_clear_pointer (&data->marker_names, g_free);
+ g_clear_pointer (&data->marker_levels, g_free);
+ g_clear_pointer (&data->marker_colors, g_free);
+ g_clear_pointer (&data->marker_types, g_free);
+ g_slice_free (InkLevelData, data);
+}
+
+static void
+pp_printer_entry_init (PpPrinterEntry *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+ self->inklevel = ink_level_data_new ();
+}
+
+typedef struct {
+ gchar *color;
+ gchar *type;
+ gchar *name;
+ gint level;
+} MarkerItem;
+
+static gint
+markers_cmp (gconstpointer a,
+ gconstpointer b)
+{
+ MarkerItem *x = (MarkerItem*) a;
+ MarkerItem *y = (MarkerItem*) b;
+
+ if (x->level < y->level)
+ return 1;
+ else if (x->level == y->level)
+ return 0;
+ else
+ return -1;
+}
+
+static gchar *
+sanitize_printer_model (const gchar *printer_make_and_model)
+{
+ gchar *breakpoint = NULL, *tmp2 = NULL;
+ g_autofree gchar *tmp = NULL;
+ gchar backup;
+ size_t length = 0;
+ gchar *forbidden[] = {
+ "foomatic",
+ ",",
+ "hpijs",
+ "hpcups",
+ "(recommended)",
+ "postscript (recommended)",
+ NULL };
+ int i;
+
+ tmp = g_ascii_strdown (printer_make_and_model, -1);
+
+ for (i = 0; i < g_strv_length (forbidden); i++)
+ {
+ tmp2 = g_strrstr (tmp, forbidden[i]);
+ if (breakpoint == NULL ||
+ (tmp2 != NULL && tmp2 < breakpoint))
+ breakpoint = tmp2;
+ }
+
+ if (breakpoint)
+ {
+ backup = *breakpoint;
+ *breakpoint = '\0';
+ length = strlen (tmp);
+ *breakpoint = backup;
+
+ if (length > 0)
+ return g_strndup (printer_make_and_model, length);
+ }
+ else
+ return g_strdup (printer_make_and_model);
+
+ return NULL;
+}
+
+static gboolean
+supply_level_is_empty (PpPrinterEntry *self)
+{
+ return !((self->inklevel->marker_levels != NULL) &&
+ (self->inklevel->marker_colors != NULL) &&
+ (self->inklevel->marker_names != NULL) &&
+ (self->inklevel->marker_types != NULL));
+}
+
+/* To tone down the colors in the supply level bar
+ * we shade them by darkening the hue.
+ *
+ * Obs.: we don't know whether the color is already
+ * shaded.
+ *
+ */
+static void
+tone_down_color (GdkRGBA *color,
+ gdouble hue_ratio,
+ gdouble saturation_ratio,
+ gdouble value_ratio)
+{
+ gfloat h, s, v;
+
+ gtk_rgb_to_hsv (color->red, color->green, color->blue,
+ &h, &s, &v);
+ gtk_hsv_to_rgb (h * hue_ratio, s * saturation_ratio, v * value_ratio,
+ &color->red, &color->green, &color->blue);
+}
+
+static void
+supply_levels_draw_cb (GtkDrawingArea *drawing_area,
+ cairo_t *cr,
+ int width,
+ int height,
+ gpointer user_data)
+{
+ PpPrinterEntry *self = PP_PRINTER_ENTRY (user_data);
+ GtkStyleContext *context;
+ gboolean is_empty = TRUE;
+ g_autofree gchar *tooltip_text = NULL;
+ int i;
+
+ context = gtk_widget_get_style_context (GTK_WIDGET (self->supply_drawing_area));
+
+ gtk_render_background (context, cr, 0, 0, width, height);
+
+ if (!supply_level_is_empty (self))
+ {
+ GSList *markers = NULL;
+ GSList *tmp_list = NULL;
+ gchar **marker_levelsv = NULL;
+ gchar **marker_colorsv = NULL;
+ gchar **marker_namesv = NULL;
+ gchar **marker_typesv = NULL;
+
+ gtk_style_context_save (context);
+
+ marker_levelsv = g_strsplit (self->inklevel->marker_levels, ",", -1);
+ marker_colorsv = g_strsplit (self->inklevel->marker_colors, ",", -1);
+ marker_namesv = g_strsplit (self->inklevel->marker_names, ",", -1);
+ marker_typesv = g_strsplit (self->inklevel->marker_types, ",", -1);
+
+ if (g_strv_length (marker_levelsv) == g_strv_length (marker_colorsv) &&
+ g_strv_length (marker_colorsv) == g_strv_length (marker_namesv) &&
+ g_strv_length (marker_namesv) == g_strv_length (marker_typesv))
+ {
+ for (i = 0; i < g_strv_length (marker_levelsv); i++)
+ {
+ MarkerItem *marker;
+
+ if (g_strcmp0 (marker_typesv[i], "ink") == 0 ||
+ g_strcmp0 (marker_typesv[i], "toner") == 0 ||
+ g_strcmp0 (marker_typesv[i], "inkCartridge") == 0 ||
+ g_strcmp0 (marker_typesv[i], "tonerCartridge") == 0)
+ {
+ marker = g_new0 (MarkerItem, 1);
+ marker->type = g_strdup (marker_typesv[i]);
+ marker->name = g_strdup (marker_namesv[i]);
+ marker->color = g_strdup (marker_colorsv[i]);
+ marker->level = atoi (marker_levelsv[i]);
+
+ markers = g_slist_prepend (markers, marker);
+ }
+ }
+
+ markers = g_slist_sort (markers, markers_cmp);
+
+ for (tmp_list = markers; tmp_list; tmp_list = tmp_list->next)
+ {
+ GdkRGBA color = {0.0, 0.0, 0.0, 1.0};
+ double display_value;
+ int value;
+
+ value = ((MarkerItem*) tmp_list->data)->level;
+
+ gdk_rgba_parse (&color, ((MarkerItem*) tmp_list->data)->color);
+ tone_down_color (&color, 1.0, 0.6, 0.9);
+
+ if (value > 0)
+ {
+ display_value = value / 100.0 * (width - 3.0);
+ gdk_cairo_set_source_rgba (cr, &color);
+ cairo_rectangle (cr, 2.0, 2.0, display_value, SUPPLY_BAR_HEIGHT);
+ cairo_fill (cr);
+
+ tone_down_color (&color, 1.0, 1.0, 0.85);
+ gdk_cairo_set_source_rgba (cr, &color);
+ cairo_set_line_width (cr, 1.0);
+ cairo_rectangle (cr, 1.5, 1.5, display_value, SUPPLY_BAR_HEIGHT + 1);
+ cairo_stroke (cr);
+
+ is_empty = FALSE;
+ }
+
+ if (tooltip_text)
+ {
+ g_autofree gchar *old_tooltip_text = g_steal_pointer (&tooltip_text);
+ tooltip_text = g_strdup_printf ("%s\n%s",
+ old_tooltip_text,
+ ((MarkerItem*) tmp_list->data)->name);
+ }
+ else
+ tooltip_text = g_strdup_printf ("%s",
+ ((MarkerItem*) tmp_list->data)->name);
+ }
+
+ gtk_render_frame (context, cr, 1, 1, width - 1, SUPPLY_BAR_HEIGHT);
+
+ for (tmp_list = markers; tmp_list; tmp_list = tmp_list->next)
+ {
+ g_free (((MarkerItem*) tmp_list->data)->name);
+ g_free (((MarkerItem*) tmp_list->data)->type);
+ g_free (((MarkerItem*) tmp_list->data)->color);
+ }
+ g_slist_free_full (markers, g_free);
+ }
+
+ gtk_style_context_restore (context);
+
+ if (tooltip_text)
+ {
+ gtk_widget_set_tooltip_text (GTK_WIDGET (self->supply_drawing_area), tooltip_text);
+ }
+ else
+ {
+ gtk_widget_set_tooltip_text (GTK_WIDGET (self->supply_drawing_area), NULL);
+ gtk_widget_set_has_tooltip (GTK_WIDGET (self->supply_drawing_area), FALSE);
+ }
+ }
+
+ gtk_widget_set_visible (GTK_WIDGET (self->printer_inklevel_label), !is_empty);
+ gtk_widget_set_visible (GTK_WIDGET (self->supply_frame), !is_empty);
+}
+
+static void
+on_printer_rename_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ PpPrinterEntry *self = user_data;
+
+ if (!pp_printer_rename_finish (PP_PRINTER (source_object), result, NULL))
+ return;
+
+ g_signal_emit_by_name (self, "printer-renamed", pp_printer_get_name (PP_PRINTER (source_object)));
+}
+
+static void
+show_printer_details_response_cb (PpDetailsDialog *dialog,
+ gint reponse,
+ PpPrinterEntry *self)
+{
+ const gchar *new_name;
+ const gchar *new_location;
+
+ new_location = pp_details_dialog_get_printer_location (dialog);
+ if (g_strcmp0 (self->printer_location, new_location) != 0)
+ printer_set_location (self->printer_name, new_location);
+
+ new_name = pp_details_dialog_get_printer_name (dialog);
+ if (g_strcmp0 (self->printer_name, new_name) != 0 && printer_name_is_valid (new_name))
+ {
+ g_autoptr(PpPrinter) printer = pp_printer_new (self->printer_name);
+
+ pp_printer_rename_async (printer,
+ new_name,
+ NULL,
+ on_printer_rename_cb,
+ self);
+ }
+
+ g_signal_emit_by_name (self, "printer-changed");
+
+ gtk_window_destroy (GTK_WINDOW (dialog));
+}
+
+static void
+on_show_printer_details_dialog (GtkButton *button,
+ PpPrinterEntry *self)
+{
+ PpDetailsDialog *dialog = pp_details_dialog_new (self->printer_name,
+ self->printer_location,
+ self->printer_hostname,
+ self->printer_make_and_model,
+ self->is_authorized);
+
+ gtk_window_set_transient_for (GTK_WINDOW (dialog),
+ GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (self))));
+
+ g_signal_connect (dialog, "response", G_CALLBACK (show_printer_details_response_cb), self);
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+static void
+on_show_printer_options_dialog (GtkButton *button,
+ PpPrinterEntry *self)
+{
+ PpOptionsDialog *dialog;
+
+ dialog = pp_options_dialog_new (self->printer_name, self->is_authorized);
+
+ gtk_window_set_transient_for (GTK_WINDOW (dialog),
+ GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (self))));
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+static void
+set_as_default_printer (GtkCheckButton *button,
+ PpPrinterEntry *self)
+{
+ printer_set_default (self->printer_name);
+
+ g_signal_emit_by_name (self, "printer-changed");
+}
+
+static void
+check_clean_heads_maintenance_command_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ PpPrinterEntry *self = user_data;
+ gboolean is_supported = FALSE;
+ g_autoptr(GError) error = NULL;
+
+ is_supported = pp_maintenance_command_is_supported_finish (PP_MAINTENANCE_COMMAND (source_object), res, &error);
+ if (error != NULL)
+ {
+ g_debug ("Could not check 'Clean' maintenance command: %s", error->message);
+ return;
+ }
+
+ if (is_supported)
+ {
+ gtk_widget_show (GTK_WIDGET (self->clean_heads_menuitem));
+ }
+}
+
+static void
+check_clean_heads_maintenance_command (PpPrinterEntry *self)
+{
+ if (self->clean_command == NULL)
+ return;
+
+ g_object_ref (self->clean_command);
+ self->check_clean_heads_cancellable = g_cancellable_new ();
+
+ pp_maintenance_command_is_supported_async (self->clean_command,
+ self->check_clean_heads_cancellable,
+ check_clean_heads_maintenance_command_cb,
+ self);
+}
+
+static void
+clean_heads_maintenance_command_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ PpPrinterEntry *self = user_data;
+ g_autoptr(GError) error = NULL;
+
+ if (!pp_maintenance_command_execute_finish (PP_MAINTENANCE_COMMAND (source_object), res, &error))
+ g_warning ("Error cleaning print heads for %s: %s", self->printer_name, error->message);
+}
+
+static void
+clean_heads (GtkButton *button,
+ PpPrinterEntry *self)
+{
+ if (self->clean_command == NULL)
+ return;
+
+ g_object_ref (self->clean_command);
+ pp_maintenance_command_execute_async (self->clean_command,
+ NULL,
+ clean_heads_maintenance_command_cb,
+ self);
+}
+
+static void
+remove_printer (GtkButton *button,
+ PpPrinterEntry *self)
+{
+ g_signal_emit_by_name (self, "printer-delete");
+}
+
+static void
+get_jobs_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ PpPrinterEntry *self = user_data;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) jobs = NULL;
+ g_autofree gchar *button_label = NULL;
+
+ jobs = pp_printer_get_jobs_finish (PP_PRINTER (source_object), result, &error);
+
+ if (error != NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ g_warning ("Could not get jobs: %s", error->message);
+ }
+
+ return;
+ }
+
+ if (jobs->len == 0)
+ {
+ /* Translators: This is the label of the button that opens the Jobs Dialog. */
+ button_label = g_strdup (_("No Active Jobs"));
+ }
+ else
+ {
+ /* Translators: This is the label of the button that opens the Jobs Dialog. */
+ button_label = g_strdup_printf (ngettext ("%u Job", "%u Jobs", jobs->len), jobs->len);
+ }
+
+ gtk_button_set_label (GTK_BUTTON (self->show_jobs_dialog_button), button_label);
+ gtk_widget_set_sensitive (self->show_jobs_dialog_button, jobs->len > 0);
+
+ if (self->pp_jobs_dialog != NULL)
+ {
+ pp_jobs_dialog_update (self->pp_jobs_dialog);
+ }
+
+ g_clear_object (&self->get_jobs_cancellable);
+}
+
+void
+pp_printer_entry_update_jobs_count (PpPrinterEntry *self)
+{
+ g_autoptr(PpPrinter) printer = NULL;
+
+ g_cancellable_cancel (self->get_jobs_cancellable);
+ g_clear_object (&self->get_jobs_cancellable);
+
+ self->get_jobs_cancellable = g_cancellable_new ();
+
+ printer = pp_printer_new (self->printer_name);
+ pp_printer_get_jobs_async (printer,
+ TRUE,
+ CUPS_WHICHJOBS_ACTIVE,
+ self->get_jobs_cancellable,
+ get_jobs_cb,
+ self);
+}
+
+static void
+jobs_dialog_response_cb (GtkDialog *dialog,
+ gint response_id,
+ gpointer user_data)
+{
+ PpPrinterEntry *self = (PpPrinterEntry*) user_data;
+
+ if (self->pp_jobs_dialog != NULL)
+ {
+ gtk_window_destroy (GTK_WINDOW (self->pp_jobs_dialog));
+ self->pp_jobs_dialog = NULL;
+ }
+}
+
+void
+pp_printer_entry_show_jobs_dialog (PpPrinterEntry *self)
+{
+ if (self->pp_jobs_dialog == NULL)
+ {
+ self->pp_jobs_dialog = pp_jobs_dialog_new (self->printer_name);
+ g_signal_connect_object (self->pp_jobs_dialog, "response", G_CALLBACK (jobs_dialog_response_cb), self, 0);
+ gtk_window_set_transient_for (GTK_WINDOW (self->pp_jobs_dialog), GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (self))));
+ gtk_window_present (GTK_WINDOW (self->pp_jobs_dialog));
+ }
+}
+
+void
+pp_printer_entry_authenticate_jobs (PpPrinterEntry *self)
+{
+ pp_printer_entry_show_jobs_dialog (self);
+ pp_jobs_dialog_authenticate_jobs (self->pp_jobs_dialog);
+}
+
+static void
+show_jobs_dialog (GtkButton *button,
+ gpointer user_data)
+{
+ pp_printer_entry_show_jobs_dialog (PP_PRINTER_ENTRY (user_data));
+}
+
+enum
+{
+ PRINTER_READY = 3,
+ PRINTER_PROCESSING,
+ PRINTER_STOPPED
+};
+
+static void
+restart_printer (GtkButton *button,
+ PpPrinterEntry *self)
+{
+ if (self->printer_state == PRINTER_STOPPED)
+ printer_set_enabled (self->printer_name, TRUE);
+
+ if (!self->is_accepting_jobs)
+ printer_set_accepting_jobs (self->printer_name, TRUE, NULL);
+
+ g_signal_emit_by_name (self, "printer-changed");
+}
+
+GSList *
+pp_printer_entry_get_size_group_widgets (PpPrinterEntry *self)
+{
+ GSList *widgets = NULL;
+
+ widgets = g_slist_prepend (widgets, self->printer_icon);
+ widgets = g_slist_prepend (widgets, self->printer_location_label);
+ widgets = g_slist_prepend (widgets, self->printer_model_label);
+ widgets = g_slist_prepend (widgets, self->printer_inklevel_label);
+
+ return widgets;
+}
+
+PpPrinterEntry *
+pp_printer_entry_new (cups_dest_t printer,
+ gboolean is_authorized)
+{
+ PpPrinterEntry *self;
+
+ self = g_object_new (PP_PRINTER_ENTRY_TYPE, NULL);
+
+ self->printer_name = g_strdup (printer.name);
+
+ self->clean_command = pp_maintenance_command_new (self->printer_name,
+ "Clean",
+ "all",
+ /* Translators: Name of job which makes printer to clean its heads */
+ _("Clean print heads"));
+ check_clean_heads_maintenance_command (self);
+
+ gtk_drawing_area_set_draw_func (self->supply_drawing_area,
+ supply_levels_draw_cb,
+ self,
+ NULL);
+
+ pp_printer_entry_update (self, printer, is_authorized);
+
+ return self;
+}
+
+const gchar *
+pp_printer_entry_get_name (PpPrinterEntry *self)
+{
+ g_return_val_if_fail (PP_IS_PRINTER_ENTRY (self), NULL);
+ return self->printer_name;
+}
+
+const gchar *
+pp_printer_entry_get_location (PpPrinterEntry *self)
+{
+ g_return_val_if_fail (PP_IS_PRINTER_ENTRY (self), NULL);
+ return self->printer_location;
+}
+
+void
+pp_printer_entry_update (PpPrinterEntry *self,
+ cups_dest_t printer,
+ gboolean is_authorized)
+{
+ cups_ptype_t printer_type = 0;
+ gboolean is_accepting_jobs = TRUE;
+ gboolean ink_supply_is_empty;
+ g_autofree gchar *instance = NULL;
+ const gchar *printer_uri = NULL;
+ const gchar *device_uri = NULL;
+ const gchar *location = NULL;
+ g_autofree gchar *printer_icon_name = NULL;
+ const gchar *printer_make_and_model = NULL;
+ const gchar *reason = NULL;
+ gchar **printer_reasons = NULL;
+ g_autofree gchar *status = NULL;
+ g_autofree gchar *printer_status = NULL;
+ int i, j;
+ static const char * const reasons[] =
+ {
+ "toner-low",
+ "toner-empty",
+ "developer-low",
+ "developer-empty",
+ "marker-supply-low",
+ "marker-supply-empty",
+ "cover-open",
+ "door-open",
+ "media-low",
+ "media-empty",
+ "offline",
+ "paused",
+ "marker-waste-almost-full",
+ "marker-waste-full",
+ "opc-near-eol",
+ "opc-life-over"
+ };
+ static const char * statuses[] =
+ {
+ /* Translators: The printer is low on toner */
+ N_("Low on toner"),
+ /* Translators: The printer has no toner left */
+ N_("Out of toner"),
+ /* Translators: "Developer" is a chemical for photo development,
+ * http://en.wikipedia.org/wiki/Photographic_developer */
+ N_("Low on developer"),
+ /* Translators: "Developer" is a chemical for photo development,
+ * http://en.wikipedia.org/wiki/Photographic_developer */
+ N_("Out of developer"),
+ /* Translators: "marker" is one color bin of the printer */
+ N_("Low on a marker supply"),
+ /* Translators: "marker" is one color bin of the printer */
+ N_("Out of a marker supply"),
+ /* Translators: One or more covers on the printer are open */
+ N_("Open cover"),
+ /* Translators: One or more doors on the printer are open */
+ N_("Open door"),
+ /* Translators: At least one input tray is low on media */
+ N_("Low on paper"),
+ /* Translators: At least one input tray is empty */
+ N_("Out of paper"),
+ /* Translators: The printer is offline */
+ NC_("printer state", "Offline"),
+ /* Translators: Someone has stopped the Printer */
+ NC_("printer state", "Stopped"),
+ /* Translators: The printer marker supply waste receptacle is almost full */
+ N_("Waste receptacle almost full"),
+ /* Translators: The printer marker supply waste receptacle is full */
+ N_("Waste receptacle full"),
+ /* Translators: Optical photo conductors are used in laser printers */
+ N_("The optical photo conductor is near end of life"),
+ /* Translators: Optical photo conductors are used in laser printers */
+ N_("The optical photo conductor is no longer functioning")
+ };
+
+ if (printer.instance)
+ {
+ instance = g_strdup_printf ("%s / %s", printer.name, printer.instance);
+ }
+ else
+ {
+ instance = g_strdup (printer.name);
+ }
+
+ self->printer_state = PRINTER_READY;
+
+ for (i = 0; i < printer.num_options; i++)
+ {
+ if (g_strcmp0 (printer.options[i].name, "device-uri") == 0)
+ device_uri = printer.options[i].value;
+ else if (g_strcmp0 (printer.options[i].name, "printer-uri-supported") == 0)
+ printer_uri = printer.options[i].value;
+ else if (g_strcmp0 (printer.options[i].name, "printer-type") == 0)
+ printer_type = atoi (printer.options[i].value);
+ else if (g_strcmp0 (printer.options[i].name, "printer-location") == 0)
+ location = printer.options[i].value;
+ else if (g_strcmp0 (printer.options[i].name, "printer-state-reasons") == 0)
+ reason = printer.options[i].value;
+ else if (g_strcmp0 (printer.options[i].name, "marker-names") == 0)
+ {
+ g_free (self->inklevel->marker_names);
+ self->inklevel->marker_names = g_strcompress (g_strdup (printer.options[i].value));
+ }
+ else if (g_strcmp0 (printer.options[i].name, "marker-levels") == 0)
+ {
+ g_free (self->inklevel->marker_levels);
+ self->inklevel->marker_levels = g_strdup (printer.options[i].value);
+ }
+ else if (g_strcmp0 (printer.options[i].name, "marker-colors") == 0)
+ {
+ g_free (self->inklevel->marker_colors);
+ self->inklevel->marker_colors = g_strdup (printer.options[i].value);
+ }
+ else if (g_strcmp0 (printer.options[i].name, "marker-types") == 0)
+ {
+ g_free (self->inklevel->marker_types);
+ self->inklevel->marker_types = g_strdup (printer.options[i].value);
+ }
+ else if (g_strcmp0 (printer.options[i].name, "printer-make-and-model") == 0)
+ printer_make_and_model = printer.options[i].value;
+ else if (g_strcmp0 (printer.options[i].name, "printer-state") == 0)
+ self->printer_state = atoi (printer.options[i].value);
+ else if (g_strcmp0 (printer.options[i].name, "printer-is-accepting-jobs") == 0)
+ {
+ if (g_strcmp0 (printer.options[i].value, "true") == 0)
+ is_accepting_jobs = TRUE;
+ else
+ is_accepting_jobs = FALSE;
+ }
+ }
+
+ /* Find the first of the most severe reasons
+ * and show it in the status field
+ */
+ if (reason && !g_str_equal (reason, "none"))
+ {
+ int errors = 0, warnings = 0, reports = 0;
+ int error_index = -1, warning_index = -1, report_index = -1;
+
+ printer_reasons = g_strsplit (reason, ",", -1);
+ for (i = 0; i < g_strv_length (printer_reasons); i++)
+ {
+ for (j = 0; j < G_N_ELEMENTS (reasons); j++)
+ if (strncmp (printer_reasons[i], reasons[j], strlen (reasons[j])) == 0)
+ {
+ if (g_str_has_suffix (printer_reasons[i], "-report"))
+ {
+ if (reports == 0)
+ report_index = j;
+ reports++;
+ }
+ else if (g_str_has_suffix (printer_reasons[i], "-warning"))
+ {
+ if (warnings == 0)
+ warning_index = j;
+ warnings++;
+ }
+ else
+ {
+ if (errors == 0)
+ error_index = j;
+ errors++;
+ }
+ }
+ }
+ g_strfreev (printer_reasons);
+
+ if (error_index >= 0)
+ status = g_strdup (_(statuses[error_index]));
+ else if (warning_index >= 0)
+ status = g_strdup (_(statuses[warning_index]));
+ else if (report_index >= 0)
+ status = g_strdup (_(statuses[report_index]));
+ }
+
+ if ((self->printer_state == PRINTER_STOPPED || !is_accepting_jobs) &&
+ status != NULL && status[0] != '\0')
+ {
+ gtk_label_set_label (self->error_status, status);
+ gtk_widget_set_visible (GTK_WIDGET (self->printer_error), TRUE);
+ }
+ else
+ {
+ gtk_label_set_label (self->error_status, "");
+ gtk_widget_set_visible (GTK_WIDGET (self->printer_error), FALSE);
+ }
+
+ switch (self->printer_state)
+ {
+ case PRINTER_READY:
+ if (is_accepting_jobs)
+ {
+ /* Translators: Printer's state (can start new job without waiting) */
+ printer_status = g_strdup ( C_("printer state", "Ready"));
+ }
+ else
+ {
+ /* Translators: Printer's state (printer is ready but doesn't accept new jobs) */
+ printer_status = g_strdup ( C_("printer state", "Does not accept jobs"));
+ }
+ break;
+ case PRINTER_PROCESSING:
+ /* Translators: Printer's state (jobs are processing) */
+ printer_status = g_strdup ( C_("printer state", "Processing"));
+ break;
+ case PRINTER_STOPPED:
+ /* Translators: Printer's state (no jobs can be processed) */
+ printer_status = g_strdup ( C_("printer state", "Stopped"));
+ break;
+ }
+
+ if (printer_is_local (printer_type, device_uri))
+ printer_icon_name = g_strdup ("printer");
+ else
+ printer_icon_name = g_strdup ("printer-network");
+
+ g_free (self->printer_location);
+ self->printer_location = g_strdup (location);
+
+ self->is_accepting_jobs = is_accepting_jobs;
+ self->is_authorized = is_authorized;
+
+ g_free (self->printer_hostname);
+ self->printer_hostname = printer_get_hostname (printer_type, device_uri, printer_uri);
+
+ gtk_image_set_from_icon_name (self->printer_icon, printer_icon_name);
+ gtk_label_set_text (self->printer_status, printer_status);
+ gtk_label_set_text (self->printer_name_label, instance);
+ g_signal_handlers_block_by_func (self->printer_default_checkbutton, set_as_default_printer, self);
+ gtk_check_button_set_active (self->printer_default_checkbutton, printer.is_default);
+ g_signal_handlers_unblock_by_func (self->printer_default_checkbutton, set_as_default_printer, self);
+
+ self->printer_make_and_model = sanitize_printer_model (printer_make_and_model);
+
+ if (self->printer_make_and_model == NULL || self->printer_make_and_model[0] == '\0')
+ {
+ gtk_widget_hide (GTK_WIDGET (self->printer_model_label));
+ gtk_widget_hide (GTK_WIDGET (self->printer_model));
+ }
+ else
+ {
+ gtk_label_set_text (self->printer_model, self->printer_make_and_model);
+ }
+
+ if (location != NULL && location[0] == '\0')
+ {
+ gtk_widget_hide (GTK_WIDGET (self->printer_location_label));
+ gtk_widget_hide (GTK_WIDGET (self->printer_location_address_label));
+ }
+ else
+ {
+ gtk_label_set_text (self->printer_location_address_label, location);
+ }
+
+ ink_supply_is_empty = supply_level_is_empty (self);
+ gtk_widget_set_visible (GTK_WIDGET (self->printer_inklevel_label), !ink_supply_is_empty);
+ gtk_widget_set_visible (GTK_WIDGET (self->supply_frame), !ink_supply_is_empty);
+
+ pp_printer_entry_update_jobs_count (self);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->printer_default_checkbutton), self->is_authorized);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->remove_printer_menuitem), self->is_authorized);
+}
+
+static void
+pp_printer_entry_dispose (GObject *object)
+{
+ PpPrinterEntry *self = PP_PRINTER_ENTRY (object);
+
+ g_cancellable_cancel (self->get_jobs_cancellable);
+ g_cancellable_cancel (self->check_clean_heads_cancellable);
+
+ g_clear_pointer (&self->printer_name, g_free);
+ g_clear_pointer (&self->printer_location, g_free);
+ g_clear_pointer (&self->printer_make_and_model, g_free);
+ g_clear_pointer (&self->printer_hostname, g_free);
+ g_clear_pointer (&self->inklevel, ink_level_data_free);
+ g_clear_object (&self->get_jobs_cancellable);
+ g_clear_object (&self->check_clean_heads_cancellable);
+ g_clear_object (&self->clean_command);
+
+ G_OBJECT_CLASS (pp_printer_entry_parent_class)->dispose (object);
+}
+
+static void
+pp_printer_entry_class_init (PpPrinterEntryClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/printers/printer-entry.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_icon);
+ gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_name_label);
+ gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_status);
+ gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_model_label);
+ gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_model);
+ gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_location_label);
+ gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_location_address_label);
+ gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_inklevel_label);
+ gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, supply_frame);
+ gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, supply_drawing_area);
+ gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_default_checkbutton);
+ gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, show_jobs_dialog_button);
+ gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, clean_heads_menuitem);
+ gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, remove_printer_menuitem);
+ gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, error_status);
+ gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_error);
+
+ gtk_widget_class_bind_template_callback (widget_class, on_show_printer_details_dialog);
+ gtk_widget_class_bind_template_callback (widget_class, on_show_printer_options_dialog);
+ gtk_widget_class_bind_template_callback (widget_class, set_as_default_printer);
+ gtk_widget_class_bind_template_callback (widget_class, clean_heads);
+ gtk_widget_class_bind_template_callback (widget_class, remove_printer);
+ gtk_widget_class_bind_template_callback (widget_class, show_jobs_dialog);
+ gtk_widget_class_bind_template_callback (widget_class, restart_printer);
+
+ object_class->dispose = pp_printer_entry_dispose;
+
+ signals[IS_DEFAULT_PRINTER] =
+ g_signal_new ("printer-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+
+ signals[PRINTER_DELETE] =
+ g_signal_new ("printer-delete",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+
+ signals[PRINTER_RENAMED] =
+ g_signal_new ("printer-renamed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 1,
+ G_TYPE_STRING);
+}
diff --git a/panels/printers/pp-printer-entry.h b/panels/printers/pp-printer-entry.h
new file mode 100644
index 0000000..1c6b3dc
--- /dev/null
+++ b/panels/printers/pp-printer-entry.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2017 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Felipe Borges <felipeborges@gnome.org>
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <cups/cups.h>
+
+#define PP_PRINTER_ENTRY_TYPE (pp_printer_entry_get_type ())
+G_DECLARE_FINAL_TYPE (PpPrinterEntry, pp_printer_entry, PP, PRINTER_ENTRY, GtkListBoxRow)
+
+PpPrinterEntry *pp_printer_entry_new (cups_dest_t printer,
+ gboolean is_authorized);
+
+const gchar *pp_printer_entry_get_name (PpPrinterEntry *self);
+
+const gchar *pp_printer_entry_get_location (PpPrinterEntry *self);
+
+void pp_printer_entry_update_jobs_count (PpPrinterEntry *self);
+
+GSList *pp_printer_entry_get_size_group_widgets (PpPrinterEntry *self);
+
+void pp_printer_entry_show_jobs_dialog (PpPrinterEntry *self);
+
+void pp_printer_entry_authenticate_jobs (PpPrinterEntry *self);
+
+void pp_printer_entry_update (PpPrinterEntry *self,
+ cups_dest_t printer,
+ gboolean is_authorized);
diff --git a/panels/printers/pp-printer.c b/panels/printers/pp-printer.c
new file mode 100644
index 0000000..76d0bfc
--- /dev/null
+++ b/panels/printers/pp-printer.c
@@ -0,0 +1,562 @@
+/*
+ * Copyright (C) 2016 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Martin Hatina <mhatina@redhat.com>
+ * Marek Kasik <mkasik@redhat.com>
+ */
+
+#include "pp-printer.h"
+
+#include "pp-job.h"
+
+#if (CUPS_VERSION_MAJOR == 1) && (CUPS_VERSION_MINOR <= 6)
+#define IPP_STATE_IDLE IPP_IDLE
+#endif
+
+struct _PpPrinter
+{
+ GObject parent_instance;
+ gchar *printer_name;
+};
+
+G_DEFINE_TYPE (PpPrinter, pp_printer, G_TYPE_OBJECT)
+
+static void
+pp_printer_dispose (GObject *object)
+{
+ PpPrinter *self = PP_PRINTER (object);
+
+ g_clear_pointer (&self->printer_name, g_free);
+
+ G_OBJECT_CLASS (pp_printer_parent_class)->dispose (object);
+}
+
+static void
+pp_printer_class_init (PpPrinterClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->dispose = pp_printer_dispose;
+}
+
+static void
+pp_printer_init (PpPrinter *self)
+{
+}
+
+PpPrinter *
+pp_printer_new (const gchar *name)
+{
+ PpPrinter *self = g_object_new (PP_TYPE_PRINTER, NULL);
+
+ self->printer_name = g_strdup (name);
+
+ return self;
+}
+
+const gchar *
+pp_printer_get_name (PpPrinter *self)
+{
+ g_return_val_if_fail (PP_IS_PRINTER (self), NULL);
+ return self->printer_name;
+}
+
+static void
+printer_rename_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ PpPrinter *self = PP_PRINTER (source_object);
+ gboolean result;
+ const gchar *new_printer_name = task_data;
+
+ result = printer_rename (self->printer_name, new_printer_name);
+
+ if (result)
+ {
+ g_free (self->printer_name);
+ self->printer_name = g_strdup (new_printer_name);
+ }
+
+ g_task_return_boolean (task, result);
+}
+
+static void
+printer_rename_dbus_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ PpPrinter *self;
+ g_autoptr(GVariant) output = NULL;
+ gboolean result = FALSE;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GTask) task = user_data;
+
+ output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ res,
+ &error);
+
+ if (output != NULL)
+ {
+ const gchar *ret_error;
+
+ self = g_task_get_source_object (task);
+
+ g_variant_get (output, "(&s)", &ret_error);
+ if (ret_error[0] != '\0')
+ {
+ g_warning ("cups-pk-helper: renaming of printer %s failed: %s", self->printer_name, ret_error);
+ }
+ else
+ {
+ result = TRUE;
+ g_free (self->printer_name);
+ self->printer_name = g_strdup (g_task_get_task_data (task));
+ }
+
+ g_task_return_boolean (task, result);
+ }
+ else
+ {
+ if (error->domain == G_DBUS_ERROR &&
+ (error->code == G_DBUS_ERROR_SERVICE_UNKNOWN ||
+ error->code == G_DBUS_ERROR_UNKNOWN_METHOD))
+ {
+ g_warning ("Update cups-pk-helper to at least 0.2.6 please to be able to use PrinterRename method.");
+
+ g_task_run_in_thread (task, printer_rename_thread);
+ }
+ else
+ {
+ g_task_return_boolean (task, FALSE);
+ }
+ }
+}
+
+static void
+get_bus_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ PpPrinter *self;
+ GDBusConnection *bus;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GTask) task = user_data;
+
+ bus = g_bus_get_finish (res, &error);
+ if (bus != NULL)
+ {
+ self = g_task_get_source_object (task);
+ g_dbus_connection_call (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "PrinterRename",
+ g_variant_new ("(ss)",
+ self->printer_name,
+ g_task_get_task_data (task)),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ g_task_get_cancellable (task),
+ printer_rename_dbus_cb,
+ task);
+ g_steal_pointer (&task);
+ }
+ else
+ {
+ g_warning ("Failed to get system bus: %s", error->message);
+ g_task_return_boolean (task, FALSE);
+ }
+}
+
+void
+pp_printer_rename_async (PpPrinter *self,
+ const gchar *new_printer_name,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+
+ g_return_if_fail (new_printer_name != NULL);
+
+ task = g_task_new (G_OBJECT (self), cancellable, callback, user_data);
+ g_task_set_task_data (task, g_strdup (new_printer_name), g_free);
+
+ g_bus_get (G_BUS_TYPE_SYSTEM,
+ cancellable,
+ get_bus_cb,
+ task);
+}
+
+gboolean
+pp_printer_rename_finish (PpPrinter *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+typedef struct
+{
+ gboolean myjobs;
+ gint which_jobs;
+} GetJobsData;
+
+static void
+get_jobs_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ ipp_attribute_t *attr = NULL;
+ static gchar *printer_attributes[] = { "auth-info-required" };
+ GetJobsData *get_jobs_data = task_data;
+ cups_job_t *jobs = NULL;
+ PpPrinter *self = PP_PRINTER (source_object);
+ gboolean auth_info_is_required;
+ PpJob *job;
+ ipp_t *job_request;
+ ipp_t *job_response;
+ ipp_t *printer_request;
+ ipp_t *printer_response;
+ gchar **auth_info_required = NULL;
+ g_autofree gchar *printer_name = NULL;
+ g_autoptr(GPtrArray) array = NULL;
+ gint num_jobs;
+ gint i, j;
+
+ num_jobs = cupsGetJobs (&jobs,
+ self->printer_name,
+ get_jobs_data->myjobs ? 1 : 0,
+ get_jobs_data->which_jobs);
+
+ array = g_ptr_array_new_with_free_func (g_object_unref);
+ for (i = 0; i < num_jobs; i++)
+ {
+ auth_info_is_required = FALSE;
+ if (jobs[i].state == IPP_JOB_HELD)
+ {
+ g_autofree gchar *job_uri = g_strdup_printf ("ipp://localhost/jobs/%d", jobs[i].id);
+
+ job_request = ippNewRequest (IPP_GET_JOB_ATTRIBUTES);
+ ippAddString (job_request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "job-uri", NULL, job_uri);
+ ippAddString (job_request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, cupsUser ());
+ ippAddString (job_request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", NULL, "job-hold-until");
+ job_response = cupsDoRequest (CUPS_HTTP_DEFAULT, job_request, "/");
+
+ if (job_response != NULL)
+ {
+ attr = ippFindAttribute (job_response, "job-hold-until", IPP_TAG_ZERO);
+ if (attr != NULL && g_strcmp0 (ippGetString (attr, 0, NULL), "auth-info-required") == 0)
+ {
+ auth_info_is_required = TRUE;
+
+ if (auth_info_required == NULL)
+ {
+ g_autofree gchar *printer_uri = g_strdup_printf ("ipp://localhost/printers/%s", self->printer_name);
+
+ printer_request = ippNewRequest (IPP_GET_PRINTER_ATTRIBUTES);
+ ippAddString (printer_request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, printer_uri);
+ ippAddString (printer_request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, cupsUser ());
+ ippAddStrings (printer_request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", 1, NULL, (const char **) printer_attributes);
+ printer_response = cupsDoRequest (CUPS_HTTP_DEFAULT, printer_request, "/");
+
+ if (printer_response != NULL)
+ {
+ attr = ippFindAttribute (printer_response, "auth-info-required", IPP_TAG_ZERO);
+ if (attr != NULL)
+ {
+ auth_info_required = g_new0 (gchar *, ippGetCount (attr) + 1);
+ for (j = 0; j < ippGetCount (attr); j++)
+ auth_info_required[j] = g_strdup (ippGetString (attr, j, NULL));
+ }
+
+ ippDelete (printer_response);
+ }
+ }
+ }
+
+ ippDelete (job_response);
+ }
+ }
+
+ job = pp_job_new (jobs[i].id, jobs[i].title, jobs[i].state, jobs[i].priority, auth_info_is_required ? auth_info_required : NULL);
+ g_ptr_array_add (array, job);
+ }
+
+ g_strfreev (auth_info_required);
+ cupsFreeJobs (num_jobs, jobs);
+
+ if (g_task_set_return_on_cancel (task, FALSE))
+ {
+ g_task_return_pointer (task, g_steal_pointer (&array), (GDestroyNotify) g_ptr_array_unref);
+ }
+}
+
+void
+pp_printer_get_jobs_async (PpPrinter *self,
+ gboolean myjobs,
+ gint which_jobs,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GetJobsData *get_jobs_data;
+ g_autoptr(GTask) task = NULL;
+
+ get_jobs_data = g_new (GetJobsData, 1);
+ get_jobs_data->myjobs = myjobs;
+ get_jobs_data->which_jobs = which_jobs;
+
+ task = g_task_new (G_OBJECT (self), cancellable, callback, user_data);
+ g_task_set_task_data (task, get_jobs_data, g_free);
+ g_task_set_return_on_cancel (task, TRUE);
+ g_task_run_in_thread (task, get_jobs_thread);
+}
+
+GPtrArray *
+pp_printer_get_jobs_finish (PpPrinter *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
+
+ return g_task_propagate_pointer (G_TASK (res), error);
+}
+
+static void
+pp_printer_delete_dbus_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ PpPrinter *self;
+ g_autoptr(GVariant) output = NULL;
+ gboolean result = FALSE;
+ g_autoptr(GError) error = NULL;
+ GTask *task = user_data;
+
+ output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ res,
+ &error);
+
+ if (output != NULL)
+ {
+ const gchar *ret_error;
+
+ self = g_task_get_source_object (task);
+
+ g_variant_get (output, "(&s)", &ret_error);
+ if (ret_error[0] != '\0')
+ g_warning ("cups-pk-helper: removing of printer %s failed: %s", self->printer_name, ret_error);
+ else
+ result = TRUE;
+
+ g_task_return_boolean (task, result);
+ }
+ else
+ {
+ g_warning ("%s", error->message);
+
+ g_task_return_boolean (task, FALSE);
+ }
+}
+
+static void
+pp_printer_delete_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ PpPrinter *self;
+ GDBusConnection *bus;
+ g_autoptr(GError) error = NULL;
+ GTask *task = user_data;
+
+ bus = g_bus_get_finish (res, &error);
+ if (bus != NULL)
+ {
+ self = g_task_get_source_object (task);
+
+ g_dbus_connection_call (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "PrinterDelete",
+ g_variant_new ("(s)", self->printer_name),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ g_task_get_cancellable (task),
+ pp_printer_delete_dbus_cb,
+ task);
+ }
+ else
+ {
+ g_warning ("Failed to get system bus: %s", error->message);
+ g_task_return_boolean (task, FALSE);
+ }
+}
+
+void
+pp_printer_delete_async (PpPrinter *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+
+ task = g_task_new (G_OBJECT (self), cancellable, callback, user_data);
+
+ g_bus_get (G_BUS_TYPE_SYSTEM,
+ cancellable,
+ pp_printer_delete_cb,
+ task);
+}
+
+gboolean
+pp_printer_delete_finish (PpPrinter *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+typedef struct
+{
+ gchar *filename;
+ gchar *job_name;
+} PrintFileData;
+
+static void
+print_file_data_free (PrintFileData *print_file_data)
+{
+ g_free (print_file_data->filename);
+ g_free (print_file_data->job_name);
+
+ g_slice_free (PrintFileData, print_file_data);
+}
+
+static void
+print_file_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ PpPrinter *self = PP_PRINTER (source_object);
+ PrintFileData *print_file_data;
+ cups_ptype_t type = 0;
+ cups_dest_t *dest = NULL;
+ const gchar *printer_type = NULL;
+ gboolean ret = FALSE;
+ g_autofree gchar *printer_uri = NULL;
+ g_autofree gchar *resource = NULL;
+ ipp_t *response = NULL;
+ ipp_t *request;
+
+ dest = cupsGetNamedDest (CUPS_HTTP_DEFAULT, self->printer_name, NULL);
+ if (dest != NULL)
+ {
+ printer_type = cupsGetOption ("printer-type",
+ dest->num_options,
+ dest->options);
+ cupsFreeDests (1, dest);
+
+ if (printer_type)
+ type = atoi (printer_type);
+ }
+
+ if (type & CUPS_PRINTER_CLASS)
+ {
+ printer_uri = g_strdup_printf ("ipp://localhost/classes/%s", self->printer_name);
+ resource = g_strdup_printf ("/classes/%s", self->printer_name);
+ }
+ else
+ {
+ printer_uri = g_strdup_printf ("ipp://localhost/printers/%s", self->printer_name);
+ resource = g_strdup_printf ("/printers/%s", self->printer_name);
+ }
+
+ print_file_data = g_task_get_task_data (task);
+
+ request = ippNewRequest (IPP_PRINT_JOB);
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, printer_uri);
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, cupsUser ());
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "job-name", NULL, print_file_data->job_name);
+ response = cupsDoFileRequest (CUPS_HTTP_DEFAULT, request, resource, print_file_data->filename);
+
+ if (response != NULL)
+ {
+ if (ippGetState (response) == IPP_ERROR)
+ g_warning ("An error has occurred during printing of test page.");
+ if (ippGetState (response) == IPP_STATE_IDLE)
+ ret = TRUE;
+
+ ippDelete (response);
+ }
+
+ if (g_task_set_return_on_cancel (task, FALSE))
+ {
+ g_task_return_boolean (task, ret);
+ }
+}
+
+void
+pp_printer_print_file_async (PpPrinter *self,
+ const gchar *filename,
+ const gchar *job_name,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ PrintFileData *print_file_data;
+ g_autoptr(GTask) task = NULL;
+
+ print_file_data = g_new (PrintFileData, 1);
+ print_file_data->filename = g_strdup (filename);
+ print_file_data->job_name = g_strdup (job_name);
+
+ task = g_task_new (G_OBJECT (self), cancellable, callback, user_data);
+
+ g_task_set_return_on_cancel (task, TRUE);
+ g_task_set_task_data (task, print_file_data, (GDestroyNotify) print_file_data_free);
+
+ g_task_run_in_thread (task, print_file_thread);
+}
+
+gboolean
+pp_printer_print_file_finish (PpPrinter *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
diff --git a/panels/printers/pp-printer.h b/panels/printers/pp-printer.h
new file mode 100644
index 0000000..a63fbb9
--- /dev/null
+++ b/panels/printers/pp-printer.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2016 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Martin Hatina <mhatina@redhat.com>
+ * Marek Kasik <mkasik@redhat.com>
+ */
+
+#pragma once
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include "pp-utils.h"
+
+G_BEGIN_DECLS
+
+#define PP_TYPE_PRINTER (pp_printer_get_type ())
+G_DECLARE_FINAL_TYPE (PpPrinter, pp_printer, PP, PRINTER, GObject)
+
+GType pp_printer_get_type (void) G_GNUC_CONST;
+
+PpPrinter *pp_printer_new (const gchar *name);
+
+const gchar *pp_printer_get_name (PpPrinter *printer);
+
+void pp_printer_rename_async (PpPrinter *printer,
+ const gchar *new_printer_name,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean pp_printer_rename_finish (PpPrinter *printer,
+ GAsyncResult *res,
+ GError **error);
+
+void pp_printer_delete_async (PpPrinter *printer,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean pp_printer_delete_finish (PpPrinter *printer,
+ GAsyncResult *res,
+ GError **error);
+
+void pp_printer_get_jobs_async (PpPrinter *printer,
+ gboolean myjobs,
+ gint which_jobs,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GPtrArray *pp_printer_get_jobs_finish (PpPrinter *printer,
+ GAsyncResult *res,
+ GError **error);
+
+void pp_printer_print_file_async (PpPrinter *printer,
+ const gchar *filename,
+ const gchar *job_name,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean pp_printer_print_file_finish (PpPrinter *printer,
+ GAsyncResult *res,
+ GError **error);
+
+G_END_DECLS
diff --git a/panels/printers/pp-samba.c b/panels/printers/pp-samba.c
new file mode 100644
index 0000000..5eaf5b7
--- /dev/null
+++ b/panels/printers/pp-samba.c
@@ -0,0 +1,414 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 - 2013 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marek Kasik <mkasik@redhat.com>
+ */
+
+#include "pp-samba.h"
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <libsmbclient.h>
+#include <errno.h>
+
+#define POLL_DELAY 100000
+
+struct _PpSamba
+{
+ PpHost parent_instance;
+
+ /* Auth info */
+ gchar *username;
+ gchar *password;
+ gboolean waiting;
+};
+
+G_DEFINE_TYPE (PpSamba, pp_samba, PP_TYPE_HOST);
+
+static void
+pp_samba_finalize (GObject *object)
+{
+ PpSamba *self = PP_SAMBA (object);
+
+ g_clear_pointer (&self->username, g_free);
+ g_clear_pointer (&self->password, g_free);
+
+ G_OBJECT_CLASS (pp_samba_parent_class)->finalize (object);
+}
+
+static void
+pp_samba_class_init (PpSambaClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = pp_samba_finalize;
+}
+
+static void
+pp_samba_init (PpSamba *samba)
+{
+}
+
+PpSamba *
+pp_samba_new (const gchar *hostname)
+{
+ return g_object_new (PP_TYPE_SAMBA,
+ "hostname", hostname,
+ NULL);
+}
+
+typedef struct
+{
+ PpSamba *samba;
+ GPtrArray *devices;
+ GMainContext *context;
+ gboolean auth_if_needed;
+ gboolean hostname_set;
+ gboolean cancelled;
+} SMBData;
+
+static void
+smb_data_free (SMBData *data)
+{
+ if (data)
+ {
+ g_ptr_array_unref (data->devices);
+
+ g_free (data);
+ }
+}
+
+static gboolean
+get_auth_info (gpointer user_data)
+{
+ SMBData *data = (SMBData *) user_data;
+ PpSamba *samba = PP_SAMBA (data->samba);
+
+ g_signal_emit_by_name (samba, "authentication-required");
+
+ return FALSE;
+}
+
+void
+pp_samba_set_auth_info (PpSamba *samba,
+ const gchar *username,
+ const gchar *password)
+{
+ g_free (samba->username);
+ if ((username != NULL) && (username[0] != '\0'))
+ samba->username = g_strdup (username);
+ else
+ samba->username = NULL;
+
+ g_free (samba->password);
+ if ((password != NULL) && (password[0] != '\0'))
+ samba->password = g_strdup (password);
+ else
+ samba->password = NULL;
+
+ samba->waiting = FALSE;
+}
+
+static void
+auth_fn (SMBCCTX *smb_context,
+ const char *server,
+ const char *share,
+ char *workgroup,
+ int wgmaxlen,
+ char *username,
+ int unmaxlen,
+ char *password,
+ int pwmaxlen)
+{
+ PpSamba *samba;
+ g_autoptr(GSource) source = NULL;
+ SMBData *data;
+
+ data = (SMBData *) smbc_getOptionUserData (smb_context);
+ samba = data->samba;
+
+ if (!data->cancelled)
+ {
+ samba->username = g_strdup (username);
+ samba->password = g_strdup (password);
+
+ source = g_idle_source_new ();
+ g_source_set_callback (source,
+ get_auth_info,
+ data,
+ NULL);
+ g_source_attach (source, data->context);
+
+ samba->waiting = TRUE;
+
+ /*
+ * smbclient needs to get authentication data
+ * from this synchronous callback so we are blocking
+ * until we get them
+ */
+ while (samba->waiting)
+ {
+ g_usleep (POLL_DELAY);
+ }
+
+ /* Samba tries to call the auth_fn again if we just set the values
+ * to NULL when we want to cancel the authentication
+ */
+ if (samba->username == NULL && samba->password == NULL)
+ data->cancelled = TRUE;
+
+ if (samba->username != NULL)
+ {
+ if (g_strcmp0 (username, samba->username) != 0)
+ g_strlcpy (username, samba->username, unmaxlen);
+ }
+ else
+ {
+ username[0] = '\0';
+ }
+
+ if (samba->password != NULL)
+ {
+ if (g_strcmp0 (password, samba->password) != 0)
+ g_strlcpy (password, samba->password, pwmaxlen);
+ }
+ else
+ {
+ password[0] = '\0';
+ }
+
+ }
+}
+
+static void
+anonymous_auth_fn (SMBCCTX *smb_context,
+ const char *server,
+ const char *share,
+ char *workgroup,
+ int wgmaxlen,
+ char *username,
+ int unmaxlen,
+ char *password,
+ int pwmaxlen)
+{
+ username[0] = '\0';
+ password[0] = '\0';
+}
+
+static void
+list_dir (SMBCCTX *smb_context,
+ const gchar *dirname,
+ const gchar *path,
+ GCancellable *cancellable,
+ SMBData *data)
+{
+ struct smbc_dirent *dirent;
+ smbc_closedir_fn smbclient_closedir;
+ smbc_readdir_fn smbclient_readdir;
+ smbc_opendir_fn smbclient_opendir;
+ const gchar *host_name;
+ SMBCFILE *dir;
+
+ if (!g_cancellable_is_cancelled (cancellable))
+ {
+ smbclient_closedir = smbc_getFunctionClosedir (smb_context);
+ smbclient_readdir = smbc_getFunctionReaddir (smb_context);
+ smbclient_opendir = smbc_getFunctionOpendir (smb_context);
+
+ dir = smbclient_opendir (smb_context, dirname);
+ if (!dir && errno == EACCES)
+ {
+ if (g_str_has_prefix (dirname, "smb://"))
+ host_name = dirname + 6;
+ else
+ host_name = dirname;
+
+ if (data->auth_if_needed)
+ {
+ data->cancelled = FALSE;
+ smbc_setFunctionAuthDataWithContext (smb_context, auth_fn);
+ dir = smbclient_opendir (smb_context, dirname);
+ smbc_setFunctionAuthDataWithContext (smb_context, anonymous_auth_fn);
+
+ if (data->cancelled)
+ {
+ PpPrintDevice *device = g_object_new (PP_TYPE_PRINT_DEVICE,
+ "host-name", host_name,
+ "is-authenticated-server", TRUE,
+ NULL);
+ g_ptr_array_add (data->devices, device);
+
+ if (dir)
+ smbclient_closedir (smb_context, dir);
+ return;
+ }
+ }
+ else
+ {
+ PpPrintDevice *device = g_object_new (PP_TYPE_PRINT_DEVICE,
+ "host-name", host_name,
+ "is-authenticated-server", TRUE,
+ NULL);
+ g_ptr_array_add (data->devices, device);
+ }
+ }
+
+ while (dir && (dirent = smbclient_readdir (smb_context, dir)))
+ {
+ g_autofree gchar *subdirname = NULL;
+ g_autofree gchar *subpath = NULL;
+
+ if (dirent->smbc_type == SMBC_WORKGROUP)
+ {
+ subdirname = g_strdup_printf ("%s%s", dirname, dirent->name);
+ subpath = g_strdup_printf ("%s%s", path, dirent->name);
+ }
+
+ if (dirent->smbc_type == SMBC_SERVER)
+ {
+ subdirname = g_strdup_printf ("smb://%s", dirent->name);
+ subpath = g_strdup_printf ("%s//%s", path, dirent->name);
+ }
+
+ if (dirent->smbc_type == SMBC_PRINTER_SHARE)
+ {
+ g_autofree gchar *uri = NULL;
+ g_autofree gchar *device_name = NULL;
+ g_autofree gchar *device_uri = NULL;
+ PpPrintDevice *device;
+
+ uri = g_strdup_printf ("%s/%s", dirname, dirent->name);
+ device_uri = g_uri_escape_string (uri,
+ G_URI_RESERVED_CHARS_GENERIC_DELIMITERS
+ G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS,
+ FALSE);
+
+ device_name = g_strdup (dirent->name);
+ g_strcanon (device_name, ALLOWED_CHARACTERS, '-');
+
+ device = g_object_new (PP_TYPE_PRINT_DEVICE,
+ "device-uri", device_uri,
+ "is-network-device", TRUE,
+ "device-info", dirent->comment,
+ "device-name", device_name,
+ "acquisition-method", data->hostname_set ? ACQUISITION_METHOD_SAMBA_HOST : ACQUISITION_METHOD_SAMBA,
+ "device-location", path,
+ "host-name", dirname,
+ NULL);
+
+ g_ptr_array_add (data->devices, device);
+ }
+
+ if (subdirname)
+ {
+ list_dir (smb_context,
+ subdirname,
+ subpath,
+ cancellable,
+ data);
+ }
+ }
+
+ if (dir)
+ smbclient_closedir (smb_context, dir);
+ }
+}
+
+static void
+_pp_samba_get_devices_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ static GMutex mutex;
+ SMBData *data = (SMBData *) task_data;
+ SMBCCTX *smb_context;
+
+ data->devices = g_ptr_array_new_with_free_func (g_object_unref);
+ data->samba = PP_SAMBA (source_object);
+
+ g_mutex_lock (&mutex);
+
+ smb_context = smbc_new_context ();
+ if (smb_context)
+ {
+ if (smbc_init_context (smb_context))
+ {
+ g_autofree gchar *hostname = NULL;
+ g_autofree gchar *dirname = NULL;
+ g_autofree gchar *path = NULL;
+
+ smbc_setOptionUserData (smb_context, data);
+
+ g_object_get (source_object, "hostname", &hostname, NULL);
+ if (hostname != NULL)
+ {
+ dirname = g_strdup_printf ("smb://%s", hostname);
+ path = g_strdup_printf ("//%s", hostname);
+ }
+ else
+ {
+ dirname = g_strdup_printf ("smb://");
+ path = g_strdup_printf ("//");
+ }
+
+ smbc_setFunctionAuthDataWithContext (smb_context, anonymous_auth_fn);
+ list_dir (smb_context, dirname, path, cancellable, data);
+ }
+
+ smbc_free_context (smb_context, 1);
+ }
+
+ g_mutex_unlock (&mutex);
+
+ g_task_return_pointer (task, g_ptr_array_ref (data->devices), (GDestroyNotify) g_ptr_array_unref);
+}
+
+void
+pp_samba_get_devices_async (PpSamba *samba,
+ gboolean auth_if_needed,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+ SMBData *data;
+ g_autofree gchar *hostname = NULL;
+
+ g_object_get (G_OBJECT (samba), "hostname", &hostname, NULL);
+
+ task = g_task_new (samba, cancellable, callback, user_data);
+ data = g_new0 (SMBData, 1);
+ data->devices = NULL;
+ data->context = g_main_context_default ();
+ data->hostname_set = hostname != NULL;
+ data->auth_if_needed = auth_if_needed;
+
+ g_task_set_task_data (task, data, (GDestroyNotify) smb_data_free);
+ g_task_run_in_thread (task, _pp_samba_get_devices_thread);
+}
+
+GPtrArray *
+pp_samba_get_devices_finish (PpSamba *samba,
+ GAsyncResult *res,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (res, samba), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ return g_task_propagate_pointer (G_TASK (res), error);
+}
diff --git a/panels/printers/pp-samba.h b/panels/printers/pp-samba.h
new file mode 100644
index 0000000..0801317
--- /dev/null
+++ b/panels/printers/pp-samba.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 - 2013 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marek Kasik <mkasik@redhat.com>
+ */
+
+#pragma once
+
+#include "pp-host.h"
+#include "pp-utils.h"
+
+G_BEGIN_DECLS
+
+#define PP_TYPE_SAMBA (pp_samba_get_type ())
+G_DECLARE_FINAL_TYPE (PpSamba, pp_samba, PP, SAMBA, PpHost)
+
+PpSamba *pp_samba_new (const gchar *hostname);
+
+void pp_samba_get_devices_async (PpSamba *samba,
+ gboolean auth_if_needed,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GPtrArray *pp_samba_get_devices_finish (PpSamba *samba,
+ GAsyncResult *result,
+ GError **error);
+
+void pp_samba_set_auth_info (PpSamba *samba,
+ const gchar *username,
+ const gchar *password);
+
+G_END_DECLS
diff --git a/panels/printers/pp-utils.c b/panels/printers/pp-utils.c
new file mode 100644
index 0000000..750b634
--- /dev/null
+++ b/panels/printers/pp-utils.c
@@ -0,0 +1,3645 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2009-2010 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <gtk/gtk.h>
+#include <cups/cups.h>
+#include <cups/ppd.h>
+
+#include "pp-utils.h"
+
+#define DBUS_TIMEOUT 120000
+#define DBUS_TIMEOUT_LONG 600000
+
+#if (CUPS_VERSION_MAJOR > 1) || (CUPS_VERSION_MINOR > 5)
+#define HAVE_CUPS_1_6 1
+#endif
+
+#ifndef HAVE_CUPS_1_6
+#define ippGetCount(attr) attr->num_values
+#define ippGetGroupTag(attr) attr->group_tag
+#define ippGetValueTag(attr) attr->value_tag
+#define ippGetName(attr) attr->name
+#define ippGetStatusCode(ipp) ipp->request.status.status_code
+#define ippGetInteger(attr, element) attr->values[element].integer
+#define ippGetString(attr, element, language) attr->values[element].string.text
+#define ippGetBoolean(attr, element) attr->values[element].boolean
+
+static int
+ippGetRange (ipp_attribute_t *attr,
+ int element,
+ int *upper)
+{
+ *upper = attr->values[element].range.upper;
+ return (attr->values[element].range.lower);
+}
+
+static ipp_attribute_t *
+ippFirstAttribute (ipp_t *ipp)
+{
+ if (!ipp)
+ return (NULL);
+ return (ipp->current = ipp->attrs);
+}
+
+static ipp_attribute_t *
+ippNextAttribute (ipp_t *ipp)
+{
+ if (!ipp || !ipp->current)
+ return (NULL);
+ return (ipp->current = ipp->current->next);
+}
+#endif
+
+#if (CUPS_VERSION_MAJOR == 1) && (CUPS_VERSION_MINOR <= 6)
+#define HTTP_URI_STATUS_OK HTTP_URI_OK
+#endif
+
+gchar *
+get_tag_value (const gchar *tag_string, const gchar *tag_name)
+{
+ gchar **tag_string_splitted = NULL;
+ gchar *tag_value = NULL;
+ gint tag_name_length;
+ gint i;
+
+ if (tag_string && tag_name)
+ {
+ tag_name_length = strlen (tag_name);
+ tag_string_splitted = g_strsplit (tag_string, ";", 0);
+ if (tag_string_splitted)
+ {
+ for (i = 0; i < g_strv_length (tag_string_splitted); i++)
+ if (g_ascii_strncasecmp (tag_string_splitted[i], tag_name, tag_name_length) == 0)
+ if (strlen (tag_string_splitted[i]) > tag_name_length + 1)
+ tag_value = g_strdup (tag_string_splitted[i] + tag_name_length + 1);
+
+ g_strfreev (tag_string_splitted);
+ }
+ }
+
+ return tag_value;
+}
+
+
+/*
+ * Normalize given string so that it is lowercase, doesn't
+ * have trailing or leading whitespaces and digits doesn't
+ * neighbour with alphabetic.
+ * (see cupshelpers/ppds.py from system-config-printer)
+ */
+static gchar *
+normalize (const gchar *input_string)
+{
+ gchar *result = NULL;
+ gint i, j = 0, k = -1;
+
+ if (input_string)
+ {
+ g_autofree gchar *tmp = g_strstrip (g_ascii_strdown (input_string, -1));
+ if (tmp)
+ {
+ g_autofree gchar *res = g_new (gchar, 2 * strlen (tmp));
+
+ for (i = 0; i < strlen (tmp); i++)
+ {
+ if ((g_ascii_isalpha (tmp[i]) && k >= 0 && g_ascii_isdigit (res[k])) ||
+ (g_ascii_isdigit (tmp[i]) && k >= 0 && g_ascii_isalpha (res[k])))
+ {
+ res[j] = ' ';
+ k = j++;
+ res[j] = tmp[i];
+ k = j++;
+ }
+ else
+ {
+ if (g_ascii_isspace (tmp[i]) || !g_ascii_isalnum (tmp[i]))
+ {
+ if (!(k >= 0 && res[k] == ' '))
+ {
+ res[j] = ' ';
+ k = j++;
+ }
+ }
+ else
+ {
+ res[j] = tmp[i];
+ k = j++;
+ }
+ }
+ }
+
+ res[j] = '\0';
+
+ result = g_strdup (res);
+ }
+ }
+
+ return result;
+}
+
+
+char *
+get_dest_attr (const char *dest_name,
+ const char *attr)
+{
+ cups_dest_t *dests;
+ int num_dests;
+ cups_dest_t *dest;
+ const char *value;
+ char *ret;
+
+ if (dest_name == NULL)
+ return NULL;
+
+ ret = NULL;
+
+ num_dests = cupsGetDests (&dests);
+ if (num_dests < 1) {
+ g_debug ("Unable to get printer destinations");
+ return NULL;
+ }
+
+ dest = cupsGetDest (dest_name, NULL, num_dests, dests);
+ if (dest == NULL) {
+ g_debug ("Unable to find a printer named '%s'", dest_name);
+ goto out;
+ }
+
+ value = cupsGetOption (attr, dest->num_options, dest->options);
+ if (value == NULL) {
+ g_debug ("Unable to get %s for '%s'", attr, dest_name);
+ goto out;
+ }
+ ret = g_strdup (value);
+out:
+ cupsFreeDests (num_dests, dests);
+
+ return ret;
+}
+
+gchar *
+get_ppd_attribute (const gchar *ppd_file_name,
+ const gchar *attribute_name)
+{
+ ppd_file_t *ppd_file = NULL;
+ ppd_attr_t *ppd_attr = NULL;
+ gchar *result = NULL;
+
+ if (ppd_file_name)
+ {
+ ppd_file = ppdOpenFile (ppd_file_name);
+
+ if (ppd_file)
+ {
+ ppd_attr = ppdFindAttr (ppd_file, attribute_name, NULL);
+ if (ppd_attr != NULL)
+ result = g_strdup (ppd_attr->value);
+ ppdClose (ppd_file);
+ }
+ }
+
+ return result;
+}
+
+/* Set default destination in ~/.cups/lpoptions.
+ * Unset default destination if "dest" is NULL.
+ */
+void
+set_local_default_printer (const gchar *printer_name)
+{
+ cups_dest_t *dests = NULL;
+ int num_dests = 0;
+ int i;
+
+ num_dests = cupsGetDests (&dests);
+
+ for (i = 0; i < num_dests; i ++)
+ {
+ if (printer_name && g_strcmp0 (dests[i].name, printer_name) == 0)
+ dests[i].is_default = 1;
+ else
+ dests[i].is_default = 0;
+ }
+
+ cupsSetDests (num_dests, dests);
+}
+
+/*
+ * This function does something which should be provided by CUPS...
+ * It returns FALSE if the renaming fails.
+ */
+gboolean
+printer_rename (const gchar *old_name,
+ const gchar *new_name)
+{
+ ipp_attribute_t *attr = NULL;
+ cups_ptype_t printer_type = 0;
+ cups_dest_t *dests = NULL;
+ cups_dest_t *dest = NULL;
+ cups_job_t *jobs = NULL;
+ g_autoptr(GDBusConnection) bus = NULL;
+ const gchar *printer_location = NULL;
+ const gchar *printer_info = NULL;
+ const gchar *printer_uri = NULL;
+ const gchar *device_uri = NULL;
+ const gchar *job_sheets = NULL;
+ gboolean result = FALSE;
+ gboolean accepting = TRUE;
+ gboolean printer_paused = FALSE;
+ gboolean default_printer = FALSE;
+ gboolean printer_shared = FALSE;
+ g_autoptr(GError) error = NULL;
+ http_t *http;
+ g_autofree gchar *ppd_link = NULL;
+ g_autofree gchar *ppd_filename = NULL;
+ gchar **sheets = NULL;
+ gchar **users_allowed = NULL;
+ gchar **users_denied = NULL;
+ gchar **member_names = NULL;
+ const gchar *start_sheet = NULL;
+ const gchar *end_sheet = NULL;
+ g_autofree gchar *error_policy = NULL;
+ g_autofree gchar *op_policy = NULL;
+ ipp_t *request;
+ ipp_t *response;
+ gint i;
+ int num_dests = 0;
+ int num_jobs = 0;
+ static const char * const requested_attrs[] = {
+ "printer-error-policy",
+ "printer-op-policy",
+ "requesting-user-name-allowed",
+ "requesting-user-name-denied",
+ "member-names"};
+
+ if (old_name == NULL ||
+ old_name[0] == '\0' ||
+ new_name == NULL ||
+ new_name[0] == '\0' ||
+ g_strcmp0 (old_name, new_name) == 0)
+ return FALSE;
+
+ num_dests = cupsGetDests (&dests);
+
+ dest = cupsGetDest (new_name, NULL, num_dests, dests);
+ if (dest)
+ {
+ cupsFreeDests (num_dests, dests);
+ return FALSE;
+ }
+
+ num_jobs = cupsGetJobs (&jobs, old_name, 0, CUPS_WHICHJOBS_ACTIVE);
+ cupsFreeJobs (num_jobs, jobs);
+ if (num_jobs > 1)
+ {
+ g_warning ("There are queued jobs on printer %s!", old_name);
+ cupsFreeDests (num_dests, dests);
+ return FALSE;
+ }
+
+ /*
+ * Gather some informations about the original printer
+ */
+ dest = cupsGetDest (old_name, NULL, num_dests, dests);
+ if (dest)
+ {
+ for (i = 0; i < dest->num_options; i++)
+ {
+ if (g_strcmp0 (dest->options[i].name, "printer-is-accepting-jobs") == 0)
+ accepting = g_strcmp0 (dest->options[i].value, "true") == 0;
+ else if (g_strcmp0 (dest->options[i].name, "printer-is-shared") == 0)
+ printer_shared = g_strcmp0 (dest->options[i].value, "true") == 0;
+ else if (g_strcmp0 (dest->options[i].name, "device-uri") == 0)
+ device_uri = dest->options[i].value;
+ else if (g_strcmp0 (dest->options[i].name, "printer-uri-supported") == 0)
+ printer_uri = dest->options[i].value;
+ else if (g_strcmp0 (dest->options[i].name, "printer-info") == 0)
+ printer_info = dest->options[i].value;
+ else if (g_strcmp0 (dest->options[i].name, "printer-location") == 0)
+ printer_location = dest->options[i].value;
+ else if (g_strcmp0 (dest->options[i].name, "printer-state") == 0)
+ printer_paused = g_strcmp0 (dest->options[i].value, "5") == 0;
+ else if (g_strcmp0 (dest->options[i].name, "job-sheets") == 0)
+ job_sheets = dest->options[i].value;
+ else if (g_strcmp0 (dest->options[i].name, "printer-type") == 0)
+ printer_type = atoi (dest->options[i].value);
+ }
+ default_printer = dest->is_default;
+ }
+ cupsFreeDests (num_dests, dests);
+
+ if (accepting)
+ {
+ printer_set_accepting_jobs (old_name, FALSE, NULL);
+
+ num_jobs = cupsGetJobs (&jobs, old_name, 0, CUPS_WHICHJOBS_ACTIVE);
+ cupsFreeJobs (num_jobs, jobs);
+ if (num_jobs > 1)
+ {
+ printer_set_accepting_jobs (old_name, accepting, NULL);
+ g_warning ("There are queued jobs on printer %s!", old_name);
+ return FALSE;
+ }
+ }
+
+
+ /*
+ * Gather additional informations about the original printer
+ */
+#ifdef HAVE_CUPS_HTTPCONNECT2
+ http = httpConnect2 (cupsServer (), ippPort (), NULL, AF_UNSPEC,
+ cupsEncryption (), 1, 30000, NULL);
+#else
+ http = httpConnectEncrypt (cupsServer (), ippPort (), cupsEncryption ());
+#endif
+ if (http != NULL)
+ {
+ request = ippNewRequest (IPP_GET_PRINTER_ATTRIBUTES);
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, printer_uri);
+ ippAddStrings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", G_N_ELEMENTS (requested_attrs), NULL, requested_attrs);
+ response = cupsDoRequest (http, request, "/");
+
+ if (response)
+ {
+ if (ippGetStatusCode (response) <= IPP_OK_CONFLICT)
+ {
+ attr = ippFindAttribute (response, "printer-error-policy", IPP_TAG_NAME);
+ if (attr)
+ error_policy = g_strdup (ippGetString (attr, 0, NULL));
+
+ attr = ippFindAttribute (response, "printer-op-policy", IPP_TAG_NAME);
+ if (attr)
+ op_policy = g_strdup (ippGetString (attr, 0, NULL));
+
+ attr = ippFindAttribute (response, "requesting-user-name-allowed", IPP_TAG_NAME);
+ if (attr && ippGetCount (attr) > 0)
+ {
+ users_allowed = g_new0 (gchar *, ippGetCount (attr) + 1);
+ for (i = 0; i < ippGetCount (attr); i++)
+ users_allowed[i] = g_strdup (ippGetString (attr, i, NULL));
+ }
+
+ attr = ippFindAttribute (response, "requesting-user-name-denied", IPP_TAG_NAME);
+ if (attr && ippGetCount (attr) > 0)
+ {
+ users_denied = g_new0 (gchar *, ippGetCount (attr) + 1);
+ for (i = 0; i < ippGetCount (attr); i++)
+ users_denied[i] = g_strdup (ippGetString (attr, i, NULL));
+ }
+
+ attr = ippFindAttribute (response, "member-names", IPP_TAG_NAME);
+ if (attr && ippGetCount (attr) > 0)
+ {
+ member_names = g_new0 (gchar *, ippGetCount (attr) + 1);
+ for (i = 0; i < ippGetCount (attr); i++)
+ member_names[i] = g_strdup (ippGetString (attr, i, NULL));
+ }
+ }
+ ippDelete (response);
+ }
+ httpClose (http);
+ }
+
+ if (job_sheets)
+ {
+ sheets = g_strsplit (job_sheets, ",", 0);
+ if (g_strv_length (sheets) > 1)
+ {
+ start_sheet = sheets[0];
+ end_sheet = sheets[1];
+ }
+ }
+
+ ppd_link = g_strdup (cupsGetPPD (old_name));
+ if (ppd_link)
+ {
+ ppd_filename = g_file_read_link (ppd_link, NULL);
+
+ if (!ppd_filename)
+ ppd_filename = g_strdup (ppd_link);
+ }
+
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!bus)
+ {
+ g_warning ("Failed to get system bus: %s", error->message);
+ }
+ else
+ {
+ if (printer_type & CUPS_PRINTER_CLASS)
+ {
+ if (member_names)
+ for (i = 0; i < g_strv_length (member_names); i++)
+ class_add_printer (new_name, member_names[i]);
+ }
+ else
+ {
+ g_autoptr(GVariant) output = NULL;
+ g_autoptr(GError) add_error = NULL;
+
+ output = g_dbus_connection_call_sync (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "PrinterAddWithPpdFile",
+ g_variant_new ("(sssss)",
+ new_name,
+ device_uri ? device_uri : "",
+ ppd_filename ? ppd_filename : "",
+ printer_info ? printer_info : "",
+ printer_location ? printer_location : ""),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &add_error);
+
+ if (output)
+ {
+ const gchar *ret_error;
+
+ g_variant_get (output, "(&s)", &ret_error);
+ if (ret_error[0] != '\0')
+ g_warning ("cups-pk-helper: rename of printer %s to %s failed: %s", old_name, new_name, ret_error);
+ }
+ else
+ {
+ g_warning ("%s", add_error->message);
+ }
+ }
+ }
+
+ if (ppd_link)
+ {
+ g_unlink (ppd_link);
+ }
+
+ num_dests = cupsGetDests (&dests);
+ dest = cupsGetDest (new_name, NULL, num_dests, dests);
+ if (dest)
+ {
+ printer_set_accepting_jobs (new_name, accepting, NULL);
+ printer_set_enabled (new_name, !printer_paused);
+ printer_set_shared (new_name, printer_shared);
+ printer_set_job_sheets (new_name, start_sheet, end_sheet);
+ printer_set_policy (new_name, op_policy, FALSE);
+ printer_set_policy (new_name, error_policy, TRUE);
+ printer_set_users (new_name, users_allowed, TRUE);
+ printer_set_users (new_name, users_denied, FALSE);
+ if (default_printer)
+ printer_set_default (new_name);
+
+ printer_delete (old_name);
+
+ result = TRUE;
+ }
+ else
+ printer_set_accepting_jobs (old_name, accepting, NULL);
+
+ cupsFreeDests (num_dests, dests);
+ if (sheets)
+ g_strfreev (sheets);
+ if (users_allowed)
+ g_strfreev (users_allowed);
+ if (users_denied)
+ g_strfreev (users_denied);
+
+ return result;
+}
+
+gboolean
+printer_set_location (const gchar *printer_name,
+ const gchar *location)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+ g_autoptr(GVariant) output = NULL;
+ const gchar *ret_error;
+ g_autoptr(GError) error = NULL;
+
+ if (!printer_name || !location)
+ return TRUE;
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!bus)
+ {
+ g_warning ("Failed to get system bus: %s", error->message);
+ return TRUE;
+ }
+
+ output = g_dbus_connection_call_sync (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "PrinterSetLocation",
+ g_variant_new ("(ss)", printer_name, location),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if (output == NULL)
+ {
+ g_warning ("%s", error->message);
+ return FALSE;
+ }
+
+ g_variant_get (output, "(&s)", &ret_error);
+ if (ret_error[0] != '\0')
+ {
+ g_warning ("cups-pk-helper: setting of location for printer %s failed: %s", printer_name, ret_error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+printer_set_accepting_jobs (const gchar *printer_name,
+ gboolean accepting_jobs,
+ const gchar *reason)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+ g_autoptr(GVariant) output = NULL;
+ const gchar *ret_error;
+ g_autoptr(GError) error = NULL;
+
+ if (!printer_name)
+ return TRUE;
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!bus)
+ {
+ g_warning ("Failed to get system bus: %s", error->message);
+ return TRUE;
+ }
+
+ output = g_dbus_connection_call_sync (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "PrinterSetAcceptJobs",
+ g_variant_new ("(sbs)",
+ printer_name,
+ accepting_jobs,
+ reason ? reason : ""),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if (output == NULL)
+ {
+ g_warning ("%s", error->message);
+ return FALSE;
+ }
+
+ g_variant_get (output, "(&s)", &ret_error);
+ if (ret_error[0] != '\0')
+ {
+ g_warning ("cups-pk-helper: setting of acceptance of jobs for printer %s failed: %s", printer_name, ret_error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+printer_set_enabled (const gchar *printer_name,
+ gboolean enabled)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+ g_autoptr(GVariant) output = NULL;
+ const gchar *ret_error;
+ g_autoptr(GError) error = NULL;
+
+ if (!printer_name)
+ return TRUE;
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!bus)
+ {
+ g_warning ("Failed to get system bus: %s", error->message);
+ return TRUE;
+ }
+
+ output = g_dbus_connection_call_sync (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "PrinterSetEnabled",
+ g_variant_new ("(sb)", printer_name, enabled),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if (output == NULL)
+ {
+ g_warning ("%s", error->message);
+ return FALSE;
+ }
+
+ g_variant_get (output, "(&s)", &ret_error);
+ if (ret_error[0] != '\0')
+ {
+ g_warning ("cups-pk-helper: setting of enablement of printer %s failed: %s", printer_name, ret_error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+printer_delete (const gchar *printer_name)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+ g_autoptr(GVariant) output = NULL;
+ const gchar *ret_error;
+ g_autoptr(GError) error = NULL;
+
+ if (!printer_name)
+ return TRUE;
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!bus)
+ {
+ g_warning ("Failed to get system bus: %s", error->message);
+ return TRUE;
+ }
+
+ output = g_dbus_connection_call_sync (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "PrinterDelete",
+ g_variant_new ("(s)", printer_name),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if (output == NULL)
+ {
+ g_warning ("%s", error->message);
+ return FALSE;
+ }
+
+ g_variant_get (output, "(&s)", &ret_error);
+ if (ret_error[0] != '\0')
+ {
+ g_warning ("cups-pk-helper: removing of printer %s failed: %s", printer_name, ret_error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+printer_set_default (const gchar *printer_name)
+{
+ const char *cups_server;
+ g_autoptr(GError) error = NULL;
+
+ if (!printer_name)
+ return TRUE;
+
+ cups_server = cupsServer ();
+ if (g_ascii_strncasecmp (cups_server, "localhost", 9) == 0 ||
+ g_ascii_strncasecmp (cups_server, "127.0.0.1", 9) == 0 ||
+ g_ascii_strncasecmp (cups_server, "::1", 3) == 0 ||
+ cups_server[0] == '/')
+ {
+ g_autoptr(GDBusConnection) bus = NULL;
+ g_autoptr(GVariant) output = NULL;
+ const gchar *ret_error;
+
+ /* Clean .cups/lpoptions before setting
+ * default printer on local CUPS server.
+ */
+ set_local_default_printer (NULL);
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!bus)
+ {
+ g_warning ("Failed to get system bus: %s", error->message);
+ return FALSE;
+ }
+
+ output = g_dbus_connection_call_sync (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "PrinterSetDefault",
+ g_variant_new ("(s)", printer_name),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if (output == NULL)
+ {
+ g_warning ("%s", error->message);
+ return FALSE;
+ }
+
+ g_variant_get (output, "(&s)", &ret_error);
+ if (ret_error[0] != '\0')
+ {
+ g_warning ("cups-pk-helper: setting default printer to %s failed: %s", printer_name, ret_error);
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+ else
+ /* Store default printer to .cups/lpoptions
+ * if we are connected to a remote CUPS server.
+ */
+ {
+ set_local_default_printer (printer_name);
+ return TRUE;
+ }
+}
+
+gboolean
+printer_set_shared (const gchar *printer_name,
+ gboolean shared)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+ g_autoptr(GVariant) output = NULL;
+ const gchar *ret_error;
+ g_autoptr(GError) error = NULL;
+
+ if (!printer_name)
+ return TRUE;
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!bus)
+ {
+ g_warning ("Failed to get system bus: %s", error->message);
+ return TRUE;
+ }
+
+ output = g_dbus_connection_call_sync (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "PrinterSetShared",
+ g_variant_new ("(sb)", printer_name, shared),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if (output == NULL)
+ {
+ g_warning ("%s", error->message);
+ return FALSE;
+ }
+
+ g_variant_get (output, "(&s)", &ret_error);
+ if (ret_error[0] != '\0')
+ {
+ g_warning ("cups-pk-helper: setting of sharing of printer %s failed: %s", printer_name, ret_error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+printer_set_job_sheets (const gchar *printer_name,
+ const gchar *start_sheet,
+ const gchar *end_sheet)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+ g_autoptr(GVariant) output = NULL;
+ const gchar *ret_error;
+ g_autoptr(GError) error = NULL;
+
+ if (!printer_name || !start_sheet || !end_sheet)
+ return TRUE;
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!bus)
+ {
+ g_warning ("Failed to get system bus: %s", error->message);
+ return TRUE;
+ }
+
+ output = g_dbus_connection_call_sync (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "PrinterSetJobSheets",
+ g_variant_new ("(sss)", printer_name, start_sheet, end_sheet),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if (output == NULL)
+ {
+ g_warning ("%s", error->message);
+ return FALSE;
+ }
+
+ g_variant_get (output, "(&s)", &ret_error);
+ if (ret_error[0] != '\0')
+ {
+ g_warning ("cups-pk-helper: setting of job sheets for printer %s failed: %s", printer_name, ret_error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+printer_set_policy (const gchar *printer_name,
+ const gchar *policy,
+ gboolean error_policy)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+ g_autoptr(GVariant) output = NULL;
+ const gchar *ret_error;
+ g_autoptr(GError) error = NULL;
+
+ if (!printer_name || !policy)
+ return TRUE;
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!bus)
+ {
+ g_warning ("Failed to get system bus: %s", error->message);
+ return TRUE;
+ }
+
+ if (error_policy)
+ output = g_dbus_connection_call_sync (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "PrinterSetErrorPolicy",
+ g_variant_new ("(ss)", printer_name, policy),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+ else
+ output = g_dbus_connection_call_sync (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "PrinterSetOpPolicy",
+ g_variant_new ("(ss)", printer_name, policy),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if (output == NULL)
+ {
+ g_warning ("%s", error->message);
+ return FALSE;
+ }
+
+ g_variant_get (output, "(&s)", &ret_error);
+ if (ret_error[0] != '\0')
+ {
+ g_warning ("cups-pk-helper: setting of a policy for printer %s failed: %s", printer_name, ret_error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+printer_set_users (const gchar *printer_name,
+ gchar **users,
+ gboolean allowed)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+ GVariantBuilder array_builder;
+ gint i;
+ g_autoptr(GVariant) output = NULL;
+ const gchar *ret_error;
+ g_autoptr(GError) error = NULL;
+
+ if (!printer_name || !users)
+ return TRUE;
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!bus)
+ {
+ g_warning ("Failed to get system bus: %s", error->message);
+ return TRUE;
+ }
+
+ g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("as"));
+ for (i = 0; users[i]; i++)
+ g_variant_builder_add (&array_builder, "s", users[i]);
+
+ if (allowed)
+ output = g_dbus_connection_call_sync (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "PrinterSetUsersAllowed",
+ g_variant_new ("(sas)", printer_name, &array_builder),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+ else
+ output = g_dbus_connection_call_sync (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "PrinterSetUsersDenied",
+ g_variant_new ("(sas)", printer_name, &array_builder),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if (output == NULL)
+ {
+ g_warning ("%s", error->message);
+ return FALSE;
+ }
+
+ g_variant_get (output, "(&s)", &ret_error);
+ if (ret_error[0] != '\0')
+ {
+ g_warning ("cups-pk-helper: setting of access list for printer %s failed: %s", printer_name, ret_error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+class_add_printer (const gchar *class_name,
+ const gchar *printer_name)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+ g_autoptr(GVariant) output = NULL;
+ const gchar *ret_error;
+ g_autoptr(GError) error = NULL;
+
+ if (!class_name || !printer_name)
+ return TRUE;
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!bus)
+ {
+ g_warning ("Failed to get system bus: %s", error->message);
+ return TRUE;
+ }
+
+ output = g_dbus_connection_call_sync (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "ClassAddPrinter",
+ g_variant_new ("(ss)", class_name, printer_name),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if (output == NULL)
+ {
+ g_warning ("%s", error->message);
+ return FALSE;
+ }
+
+ g_variant_get (output, "(&s)", &ret_error);
+ if (ret_error[0] != '\0')
+ {
+ g_warning ("cups-pk-helper: adding of printer %s to class %s failed: %s", printer_name, class_name, ret_error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+printer_is_local (cups_ptype_t printer_type,
+ const gchar *device_uri)
+{
+ gboolean result = TRUE;
+ char scheme[HTTP_MAX_URI];
+ char username[HTTP_MAX_URI];
+ char hostname[HTTP_MAX_URI];
+ char resource[HTTP_MAX_URI];
+ int port;
+
+ if (printer_type &
+ (CUPS_PRINTER_DISCOVERED |
+ CUPS_PRINTER_REMOTE |
+ CUPS_PRINTER_IMPLICIT))
+ result = FALSE;
+
+ if (device_uri == NULL || !result)
+ return result;
+
+ httpSeparateURI (HTTP_URI_CODING_ALL, device_uri,
+ scheme, sizeof (scheme),
+ username, sizeof (username),
+ hostname, sizeof (hostname),
+ &port,
+ resource, sizeof (resource));
+
+ if (g_str_equal (scheme, "ipp") ||
+ g_str_equal (scheme, "smb") ||
+ g_str_equal (scheme, "socket") ||
+ g_str_equal (scheme, "lpd"))
+ result = FALSE;
+
+ return result;
+}
+
+gchar*
+printer_get_hostname (cups_ptype_t printer_type,
+ const gchar *device_uri,
+ const gchar *printer_uri)
+{
+ gboolean local = TRUE;
+ gchar *result = NULL;
+ char scheme[HTTP_MAX_URI];
+ char username[HTTP_MAX_URI];
+ char hostname[HTTP_MAX_URI];
+ char resource[HTTP_MAX_URI];
+ int port;
+
+ if (device_uri == NULL)
+ return result;
+
+ if (printer_type & (CUPS_PRINTER_DISCOVERED |
+ CUPS_PRINTER_REMOTE |
+ CUPS_PRINTER_IMPLICIT))
+ {
+ if (printer_uri)
+ {
+ httpSeparateURI (HTTP_URI_CODING_ALL, printer_uri,
+ scheme, sizeof (scheme),
+ username, sizeof (username),
+ hostname, sizeof (hostname),
+ &port,
+ resource, sizeof (resource));
+
+ if (hostname[0] != '\0')
+ result = g_strdup (hostname);
+ }
+
+ local = FALSE;
+ }
+
+ if (result == NULL && device_uri)
+ {
+ httpSeparateURI (HTTP_URI_CODING_ALL, device_uri,
+ scheme, sizeof (scheme),
+ username, sizeof (username),
+ hostname, sizeof (hostname),
+ &port,
+ resource, sizeof (resource));
+
+ if (g_str_equal (scheme, "ipp") ||
+ g_str_equal (scheme, "smb") ||
+ g_str_equal (scheme, "socket") ||
+ g_str_equal (scheme, "lpd"))
+ {
+ if (hostname[0] != '\0')
+ result = g_strdup (hostname);
+
+ local = FALSE;
+ }
+ }
+
+ if (local)
+ result = g_strdup ("localhost");
+
+ return result;
+}
+
+/* Returns default page size for current locale */
+const gchar *
+get_page_size_from_locale (void)
+{
+ if (g_str_equal (gtk_paper_size_get_default (), GTK_PAPER_NAME_LETTER))
+ return "Letter";
+ else
+ return "A4";
+}
+
+typedef struct
+{
+ gchar *printer_name;
+ gchar **attributes_names;
+ GHashTable *result;
+ GIACallback callback;
+ gpointer user_data;
+ GMainContext *context;
+} GIAData;
+
+static GIAData *
+gia_data_new (const gchar *printer_name, gchar **attributes_names, GIACallback callback, gpointer user_data)
+{
+ GIAData *data;
+
+ data = g_new0 (GIAData, 1);
+ data->printer_name = g_strdup (printer_name);
+ data->attributes_names = g_strdupv (attributes_names);
+ data->callback = callback;
+ data->user_data = user_data;
+ data->context = g_main_context_ref_thread_default ();
+
+ return data;
+}
+
+static void
+gia_data_free (GIAData *data)
+{
+ g_free (data->printer_name);
+ if (data->attributes_names)
+ g_strfreev (data->attributes_names);
+ if (data->result)
+ g_hash_table_unref (data->result);
+ if (data->context)
+ g_main_context_unref (data->context);
+ g_free (data);
+}
+
+static gboolean
+get_ipp_attributes_idle_cb (gpointer user_data)
+{
+ GIAData *data = (GIAData *) user_data;
+
+ data->callback (data->result, data->user_data);
+
+ return FALSE;
+}
+
+static void
+get_ipp_attributes_cb (gpointer user_data)
+{
+ GIAData *data = user_data;
+ g_autoptr(GSource) idle_source = NULL;
+
+ idle_source = g_idle_source_new ();
+ g_source_set_callback (idle_source,
+ get_ipp_attributes_idle_cb,
+ data,
+ (GDestroyNotify) gia_data_free);
+ g_source_attach (idle_source, data->context);
+}
+
+static void
+ipp_attribute_free2 (gpointer attr)
+{
+ IPPAttribute *attribute = (IPPAttribute *) attr;
+ ipp_attribute_free (attribute);
+}
+
+static gpointer
+get_ipp_attributes_func (gpointer user_data)
+{
+ ipp_attribute_t *attr = NULL;
+ GIAData *data = user_data;
+ ipp_t *request;
+ ipp_t *response = NULL;
+ g_autofree gchar *printer_uri = NULL;
+ char **requested_attrs = NULL;
+ gint i, j, length = 0;
+
+ printer_uri = g_strdup_printf ("ipp://localhost/printers/%s", data->printer_name);
+
+ if (data->attributes_names)
+ {
+ length = g_strv_length (data->attributes_names);
+
+ requested_attrs = g_new0 (char *, length);
+ for (i = 0; data->attributes_names[i]; i++)
+ requested_attrs[i] = g_strdup (data->attributes_names[i]);
+
+ request = ippNewRequest (IPP_GET_PRINTER_ATTRIBUTES);
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, printer_uri);
+ ippAddStrings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", length, NULL, (const char **) requested_attrs);
+ response = cupsDoRequest (CUPS_HTTP_DEFAULT, request, "/");
+ }
+
+ if (response)
+ {
+ if (ippGetStatusCode (response) <= IPP_OK_CONFLICT)
+ {
+ for (j = 0; j < length; j++)
+ {
+ attr = ippFindAttribute (response, requested_attrs[j], IPP_TAG_ZERO);
+ if (attr && ippGetCount (attr) > 0 && ippGetValueTag (attr) != IPP_TAG_NOVALUE)
+ {
+ IPPAttribute *attribute;
+
+ attribute = g_new0 (IPPAttribute, 1);
+ attribute->attribute_name = g_strdup (requested_attrs[j]);
+ attribute->attribute_values = g_new0 (IPPAttributeValue, ippGetCount (attr));
+ attribute->num_of_values = ippGetCount (attr);
+
+ if (ippGetValueTag (attr) == IPP_TAG_INTEGER ||
+ ippGetValueTag (attr) == IPP_TAG_ENUM)
+ {
+ attribute->attribute_type = IPP_ATTRIBUTE_TYPE_INTEGER;
+
+ for (i = 0; i < ippGetCount (attr); i++)
+ attribute->attribute_values[i].integer_value = ippGetInteger (attr, i);
+ }
+ else if (ippGetValueTag (attr) == IPP_TAG_NAME ||
+ ippGetValueTag (attr) == IPP_TAG_STRING ||
+ ippGetValueTag (attr) == IPP_TAG_TEXT ||
+ ippGetValueTag (attr) == IPP_TAG_URI ||
+ ippGetValueTag (attr) == IPP_TAG_KEYWORD ||
+ ippGetValueTag (attr) == IPP_TAG_URISCHEME)
+ {
+ attribute->attribute_type = IPP_ATTRIBUTE_TYPE_STRING;
+
+ for (i = 0; i < ippGetCount (attr); i++)
+ attribute->attribute_values[i].string_value = g_strdup (ippGetString (attr, i, NULL));
+ }
+ else if (ippGetValueTag (attr) == IPP_TAG_RANGE)
+ {
+ attribute->attribute_type = IPP_ATTRIBUTE_TYPE_RANGE;
+
+ for (i = 0; i < ippGetCount (attr); i++)
+ {
+ attribute->attribute_values[i].lower_range =
+ ippGetRange (attr, i, &(attribute->attribute_values[i].upper_range));
+ }
+ }
+ else if (ippGetValueTag (attr) == IPP_TAG_BOOLEAN)
+ {
+ attribute->attribute_type = IPP_ATTRIBUTE_TYPE_BOOLEAN;
+
+ for (i = 0; i < ippGetCount (attr); i++)
+ attribute->attribute_values[i].boolean_value = ippGetBoolean (attr, i);
+ }
+
+ if (!data->result)
+ data->result = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, ipp_attribute_free2);
+
+ g_hash_table_insert (data->result, g_strdup (requested_attrs[j]), attribute);
+ }
+ }
+ }
+
+ ippDelete (response);
+ }
+
+
+ for (i = 0; i < length; i++)
+ g_free (requested_attrs[i]);
+ g_free (requested_attrs);
+
+ get_ipp_attributes_cb (data);
+
+ return NULL;
+}
+
+void
+get_ipp_attributes_async (const gchar *printer_name,
+ gchar **attributes_names,
+ GIACallback callback,
+ gpointer user_data)
+{
+ GIAData *data;
+ g_autoptr(GThread) thread = NULL;
+ g_autoptr(GError) error = NULL;
+
+ data = gia_data_new (printer_name, attributes_names, callback, user_data);
+
+ thread = g_thread_try_new ("get-ipp-attributes",
+ get_ipp_attributes_func,
+ data,
+ &error);
+
+ if (!thread)
+ {
+ g_warning ("%s", error->message);
+ callback (NULL, user_data);
+
+ gia_data_free (data);
+ }
+}
+
+IPPAttribute *
+ipp_attribute_copy (IPPAttribute *attr)
+{
+ IPPAttribute *result = NULL;
+ gint i;
+
+ if (attr)
+ {
+ result = g_new0 (IPPAttribute, 1);
+
+ *result = *attr;
+ result->attribute_name = g_strdup (attr->attribute_name);
+ result->attribute_values = g_new0 (IPPAttributeValue, attr->num_of_values);
+ for (i = 0; i < attr->num_of_values; i++)
+ {
+ result->attribute_values[i] = attr->attribute_values[i];
+ if (attr->attribute_values[i].string_value)
+ result->attribute_values[i].string_value = g_strdup (attr->attribute_values[i].string_value);
+ }
+ }
+
+ return result;
+}
+
+void
+ipp_attribute_free (IPPAttribute *attr)
+{
+ gint i;
+
+ if (attr)
+ {
+ for (i = 0; i < attr->num_of_values; i++)
+ g_free (attr->attribute_values[i].string_value);
+
+ g_free (attr->attribute_values);
+ g_free (attr->attribute_name);
+ g_free (attr);
+ }
+}
+
+typedef struct
+{
+ gchar *printer_name;
+ gchar *ppd_copy;
+ GCancellable *cancellable;
+ PSPCallback callback;
+ gpointer user_data;
+} PSPData;
+
+static PSPData *
+psp_data_new (const gchar *printer_name, const gchar *ppd_copy, GCancellable *cancellable, PSPCallback callback, gpointer user_data)
+{
+ PSPData *data;
+
+ data = g_new0 (PSPData, 1);
+ data->printer_name = g_strdup (printer_name);
+ data->ppd_copy = g_strdup (ppd_copy);
+ if (cancellable)
+ data->cancellable = g_object_ref (cancellable);
+ data->callback = callback;
+ data->user_data = user_data;
+ return data;
+}
+
+static void
+psp_data_free (PSPData *data)
+{
+ g_free (data->printer_name);
+ if (data->ppd_copy != NULL)
+ {
+ g_unlink (data->ppd_copy);
+ g_free (data->ppd_copy);
+ }
+ g_clear_object (&data->cancellable);
+ g_free (data);
+}
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (PSPData, psp_data_free)
+
+static void
+printer_set_ppd_async_dbus_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GVariant) output = NULL;
+ gboolean result = FALSE;
+ g_autoptr(PSPData) data = user_data;
+ g_autoptr(GError) error = NULL;
+
+ output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ res,
+ &error);
+
+ if (output)
+ {
+ const gchar *ret_error;
+
+ g_variant_get (output, "(&s)", &ret_error);
+ if (ret_error[0] != '\0')
+ g_warning ("cups-pk-helper: setting of driver for printer %s failed: %s", data->printer_name, ret_error);
+ else
+ result = TRUE;
+ }
+ else
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("%s", error->message);
+ }
+
+ /* Don't call callback if cancelled */
+ if (!data->cancellable ||
+ !g_cancellable_is_cancelled (data->cancellable))
+ data->callback (data->printer_name,
+ result,
+ data->user_data);
+}
+
+/*
+ * Set ppd for given printer.
+ * Don't use this for classes, just for printers.
+ */
+void
+printer_set_ppd_async (const gchar *printer_name,
+ const gchar *ppd_name,
+ GCancellable *cancellable,
+ PSPCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+ g_autoptr(GError) error = NULL;
+
+ if (printer_name == NULL ||
+ printer_name[0] == '\0')
+ {
+ callback (printer_name, FALSE, user_data);
+ return;
+ }
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!bus)
+ {
+ g_warning ("Failed to get system bus: %s", error->message);
+ callback (printer_name, FALSE, user_data);
+ return;
+ }
+
+ g_dbus_connection_call (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "PrinterAdd",
+ g_variant_new ("(sssss)",
+ printer_name,
+ "",
+ ppd_name,
+ "",
+ ""),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ printer_set_ppd_async_dbus_cb,
+ psp_data_new (printer_name, NULL, cancellable, callback, user_data));
+}
+
+static void
+printer_set_ppd_file_async_scb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+ gboolean success;
+ g_autoptr(PSPData) data = user_data;
+ g_autoptr(GError) error = NULL;
+
+ success = g_file_copy_finish (G_FILE (source_object),
+ res,
+ &error);
+
+ if (!success)
+ {
+ g_warning ("%s", error->message);
+ data->callback (data->printer_name, FALSE, data->user_data);
+ return;
+ }
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!bus)
+ {
+ g_warning ("Failed to get system bus: %s", error->message);
+ data->callback (data->printer_name, FALSE, data->user_data);
+ return;
+ }
+
+ g_dbus_connection_call (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "PrinterAddWithPpdFile",
+ g_variant_new ("(sssss)",
+ data->printer_name,
+ "",
+ data->ppd_copy,
+ "",
+ ""),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ data->cancellable,
+ printer_set_ppd_async_dbus_cb,
+ data);
+ g_steal_pointer (&data);
+}
+
+/*
+ * Set ppd for given printer.
+ * Don't use this for classes, just for printers.
+ */
+void
+printer_set_ppd_file_async (const gchar *printer_name,
+ const gchar *ppd_filename,
+ GCancellable *cancellable,
+ PSPCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GFileIOStream) stream = NULL;
+ g_autoptr(GFile) source_ppd_file = NULL;
+ g_autoptr(GFile) destination_ppd_file = NULL;
+
+ if (printer_name == NULL ||
+ printer_name[0] == '\0')
+ {
+ callback (printer_name, FALSE, user_data);
+ return;
+ }
+
+ /*
+ * We need to copy the PPD to temp directory at first.
+ * This is needed because of SELinux.
+ */
+ source_ppd_file = g_file_new_for_path (ppd_filename);
+ destination_ppd_file = g_file_new_tmp ("g-c-c-XXXXXX.ppd", &stream, NULL);
+
+ g_file_copy_async (source_ppd_file,
+ destination_ppd_file,
+ G_FILE_COPY_OVERWRITE,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ NULL,
+ NULL,
+ printer_set_ppd_file_async_scb,
+ psp_data_new (printer_name, g_file_get_path (destination_ppd_file), cancellable, callback, user_data));
+}
+
+typedef void (*GPACallback) (gchar **attribute_values,
+ gpointer user_data);
+
+typedef struct
+{
+ gchar **ppds_names;
+ gchar *attribute_name;
+ gchar **result;
+ GPACallback callback;
+ gpointer user_data;
+ GMainContext *context;
+} GPAData;
+
+static GPAData *
+gpa_data_new (gchar **ppds_names, gchar *attribute_name, GPACallback callback, gpointer user_data)
+{
+ GPAData *data;
+
+ data = g_new0 (GPAData, 1);
+ data->ppds_names = g_strdupv (ppds_names);
+ data->attribute_name = g_strdup (attribute_name);
+ data->callback = callback;
+ data->user_data = user_data;
+ data->context = g_main_context_ref_thread_default ();
+
+ return data;
+}
+
+static void
+gpa_data_free (GPAData *data)
+{
+ g_free (data->attribute_name);
+ g_strfreev (data->ppds_names);
+ if (data->result != NULL)
+ g_strfreev (data->result);
+ if (data->context)
+ g_main_context_unref (data->context);
+ g_free (data);
+}
+
+static gboolean
+get_ppds_attribute_idle_cb (gpointer user_data)
+{
+ GPAData *data = (GPAData *) user_data;
+
+ data->callback (data->result, data->user_data);
+
+ return FALSE;
+}
+
+static void
+get_ppds_attribute_cb (gpointer user_data)
+{
+ GPAData *data = (GPAData *) user_data;
+ g_autoptr(GSource) idle_source = NULL;
+
+ idle_source = g_idle_source_new ();
+ g_source_set_callback (idle_source,
+ get_ppds_attribute_idle_cb,
+ data,
+ (GDestroyNotify) gpa_data_free);
+ g_source_attach (idle_source, data->context);
+}
+
+static gpointer
+get_ppds_attribute_func (gpointer user_data)
+{
+ ppd_file_t *ppd_file;
+ ppd_attr_t *ppd_attr;
+ GPAData *data = user_data;
+ gint i;
+
+ data->result = g_new0 (gchar *, g_strv_length (data->ppds_names) + 1);
+ for (i = 0; data->ppds_names[i]; i++)
+ {
+ g_autofree gchar *ppd_filename = g_strdup (cupsGetServerPPD (CUPS_HTTP_DEFAULT, data->ppds_names[i]));
+ if (ppd_filename)
+ {
+ ppd_file = ppdOpenFile (ppd_filename);
+ if (ppd_file)
+ {
+ ppd_attr = ppdFindAttr (ppd_file, data->attribute_name, NULL);
+ if (ppd_attr != NULL)
+ data->result[i] = g_strdup (ppd_attr->value);
+
+ ppdClose (ppd_file);
+ }
+
+ g_unlink (ppd_filename);
+ }
+ }
+
+ get_ppds_attribute_cb (data);
+
+ return NULL;
+}
+
+/*
+ * Get values of requested PPD attribute for given PPDs.
+ */
+static void
+get_ppds_attribute_async (gchar **ppds_names,
+ gchar *attribute_name,
+ GPACallback callback,
+ gpointer user_data)
+{
+ GPAData *data;
+ g_autoptr(GThread) thread = NULL;
+ g_autoptr(GError) error = NULL;
+
+ if (!ppds_names || !attribute_name)
+ {
+ callback (NULL, user_data);
+ return;
+ }
+
+ data = gpa_data_new (ppds_names, attribute_name, callback, user_data);
+
+ thread = g_thread_try_new ("get-ppds-attribute",
+ get_ppds_attribute_func,
+ data,
+ &error);
+
+ if (!thread)
+ {
+ g_warning ("%s", error->message);
+ callback (NULL, user_data);
+
+ gpa_data_free (data);
+ }
+}
+
+
+
+typedef void (*GDACallback) (gchar *device_id,
+ gchar *device_make_and_model,
+ gchar *device_uri,
+ gpointer user_data);
+
+typedef struct
+{
+ gchar *printer_name;
+ gchar *device_uri;
+ GList *backend_list;
+ GCancellable *cancellable;
+ GDACallback callback;
+ gpointer user_data;
+} GDAData;
+
+static GDAData *
+gda_data_new (const gchar *printer_name, GCancellable *cancellable, GDACallback callback, gpointer user_data)
+{
+ GDAData *data;
+
+ data = g_new0 (GDAData, 1);
+ data->printer_name = g_strdup (printer_name);
+ if (cancellable)
+ data->cancellable = g_object_ref (cancellable);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ return data;
+}
+
+static void
+gda_data_free (GDAData *data)
+{
+ g_free (data->printer_name);
+ g_free (data->device_uri);
+ g_list_free_full(data->backend_list, g_free);
+ g_clear_object (&data->cancellable);
+ g_free (data);
+}
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (GDAData, gda_data_free)
+
+typedef struct
+{
+ gchar *printer_name;
+ gint count;
+ PPDName **result;
+ GCancellable *cancellable;
+ GPNCallback callback;
+ gpointer user_data;
+} GPNData;
+
+static GPNData *
+gpn_data_new (const gchar *printer_name, gint count, GCancellable *cancellable, GPNCallback callback, gpointer user_data)
+{
+ GPNData *data;
+
+ data = g_new0 (GPNData, 1);
+ data->printer_name = g_strdup (printer_name);
+ data->count = count;
+ if (cancellable)
+ data->cancellable = g_object_ref (cancellable);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ return data;
+}
+
+static void
+gpn_data_free (GPNData *data)
+{
+ g_free (data->printer_name);
+ if (data->result != NULL)
+ {
+ for (int i = 0; data->result[i]; i++)
+ {
+ g_free (data->result[i]->ppd_name);
+ g_free (data->result[i]->ppd_display_name);
+ g_free (data->result[i]);
+ }
+ g_free (data->result);
+ }
+ g_clear_object (&data->cancellable);
+ g_free (data);
+}
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (GPNData, gpn_data_free)
+
+static void
+get_ppd_names_async_cb (gchar **attribute_values,
+ gpointer user_data)
+{
+ g_autoptr(GPNData) data = user_data;
+ gint i;
+
+ if (g_cancellable_is_cancelled (data->cancellable))
+ {
+ data->callback (NULL,
+ data->printer_name,
+ TRUE,
+ data->user_data);
+ return;
+ }
+
+ if (attribute_values)
+ {
+ for (i = 0; attribute_values[i]; i++)
+ data->result[i]->ppd_display_name = g_strdup (attribute_values[i]);
+ }
+
+ data->callback (data->result,
+ data->printer_name,
+ FALSE,
+ data->user_data);
+}
+
+static void
+get_ppd_names_async_dbus_scb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GVariant) output = NULL;
+ PPDName *ppd_item;
+ PPDName **result = NULL;
+ g_autoptr(GPNData) data = user_data;
+ g_autoptr(GError) error = NULL;
+ GList *driver_list = NULL;
+ GList *iter;
+ gint i, j, n = 0;
+ static const char * const match_levels[] = {
+ "exact-cmd",
+ "exact",
+ "close",
+ "generic",
+ "none"};
+
+ output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ res,
+ &error);
+
+ if (output)
+ {
+ g_autoptr(GVariant) array = NULL;
+
+ g_variant_get (output, "(@a(ss))",
+ &array);
+
+ for (j = 0; j < G_N_ELEMENTS (match_levels) && n < data->count; j++)
+ {
+ g_autoptr(GVariantIter) iter = NULL;
+ const gchar *driver, *match;
+
+ g_variant_get (array,
+ "a(ss)",
+ &iter);
+
+ while (g_variant_iter_next (iter, "(&s&s)", &driver, &match))
+ {
+ if (g_str_equal (match, match_levels[j]) && n < data->count)
+ {
+ ppd_item = g_new0 (PPDName, 1);
+ ppd_item->ppd_name = g_strdup (driver);
+
+ if (g_strcmp0 (match, "exact-cmd") == 0)
+ ppd_item->ppd_match_level = PPD_EXACT_CMD_MATCH;
+ else if (g_strcmp0 (match, "exact") == 0)
+ ppd_item->ppd_match_level = PPD_EXACT_MATCH;
+ else if (g_strcmp0 (match, "close") == 0)
+ ppd_item->ppd_match_level = PPD_CLOSE_MATCH;
+ else if (g_strcmp0 (match, "generic") == 0)
+ ppd_item->ppd_match_level = PPD_GENERIC_MATCH;
+ else if (g_strcmp0 (match, "none") == 0)
+ ppd_item->ppd_match_level = PPD_NO_MATCH;
+
+ driver_list = g_list_append (driver_list, ppd_item);
+
+ n++;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("%s", error->message);
+ }
+
+ if (n > 0)
+ {
+ result = g_new0 (PPDName *, n + 1);
+ i = 0;
+ for (iter = driver_list; iter; iter = iter->next)
+ {
+ result[i] = iter->data;
+ i++;
+ }
+ }
+
+ if (result)
+ {
+ g_auto(GStrv) ppds_names = NULL;
+
+ data->result = result;
+
+ ppds_names = g_new0 (gchar *, n + 1);
+ for (i = 0; i < n; i++)
+ ppds_names[i] = g_strdup (result[i]->ppd_name);
+
+ get_ppds_attribute_async (ppds_names,
+ "NickName",
+ get_ppd_names_async_cb,
+ data);
+ g_steal_pointer (&data);
+ }
+ else
+ {
+ data->callback (NULL,
+ data->printer_name,
+ g_cancellable_is_cancelled (data->cancellable),
+ data->user_data);
+ }
+}
+
+static void
+get_device_attributes_cb (gchar *device_id,
+ gchar *device_make_and_model,
+ gchar *device_uri,
+ gpointer user_data)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPNData) data = user_data;
+
+ if (g_cancellable_is_cancelled (data->cancellable))
+ {
+ data->callback (NULL,
+ data->printer_name,
+ TRUE,
+ data->user_data);
+ return;
+ }
+
+ if (!device_id || !device_make_and_model || !device_uri)
+ {
+ data->callback (NULL,
+ data->printer_name,
+ FALSE,
+ data->user_data);
+ return;
+ }
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
+ if (!bus)
+ {
+ g_warning ("Failed to get system bus: %s", error->message);
+ data->callback (NULL,
+ data->printer_name,
+ FALSE,
+ data->user_data);
+ return;
+ }
+
+ g_dbus_connection_call (bus,
+ SCP_BUS,
+ SCP_PATH,
+ SCP_IFACE,
+ "GetBestDrivers",
+ g_variant_new ("(sss)",
+ device_id,
+ device_make_and_model,
+ device_uri),
+ G_VARIANT_TYPE ("(a(ss))"),
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_TIMEOUT_LONG,
+ data->cancellable,
+ get_ppd_names_async_dbus_scb,
+ data);
+ g_steal_pointer (&data);
+}
+
+/*
+ * Special item for the list of backends. It represents
+ * backends not present in the list itself.
+ */
+#define OTHER_BACKENDS "other-backends"
+
+/*
+ * List of CUPS backends sorted according to their speed,
+ * the fastest is the first one. The last item represents
+ * backends not present in the list.
+ */
+const gchar *cups_backends[] = {
+ "usb",
+ "socket",
+ "serial",
+ "parallel",
+ "lpd",
+ "ipp",
+ "hp",
+ "dnssd",
+ "snmp",
+ "bluetooth",
+ "beh",
+ "ncp",
+ "hpfax",
+ OTHER_BACKENDS
+};
+
+static GList *
+create_backends_list ()
+{
+ GList *list = NULL;
+ gint i;
+
+ for (i = 0; i < G_N_ELEMENTS (cups_backends); i++)
+ list = g_list_prepend (list, g_strdup (cups_backends[i]));
+ list = g_list_reverse (list);
+
+ return list;
+}
+
+static GVariantBuilder *
+create_other_backends_array ()
+{
+ GVariantBuilder *builder;
+ gint i;
+
+ builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+ for (i = 0; i < G_N_ELEMENTS (cups_backends) - 1; i++)
+ g_variant_builder_add (builder, "s", cups_backends[i]);
+
+ return builder;
+}
+
+static void
+get_device_attributes_async_dbus_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+
+{
+ g_autoptr(GVariant) output = NULL;
+ g_autoptr(GDAData) data = user_data;
+ g_autoptr(GError) error = NULL;
+ gchar *device_id = NULL;
+ gchar *device_make_and_model = NULL;
+
+ output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ res,
+ &error);
+
+ if (output)
+ {
+ const gchar *ret_error;
+ g_autoptr(GVariant) devices_variant = NULL;
+ gint index = -1;
+
+ g_variant_get (output, "(&s@a{ss})",
+ &ret_error,
+ &devices_variant);
+
+ if (ret_error[0] != '\0')
+ {
+ g_warning ("cups-pk-helper: getting of attributes for printer %s failed: %s", data->printer_name, ret_error);
+ }
+
+ if (data->device_uri)
+ {
+ g_autoptr(GVariantIter) iter = NULL;
+ const gchar *key, *value;
+ g_autofree gchar *suffix = NULL;
+
+ g_variant_get (devices_variant,
+ "a{ss}",
+ &iter);
+
+ while (g_variant_iter_next (iter, "{&s&s}", &key, &value))
+ {
+ if (g_str_equal (value, data->device_uri))
+ {
+ gchar *number = g_strrstr (key, ":");
+ if (number != NULL)
+ {
+ gchar *endptr;
+
+ number++;
+ index = g_ascii_strtoll (number, &endptr, 10);
+ if (index == 0 && endptr == (number))
+ index = -1;
+ }
+ }
+ }
+
+ suffix = g_strdup_printf (":%d", index);
+
+ g_variant_get (devices_variant,
+ "a{ss}",
+ &iter);
+
+ while (g_variant_iter_next (iter, "{&s&s}", &key, &value))
+ {
+ if (g_str_has_suffix (key, suffix))
+ {
+ if (g_str_has_prefix (key, "device-id"))
+ {
+ device_id = g_strdup (value);
+ }
+
+ if (g_str_has_prefix (key, "device-make-and-model"))
+ {
+ device_make_and_model = g_strdup (value);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("%s", error->message);
+ }
+
+ if (!device_id || !device_make_and_model)
+ {
+ GVariantBuilder *include_scheme_builder = NULL;
+ GVariantBuilder *exclude_scheme_builder = NULL;
+
+ g_free (device_id);
+ g_free (device_make_and_model);
+
+ device_id = NULL;
+ device_make_and_model = NULL;
+
+ if (data->backend_list && !g_cancellable_is_cancelled (data->cancellable))
+ {
+ const gchar *backend_name;
+
+ backend_name = data->backend_list->data;
+
+ if (g_strcmp0 (backend_name, OTHER_BACKENDS) != 0)
+ {
+ include_scheme_builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+ g_variant_builder_add (include_scheme_builder, "s", backend_name);
+ }
+ else
+ {
+ exclude_scheme_builder = create_other_backends_array ();
+ }
+
+ data->backend_list = g_list_delete_link (data->backend_list, data->backend_list);
+
+ g_dbus_connection_call (G_DBUS_CONNECTION (g_object_ref (source_object)),
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "DevicesGet",
+ g_variant_new ("(iiasas)",
+ 0,
+ 0,
+ include_scheme_builder,
+ exclude_scheme_builder),
+ G_VARIANT_TYPE ("(sa{ss})"),
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_TIMEOUT,
+ data->cancellable,
+ get_device_attributes_async_dbus_cb,
+ data);
+ g_steal_pointer (&data);
+
+ if (include_scheme_builder)
+ g_variant_builder_unref (include_scheme_builder);
+
+ if (exclude_scheme_builder)
+ g_variant_builder_unref (exclude_scheme_builder);
+
+ return;
+ }
+ }
+
+ data->callback (device_id,
+ device_make_and_model,
+ data->device_uri,
+ data->user_data);
+}
+
+static void
+get_device_attributes_async_scb (GHashTable *result,
+ gpointer user_data)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+ GVariantBuilder include_scheme_builder;
+ IPPAttribute *attr;
+ g_autoptr(GDAData) data = user_data;
+ g_autoptr(GError) error = NULL;
+
+ if (result)
+ {
+ attr = g_hash_table_lookup (result, "device-uri");
+ if (attr && attr->attribute_type == IPP_ATTRIBUTE_TYPE_STRING &&
+ attr->num_of_values > 0)
+ data->device_uri = g_strdup (attr->attribute_values[0].string_value);
+ g_hash_table_unref (result);
+ }
+
+ if (g_cancellable_is_cancelled (data->cancellable))
+ {
+ data->callback (NULL, NULL, NULL, data->user_data);
+ return;
+ }
+
+ if (!data->device_uri)
+ {
+ data->callback (NULL, NULL, NULL, data->user_data);
+ return;
+ }
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!bus)
+ {
+ g_warning ("Failed to get system bus: %s", error->message);
+ data->callback (NULL, NULL, NULL, data->user_data);
+ return;
+ }
+
+ data->backend_list = create_backends_list ();
+
+ g_variant_builder_init (&include_scheme_builder, G_VARIANT_TYPE ("as"));
+ g_variant_builder_add (&include_scheme_builder, "s", data->backend_list->data);
+
+ data->backend_list = g_list_delete_link (data->backend_list, data->backend_list);
+
+ g_dbus_connection_call (g_object_ref (bus),
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "DevicesGet",
+ g_variant_new ("(iiasas)",
+ 0,
+ 0,
+ &include_scheme_builder,
+ NULL),
+ G_VARIANT_TYPE ("(sa{ss})"),
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_TIMEOUT,
+ data->cancellable,
+ get_device_attributes_async_dbus_cb,
+ data);
+ g_steal_pointer (&data);
+}
+
+/*
+ * Get device-id, device-make-and-model and device-uri for given printer.
+ */
+static void
+get_device_attributes_async (const gchar *printer_name,
+ GCancellable *cancellable,
+ GDACallback callback,
+ gpointer user_data)
+{
+ g_auto(GStrv) attributes = NULL;
+
+ if (!printer_name)
+ {
+ callback (NULL, NULL, NULL, user_data);
+ return;
+ }
+
+ attributes = g_new0 (gchar *, 2);
+ attributes[0] = g_strdup ("device-uri");
+
+ get_ipp_attributes_async (printer_name,
+ attributes,
+ get_device_attributes_async_scb,
+ gda_data_new (printer_name, cancellable, callback, user_data));
+}
+
+/*
+ * Return "count" best matching driver names for given printer.
+ */
+void
+get_ppd_names_async (gchar *printer_name,
+ gint count,
+ GCancellable *cancellable,
+ GPNCallback callback,
+ gpointer user_data)
+{
+ if (!printer_name)
+ {
+ callback (NULL, NULL, TRUE, user_data);
+ return;
+ }
+
+ /*
+ * We have to find out device-id for this printer at first.
+ */
+ get_device_attributes_async (printer_name,
+ cancellable,
+ get_device_attributes_cb,
+ gpn_data_new (printer_name, count, cancellable, callback, user_data));
+}
+
+typedef struct
+{
+ PPDList *result;
+ GCancellable *cancellable;
+ GAPCallback callback;
+ gpointer user_data;
+ GMainContext *context;
+} GAPData;
+
+static GAPData *
+gap_data_new (GCancellable *cancellable, GAPCallback callback, gpointer user_data)
+{
+ GAPData *data;
+
+ data = g_new0 (GAPData, 1);
+ if (cancellable)
+ data->cancellable = g_object_ref (cancellable);
+ data->callback = callback;
+ data->user_data = user_data;
+ data->context = g_main_context_ref_thread_default ();
+
+ return data;
+}
+
+static void
+gap_data_free (GAPData *data)
+{
+ if (data->result != NULL)
+ ppd_list_free (data->result);
+ g_clear_object (&data->cancellable);
+ if (data->context)
+ g_main_context_unref (data->context);
+ g_free (data);
+}
+
+static gboolean
+get_all_ppds_idle_cb (gpointer user_data)
+{
+ GAPData *data = user_data;
+
+ if (!g_cancellable_is_cancelled (data->cancellable))
+ data->callback (data->result, data->user_data);
+
+ return FALSE;
+}
+
+static void
+get_all_ppds_cb (gpointer user_data)
+{
+ GAPData *data = user_data;
+ g_autoptr(GSource) idle_source = NULL;
+
+ idle_source = g_idle_source_new ();
+ g_source_set_callback (idle_source,
+ get_all_ppds_idle_cb,
+ data,
+ (GDestroyNotify) gap_data_free);
+ g_source_attach (idle_source, data->context);
+}
+
+static const struct {
+ const char *normalized_name;
+ const char *display_name;
+} manufacturers_names[] = {
+ { "alps", "Alps" },
+ { "anitech", "Anitech" },
+ { "apple", "Apple" },
+ { "apollo", "Apollo" },
+ { "brother", "Brother" },
+ { "canon", "Canon" },
+ { "citizen", "Citizen" },
+ { "citoh", "Citoh" },
+ { "compaq", "Compaq" },
+ { "dec", "DEC" },
+ { "dell", "Dell" },
+ { "dnp", "DNP" },
+ { "dymo", "Dymo" },
+ { "epson", "Epson" },
+ { "fujifilm", "Fujifilm" },
+ { "fujitsu", "Fujitsu" },
+ { "gelsprinter", "Ricoh" },
+ { "generic", "Generic" },
+ { "genicom", "Genicom" },
+ { "gestetner", "Gestetner" },
+ { "hewlett packard", "Hewlett-Packard" },
+ { "heidelberg", "Heidelberg" },
+ { "hitachi", "Hitachi" },
+ { "hp", "Hewlett-Packard" },
+ { "ibm", "IBM" },
+ { "imagen", "Imagen" },
+ { "imagistics", "Imagistics" },
+ { "infoprint", "InfoPrint" },
+ { "infotec", "Infotec" },
+ { "intellitech", "Intellitech" },
+ { "kodak", "Kodak" },
+ { "konica minolta", "Minolta" },
+ { "kyocera", "Kyocera" },
+ { "kyocera mita", "Kyocera" },
+ { "lanier", "Lanier" },
+ { "lexmark international", "Lexmark" },
+ { "lexmark", "Lexmark" },
+ { "minolta", "Minolta" },
+ { "minolta qms", "Minolta" },
+ { "mitsubishi", "Mitsubishi" },
+ { "nec", "NEC" },
+ { "nrg", "NRG" },
+ { "oce", "Oce" },
+ { "oki", "Oki" },
+ { "oki data corp", "Oki" },
+ { "olivetti", "Olivetti" },
+ { "olympus", "Olympus" },
+ { "panasonic", "Panasonic" },
+ { "pcpi", "PCPI" },
+ { "pentax", "Pentax" },
+ { "qms", "QMS" },
+ { "raven", "Raven" },
+ { "raw", "Raw" },
+ { "ricoh", "Ricoh" },
+ { "samsung", "Samsung" },
+ { "savin", "Savin" },
+ { "seiko", "Seiko" },
+ { "sharp", "Sharp" },
+ { "shinko", "Shinko" },
+ { "sipix", "SiPix" },
+ { "sony", "Sony" },
+ { "star", "Star" },
+ { "tally", "Tally" },
+ { "tektronix", "Tektronix" },
+ { "texas instruments", "Texas Instruments" },
+ { "toshiba", "Toshiba" },
+ { "toshiba tec corp.", "Toshiba" },
+ { "xante", "Xante" },
+ { "xerox", "Xerox" },
+ { "zebra", "Zebra" },
+};
+
+static gpointer
+get_all_ppds_func (gpointer user_data)
+{
+ ipp_attribute_t *attr;
+ GHashTable *ppds_hash = NULL;
+ GHashTable *manufacturers_hash = NULL;
+ GAPData *data = user_data;
+ PPDName *item;
+ ipp_t *request;
+ ipp_t *response;
+ GList *list;
+ gchar *manufacturer_display_name;
+ gint i, j;
+
+ request = ippNewRequest (CUPS_GET_PPDS);
+ response = cupsDoRequest (CUPS_HTTP_DEFAULT, request, "/");
+
+ if (response &&
+ ippGetStatusCode (response) <= IPP_OK_CONFLICT)
+ {
+ /*
+ * This hash contains names of manufacturers as keys and
+ * values are GLists of PPD names.
+ */
+ ppds_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ /*
+ * This hash contains all possible names of manufacturers as keys
+ * and values are just first occurrences of their equivalents.
+ * This is for mapping of e.g. "Hewlett Packard" and "HP" to the same name
+ * (the one which comes first).
+ */
+ manufacturers_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ for (i = 0; i < G_N_ELEMENTS (manufacturers_names); i++)
+ {
+ g_hash_table_insert (manufacturers_hash,
+ g_strdup (manufacturers_names[i].normalized_name),
+ g_strdup (manufacturers_names[i].display_name));
+ }
+
+ for (attr = ippFirstAttribute (response); attr != NULL; attr = ippNextAttribute (response))
+ {
+ const gchar *ppd_device_id = NULL;
+ const gchar *ppd_make_and_model = NULL;
+ const gchar *ppd_name = NULL;
+ const gchar *ppd_product = NULL;
+ const gchar *ppd_make = NULL;
+ g_autofree gchar *mdl = NULL;
+ g_autofree gchar *mfg = NULL;
+ g_autofree gchar *mfg_normalized = NULL;
+
+ while (attr != NULL && ippGetGroupTag (attr) != IPP_TAG_PRINTER)
+ attr = ippNextAttribute (response);
+
+ if (attr == NULL)
+ break;
+
+ while (attr != NULL && ippGetGroupTag (attr) == IPP_TAG_PRINTER)
+ {
+ if (g_strcmp0 (ippGetName (attr), "ppd-device-id") == 0 &&
+ ippGetValueTag (attr) == IPP_TAG_TEXT)
+ ppd_device_id = ippGetString (attr, 0, NULL);
+ else if (g_strcmp0 (ippGetName (attr), "ppd-make-and-model") == 0 &&
+ ippGetValueTag (attr) == IPP_TAG_TEXT)
+ ppd_make_and_model = ippGetString (attr, 0, NULL);
+ else if (g_strcmp0 (ippGetName (attr), "ppd-name") == 0 &&
+ ippGetValueTag (attr) == IPP_TAG_NAME)
+ ppd_name = ippGetString (attr, 0, NULL);
+ else if (g_strcmp0 (ippGetName (attr), "ppd-product") == 0 &&
+ ippGetValueTag (attr) == IPP_TAG_TEXT)
+ ppd_product = ippGetString (attr, 0, NULL);
+ else if (g_strcmp0 (ippGetName (attr), "ppd-make") == 0 &&
+ ippGetValueTag (attr) == IPP_TAG_TEXT)
+ ppd_make = ippGetString (attr, 0, NULL);
+
+ attr = ippNextAttribute (response);
+ }
+
+ /* Get manufacturer's name */
+ if (ppd_device_id && ppd_device_id[0] != '\0')
+ {
+ mfg = get_tag_value (ppd_device_id, "mfg");
+ if (!mfg)
+ mfg = get_tag_value (ppd_device_id, "manufacturer");
+ mfg_normalized = normalize (mfg);
+ }
+
+ if (!mfg &&
+ ppd_make &&
+ ppd_make[0] != '\0')
+ {
+ mfg = g_strdup (ppd_make);
+ mfg_normalized = normalize (ppd_make);
+ }
+
+ /* Get model */
+ if (ppd_make_and_model &&
+ ppd_make_and_model[0] != '\0')
+ {
+ mdl = g_strdup (ppd_make_and_model);
+ }
+
+ if (!mdl &&
+ ppd_product &&
+ ppd_product[0] != '\0')
+ {
+ mdl = g_strdup (ppd_product);
+ }
+
+ if (!mdl &&
+ ppd_device_id &&
+ ppd_device_id[0] != '\0')
+ {
+ mdl = get_tag_value (ppd_device_id, "mdl");
+ if (!mdl)
+ mdl = get_tag_value (ppd_device_id, "model");
+ }
+
+ if (ppd_name && ppd_name[0] != '\0' &&
+ mdl && mdl[0] != '\0' &&
+ mfg && mfg[0] != '\0')
+ {
+ manufacturer_display_name = g_hash_table_lookup (manufacturers_hash, mfg_normalized);
+ if (!manufacturer_display_name)
+ {
+ g_hash_table_insert (manufacturers_hash, g_strdup (mfg_normalized), g_strdup (mfg));
+ }
+ else
+ {
+ g_free (mfg_normalized);
+ mfg_normalized = normalize (manufacturer_display_name);
+ }
+
+ item = g_new0 (PPDName, 1);
+ item->ppd_name = g_strdup (ppd_name);
+ item->ppd_display_name = g_strdup (mdl);
+ item->ppd_match_level = -1;
+
+ list = g_hash_table_lookup (ppds_hash, mfg_normalized);
+ if (list)
+ {
+ list = g_list_append (list, item);
+ }
+ else
+ {
+ list = g_list_append (list, item);
+ g_hash_table_insert (ppds_hash, g_strdup (mfg_normalized), list);
+ }
+ }
+
+ if (attr == NULL)
+ break;
+ }
+ }
+
+ if (response)
+ ippDelete(response);
+
+ if (ppds_hash &&
+ manufacturers_hash)
+ {
+ GHashTableIter iter;
+ gpointer key;
+ gpointer value;
+ GList *ppd_item;
+ GList *sort_list = NULL;
+ GList *list_iter;
+ gchar *name;
+
+ data->result = g_new0 (PPDList, 1);
+ data->result->num_of_manufacturers = g_hash_table_size (ppds_hash);
+ data->result->manufacturers = g_new0 (PPDManufacturerItem *, data->result->num_of_manufacturers);
+
+ g_hash_table_iter_init (&iter, ppds_hash);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ sort_list = g_list_append (sort_list, g_strdup (key));
+ }
+
+ /* Sort list of manufacturers */
+ sort_list = g_list_sort (sort_list, (GCompareFunc) g_strcmp0);
+
+ /*
+ * Fill resulting list of lists (list of manufacturers where
+ * each item contains list of PPD names)
+ */
+ i = 0;
+ for (list_iter = sort_list; list_iter; list_iter = list_iter->next)
+ {
+ name = (gchar *) list_iter->data;
+ value = g_hash_table_lookup (ppds_hash, name);
+
+ data->result->manufacturers[i] = g_new0 (PPDManufacturerItem, 1);
+ data->result->manufacturers[i]->manufacturer_name = g_strdup (name);
+ data->result->manufacturers[i]->manufacturer_display_name = g_strdup (g_hash_table_lookup (manufacturers_hash, name));
+ data->result->manufacturers[i]->num_of_ppds = g_list_length ((GList *) value);
+ data->result->manufacturers[i]->ppds = g_new0 (PPDName *, data->result->manufacturers[i]->num_of_ppds);
+
+ for (ppd_item = (GList *) value, j = 0; ppd_item; ppd_item = ppd_item->next, j++)
+ {
+ data->result->manufacturers[i]->ppds[j] = ppd_item->data;
+ }
+
+ g_list_free ((GList *) value);
+
+ i++;
+ }
+
+ g_list_free_full (sort_list, g_free);
+ g_hash_table_destroy (ppds_hash);
+ g_hash_table_destroy (manufacturers_hash);
+ }
+
+ get_all_ppds_cb (data);
+
+ return NULL;
+}
+
+/*
+ * Get names of all installed PPDs sorted by manufacturers names.
+ */
+void
+get_all_ppds_async (GCancellable *cancellable,
+ GAPCallback callback,
+ gpointer user_data)
+{
+ GAPData *data;
+ g_autoptr(GThread) thread = NULL;
+ g_autoptr(GError) error = NULL;
+
+ data = gap_data_new (cancellable, callback, user_data);
+
+ thread = g_thread_try_new ("get-all-ppds",
+ get_all_ppds_func,
+ data,
+ &error);
+
+ if (!thread)
+ {
+ g_warning ("%s", error->message);
+ callback (NULL, user_data);
+
+ gap_data_free (data);
+ }
+}
+
+PPDList *
+ppd_list_copy (PPDList *list)
+{
+ PPDList *result = NULL;
+ gint i, j;
+
+ if (list)
+ {
+ result = g_new0 (PPDList, 1);
+ result->num_of_manufacturers = list->num_of_manufacturers;
+ result->manufacturers = g_new0 (PPDManufacturerItem *, list->num_of_manufacturers);
+
+ for (i = 0; i < result->num_of_manufacturers; i++)
+ {
+ result->manufacturers[i] = g_new0 (PPDManufacturerItem, 1);
+ result->manufacturers[i]->num_of_ppds = list->manufacturers[i]->num_of_ppds;
+ result->manufacturers[i]->ppds = g_new0 (PPDName *, result->manufacturers[i]->num_of_ppds);
+
+ result->manufacturers[i]->manufacturer_display_name =
+ g_strdup (list->manufacturers[i]->manufacturer_display_name);
+
+ result->manufacturers[i]->manufacturer_name =
+ g_strdup (list->manufacturers[i]->manufacturer_name);
+
+ for (j = 0; j < result->manufacturers[i]->num_of_ppds; j++)
+ {
+ result->manufacturers[i]->ppds[j] = g_new0 (PPDName, 1);
+
+ result->manufacturers[i]->ppds[j]->ppd_display_name =
+ g_strdup (list->manufacturers[i]->ppds[j]->ppd_display_name);
+
+ result->manufacturers[i]->ppds[j]->ppd_name =
+ g_strdup (list->manufacturers[i]->ppds[j]->ppd_name);
+
+ result->manufacturers[i]->ppds[j]->ppd_match_level =
+ list->manufacturers[i]->ppds[j]->ppd_match_level;
+ }
+ }
+ }
+
+ return result;
+}
+
+void
+ppd_list_free (PPDList *list)
+{
+ gint i, j;
+
+ if (list)
+ {
+ for (i = 0; i < list->num_of_manufacturers; i++)
+ {
+ for (j = 0; j < list->manufacturers[i]->num_of_ppds; j++)
+ {
+ g_free (list->manufacturers[i]->ppds[j]->ppd_name);
+ g_free (list->manufacturers[i]->ppds[j]->ppd_display_name);
+ g_free (list->manufacturers[i]->ppds[j]);
+ }
+
+ g_free (list->manufacturers[i]->manufacturer_name);
+ g_free (list->manufacturers[i]->manufacturer_display_name);
+ g_free (list->manufacturers[i]->ppds);
+ g_free (list->manufacturers[i]);
+ }
+
+ g_free (list->manufacturers);
+ g_free (list);
+ }
+}
+
+gchar *
+get_standard_manufacturers_name (const gchar *name)
+{
+ g_autofree gchar *normalized_name = NULL;
+ gint i;
+
+ if (name == NULL)
+ return NULL;
+
+ normalized_name = normalize (name);
+
+ for (i = 0; i < G_N_ELEMENTS (manufacturers_names); i++)
+ {
+ if (g_strcmp0 (manufacturers_names[i].normalized_name, normalized_name) == 0)
+ {
+ return g_strdup (manufacturers_names[i].display_name);
+ }
+ }
+
+ return NULL;
+}
+
+typedef struct
+{
+ gchar *printer_name;
+ gchar *host_name;
+ gint port;
+ gchar *result;
+ PGPCallback callback;
+ gpointer user_data;
+ GMainContext *context;
+} PGPData;
+
+static PGPData *
+pgp_data_new (const gchar *printer_name, const gchar *host_name, gint port, PGPCallback callback, gpointer user_data)
+{
+ PGPData *data;
+
+ data = g_new0 (PGPData, 1);
+ data->printer_name = g_strdup (printer_name);
+ data->host_name = g_strdup (host_name);
+ data->port = port;
+ data->callback = callback;
+ data->user_data = user_data;
+ data->context = g_main_context_ref_thread_default ();
+
+ return data;
+}
+
+static void
+pgp_data_free (PGPData *data)
+{
+ g_free (data->printer_name);
+ g_free (data->host_name);
+ g_free (data->result);
+ if (data->context)
+ g_main_context_unref (data->context);
+ g_free (data);
+}
+
+static gboolean
+printer_get_ppd_idle_cb (gpointer user_data)
+{
+ PGPData *data = user_data;
+
+ data->callback (data->result, data->user_data);
+
+ return FALSE;
+}
+
+static void
+printer_get_ppd_cb (gpointer user_data)
+{
+ PGPData *data = user_data;
+ g_autoptr(GSource) idle_source = NULL;
+
+ idle_source = g_idle_source_new ();
+ g_source_set_callback (idle_source,
+ printer_get_ppd_idle_cb,
+ data,
+ (GDestroyNotify) pgp_data_free);
+ g_source_attach (idle_source, data->context);
+}
+
+static gpointer
+printer_get_ppd_func (gpointer user_data)
+{
+ PGPData *data = user_data;
+
+ if (data->host_name)
+ {
+ http_t *http;
+
+#ifdef HAVE_CUPS_HTTPCONNECT2
+ http = httpConnect2 (data->host_name, data->port, NULL, AF_UNSPEC,
+ HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL);
+#else
+ http = httpConnect (data->host_name, data->port);
+#endif
+ if (http)
+ {
+ data->result = g_strdup (cupsGetPPD2 (http, data->printer_name));
+ httpClose (http);
+ }
+ }
+ else
+ {
+ data->result = g_strdup (cupsGetPPD (data->printer_name));
+ }
+
+ printer_get_ppd_cb (data);
+
+ return NULL;
+}
+
+void
+printer_get_ppd_async (const gchar *printer_name,
+ const gchar *host_name,
+ gint port,
+ PGPCallback callback,
+ gpointer user_data)
+{
+ PGPData *data;
+ g_autoptr(GThread) thread = NULL;
+ g_autoptr(GError) error = NULL;
+
+ data = pgp_data_new (printer_name, host_name, port, callback, user_data);
+
+ thread = g_thread_try_new ("printer-get-ppd",
+ printer_get_ppd_func,
+ data,
+ &error);
+
+ if (!thread)
+ {
+ g_warning ("%s", error->message);
+ callback (NULL, user_data);
+
+ pgp_data_free (data);
+ }
+}
+
+typedef struct
+{
+ gchar *printer_name;
+ cups_dest_t *result;
+ GNDCallback callback;
+ gpointer user_data;
+ GMainContext *context;
+} GNDData;
+
+static GNDData *
+gnd_data_new (const gchar *printer_name, GNDCallback callback, gpointer user_data)
+{
+ GNDData *data;
+
+ data = g_new0 (GNDData, 1);
+ data->printer_name = g_strdup (printer_name);
+ data->callback = callback;
+ data->user_data = user_data;
+ data->context = g_main_context_ref_thread_default ();
+
+ return data;
+}
+
+static void
+gnd_data_free (GNDData *data)
+{
+ g_free (data->printer_name);
+ if (data->context)
+ g_main_context_unref (data->context);
+ g_free (data);
+}
+
+static gboolean
+get_named_dest_idle_cb (gpointer user_data)
+{
+ GNDData *data = user_data;
+
+ data->callback (data->result, data->user_data);
+
+ return FALSE;
+}
+
+static void
+get_named_dest_cb (gpointer user_data)
+{
+ GNDData *data = user_data;
+ g_autoptr(GSource) idle_source = NULL;
+
+ idle_source = g_idle_source_new ();
+ g_source_set_callback (idle_source,
+ get_named_dest_idle_cb,
+ data,
+ (GDestroyNotify) gnd_data_free);
+ g_source_attach (idle_source, data->context);
+}
+
+static gpointer
+get_named_dest_func (gpointer user_data)
+{
+ GNDData *data = user_data;
+
+ data->result = cupsGetNamedDest (CUPS_HTTP_DEFAULT, data->printer_name, NULL);
+
+ get_named_dest_cb (data);
+
+ return NULL;
+}
+
+void
+get_named_dest_async (const gchar *printer_name,
+ GNDCallback callback,
+ gpointer user_data)
+{
+ GNDData *data;
+ g_autoptr(GThread) thread = NULL;
+ g_autoptr(GError) error = NULL;
+
+ data = gnd_data_new (printer_name, callback, user_data);
+
+ thread = g_thread_try_new ("get-named-dest",
+ get_named_dest_func,
+ data,
+ &error);
+
+ if (!thread)
+ {
+ g_warning ("%s", error->message);
+ callback (NULL, user_data);
+
+ gnd_data_free (data);
+ }
+}
+
+typedef struct
+{
+ GCancellable *cancellable;
+ PAOCallback callback;
+ gpointer user_data;
+} PAOData;
+
+static PAOData *
+pao_data_new (GCancellable *cancellable, PAOCallback callback, gpointer user_data)
+{
+ PAOData *data;
+
+ data = g_new0 (PAOData, 1);
+ if (cancellable)
+ data->cancellable = g_object_ref (cancellable);
+ data->callback = callback;
+ data->user_data = user_data;
+ return data;
+}
+
+static void
+pao_data_free (PAOData *data)
+{
+ g_clear_object (&data->cancellable);
+ g_free (data);
+}
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (PAOData, pao_data_free)
+
+static void
+printer_add_option_async_dbus_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GVariant) output = NULL;
+ gboolean success = FALSE;
+ g_autoptr(PAOData) data = user_data;
+ g_autoptr(GError) error = NULL;
+
+ output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ res,
+ &error);
+
+ if (output)
+ {
+ const gchar *ret_error;
+
+ g_variant_get (output, "(&s)", &ret_error);
+ if (ret_error[0] != '\0')
+ g_warning ("cups-pk-helper: setting of an option failed: %s", ret_error);
+ else
+ success = TRUE;
+ }
+ else
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("%s", error->message);
+ }
+
+ if (!g_cancellable_is_cancelled (data->cancellable))
+ data->callback (success, data->user_data);
+}
+
+void
+printer_add_option_async (const gchar *printer_name,
+ const gchar *option_name,
+ gchar **values,
+ gboolean set_default,
+ GCancellable *cancellable,
+ PAOCallback callback,
+ gpointer user_data)
+{
+ GVariantBuilder array_builder;
+ g_autoptr(GDBusConnection) bus = NULL;
+ g_autoptr(GError) error = NULL;
+ gint i;
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!bus)
+ {
+ g_warning ("Failed to get system bus: %s", error->message);
+ callback (FALSE, user_data);
+ return;
+ }
+
+ g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("as"));
+ if (values)
+ {
+ for (i = 0; values[i]; i++)
+ g_variant_builder_add (&array_builder, "s", values[i]);
+ }
+
+ g_dbus_connection_call (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ set_default ? "PrinterAddOptionDefault" :
+ "PrinterAddOption",
+ g_variant_new ("(ssas)",
+ printer_name,
+ option_name,
+ &array_builder),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_TIMEOUT,
+ cancellable,
+ printer_add_option_async_dbus_cb,
+ pao_data_new (cancellable, callback, user_data));
+}
+
+typedef struct
+{
+ GList *backend_list;
+ GCancellable *cancellable;
+ GCDCallback callback;
+ gpointer user_data;
+} GCDData;
+
+static GCDData *
+gcd_data_new (GList *backend_list, GCancellable *cancellable, GCDCallback callback, gpointer user_data)
+{
+ GCDData *data;
+
+ data = g_new0 (GCDData, 1);
+ data->backend_list = backend_list;
+ if (cancellable)
+ data->cancellable = g_object_ref (cancellable);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ return data;
+}
+
+static void
+gcd_data_free (GCDData *data)
+{
+ g_list_free_full (data->backend_list, g_free);
+ g_clear_object (&data->cancellable);
+ g_free (data);
+}
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (GCDData, gcd_data_free)
+
+static gint
+get_suffix_index (const gchar *string)
+{
+ gchar *number;
+ gchar *endptr;
+ gint index = -1;
+
+ number = g_strrstr (string, ":");
+ if (number)
+ {
+ number++;
+ index = g_ascii_strtoll (number, &endptr, 10);
+ if (index == 0 && endptr == number)
+ index = -1;
+ }
+
+ return index;
+}
+
+static void
+get_cups_devices_async_dbus_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+
+{
+ g_autoptr(GPtrArray) devices = NULL;
+ g_autoptr(GVariant) output = NULL;
+ g_autoptr(GCDData) data = user_data;
+ g_autoptr(GError) error = NULL;
+ gint num_of_devices = 0;
+
+ output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ res,
+ &error);
+
+ if (output)
+ {
+ const gchar *ret_error;
+ g_autoptr(GVariant) devices_variant = NULL;
+ gboolean is_network_device;
+ g_autoptr(GVariantIter) iter = NULL;
+ const gchar *key, *value;
+ gint index = -1, max_index = -1, i;
+
+ g_variant_get (output, "(&s@a{ss})",
+ &ret_error,
+ &devices_variant);
+
+ if (ret_error[0] != '\0')
+ {
+ g_warning ("cups-pk-helper: getting of CUPS devices failed: %s", ret_error);
+ }
+
+ g_variant_get (devices_variant, "a{ss}", &iter);
+ while (g_variant_iter_next (iter, "{&s&s}", &key, &value))
+ {
+ index = get_suffix_index (key);
+ if (index > max_index)
+ max_index = index;
+ }
+
+ if (max_index >= 0)
+ {
+ g_autoptr(GVariantIter) iter2 = NULL;
+
+ num_of_devices = max_index + 1;
+ devices = g_ptr_array_new_with_free_func (g_object_unref);
+ for (i = 0; i < num_of_devices; i++)
+ g_ptr_array_add (devices, pp_print_device_new ());
+
+ g_variant_get (devices_variant, "a{ss}", &iter2);
+ while (g_variant_iter_next (iter2, "{&s&s}", &key, &value))
+ {
+ PpPrintDevice *device;
+
+ index = get_suffix_index (key);
+ if (index >= 0)
+ {
+ device = g_ptr_array_index (devices, index);
+ if (g_str_has_prefix (key, "device-class"))
+ {
+ is_network_device = g_strcmp0 (value, "network") == 0;
+ g_object_set (device, "is-network-device", is_network_device, NULL);
+ }
+ else if (g_str_has_prefix (key, "device-id"))
+ g_object_set (device, "device-id", value, NULL);
+ else if (g_str_has_prefix (key, "device-info"))
+ g_object_set (device, "device-info", value, NULL);
+ else if (g_str_has_prefix (key, "device-make-and-model"))
+ {
+ g_object_set (device,
+ "device-make-and-model", value,
+ "device-name", value,
+ NULL);
+ }
+ else if (g_str_has_prefix (key, "device-uri"))
+ g_object_set (device, "device-uri", value, NULL);
+ else if (g_str_has_prefix (key, "device-location"))
+ g_object_set (device, "device-location", value, NULL);
+
+ g_object_set (device, "acquisition-method", ACQUISITION_METHOD_DEFAULT_CUPS_SERVER, NULL);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("%s", error->message);
+
+ data->callback (devices,
+ TRUE,
+ g_cancellable_is_cancelled (data->cancellable),
+ data->user_data);
+ return;
+ }
+
+ if (data->backend_list)
+ {
+ if (!g_cancellable_is_cancelled (data->cancellable))
+ {
+ GVariantBuilder *include_scheme_builder = NULL;
+ GVariantBuilder *exclude_scheme_builder = NULL;
+ g_autofree gchar *backend_name = NULL;
+
+ backend_name = data->backend_list->data;
+
+ data->callback (devices,
+ FALSE,
+ FALSE,
+ data->user_data);
+
+ if (g_strcmp0 (backend_name, OTHER_BACKENDS) != 0)
+ {
+ include_scheme_builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+ g_variant_builder_add (include_scheme_builder, "s", backend_name);
+ }
+ else
+ {
+ exclude_scheme_builder = create_other_backends_array ();
+ }
+
+ data->backend_list = g_list_delete_link (data->backend_list, data->backend_list);
+
+ g_dbus_connection_call (G_DBUS_CONNECTION (g_object_ref (source_object)),
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "DevicesGet",
+ g_variant_new ("(iiasas)",
+ 0,
+ 0,
+ include_scheme_builder,
+ exclude_scheme_builder),
+ G_VARIANT_TYPE ("(sa{ss})"),
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_TIMEOUT,
+ data->cancellable,
+ get_cups_devices_async_dbus_cb,
+ data);
+ g_steal_pointer (&data);
+
+ if (include_scheme_builder)
+ g_variant_builder_unref (include_scheme_builder);
+
+ if (exclude_scheme_builder)
+ g_variant_builder_unref (exclude_scheme_builder);
+
+ return;
+ }
+ else
+ {
+ data->callback (devices,
+ TRUE,
+ TRUE,
+ data->user_data);
+ }
+ }
+ else
+ {
+ data->callback (devices,
+ TRUE,
+ g_cancellable_is_cancelled (data->cancellable),
+ data->user_data);
+ }
+}
+
+void
+get_cups_devices_async (GCancellable *cancellable,
+ GCDCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+ GVariantBuilder include_scheme_builder;
+ GList *backend_list;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *backend_name = NULL;
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!bus)
+ {
+ g_warning ("Failed to get system bus: %s", error->message);
+ callback (NULL, TRUE, FALSE, user_data);
+ return;
+ }
+
+ backend_list = create_backends_list ();
+
+ backend_name = backend_list->data;
+
+ g_variant_builder_init (&include_scheme_builder, G_VARIANT_TYPE ("as"));
+ g_variant_builder_add (&include_scheme_builder, "s", backend_name);
+
+ backend_list = g_list_delete_link (backend_list, backend_list);
+
+ g_dbus_connection_call (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "DevicesGet",
+ g_variant_new ("(iiasas)",
+ 0,
+ 0,
+ &include_scheme_builder,
+ NULL),
+ G_VARIANT_TYPE ("(sa{ss})"),
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_TIMEOUT,
+ cancellable,
+ get_cups_devices_async_dbus_cb,
+ gcd_data_new (backend_list, cancellable, callback, user_data));
+}
+
+gchar *
+guess_device_hostname (PpPrintDevice *device)
+{
+ http_uri_status_t status;
+ char scheme[HTTP_MAX_URI];
+ char username[HTTP_MAX_URI];
+ char hostname[HTTP_MAX_URI];
+ char resource[HTTP_MAX_URI];
+ int port;
+ gchar *result = NULL;
+ gchar *hostname_begin;
+ gchar *hostname_end = NULL;
+
+ if (device != NULL && pp_print_device_get_device_uri (device) != NULL)
+ {
+ if (g_str_has_prefix (pp_print_device_get_device_uri (device), "socket") ||
+ g_str_has_prefix (pp_print_device_get_device_uri (device), "lpd") ||
+ g_str_has_prefix (pp_print_device_get_device_uri (device), "ipp") ||
+ g_str_has_prefix (pp_print_device_get_device_uri (device), "smb"))
+ {
+ status = httpSeparateURI (HTTP_URI_CODING_ALL,
+ pp_print_device_get_device_uri (device),
+ scheme, HTTP_MAX_URI,
+ username, HTTP_MAX_URI,
+ hostname, HTTP_MAX_URI,
+ &port,
+ resource, HTTP_MAX_URI);
+
+ if (status >= HTTP_URI_STATUS_OK &&
+ hostname[0] != '\0')
+ result = g_strdup (hostname);
+ }
+ else if ((g_str_has_prefix (pp_print_device_get_device_uri (device), "dnssd") ||
+ g_str_has_prefix (pp_print_device_get_device_uri (device), "mdns")) &&
+ pp_print_device_get_device_info (device) != NULL)
+ {
+ /*
+ * CUPS browses its printers as
+ * "PrinterName @ ComputerName" or "PrinterInfo @ ComputerName"
+ * through DNS-SD.
+ */
+ hostname_begin = g_strrstr (pp_print_device_get_device_info (device), " @ ");
+ if (hostname_begin != NULL)
+ result = g_strdup (hostname_begin + 3);
+ }
+ else if (g_str_has_prefix (pp_print_device_get_device_uri (device), "hp:/net/") ||
+ g_str_has_prefix (pp_print_device_get_device_uri (device), "hpfax:/net/"))
+ {
+ /*
+ * HPLIP printers have URI of form hp:/net/%s?ip=%s&port=%d
+ * or hp:/net/%s?ip=%s.
+ */
+ hostname_begin = g_strrstr (pp_print_device_get_device_uri (device), "ip=");
+ if (hostname_begin != NULL)
+ {
+ hostname_begin += 3;
+ hostname_end = strstr (hostname_begin, "&");
+ }
+
+ if (hostname_end != NULL)
+ result = g_strndup (hostname_begin, hostname_end - hostname_begin);
+ else
+ result = g_strdup (hostname_begin);
+ }
+ }
+
+ return result;
+}
+
+gchar *
+canonicalize_device_name (GList *device_names,
+ GPtrArray *local_cups_devices,
+ cups_dest_t *dests,
+ gint num_of_dests,
+ PpPrintDevice *device)
+{
+ PpPrintDevice *item;
+ gboolean already_present;
+ GList *iter;
+ gsize len;
+ g_autofree gchar *name = NULL;
+ gchar *occurrence;
+ gint name_index, j;
+ static const char * const residues[] = {
+ "-foomatic",
+ "-hpijs",
+ "-hpcups",
+ "-cups",
+ "-gutenprint",
+ "-series",
+ "-label-printer",
+ "-dot-matrix",
+ "-ps3",
+ "-ps2",
+ "-br-script",
+ "-kpdl",
+ "-pcl3",
+ "-pcl",
+ "-zxs",
+ "-pxl"};
+
+ if (pp_print_device_get_device_id (device) != NULL)
+ {
+ name = get_tag_value (pp_print_device_get_device_id (device), "mdl");
+ if (name == NULL)
+ name = get_tag_value (pp_print_device_get_device_id (device), "model");
+ }
+
+ if (name == NULL &&
+ pp_print_device_get_device_make_and_model (device) != NULL &&
+ pp_print_device_get_device_make_and_model (device)[0] != '\0')
+ {
+ name = g_strdup (pp_print_device_get_device_make_and_model (device));
+ }
+
+ if (name == NULL &&
+ pp_print_device_get_device_original_name (device) != NULL &&
+ pp_print_device_get_device_original_name (device)[0] != '\0')
+ {
+ name = g_strdup (pp_print_device_get_device_original_name (device));
+ }
+
+ if (name == NULL &&
+ pp_print_device_get_device_info (device) != NULL &&
+ pp_print_device_get_device_info (device)[0] != '\0')
+ {
+ name = g_strdup (pp_print_device_get_device_info (device));
+ }
+
+ if (name == NULL)
+ return NULL;
+
+ g_strstrip (name);
+ g_strcanon (name, ALLOWED_CHARACTERS, '-');
+
+ /* Remove common strings found in driver names */
+ for (j = 0; j < G_N_ELEMENTS (residues); j++)
+ {
+ g_autofree gchar *lower_name = g_ascii_strdown (name, -1);
+
+ occurrence = g_strrstr (lower_name, residues[j]);
+ if (occurrence != NULL)
+ {
+ occurrence[0] = '\0';
+ name[strlen (lower_name)] = '\0';
+ }
+ }
+
+ /* Remove trailing "-" */
+ len = strlen (name);
+ while (len-- && name[len] == '-')
+ name[len] = '\0';
+
+ /* Merge "--" to "-" */
+ occurrence = g_strrstr (name, "--");
+ while (occurrence != NULL)
+ {
+ shift_string_left (occurrence);
+ occurrence = g_strrstr (name, "--");
+ }
+
+ /* Remove leading "-" */
+ if (name[0] == '-')
+ shift_string_left (name);
+
+ name_index = 2;
+ already_present = FALSE;
+ while (TRUE)
+ {
+ g_autofree gchar *new_name = NULL;
+
+ if (already_present)
+ {
+ new_name = g_strdup_printf ("%s-%d", name, name_index);
+ name_index++;
+ }
+ else
+ {
+ new_name = g_strdup (name);
+ }
+
+ already_present = FALSE;
+ for (j = 0; j < num_of_dests; j++)
+ if (g_strcmp0 (dests[j].name, new_name) == 0)
+ already_present = TRUE;
+
+ for (iter = device_names; iter; iter = iter->next)
+ {
+ gchar *device_original_name = iter->data;
+ if (g_strcmp0 (device_original_name, new_name) == 0)
+ already_present = TRUE;
+ }
+
+ for (guint i = 0; i < local_cups_devices->len; i++)
+ {
+ item = g_ptr_array_index (local_cups_devices, i);
+ if (g_strcmp0 (pp_print_device_get_device_original_name (item), new_name) == 0)
+ already_present = TRUE;
+ }
+
+ if (!already_present)
+ return g_steal_pointer (&new_name);
+ }
+}
+
+void
+shift_string_left (gchar *str)
+{
+ gchar *next;
+
+ if (str != NULL && str[0] != '\0')
+ {
+ next = g_utf8_find_next_char (str, NULL);
+ memmove (str, next, strlen (next) + 1);
+ }
+}
+
+gboolean
+printer_name_is_valid (const gchar *str)
+{
+ const gchar *invalid_chars = " \t#/";
+ return strlen(str) == strcspn(str, invalid_chars);
+}
diff --git a/panels/printers/pp-utils.h b/panels/printers/pp-utils.h
new file mode 100644
index 0000000..332cda4
--- /dev/null
+++ b/panels/printers/pp-utils.h
@@ -0,0 +1,263 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2009-2010 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <cups/cups.h>
+
+#include "pp-print-device.h"
+
+#define ALLOWED_CHARACTERS "abcdefghijklmnopqrtsuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
+
+#define MECHANISM_BUS "org.opensuse.CupsPkHelper.Mechanism"
+
+#define SCP_BUS "org.fedoraproject.Config.Printing"
+#define SCP_PATH "/org/fedoraproject/Config/Printing"
+#define SCP_IFACE "org.fedoraproject.Config.Printing"
+
+G_BEGIN_DECLS
+
+typedef void (*UserResponseCallback) (GtkDialog *dialog, gint response_id, gpointer user_data);
+
+/*
+ * Match level of PPD driver.
+ */
+enum
+{
+ PPD_NO_MATCH = 0,
+ PPD_GENERIC_MATCH,
+ PPD_CLOSE_MATCH,
+ PPD_EXACT_MATCH,
+ PPD_EXACT_CMD_MATCH
+};
+
+enum
+{
+ ACQUISITION_METHOD_DEFAULT_CUPS_SERVER = 0,
+ ACQUISITION_METHOD_REMOTE_CUPS_SERVER,
+ ACQUISITION_METHOD_SNMP,
+ ACQUISITION_METHOD_SAMBA,
+ ACQUISITION_METHOD_SAMBA_HOST,
+ ACQUISITION_METHOD_JETDIRECT,
+ ACQUISITION_METHOD_LPD
+};
+
+typedef struct
+{
+ gchar *ppd_name;
+ gchar *ppd_display_name;
+ gint ppd_match_level;
+} PPDName;
+
+typedef struct
+{
+ gchar *manufacturer_name;
+ gchar *manufacturer_display_name;
+ PPDName **ppds;
+ gsize num_of_ppds;
+} PPDManufacturerItem;
+
+typedef struct
+{
+ PPDManufacturerItem **manufacturers;
+ gsize num_of_manufacturers;
+} PPDList;
+
+gchar *get_tag_value (const gchar *tag_string,
+ const gchar *tag_name);
+
+char *get_dest_attr (const char *dest_name,
+ const char *attr);
+
+gchar *get_ppd_attribute (const gchar *ppd_file_name,
+ const gchar *attribute_name);
+
+void set_local_default_printer (const gchar *printer_name);
+
+gboolean printer_set_location (const gchar *printer_name,
+ const gchar *location);
+
+gboolean printer_set_accepting_jobs (const gchar *printer_name,
+ gboolean accepting_jobs,
+ const gchar *reason);
+
+gboolean printer_set_enabled (const gchar *printer_name,
+ gboolean enabled);
+
+gboolean printer_rename (const gchar *old_name,
+ const gchar *new_name);
+
+gboolean printer_delete (const gchar *printer_name);
+
+gboolean printer_set_default (const gchar *printer_name);
+
+gboolean printer_set_shared (const gchar *printer_name,
+ gboolean shared);
+
+gboolean printer_set_job_sheets (const gchar *printer_name,
+ const gchar *start_sheet,
+ const gchar *end_sheet);
+
+gboolean printer_set_policy (const gchar *printer_name,
+ const gchar *policy,
+ gboolean error_policy);
+
+gboolean printer_set_users (const gchar *printer_name,
+ gchar **users,
+ gboolean allowed);
+
+gboolean class_add_printer (const gchar *class_name,
+ const gchar *printer_name);
+
+gboolean printer_is_local (cups_ptype_t printer_type,
+ const gchar *device_uri);
+
+gchar *printer_get_hostname (cups_ptype_t printer_type,
+ const gchar *device_uri,
+ const gchar *printer_uri);
+
+typedef void (*PSPCallback) (const gchar *printer_name,
+ gboolean success,
+ gpointer user_data);
+
+void printer_set_ppd_async (const gchar *printer_name,
+ const gchar *ppd_name,
+ GCancellable *cancellable,
+ PSPCallback callback,
+ gpointer user_data);
+
+void printer_set_ppd_file_async (const gchar *printer_name,
+ const gchar *ppd_filename,
+ GCancellable *cancellable,
+ PSPCallback callback,
+ gpointer user_data);
+
+typedef void (*GPNCallback) (PPDName **names,
+ const gchar *printer_name,
+ gboolean cancelled,
+ gpointer user_data);
+
+void get_ppd_names_async (gchar *printer_name,
+ gint count,
+ GCancellable *cancellable,
+ GPNCallback callback,
+ gpointer user_data);
+
+typedef void (*GAPCallback) (PPDList *ppds,
+ gpointer user_data);
+
+void get_all_ppds_async (GCancellable *cancellable,
+ GAPCallback callback,
+ gpointer user_data);
+
+PPDList *ppd_list_copy (PPDList *list);
+void ppd_list_free (PPDList *list);
+
+enum
+{
+ IPP_ATTRIBUTE_TYPE_INTEGER = 0,
+ IPP_ATTRIBUTE_TYPE_STRING,
+ IPP_ATTRIBUTE_TYPE_RANGE,
+ IPP_ATTRIBUTE_TYPE_BOOLEAN
+};
+
+typedef struct
+{
+ gboolean boolean_value;
+ gchar *string_value;
+ gint integer_value;
+ gint lower_range;
+ gint upper_range;
+} IPPAttributeValue;
+
+typedef struct
+{
+ gchar *attribute_name;
+ IPPAttributeValue *attribute_values;
+ gint num_of_values;
+ gint attribute_type;
+} IPPAttribute;
+
+typedef void (*GIACallback) (GHashTable *table,
+ gpointer user_data);
+
+void get_ipp_attributes_async (const gchar *printer_name,
+ gchar **attributes_names,
+ GIACallback callback,
+ gpointer user_data);
+
+IPPAttribute *ipp_attribute_copy (IPPAttribute *attr);
+
+void ipp_attribute_free (IPPAttribute *attr);
+
+gchar *get_standard_manufacturers_name (const gchar *name);
+
+typedef void (*PGPCallback) (const gchar *ppd_filename,
+ gpointer user_data);
+
+void printer_get_ppd_async (const gchar *printer_name,
+ const gchar *host_name,
+ gint port,
+ PGPCallback callback,
+ gpointer user_data);
+
+/* NOTE: 'destination' is passed with ownership as cupsCopyDest doesn't seem to work as expected */
+typedef void (*GNDCallback) (cups_dest_t *destination,
+ gpointer user_data);
+
+void get_named_dest_async (const gchar *printer_name,
+ GNDCallback callback,
+ gpointer user_data);
+
+typedef void (*PAOCallback) (gboolean success,
+ gpointer user_data);
+
+void printer_add_option_async (const gchar *printer_name,
+ const gchar *option_name,
+ gchar **values,
+ gboolean set_default,
+ GCancellable *cancellable,
+ PAOCallback callback,
+ gpointer user_data);
+
+const gchar *get_page_size_from_locale (void);
+
+typedef void (*GCDCallback) (GPtrArray *devices,
+ gboolean finished,
+ gboolean cancelled,
+ gpointer user_data);
+
+void get_cups_devices_async (GCancellable *cancellable,
+ GCDCallback callback,
+ gpointer user_data);
+
+gchar *guess_device_hostname (PpPrintDevice *device);
+
+gchar *canonicalize_device_name (GList *device_names,
+ GPtrArray *local_cups_devices,
+ cups_dest_t *dests,
+ gint num_of_dests,
+ PpPrintDevice *device);
+
+void shift_string_left (gchar *str);
+
+gboolean printer_name_is_valid (const gchar *str);
+
+G_END_DECLS
diff --git a/panels/printers/ppd-selection-dialog.ui b/panels/printers/ppd-selection-dialog.ui
new file mode 100644
index 0000000..5408792
--- /dev/null
+++ b/panels/printers/ppd-selection-dialog.ui
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.18.3 -->
+<interface>
+ <requires lib="gtk+" version="3.12"/>
+ <template class="PpPPDSelectionDialog" parent="GtkDialog">
+ <property name="width_request">600</property>
+ <property name="height_request">400</property>
+ <property name="title" translatable="yes">Select Printer Driver</property>
+ <property name="modal">True</property>
+ <property name="destroy_with_parent">True</property>
+ <child>
+ <object class="GtkBox" id="main-vbox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">10</property>
+ <property name="margin_top">10</property>
+ <property name="margin_start">10</property>
+ <property name="margin_end">10</property>
+ <child>
+ <object class="GtkBox" id="box3">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="spacing">10</property>
+ <property name="halign">fill</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="width_request">140</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="halign">fill</property>
+ <property name="has_frame">True</property>
+ <child>
+ <object class="GtkTreeView" id="ppd_selection_manufacturers_treeview">
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview-selection"/>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow2">
+ <property name="hexpand">True</property>
+ <property name="halign">fill</property>
+ <property name="has_frame">True</property>
+ <child>
+ <object class="GtkTreeView" id="ppd_selection_models_treeview">
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview-selection1"/>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="dialog-action-area1">
+ <property name="halign">fill</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">10</property>
+ <property name="margin_bottom">10</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="halign">fill</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkSpinner" id="ppd_spinner">
+ <property name="width_request">24</property>
+ <property name="height_request">24</property>
+ <property name="halign">fill</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="progress_label">
+ <property name="label" translatable="yes">Loading drivers database…</property>
+ <property name="halign">fill</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="ppd_selection_cancel_button">
+ <property name="label" translatable="yes">Cancel</property>
+ <property name="receives_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">end</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="ppd_selection_select_button">
+ <property name="label" translatable="yes">Select</property>
+ <property name="sensitive">False</property>
+ <property name="receives_default">True</property>
+ <property name="halign">end</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-6">ppd_selection_cancel_button</action-widget>
+ <action-widget response="-5">ppd_selection_select_button</action-widget>
+ </action-widgets>
+ </template>
+</interface>
diff --git a/panels/printers/printer-entry.ui b/panels/printers/printer-entry.ui
new file mode 100644
index 0000000..37fe3e0
--- /dev/null
+++ b/panels/printers/printer-entry.ui
@@ -0,0 +1,319 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.8 -->
+ <object class="GtkPopover" id="printer-menu">
+ <style>
+ <class name="menu" />
+ </style>
+
+ <child>
+ <object class="GtkGrid">
+ <property name="margin-top">10</property>
+ <property name="margin-bottom">10</property>
+ <property name="margin-start">10</property>
+ <property name="margin-end">10</property>
+
+ <child>
+ <object class="GtkModelButton">
+ <property name="text" translatable="yes">Printing Options</property>
+ <signal name="clicked" handler="on_show_printer_options_dialog"/>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkModelButton">
+ <property name="text" translatable="yes">Printer Details</property>
+ <signal name="clicked" handler="on_show_printer_details_dialog"/>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="printer_default_checkbutton">
+ <property name="valign">center</property>
+ <property name="label" translatable="yes" comments="Set this printer as default">Use Printer by Default</property>
+ <signal name="toggled" handler="set_as_default_printer"/>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ <property name="column-span">3</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkModelButton" id="clean_heads_menuitem">
+ <property name="visible">False</property>
+ <property name="text" translatable="yes" comments="Translators: This button executes command which cleans print heads of the printer.">Clean Print Heads</property>
+ <signal name="clicked" handler="clean_heads"/>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkModelButton" id="remove_printer_menuitem">
+ <property name="text" translatable="yes">Remove Printer</property>
+ <signal name="clicked" handler="remove_printer"/>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">4</property>
+ </layout>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+
+ <template class="PpPrinterEntry" parent="GtkListBoxRow">
+ <property name="valign">center</property>
+ <property name="margin-top">10</property>
+ <property name="margin-bottom">10</property>
+ <property name="margin-start">60</property>
+ <property name="margin-end">60</property>
+ <property name="activatable">False</property>
+ <property name="hexpand">True</property>
+
+ <child>
+ <object class="GtkFrame" id="content_area">
+ <property name="valign">start</property>
+ <style>
+ <class name="view"/>
+ </style>
+
+ <child>
+ <object class="GtkGrid">
+ <property name="row-spacing">8</property>
+ <property name="column-spacing">15</property>
+ <property name="margin_start">24</property>
+ <property name="margin_end">20</property>
+ <property name="margin_top">14</property>
+ <property name="margin_bottom">20</property>
+
+ <child>
+ <object class="GtkImage" id="printer_icon">
+ <property name="pixel-size">48</property>
+ <property name="icon_name">printer</property>
+ <property name="valign">center</property>
+ <property name="halign">center</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkGrid" id="printer_name_grid">
+ <property name="margin-top">10</property>
+ <property name="margin-bottom">10</property>
+ <property name="margin_start">0</property>
+ <property name="margin-end">10</property>
+ <property name="halign">start</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ <child>
+
+ <object class="GtkLabel" id="printer_name_label">
+ <property name="hexpand">True</property>
+ <property name="halign">start</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_MIDDLE</property>
+ <property name="width-chars">22</property>
+ <property name="xalign">0</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ <attribute name="scale" value="1.2"/>
+ </attributes>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="printer_status">
+ <property name="halign">start</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">12</property>
+ <property name="orientation">horizontal</property>
+ <property name="valign">center</property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">0</property>
+ </layout>
+ <child>
+
+ <object class="GtkButton" id="show_jobs_dialog_button">
+ <property name="sensitive">False</property>
+ <property name="label" translatable="yes">No Active Jobs</property>
+ <signal name="clicked" handler="show_jobs_dialog"/>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkMenuButton">
+ <property name="popover">printer-menu</property>
+ <property name="icon_name">emblem-system-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="printer_model_label">
+ <property name="label" translatable="yes">Model</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_MIDDLE</property>
+ <property name="halign">end</property>
+ <property name="xalign">1</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="printer_model">
+ <property name="halign">start</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_MIDDLE</property>
+ <property name="xalign">0</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="printer_location_label">
+ <property name="label" translatable="yes">Location</property>
+ <property name="halign">end</property>
+ <property name="xalign">1</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="printer_location_address_label">
+ <property name="halign">start</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_MIDDLE</property>
+ <property name="xalign">0</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="printer_inklevel_label">
+ <property name="label" translatable="yes">Ink Level</property>
+ <property name="halign">end</property>
+ <property name="xalign">1</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkFrame" id="supply_frame">
+ <property name="valign">center</property>
+ <property name="halign">start</property>
+ <property name="height_request">18</property>
+ <property name="width_request">300</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ <property name="column-span">2</property>
+ </layout>
+
+ <child>
+ <object class="GtkDrawingArea" id="supply_drawing_area">
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkBox" id="printer_error">
+ <property name="visible">False</property>
+ <property name="spacing">10</property>
+ <property name="margin-top">6</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">4</property>
+ <property name="column-span">3</property>
+ </layout>
+
+ <child>
+ <object class="GtkImage">
+ <property name="icon_name">dialog-warning-symbolic</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="error_status">
+ <property name="halign">start</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel">
+ <property name="hexpand">True</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" comments="Translators: This is the message which follows the printer error.">Please restart when the problem is resolved.</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkButton">
+ <property name="label" translatable="yes" comments="Translators: This is the button which restarts the printer.">Restart</property>
+ <signal name="clicked" handler="restart_printer"/>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+
+</interface>
diff --git a/panels/printers/printers.gresource.xml b/panels/printers/printers.gresource.xml
new file mode 100644
index 0000000..cecce18
--- /dev/null
+++ b/panels/printers/printers.gresource.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/printers">
+ <file preprocess="xml-stripblanks">new-printer-dialog.ui</file>
+ <file preprocess="xml-stripblanks">pp-options-dialog.ui</file>
+ <file preprocess="xml-stripblanks">ppd-selection-dialog.ui</file>
+ <file preprocess="xml-stripblanks">pp-details-dialog.ui</file>
+ <file preprocess="xml-stripblanks">pp-job-row.ui</file>
+ <file preprocess="xml-stripblanks">pp-jobs-dialog.ui</file>
+ <file preprocess="xml-stripblanks">printer-entry.ui</file>
+ <file preprocess="xml-stripblanks">printers.ui</file>
+ </gresource>
+</gresources>
diff --git a/panels/printers/printers.ui b/panels/printers/printers.ui
new file mode 100644
index 0000000..128c26e
--- /dev/null
+++ b/panels/printers/printers.ui
@@ -0,0 +1,242 @@
+<?xml version="1.0"?>
+<interface>
+ <requires lib="gtk+" version="3.12"/>
+ <object class="GtkBox" id="top-right-buttons">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkButton" id="printer-add-button">
+ <property name="sensitive">False</property>
+ <property name="use_underline">True</property>
+ <property name="label" translatable="yes" comments="Translators: This button adds new printer.">Add Printer…</property>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="search-button">
+ <property name="margin-end">6</property> <!-- since we don't have access to the shell header bar -->
+ <property name="icon_name">edit-find-symbolic</property>
+ <style>
+ <class name="image-button"/>
+ </style>
+ </object>
+ </child>
+ </object>
+
+<object class="GtkOverlay" id="overlay">
+ <child type="overlay">
+ <object class="GtkRevealer" id="notification">
+ <property name="halign">GTK_ALIGN_CENTER</property>
+ <property name="valign">GTK_ALIGN_START</property>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <style>
+ <class name="app-notification"/>
+ </style>
+ <child>
+ <object class="GtkLabel" id="notification-label">
+ <property name="wrap">True</property>
+ <property name="max_width_chars">50</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="notification-undo-button">
+ <property name="valign">GTK_ALIGN_CENTER</property>
+ <property name="label" translatable="yes" comments="Translators: This is the button which allows undoing the removal of the printer.">Undo</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="notification-dismiss-button">
+ <property name="valign">GTK_ALIGN_CENTER</property>
+ <property name="icon_name">window-close-symbolic</property>
+ <style>
+ <class name="flat"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+
+<object class="GtkBox">
+ <property name="orientation">GTK_ORIENTATION_VERTICAL</property>
+ <child>
+ <object class="CcPermissionInfobar" id="permission-infobar">
+ </object>
+ </child>
+ <child>
+
+ <object class="GtkStack" id="main-vbox">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">loading-page</property>
+ <property name="child">
+ <object class="GtkBox">
+ <child>
+ <object class="GtkSpinner" id="loading-spinner">
+ <property name="spinning">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">printers-list</property>
+ <property name="child">
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkSearchBar" id="search-bar">
+ <property name="hexpand">True</property>
+ <property name="search_mode_enabled" bind-source="search-button" bind-property="active" bind-flags="bidirectional" />
+ <child>
+ <object class="GtkSearchEntry" id="search-entry">
+ <property name="width_chars">30</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolled-window">
+ <property name="hscrollbar-policy">never</property>
+ <property name="min-content-height">490</property>
+ <property name="vexpand">True</property>
+ <child>
+ <object class="GtkBox">
+ <child>
+ <object class="GtkListBox" id="content">
+ <property name="selection-mode">GTK_SELECTION_NONE</property>
+ <property name="margin-top">32</property>
+ <property name="margin-bottom">32</property>
+ <style>
+ <class name="background"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">empty-state</property>
+ <property name="child">
+ <object class="GtkBox">
+ <property name="spacing">10</property>
+ <property name="orientation">vertical</property>
+ <property name="valign">center</property>
+ <child>
+ <object class="GtkImage">
+ <property name="valign">start</property>
+ <property name="pixel_size">80</property>
+ <property name="icon_name">printer-symbolic</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="margin_bottom">15</property>
+ <property name="label" translatable="yes">No printers</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <attributes>
+ <attribute name="scale" value="1.2"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="printer-add-button2">
+ <property name="label" translatable="yes" comments="Translators: This button adds new printer.">Add Printer…</property>
+ <property name="receives_default">True</property>
+ <property name="halign">center</property>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">no-cups-page</property>
+ <property name="child">
+ <object class="GtkBox">
+ <property name="spacing">10</property>
+ <property name="orientation">vertical</property>
+ <property name="valign">center</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="label" translatable="yes" comments="Translators: The CUPS server is not running (we can not connect to it).">Sorry! The system printing service
+ doesn’t seem to be available.</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <attributes>
+ <attribute name="scale" value="1.2"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="valign">start</property>
+ <property name="pixel_size">80</property>
+ <property name="icon_name">computer-fail-symbolic</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ </object>
+</child>
+</object>
+
+ </child>
+</object>
+
+ <object class="GtkSizeGroup" id="sizegroup1">
+ <widgets>
+ <widget name="back-button-1"/>
+ <widget name="back-spacer-label-1"/>
+ </widgets>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup2">
+ <widgets>
+ <widget name="back-button-2"/>
+ <widget name="back-spacer-label-2"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/panels/region/.indent.pro b/panels/region/.indent.pro
new file mode 100644
index 0000000..bdff074
--- /dev/null
+++ b/panels/region/.indent.pro
@@ -0,0 +1,2 @@
+-kr -i8 -pcs -lps -psl
+
diff --git a/panels/region/cc-format-chooser.c b/panels/region/cc-format-chooser.c
new file mode 100644
index 0000000..aab7832
--- /dev/null
+++ b/panels/region/cc-format-chooser.c
@@ -0,0 +1,541 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by:
+ * Matthias Clasen
+ */
+
+#define _GNU_SOURCE
+#include <config.h>
+#include "cc-format-chooser.h"
+
+#include <errno.h>
+#include <locale.h>
+#include <langinfo.h>
+#include <string.h>
+#include <glib/gi18n.h>
+#include <adwaita.h>
+
+#include "cc-common-language.h"
+#include "cc-format-preview.h"
+#include "cc-util.h"
+
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnome-desktop/gnome-languages.h>
+
+struct _CcFormatChooser {
+ GtkDialog parent_instance;
+
+ GtkWidget *title_bar;
+ GtkWidget *title_buttons;
+ GtkWidget *cancel_button;
+ GtkWidget *back_button;
+ GtkWidget *done_button;
+ GtkWidget *empty_results_view;
+ GtkWidget *main_leaflet;
+ GtkWidget *region_filter_entry;
+ GtkWidget *region_list;
+ GtkWidget *region_list_stack;
+ GtkWidget *common_region_title;
+ GtkWidget *common_region_listbox;
+ GtkWidget *region_box;
+ GtkWidget *region_title;
+ GtkWidget *region_listbox;
+ GtkWidget *preview_box;
+ CcFormatPreview *format_preview;
+ gboolean adding;
+ gboolean showing_extra;
+ gboolean no_results;
+ gchar *region;
+ gchar *preview_region;
+ gchar **filter_words;
+};
+
+G_DEFINE_TYPE (CcFormatChooser, cc_format_chooser, GTK_TYPE_DIALOG)
+
+static void
+update_check_button_for_list (GtkWidget *list_box,
+ const gchar *locale_id)
+{
+ GtkWidget *child;
+
+ for (child = gtk_widget_get_first_child (list_box);
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ {
+ if (!GTK_IS_LIST_BOX_ROW (child))
+ continue;
+
+ GtkWidget *check = g_object_get_data (G_OBJECT (child), "check");
+ const gchar *region = g_object_get_data (G_OBJECT (child), "locale-id");
+ if (check == NULL || region == NULL)
+ continue;
+
+ if (g_strcmp0 (locale_id, region) == 0)
+ gtk_widget_set_opacity (check, 1.0);
+ else
+ gtk_widget_set_opacity (check, 0.0);
+ }
+}
+
+static void
+set_locale_id (CcFormatChooser *chooser,
+ const gchar *locale_id)
+{
+ g_free (chooser->region);
+ chooser->region = g_strdup (locale_id);
+
+ update_check_button_for_list (chooser->region_listbox, locale_id);
+ update_check_button_for_list (chooser->common_region_listbox, locale_id);
+ cc_format_preview_set_region (chooser->format_preview, locale_id);
+}
+
+static gint
+sort_regions (gconstpointer a,
+ gconstpointer b,
+ gpointer data)
+{
+ const gchar *la;
+ const gchar *lb;
+
+ if (g_object_get_data (G_OBJECT (a), "locale-id") == NULL)
+ return 1;
+ if (g_object_get_data (G_OBJECT (b), "locale-id") == NULL)
+ return -1;
+
+ la = g_object_get_data (G_OBJECT (a), "locale-name");
+ lb = g_object_get_data (G_OBJECT (b), "locale-name");
+
+ return g_strcmp0 (la, lb);
+}
+
+static GtkWidget *
+padded_label_new (const char *text)
+{
+ GtkWidget *widget, *label;
+
+ widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
+ g_object_set (widget, "margin-top", 4, NULL);
+ g_object_set (widget, "margin-bottom", 4, NULL);
+ g_object_set (widget, "margin-start", 10, NULL);
+ g_object_set (widget, "margin-end", 10, NULL);
+
+ label = gtk_label_new (text);
+ gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
+ gtk_box_append (GTK_BOX (widget), label);
+
+ return widget;
+}
+
+static void
+format_chooser_back_button_clicked_cb (CcFormatChooser *self)
+{
+ g_assert (CC_IS_FORMAT_CHOOSER (self));
+
+ gtk_window_set_title (GTK_WINDOW (self), _("Formats"));
+ adw_leaflet_set_visible_child (ADW_LEAFLET (self->main_leaflet), self->region_box);
+ gtk_stack_set_visible_child (GTK_STACK (self->title_buttons), self->cancel_button);
+ gtk_widget_show (self->done_button);
+}
+
+static void
+set_preview_button_visible (GtkWidget *row,
+ gboolean visible)
+{
+ GtkWidget *button;
+
+ button = g_object_get_data (G_OBJECT (row), "preview-button");
+ g_assert (button);
+
+ gtk_widget_set_opacity (button, visible);
+ gtk_widget_set_sensitive (button, visible);
+}
+
+static void
+format_chooser_leaflet_fold_changed_cb (CcFormatChooser *self)
+{
+ GtkWidget *child;
+ gboolean folded;
+
+ g_assert (CC_IS_FORMAT_CHOOSER (self));
+
+ folded = adw_leaflet_get_folded (ADW_LEAFLET (self->main_leaflet));
+
+ for (child = gtk_widget_get_first_child (self->common_region_listbox);
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ {
+ if (GTK_IS_LIST_BOX_ROW (child))
+ set_preview_button_visible (child, folded);
+ }
+
+ for (child = gtk_widget_get_first_child (self->region_listbox);
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ {
+ if (GTK_IS_LIST_BOX_ROW (child))
+ set_preview_button_visible (child, folded);
+ }
+
+ if (!folded)
+ {
+ cc_format_preview_set_region (self->format_preview, self->region);
+ gtk_window_set_title (GTK_WINDOW (self), _("Formats"));
+ adw_leaflet_set_visible_child (ADW_LEAFLET (self->main_leaflet), self->region_box);
+ gtk_stack_set_visible_child (GTK_STACK (self->title_buttons), self->cancel_button);
+ gtk_widget_show (self->done_button);
+ }
+}
+
+static void
+preview_button_clicked_cb (CcFormatChooser *self,
+ GtkWidget *button)
+{
+ GtkWidget *row;
+ const gchar *region, *locale_name;
+
+ g_assert (CC_IS_FORMAT_CHOOSER (self));
+ g_assert (GTK_IS_WIDGET (button));
+
+ row = gtk_widget_get_ancestor (button, GTK_TYPE_LIST_BOX_ROW);
+ g_assert (row);
+
+ region = g_object_get_data (G_OBJECT (row), "locale-id");
+ locale_name = g_object_get_data (G_OBJECT (row), "locale-name");
+ cc_format_preview_set_region (self->format_preview, region);
+
+ adw_leaflet_set_visible_child (ADW_LEAFLET (self->main_leaflet), self->preview_box);
+ gtk_stack_set_visible_child (GTK_STACK (self->title_buttons), self->back_button);
+ gtk_widget_hide (self->done_button);
+
+ if (locale_name)
+ gtk_window_set_title (GTK_WINDOW (self), locale_name);
+}
+
+static GtkWidget *
+region_widget_new (CcFormatChooser *self,
+ const gchar *locale_id)
+{
+ gchar *locale_name;
+ gchar *locale_current_name;
+ gchar *locale_untranslated_name;
+ GtkWidget *row, *box, *button;
+ GtkWidget *check;
+
+ locale_name = gnome_get_country_from_locale (locale_id, locale_id);
+ if (!locale_name)
+ return NULL;
+
+ locale_current_name = gnome_get_country_from_locale (locale_id, NULL);
+ locale_untranslated_name = gnome_get_country_from_locale (locale_id, "C");
+
+ row = gtk_list_box_row_new ();
+ box = padded_label_new (locale_name);
+ gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), box);
+
+ check = gtk_image_new_from_icon_name ("object-select-symbolic");
+ gtk_widget_set_halign (check, GTK_ALIGN_START);
+ gtk_widget_set_hexpand (check, TRUE);
+ gtk_widget_set_opacity (check, 0.0);
+ gtk_box_append (GTK_BOX (box), check);
+
+ button = gtk_button_new_from_icon_name ("view-layout-symbolic");
+ g_signal_connect_object (button, "clicked", G_CALLBACK (preview_button_clicked_cb),
+ self, G_CONNECT_SWAPPED);
+ gtk_widget_show (button);
+ gtk_box_append (GTK_BOX (box), button);
+
+ g_object_set_data (G_OBJECT (row), "check", check);
+ g_object_set_data (G_OBJECT (row), "preview-button", button);
+ g_object_set_data_full (G_OBJECT (row), "locale-id", g_strdup (locale_id), g_free);
+ g_object_set_data_full (G_OBJECT (row), "locale-name", locale_name, g_free);
+ g_object_set_data_full (G_OBJECT (row), "locale-current-name", locale_current_name, g_free);
+ g_object_set_data_full (G_OBJECT (row), "locale-untranslated-name", locale_untranslated_name, g_free);
+
+ return row;
+}
+
+static void
+add_regions (CcFormatChooser *chooser,
+ gchar **locale_ids,
+ GHashTable *initial)
+{
+ g_autoptr(GList) initial_locales = NULL;
+ GtkWidget *widget;
+ GList *l;
+
+ chooser->adding = TRUE;
+ initial_locales = g_hash_table_get_keys (initial);
+
+ /* Populate Common Locales */
+ for (l = initial_locales; l != NULL; l = l->next) {
+ if (!cc_common_language_has_font (l->data))
+ continue;
+
+ widget = region_widget_new (chooser, l->data);
+ if (!widget)
+ continue;
+
+ gtk_list_box_append (GTK_LIST_BOX (chooser->common_region_listbox), widget);
+ }
+
+ /* Populate All locales */
+ while (*locale_ids) {
+ gchar *locale_id;
+
+ locale_id = *locale_ids;
+ locale_ids ++;
+
+ if (!cc_common_language_has_font (locale_id))
+ continue;
+
+ widget = region_widget_new (chooser, locale_id);
+ if (!widget)
+ continue;
+
+ gtk_list_box_append (GTK_LIST_BOX (chooser->region_listbox), widget);
+ }
+
+ chooser->adding = FALSE;
+}
+
+static void
+add_all_regions (CcFormatChooser *chooser)
+{
+ g_auto(GStrv) locale_ids = NULL;
+ g_autoptr(GHashTable) initial = NULL;
+
+ locale_ids = gnome_get_all_locales ();
+ initial = cc_common_language_get_initial_languages ();
+ add_regions (chooser, locale_ids, initial);
+}
+
+static gboolean
+match_all (gchar **words,
+ const gchar *str)
+{
+ gchar **w;
+
+ for (w = words; *w; ++w)
+ if (!strstr (str, *w))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+region_visible (GtkListBoxRow *row,
+ gpointer user_data)
+{
+ CcFormatChooser *chooser = user_data;
+ g_autofree gchar *locale_name = NULL;
+ g_autofree gchar *locale_current_name = NULL;
+ g_autofree gchar *locale_untranslated_name = NULL;
+ gboolean match = TRUE;
+
+ if (!chooser->filter_words)
+ goto end;
+
+ locale_name =
+ cc_util_normalize_casefold_and_unaccent (g_object_get_data (G_OBJECT (row), "locale-name"));
+ if (match_all (chooser->filter_words, locale_name))
+ goto end;
+
+ locale_current_name =
+ cc_util_normalize_casefold_and_unaccent (g_object_get_data (G_OBJECT (row), "locale-current-name"));
+ if (match_all (chooser->filter_words, locale_current_name))
+ goto end;
+
+ locale_untranslated_name =
+ cc_util_normalize_casefold_and_unaccent (g_object_get_data (G_OBJECT (row), "locale-untranslated-name"));
+
+ match = match_all (chooser->filter_words, locale_untranslated_name);
+
+ end:
+ if (match)
+ chooser->no_results = FALSE;
+ return match;
+}
+
+static void
+filter_changed (CcFormatChooser *chooser)
+{
+ g_autofree gchar *filter_contents = NULL;
+ gboolean visible;
+
+ g_clear_pointer (&chooser->filter_words, g_strfreev);
+
+ filter_contents =
+ cc_util_normalize_casefold_and_unaccent (gtk_editable_get_text (GTK_EDITABLE (chooser->region_filter_entry)));
+
+ /* The popular listbox is shown only if search is empty */
+ visible = filter_contents == NULL || *filter_contents == '\0';
+ gtk_widget_set_visible (chooser->common_region_listbox, visible);
+ gtk_widget_set_visible (chooser->common_region_title, visible);
+ gtk_widget_set_visible (chooser->region_title, visible);
+
+ /* Reset cached search state */
+ chooser->no_results = TRUE;
+
+ if (!filter_contents) {
+ gtk_list_box_invalidate_filter (GTK_LIST_BOX (chooser->region_listbox));
+ gtk_list_box_set_placeholder (GTK_LIST_BOX (chooser->region_listbox), NULL);
+ return;
+ }
+ chooser->filter_words = g_strsplit_set (g_strstrip (filter_contents), " ", 0);
+ gtk_list_box_invalidate_filter (GTK_LIST_BOX (chooser->region_listbox));
+
+ if (chooser->no_results)
+ gtk_stack_set_visible_child (GTK_STACK (chooser->region_list_stack),
+ GTK_WIDGET (chooser->empty_results_view));
+ else
+ gtk_stack_set_visible_child (GTK_STACK (chooser->region_list_stack),
+ GTK_WIDGET (chooser->region_list));
+}
+
+static void
+row_activated (CcFormatChooser *chooser,
+ GtkListBoxRow *row)
+{
+ const gchar *new_locale_id;
+
+ if (chooser->adding)
+ return;
+
+ new_locale_id = g_object_get_data (G_OBJECT (row), "locale-id");
+ if (g_strcmp0 (new_locale_id, chooser->region) == 0) {
+ gtk_dialog_response (GTK_DIALOG (chooser),
+ gtk_dialog_get_response_for_widget (GTK_DIALOG (chooser),
+ chooser->done_button));
+ } else {
+ set_locale_id (chooser, new_locale_id);
+ }
+}
+
+static void
+activate_default (CcFormatChooser *chooser)
+{
+ GtkWidget *focus;
+ const gchar *locale_id;
+
+ focus = gtk_window_get_focus (GTK_WINDOW (chooser));
+ if (!focus)
+ return;
+
+ locale_id = g_object_get_data (G_OBJECT (focus), "locale-id");
+ if (g_strcmp0 (locale_id, chooser->region) == 0)
+ return;
+
+ g_signal_stop_emission_by_name (chooser, "activate-default");
+ gtk_widget_activate (focus);
+}
+
+static void
+cc_format_chooser_dispose (GObject *object)
+{
+ CcFormatChooser *chooser = CC_FORMAT_CHOOSER (object);
+
+ g_clear_pointer (&chooser->filter_words, g_strfreev);
+ g_clear_pointer (&chooser->region, g_free);
+
+ G_OBJECT_CLASS (cc_format_chooser_parent_class)->dispose (object);
+}
+
+void
+cc_format_chooser_class_init (CcFormatChooserClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = cc_format_chooser_dispose;
+
+ g_type_ensure (CC_TYPE_FORMAT_PREVIEW);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/region/cc-format-chooser.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcFormatChooser, title_bar);
+ gtk_widget_class_bind_template_child (widget_class, CcFormatChooser, title_buttons);
+ gtk_widget_class_bind_template_child (widget_class, CcFormatChooser, cancel_button);
+ gtk_widget_class_bind_template_child (widget_class, CcFormatChooser, back_button);
+ gtk_widget_class_bind_template_child (widget_class, CcFormatChooser, done_button);
+ gtk_widget_class_bind_template_child (widget_class, CcFormatChooser, main_leaflet);
+ gtk_widget_class_bind_template_child (widget_class, CcFormatChooser, region_filter_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcFormatChooser, common_region_title);
+ gtk_widget_class_bind_template_child (widget_class, CcFormatChooser, common_region_listbox);
+ gtk_widget_class_bind_template_child (widget_class, CcFormatChooser, region_box);
+ gtk_widget_class_bind_template_child (widget_class, CcFormatChooser, region_title);
+ gtk_widget_class_bind_template_child (widget_class, CcFormatChooser, region_listbox);
+ gtk_widget_class_bind_template_child (widget_class, CcFormatChooser, region_list);
+ gtk_widget_class_bind_template_child (widget_class, CcFormatChooser, region_list_stack);
+ gtk_widget_class_bind_template_child (widget_class, CcFormatChooser, preview_box);
+ gtk_widget_class_bind_template_child (widget_class, CcFormatChooser, empty_results_view);
+ gtk_widget_class_bind_template_child (widget_class, CcFormatChooser, format_preview);
+
+ gtk_widget_class_bind_template_callback (widget_class, format_chooser_back_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, format_chooser_leaflet_fold_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, filter_changed);
+ gtk_widget_class_bind_template_callback (widget_class, row_activated);
+}
+
+void
+cc_format_chooser_init (CcFormatChooser *chooser)
+{
+ gtk_widget_init_template (GTK_WIDGET (chooser));
+
+ gtk_list_box_set_sort_func (GTK_LIST_BOX (chooser->common_region_listbox),
+ (GtkListBoxSortFunc)sort_regions, chooser, NULL);
+ gtk_list_box_set_sort_func (GTK_LIST_BOX (chooser->region_listbox),
+ (GtkListBoxSortFunc)sort_regions, chooser, NULL);
+ gtk_list_box_set_filter_func (GTK_LIST_BOX (chooser->region_listbox),
+ region_visible, chooser, NULL);
+
+ add_all_regions (chooser);
+ gtk_list_box_invalidate_filter (GTK_LIST_BOX (chooser->region_listbox));
+ format_chooser_leaflet_fold_changed_cb (chooser);
+
+ g_signal_connect_object (chooser, "activate-default",
+ G_CALLBACK (activate_default), chooser, G_CONNECT_SWAPPED);
+}
+
+CcFormatChooser *
+cc_format_chooser_new (void)
+{
+ return CC_FORMAT_CHOOSER (g_object_new (CC_TYPE_FORMAT_CHOOSER,
+ "use-header-bar", 1,
+ NULL));
+}
+
+void
+cc_format_chooser_clear_filter (CcFormatChooser *chooser)
+{
+ g_return_if_fail (CC_IS_FORMAT_CHOOSER (chooser));
+ gtk_editable_set_text (GTK_EDITABLE (chooser->region_filter_entry), "");
+}
+
+const gchar *
+cc_format_chooser_get_region (CcFormatChooser *chooser)
+{
+ g_return_val_if_fail (CC_IS_FORMAT_CHOOSER (chooser), NULL);
+ return chooser->region;
+}
+
+void
+cc_format_chooser_set_region (CcFormatChooser *chooser,
+ const gchar *region)
+{
+ g_return_if_fail (CC_IS_FORMAT_CHOOSER (chooser));
+ set_locale_id (chooser, region);
+}
diff --git a/panels/region/cc-format-chooser.h b/panels/region/cc-format-chooser.h
new file mode 100644
index 0000000..0248338
--- /dev/null
+++ b/panels/region/cc-format-chooser.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by:
+ * Matthias Clasen
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_FORMAT_CHOOSER (cc_format_chooser_get_type ())
+G_DECLARE_FINAL_TYPE (CcFormatChooser, cc_format_chooser, CC, FORMAT_CHOOSER, GtkDialog)
+
+CcFormatChooser *cc_format_chooser_new (void);
+void cc_format_chooser_clear_filter (CcFormatChooser *chooser);
+const gchar *cc_format_chooser_get_region (CcFormatChooser *chooser);
+void cc_format_chooser_set_region (CcFormatChooser *chooser,
+ const gchar *region);
+
+G_END_DECLS
diff --git a/panels/region/cc-format-chooser.ui b/panels/region/cc-format-chooser.ui
new file mode 100644
index 0000000..9a8cf92
--- /dev/null
+++ b/panels/region/cc-format-chooser.ui
@@ -0,0 +1,262 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcFormatChooser" parent="GtkDialog">
+ <property name="title" translatable="yes">Formats</property>
+ <property name="modal">True</property>
+ <property name="default-width">700</property>
+ <property name="default-height">500</property>
+
+ <!-- Titlebar -->
+ <child type="titlebar">
+ <object class="GtkHeaderBar" id="title_bar">
+ <property name="show-title-buttons">False</property>
+
+ <child>
+ <object class="GtkStack" id="title_buttons">
+ <property name="hhomogeneous">False</property>
+ <property name="vhomogeneous">False</property>
+
+ <!-- Cancel button -->
+ <child>
+ <object class="GtkButton" id="cancel_button">
+ <property name="valign">center</property>
+ <property name="use-underline">1</property>
+ <property name="label" translatable="yes">_Cancel</property>
+ </object>
+ </child>
+
+ <!-- Back button -->
+ <child>
+ <object class="GtkButton" id="back_button">
+ <property name="icon_name">go-previous-symbolic</property>
+ <signal name="clicked" handler="format_chooser_back_button_clicked_cb" object="CcFormatChooser" swapped="yes" />
+ <style>
+ <class name="image-button" />
+ </style>
+ <accessibility>
+ <property name="label" translatable="yes">Back</property>
+ </accessibility>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child type="end">
+ <object class="GtkButton" id="done_button">
+ <property name="valign">center</property>
+ <property name="use-underline">1</property>
+ <property name="label" translatable="yes">_Done</property>
+ <style>
+ <class name="suggested-action" />
+ </style>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="AdwLeaflet" id="main_leaflet">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <signal name="notify::fold" handler="format_chooser_leaflet_fold_changed_cb" object="CcFormatChooser" swapped="yes"/>
+ <child>
+ <object class="GtkBox" id="region_box">
+ <property name="vexpand">True</property>
+ <property name="hexpand">True</property>
+ <property name="orientation">vertical</property>
+
+ <!-- Language search -->
+ <child>
+ <object class="GtkSearchEntry" id="region_filter_entry">
+ <property name="hexpand">True</property>
+ <property name="placeholder-text" translatable="yes">Search locales…</property>
+ <property name="margin-top">18</property>
+ <property name="margin-bottom">18</property>
+ <property name="margin-start">18</property>
+ <property name="margin-end">18</property>
+ <accessibility>
+ <property name="label" translatable="yes">Search</property>
+ </accessibility>
+ <signal name="search-changed" handler="filter_changed" object="CcFormatChooser" swapped="yes" />
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkSeparator">
+ <style>
+ <class name="sidebar" />
+ </style>
+ </object>
+ </child>
+
+ <!-- Language format list -->
+ <child>
+ <object class="GtkStack" id="region_list_stack">
+ <child>
+ <object class="GtkScrolledWindow" id="region_list">
+ <property name="vexpand">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="propagate-natural-height">True</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">18</property>
+ <property name="margin-bottom">18</property>
+ <property name="margin-start">18</property>
+ <property name="margin-end">18</property>
+ <property name="orientation">vertical</property>
+
+ <!-- Common formats title -->
+ <child>
+ <object class="GtkLabel" id="common_region_title">
+ <property name="label" translatable="yes">Common Formats</property>
+ <property name="halign">start</property>
+ <property name="margin-bottom">6</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ <style>
+ <class name="dim-label" />
+ </style>
+ </object>
+ </child>
+
+ <!-- Common formats list -->
+ <child>
+ <object class="GtkListBox" id="common_region_listbox">
+ <property name="margin-bottom">24</property>
+ <property name="selection-mode">none</property>
+ <signal name="row-activated" handler="row_activated" object="CcFormatChooser" swapped="yes" />
+ <style>
+ <class name="boxed-list" />
+ </style>
+ </object>
+ </child>
+
+ <!-- Complete formats title -->
+ <child>
+ <object class="GtkLabel" id="region_title">
+ <property name="label" translatable="yes">All Formats</property>
+ <property name="halign">start</property>
+ <property name="margin-bottom">6</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ <style>
+ <class name="dim-label" />
+ </style>
+ </object>
+ </child>
+
+ <!-- Complete formats list -->
+ <child>
+ <object class="GtkListBox" id="region_listbox">
+ <property name="vexpand">True</property>
+ <property name="halign">fill</property>
+ <property name="valign">start</property>
+ <property name="selection-mode">none</property>
+ <signal name="row-activated" handler="row_activated" object="CcFormatChooser" swapped="yes" />
+ <style>
+ <class name="boxed-list" />
+ </style>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- Empty search results view -->
+ <child>
+ <object class="GtkBox" id="empty_results_view">
+ <property name="valign">center</property>
+ <property name="halign">center</property>
+ <property name="hexpand">False</property>
+ <property name="margin-bottom">18</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">system-search-symbolic</property>
+ <property name="pixel-size">64</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">No Search Results</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ <attribute name="scale" value="1.2"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="wrap">True</property>
+ <property name="max-width-chars">24</property>
+ <property name="justify">center</property>
+ <property name="label" translatable="yes">Searches can be for countries or languages.</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkSeparator" id="panel_separator">
+ <property name="orientation">vertical</property>
+ <style>
+ <class name="sidebar" />
+ </style>
+ </object>
+ </child>
+
+ <!-- Format preview -->
+ <child>
+ <object class="GtkBox" id="preview_box">
+ <property name="hexpand">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="margin_top">24</property>
+ <property name="margin_bottom">6</property>
+ <property name="halign">center</property>
+ <property name="hexpand">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Preview</property>
+ <style>
+ <class name="title-3" />
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="CcFormatPreview" id="format_preview">
+ <property name="width-request">300</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5" default="true">done_button</action-widget>
+ <action-widget response="-6">cancel_button</action-widget>
+ </action-widgets>
+ </template>
+</interface>
diff --git a/panels/region/cc-format-preview.c b/panels/region/cc-format-preview.c
new file mode 100644
index 0000000..61b434b
--- /dev/null
+++ b/panels/region/cc-format-preview.c
@@ -0,0 +1,257 @@
+/* cc-format-preview.c
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ * Copyright (C) 2020 System76, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by:
+ * Matthias Clasen
+ * Ian Douglas Scott <idscott@system76.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "cc-format-preview.h"
+
+#include <errno.h>
+#include <locale.h>
+#include <langinfo.h>
+#include <string.h>
+#include <glib/gi18n.h>
+
+struct _CcFormatPreview {
+ GtkBox parent_instance;
+
+ GtkWidget *date_format_label;
+ GtkWidget *date_time_format_label;
+ GtkWidget *measurement_format_label;
+ GtkWidget *number_format_label;
+ GtkWidget *paper_format_label;
+ GtkWidget *time_format_label;
+
+ gchar *region;
+};
+
+enum
+{
+ PROP_0,
+ PROP_REGION
+};
+
+G_DEFINE_TYPE (CcFormatPreview, cc_format_preview, GTK_TYPE_BOX)
+
+static void
+display_date (GtkWidget *label, GDateTime *dt, const gchar *format)
+{
+ g_autofree gchar *s = g_date_time_format (dt, format);
+ gtk_label_set_text (GTK_LABEL (label), g_strstrip (s));
+}
+
+static void
+update_format_examples (CcFormatPreview *self)
+{
+ const gchar *region = self->region;
+ locale_t locale;
+ locale_t old_locale;
+ g_autoptr(GDateTime) dt = NULL;
+ g_autofree gchar *s = NULL;
+#ifdef LC_MEASUREMENT
+ const gchar *fmt;
+#endif
+ g_autoptr(GtkPaperSize) paper = NULL;
+
+ if (region == NULL || region[0] == '\0')
+ return;
+
+ locale = newlocale (LC_TIME_MASK, region, (locale_t) 0);
+ if (locale == (locale_t) 0)
+ g_warning ("Failed to create locale %s: %s", region, g_strerror (errno));
+ else
+ old_locale = uselocale (locale);
+
+ dt = g_date_time_new_now_local ();
+ display_date (self->date_format_label, dt, "%x");
+ display_date (self->time_format_label, dt, "%X");
+ display_date (self->date_time_format_label, dt, "%c");
+
+ if (locale != (locale_t) 0)
+ {
+ uselocale (old_locale);
+ freelocale (locale);
+ }
+
+ locale = newlocale (LC_NUMERIC_MASK, region, (locale_t) 0);
+ if (locale == (locale_t) 0)
+ g_warning ("Failed to create locale %s: %s", region, g_strerror (errno));
+ else
+ old_locale = uselocale (locale);
+
+ s = g_strdup_printf ("%'.2f", 123456789.00);
+ gtk_label_set_text (GTK_LABEL (self->number_format_label), s);
+
+ if (locale != (locale_t) 0)
+ {
+ uselocale (old_locale);
+ freelocale (locale);
+ }
+
+#if 0
+ locale = newlocale (LC_MONETARY_MASK, region, (locale_t) 0);
+ if (locale == (locale_t) 0)
+ g_warning ("Failed to create locale %s: %s", region, g_strerror (errno));
+ else
+ old_locale = uselocale (locale);
+
+ num_info = localeconv ();
+ if (num_info != NULL)
+ gtk_label_set_text (GTK_LABEL (self->currency_format_label), num_info->currency_symbol);
+
+ if (locale != (locale_t) 0)
+ {
+ uselocale (old_locale);
+ freelocale (locale);
+ }
+#endif
+
+#ifdef LC_MEASUREMENT
+ locale = newlocale (LC_MEASUREMENT_MASK, region, (locale_t) 0);
+ if (locale == (locale_t) 0)
+ g_warning ("Failed to create locale %s: %s", region, g_strerror (errno));
+ else
+ old_locale = uselocale (locale);
+
+ fmt = nl_langinfo (_NL_MEASUREMENT_MEASUREMENT);
+ if (fmt && *fmt == 2)
+ gtk_label_set_text (GTK_LABEL (self->measurement_format_label), C_("measurement format", "Imperial"));
+ else
+ gtk_label_set_text (GTK_LABEL (self->measurement_format_label), C_("measurement format", "Metric"));
+
+ if (locale != (locale_t) 0)
+ {
+ uselocale (old_locale);
+ freelocale (locale);
+ }
+#endif
+
+#ifdef LC_PAPER
+ locale = newlocale (LC_PAPER_MASK, region, (locale_t) 0);
+ if (locale == (locale_t) 0)
+ g_warning ("Failed to create locale %s: %s", region, g_strerror (errno));
+ else
+ old_locale = uselocale (locale);
+
+ paper = gtk_paper_size_new (gtk_paper_size_get_default ());
+ gtk_label_set_text (GTK_LABEL (self->paper_format_label), gtk_paper_size_get_display_name (paper));
+
+ if (locale != (locale_t) 0)
+ {
+ uselocale (old_locale);
+ freelocale (locale);
+ }
+#endif
+}
+
+static void
+cc_format_preview_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcFormatPreview *self;
+
+ self = CC_FORMAT_PREVIEW (object);
+
+ switch (prop_id) {
+ case PROP_REGION:
+ cc_format_preview_set_region (self, g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_format_preview_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcFormatPreview *self;
+
+ self = CC_FORMAT_PREVIEW (object);
+
+ switch (prop_id) {
+ case PROP_REGION:
+ g_value_set_string (value, self->region);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_format_preview_finalize (GObject *object)
+{
+ CcFormatPreview *self = CC_FORMAT_PREVIEW (object);
+
+ g_clear_pointer (&self->region, g_free);
+
+ G_OBJECT_CLASS (cc_format_preview_parent_class)->finalize (object);
+}
+
+void
+cc_format_preview_class_init (CcFormatPreviewClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = cc_format_preview_get_property;
+ object_class->set_property = cc_format_preview_set_property;
+ object_class->finalize = cc_format_preview_finalize;
+
+ g_object_class_install_property (object_class,
+ PROP_REGION,
+ g_param_spec_string ("region",
+ "region",
+ "region",
+ NULL,
+ G_PARAM_READWRITE));
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/region/cc-format-preview.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcFormatPreview, date_format_label);
+ gtk_widget_class_bind_template_child (widget_class, CcFormatPreview, date_time_format_label);
+ gtk_widget_class_bind_template_child (widget_class, CcFormatPreview, measurement_format_label);
+ gtk_widget_class_bind_template_child (widget_class, CcFormatPreview, number_format_label);
+ gtk_widget_class_bind_template_child (widget_class, CcFormatPreview, paper_format_label);
+ gtk_widget_class_bind_template_child (widget_class, CcFormatPreview, time_format_label);
+}
+
+void
+cc_format_preview_init (CcFormatPreview *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+void
+cc_format_preview_set_region (CcFormatPreview *preview,
+ const gchar *region)
+{
+ g_free (preview->region);
+ preview->region = g_strdup (region);
+ update_format_examples (preview);
+}
diff --git a/panels/region/cc-format-preview.h b/panels/region/cc-format-preview.h
new file mode 100644
index 0000000..04d79bf
--- /dev/null
+++ b/panels/region/cc-format-preview.h
@@ -0,0 +1,38 @@
+/* cc-format-preview.c
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ * Copyright (C) 2020 System76, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by:
+ * Matthias Clasen
+ * Ian Douglas Scott <idscott@system76.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_FORMAT_PREVIEW (cc_format_preview_get_type())
+G_DECLARE_FINAL_TYPE (CcFormatPreview, cc_format_preview, CC, FORMAT_PREVIEW, GtkBox)
+
+void cc_format_preview_set_region (CcFormatPreview *preview,
+ const gchar *region);
+
+G_END_DECLS
diff --git a/panels/region/cc-format-preview.ui b/panels/region/cc-format-preview.ui
new file mode 100644
index 0000000..2773aa9
--- /dev/null
+++ b/panels/region/cc-format-preview.ui
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcFormatPreview" parent="GtkBox">
+ <property name="margin-top">24</property>
+ <property name="margin-bottom">24</property>
+ <property name="margin-start">24</property>
+ <property name="margin-end">24</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">4</property>
+ <property name="orientation">vertical</property>
+
+ <!-- Dates -->
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Dates</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="date_format_label">
+ <property name="xalign">0</property>
+ <property name="label">23 January 2013</property>
+ </object>
+ </child>
+
+ <!-- Times -->
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="margin-top">18</property>
+ <property name="label" translatable="yes">Times</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="time_format_label">
+ <property name="xalign">0</property>
+ <property name="label">11:31 AM</property>
+ </object>
+ </child>
+
+ <!-- Date & Times -->
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="margin-top">18</property>
+ <property name="label" translatable="yes">Dates &amp; Times</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="date_time_format_label">
+ <property name="xalign">0</property>
+ <property name="label">Sun Wed 2 11:31:00 KST 2013</property>
+ </object>
+ </child>
+
+ <!-- Numbers -->
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="margin-top">18</property>
+ <property name="label" translatable="yes">Numbers</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="number_format_label">
+ <property name="xalign">0</property>
+ <property name="label">123,456,789.00</property>
+ </object>
+ </child>
+
+ <!-- Measurement -->
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="margin-top">18</property>
+ <property name="label" translatable="yes">Measurement</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="measurement_format_label">
+ <property name="xalign">0</property>
+ <property name="label">Metric</property>
+ </object>
+ </child>
+
+ <!-- Paper -->
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="margin-top">18</property>
+ <property name="label" translatable="yes">Paper</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="paper_format_label">
+ <property name="xalign">0</property>
+ <property name="label">A4</property>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/region/cc-region-panel.c b/panels/region/cc-region-panel.c
new file mode 100644
index 0000000..bba51e9
--- /dev/null
+++ b/panels/region/cc-region-panel.c
@@ -0,0 +1,879 @@
+/*
+ * Copyright (C) 2010 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Sergey Udaltsov <svu@gnome.org>
+ *
+ */
+
+#include <config.h>
+#include <errno.h>
+#include <locale.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gio/gdesktopappinfo.h>
+#include <gtk/gtk.h>
+#include <polkit/polkit.h>
+
+#include "cc-region-panel.h"
+#include "cc-region-resources.h"
+#include "cc-language-chooser.h"
+#include "cc-format-chooser.h"
+
+#include "cc-common-language.h"
+
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnome-desktop/gnome-languages.h>
+#include <libgnome-desktop/gnome-xkb-info.h>
+
+#include <act/act.h>
+
+#define GNOME_SYSTEM_LOCALE_DIR "org.gnome.system.locale"
+#define KEY_REGION "region"
+
+#define DEFAULT_LOCALE "en_US.utf-8"
+
+typedef enum {
+ USER,
+ SYSTEM,
+} CcLocaleTarget;
+
+struct _CcRegionPanel {
+ CcPanel parent_instance;
+
+ GtkListBoxRow *formats_row;
+ GtkInfoBar *infobar;
+ GtkSizeGroup *input_size_group;
+ AdwActionRow *login_formats_row;
+ GtkWidget *login_group;
+ AdwActionRow *login_language_row;
+ GtkListBoxRow *language_row;
+ GtkButton *restart_button;
+
+ gboolean login_auto_apply;
+ GPermission *permission;
+ GDBusProxy *localed;
+ GDBusProxy *session;
+
+ ActUserManager *user_manager;
+ ActUser *user;
+ GSettings *locale_settings;
+
+ gchar *language;
+ gchar *region;
+ gchar *system_language;
+ gchar *system_region;
+};
+
+CC_PANEL_REGISTER (CcRegionPanel, cc_region_panel)
+
+/* Auxiliary methods */
+
+static GFile *
+get_needs_restart_file (void)
+{
+ g_autofree gchar *path = NULL;
+
+ path = g_build_filename (g_get_user_runtime_dir (),
+ "gnome-control-center-region-needs-restart",
+ NULL);
+ return g_file_new_for_path (path);
+}
+
+static void
+restart_now (CcRegionPanel *self)
+{
+ g_autoptr(GFile) file = NULL;
+
+ file = get_needs_restart_file ();
+ g_file_delete (file, NULL, NULL);
+
+ g_dbus_proxy_call (self->session,
+ "Logout",
+ g_variant_new ("(u)", 0),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, NULL, NULL);
+}
+
+static void
+set_restart_notification_visible (CcRegionPanel *self,
+ const gchar *locale,
+ gboolean visible)
+{
+ locale_t new_locale;
+ locale_t current_locale;
+ g_autoptr(GFile) file = NULL;
+ g_autoptr(GFileOutputStream) output_stream = NULL;
+ g_autoptr(GError) error = NULL;
+
+ if (locale) {
+ new_locale = newlocale (LC_MESSAGES_MASK, locale, (locale_t) 0);
+ if (new_locale != (locale_t) 0) {
+ current_locale = uselocale (new_locale);
+ uselocale (current_locale);
+ freelocale (new_locale);
+ } else {
+ g_warning ("Failed to create locale %s: %s", locale, g_strerror (errno));
+ }
+ }
+
+ gtk_info_bar_set_revealed (self->infobar, visible);
+
+ file = get_needs_restart_file ();
+
+ if (!visible) {
+ g_file_delete (file, NULL, NULL);
+ return;
+ }
+
+ output_stream = g_file_create (file, G_FILE_CREATE_NONE, NULL, &error);
+ if (output_stream == NULL) {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS))
+ g_warning ("Unable to create %s: %s", g_file_get_path (file), error->message);
+ }
+}
+
+typedef struct {
+ CcRegionPanel *self;
+ int category;
+ gchar *target_locale;
+} MaybeNotifyData;
+
+static void
+maybe_notify_data_free (MaybeNotifyData *data)
+{
+ g_free (data->target_locale);
+ g_free (data);
+}
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (MaybeNotifyData, maybe_notify_data_free)
+
+static void
+maybe_notify_finish (GObject *source,
+ GAsyncResult *res,
+ gpointer data)
+{
+ g_autoptr(MaybeNotifyData) mnd = data;
+ CcRegionPanel *self = mnd->self;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) retval = NULL;
+ g_autofree gchar *current_lang_code = NULL;
+ g_autofree gchar *current_country_code = NULL;
+ g_autofree gchar *target_lang_code = NULL;
+ g_autofree gchar *target_country_code = NULL;
+ const gchar *current_locale = NULL;
+
+ retval = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
+ if (!retval) {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to get locale: %s\n", error->message);
+ return;
+ }
+
+ g_variant_get (retval, "(&s)", &current_locale);
+
+ if (!gnome_parse_locale (current_locale,
+ &current_lang_code,
+ &current_country_code,
+ NULL,
+ NULL))
+ return;
+
+ if (!gnome_parse_locale (mnd->target_locale,
+ &target_lang_code,
+ &target_country_code,
+ NULL,
+ NULL))
+ return;
+
+ if (g_str_equal (current_lang_code, target_lang_code) == FALSE ||
+ g_str_equal (current_country_code, target_country_code) == FALSE)
+ set_restart_notification_visible (self,
+ mnd->category == LC_MESSAGES ? mnd->target_locale : NULL,
+ TRUE);
+ else
+ set_restart_notification_visible (self,
+ mnd->category == LC_MESSAGES ? mnd->target_locale : NULL,
+ FALSE);
+}
+
+static void
+maybe_notify (CcRegionPanel *self,
+ int category,
+ const gchar *target_locale)
+{
+ MaybeNotifyData *mnd;
+
+ mnd = g_new0 (MaybeNotifyData, 1);
+ mnd->self = self;
+ mnd->category = category;
+ mnd->target_locale = g_strdup (target_locale);
+
+ g_dbus_proxy_call (self->session,
+ "GetLocale",
+ g_variant_new ("(i)", category),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ maybe_notify_finish,
+ mnd);
+}
+
+static void
+set_localed_locale (CcRegionPanel *self)
+{
+ g_autoptr(GVariantBuilder) b = NULL;
+ g_autofree gchar *lang_value = NULL;
+
+ b = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+ lang_value = g_strconcat ("LANG=", self->system_language, NULL);
+ g_variant_builder_add (b, "s", lang_value);
+
+ if (self->system_region != NULL) {
+ g_autofree gchar *time_value = NULL;
+ g_autofree gchar *numeric_value = NULL;
+ g_autofree gchar *monetary_value = NULL;
+ g_autofree gchar *measurement_value = NULL;
+ g_autofree gchar *paper_value = NULL;
+ time_value = g_strconcat ("LC_TIME=", self->system_region, NULL);
+ g_variant_builder_add (b, "s", time_value);
+ numeric_value = g_strconcat ("LC_NUMERIC=", self->system_region, NULL);
+ g_variant_builder_add (b, "s", numeric_value);
+ monetary_value = g_strconcat ("LC_MONETARY=", self->system_region, NULL);
+ g_variant_builder_add (b, "s", monetary_value);
+ measurement_value = g_strconcat ("LC_MEASUREMENT=", self->system_region, NULL);
+ g_variant_builder_add (b, "s", measurement_value);
+ paper_value = g_strconcat ("LC_PAPER=", self->system_region, NULL);
+ g_variant_builder_add (b, "s", paper_value);
+ }
+ g_dbus_proxy_call (self->localed,
+ "SetLocale",
+ g_variant_new ("(asb)", b, TRUE),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, NULL, NULL);
+}
+
+static void
+set_system_language (CcRegionPanel *self,
+ const gchar *language)
+{
+ if (g_strcmp0 (language, self->system_language) == 0)
+ return;
+
+ g_free (self->system_language);
+ self->system_language = g_strdup (language);
+
+ set_localed_locale (self);
+}
+
+static void
+update_language (CcRegionPanel *self,
+ CcLocaleTarget target,
+ const gchar *language)
+{
+ switch (target) {
+ case USER:
+ if (g_strcmp0 (language, self->language) == 0)
+ return;
+ act_user_set_language (self->user, language);
+ if (self->login_auto_apply)
+ set_system_language (self, language);
+ maybe_notify (self, LC_MESSAGES, language);
+ break;
+
+ case SYSTEM:
+ set_system_language (self, language);
+ break;
+ }
+}
+
+static void
+set_system_region (CcRegionPanel *self,
+ const gchar *region)
+{
+ if (g_strcmp0 (region, self->system_region) == 0)
+ return;
+
+ g_free (self->system_region);
+ self->system_region = g_strdup (region);
+
+ set_localed_locale (self);
+}
+
+static void
+update_region (CcRegionPanel *self,
+ CcLocaleTarget target,
+ const gchar *region)
+{
+ switch (target) {
+ case USER:
+ if (g_strcmp0 (region, self->region) == 0)
+ return;
+ if (region == NULL || region[0] == '\0')
+ g_settings_reset (self->locale_settings, KEY_REGION);
+ else
+ g_settings_set_string (self->locale_settings, KEY_REGION, region);
+ if (self->login_auto_apply)
+ set_system_region (self, region);
+
+ if (region == NULL || region[0] == '\0') {
+ // Formats (region) are being reset as part of changing the language,
+ // and that already triggers the notification check.
+ return;
+ }
+
+ maybe_notify (self, LC_TIME, region);
+ break;
+
+ case SYSTEM:
+ set_system_region (self, region);
+ break;
+ }
+}
+
+static void
+language_response (CcRegionPanel *self,
+ gint response_id,
+ CcLanguageChooser *chooser)
+{
+ const gchar *language;
+
+ if (response_id == GTK_RESPONSE_OK) {
+ CcLocaleTarget target;
+
+ language = cc_language_chooser_get_language (chooser);
+ target = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (chooser), "target"));
+ update_language (self, target, language);
+
+ /* Keep format strings consistent with the user's language */
+ update_region (self, target, NULL);
+ }
+
+ gtk_window_destroy (GTK_WINDOW (chooser));
+}
+
+static const gchar *
+get_effective_language (CcRegionPanel *self,
+ CcLocaleTarget target)
+{
+ switch (target) {
+ case USER:
+ return self->language;
+ case SYSTEM:
+ return self->system_language;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
+show_language_chooser (CcRegionPanel *self,
+ CcLocaleTarget target)
+{
+ CcLanguageChooser *chooser;
+ CcShell *shell;
+
+ shell = cc_panel_get_shell (CC_PANEL (self));
+ chooser = cc_language_chooser_new ();
+ gtk_window_set_transient_for (GTK_WINDOW (chooser), GTK_WINDOW (cc_shell_get_toplevel (shell)));
+ cc_language_chooser_set_language (chooser, get_effective_language (self, target));
+ g_object_set_data (G_OBJECT (chooser), "target", GINT_TO_POINTER (target));
+ g_signal_connect_object (chooser, "response",
+ G_CALLBACK (language_response), self, G_CONNECT_SWAPPED);
+ gtk_window_present (GTK_WINDOW (chooser));
+}
+
+static const gchar *
+get_effective_region (CcRegionPanel *self,
+ CcLocaleTarget target)
+{
+ const gchar *region = NULL;
+
+ switch (target) {
+ case USER:
+ region = self->region;
+ break;
+
+ case SYSTEM:
+ region = self->system_region;
+ break;
+ }
+
+ /* Region setting might be empty - show the language because
+ * that's what LC_TIME and others will effectively be when the
+ * user logs in again. */
+ if (region == NULL || region[0] == '\0')
+ region = get_effective_language (self, target);
+
+ return region;
+}
+
+static void
+format_response (CcRegionPanel *self,
+ gint response_id,
+ CcFormatChooser *chooser)
+{
+ const gchar *region;
+
+ if (response_id == GTK_RESPONSE_OK) {
+ CcLocaleTarget target;
+
+ region = cc_format_chooser_get_region (chooser);
+ target = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (chooser), "target"));
+
+ update_region (self, target, region);
+ }
+
+ gtk_window_destroy (GTK_WINDOW (chooser));
+}
+
+static void
+show_region_chooser (CcRegionPanel *self,
+ CcLocaleTarget target)
+{
+ CcFormatChooser *chooser;
+ CcShell *shell;
+
+ shell = cc_panel_get_shell (CC_PANEL (self));
+ chooser = cc_format_chooser_new ();
+ gtk_window_set_transient_for (GTK_WINDOW (chooser), GTK_WINDOW (cc_shell_get_toplevel (shell)));
+ cc_format_chooser_set_region (chooser, get_effective_region (self, target));
+ g_object_set_data (G_OBJECT (chooser), "target", GINT_TO_POINTER (target));
+ g_signal_connect_object (chooser, "response",
+ G_CALLBACK (format_response), self, G_CONNECT_SWAPPED);
+ gtk_window_present (GTK_WINDOW (chooser));
+}
+
+static gboolean
+permission_acquired (GPermission *permission, GAsyncResult *res, const gchar *action)
+{
+ g_autoptr(GError) error = NULL;
+
+ if (!g_permission_acquire_finish (permission, res, &error)) {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to acquire permission to %s: %s\n", error->message, action);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+choose_language_permission_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ CcRegionPanel *self = user_data;
+ if (permission_acquired (G_PERMISSION (source), res, "choose language"))
+ show_language_chooser (self, SYSTEM);
+}
+
+static void
+choose_region_permission_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ CcRegionPanel *self = user_data;
+ if (permission_acquired (G_PERMISSION (source), res, "choose region"))
+ show_region_chooser (self, SYSTEM);
+}
+
+static void
+update_user_region_row (CcRegionPanel *self)
+{
+ const gchar *region = get_effective_region (self, USER);
+ g_autofree gchar *name = NULL;
+
+ if (region)
+ name = gnome_get_country_from_locale (region, region);
+
+ if (!name)
+ name = gnome_get_country_from_locale (DEFAULT_LOCALE, DEFAULT_LOCALE);
+
+ adw_action_row_set_subtitle (ADW_ACTION_ROW (self->formats_row), name);
+}
+
+static void
+update_user_language_row (CcRegionPanel *self)
+{
+ g_autofree gchar *name = NULL;
+
+ if (self->language)
+ name = gnome_get_language_from_locale (self->language, self->language);
+
+ if (!name)
+ name = gnome_get_language_from_locale (DEFAULT_LOCALE, DEFAULT_LOCALE);
+
+ adw_action_row_set_subtitle (ADW_ACTION_ROW (self->language_row), name);
+
+ /* Formats will change too if not explicitly set. */
+ update_user_region_row (self);
+}
+
+static void
+update_language_from_user (CcRegionPanel *self)
+{
+ const gchar *language = NULL;
+
+ if (act_user_is_loaded (self->user))
+ language = act_user_get_language (self->user);
+
+ if (language == NULL || *language == '\0')
+ language = setlocale (LC_MESSAGES, NULL);
+
+ g_free (self->language);
+ self->language = g_strdup (language);
+ update_user_language_row (self);
+}
+
+static void
+update_region_from_setting (CcRegionPanel *self)
+{
+ g_free (self->region);
+ self->region = g_settings_get_string (self->locale_settings, KEY_REGION);
+ update_user_region_row (self);
+}
+
+static void
+setup_language_section (CcRegionPanel *self)
+{
+ self->user = act_user_manager_get_user_by_id (self->user_manager, getuid ());
+ g_signal_connect_object (self->user, "notify::language",
+ G_CALLBACK (update_language_from_user), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->user, "notify::is-loaded",
+ G_CALLBACK (update_language_from_user), self, G_CONNECT_SWAPPED);
+
+ self->locale_settings = g_settings_new (GNOME_SYSTEM_LOCALE_DIR);
+ g_signal_connect_object (self->locale_settings, "changed::" KEY_REGION,
+ G_CALLBACK (update_region_from_setting), self, G_CONNECT_SWAPPED);
+
+ update_language_from_user (self);
+ update_region_from_setting (self);
+}
+
+static void
+update_login_region (CcRegionPanel *self)
+{
+ g_autofree gchar *name = NULL;
+
+ if (self->system_region)
+ name = gnome_get_country_from_locale (self->system_region, self->system_region);
+
+ if (!name)
+ name = gnome_get_country_from_locale (DEFAULT_LOCALE, DEFAULT_LOCALE);
+
+ adw_action_row_set_subtitle (ADW_ACTION_ROW (self->login_formats_row), name);
+}
+
+static void
+update_login_language (CcRegionPanel *self)
+{
+ g_autofree gchar *name = NULL;
+
+ if (self->system_language)
+ name = gnome_get_language_from_locale (self->system_language, self->system_language);
+
+ if (!name)
+ name = gnome_get_language_from_locale (DEFAULT_LOCALE, DEFAULT_LOCALE);
+
+ adw_action_row_set_subtitle (self->login_language_row, name);
+ update_login_region (self);
+}
+
+static void
+set_login_button_visibility (CcRegionPanel *self)
+{
+ gboolean has_multiple_users;
+ gboolean loaded;
+
+ g_object_get (self->user_manager, "is-loaded", &loaded, NULL);
+ if (!loaded)
+ return;
+
+ g_object_get (self->user_manager, "has-multiple-users", &has_multiple_users, NULL);
+
+ self->login_auto_apply = !has_multiple_users && g_permission_get_allowed (self->permission);
+ gtk_widget_set_visible (self->login_group, !self->login_auto_apply);
+
+ g_signal_handlers_disconnect_by_func (self->user_manager, set_login_button_visibility, self);
+}
+
+/* Callbacks */
+
+static void
+on_localed_properties_changed (GDBusProxy *localed_proxy,
+ GVariant *changed_properties,
+ const gchar **invalidated_properties,
+ CcRegionPanel *self)
+{
+ g_autoptr(GVariant) v = NULL;
+
+ v = g_dbus_proxy_get_cached_property (localed_proxy, "Locale");
+ if (v) {
+ g_autofree const gchar **strv = NULL;
+ gsize len;
+ gint i;
+ const gchar *lang, *messages, *time;
+
+ strv = g_variant_get_strv (v, &len);
+
+ lang = messages = time = NULL;
+ for (i = 0; strv[i]; i++) {
+ if (g_str_has_prefix (strv[i], "LANG=")) {
+ lang = strv[i] + strlen ("LANG=");
+ } else if (g_str_has_prefix (strv[i], "LC_MESSAGES=")) {
+ messages = strv[i] + strlen ("LC_MESSAGES=");
+ } else if (g_str_has_prefix (strv[i], "LC_TIME=")) {
+ time = strv[i] + strlen ("LC_TIME=");
+ }
+ }
+ if (!lang) {
+ lang = setlocale (LC_MESSAGES, NULL);
+ }
+ if (!messages) {
+ messages = lang;
+ }
+ g_free (self->system_language);
+ self->system_language = g_strdup (messages);
+ g_free (self->system_region);
+ self->system_region = g_strdup (time);
+
+ update_login_language (self);
+ }
+}
+
+static void
+localed_proxy_ready (GObject *source,
+ GAsyncResult *res,
+ gpointer data)
+{
+ CcRegionPanel *self = data;
+ GDBusProxy *proxy;
+ g_autoptr(GError) error = NULL;
+
+ proxy = g_dbus_proxy_new_finish (res, &error);
+
+ if (!proxy) {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to contact localed: %s\n", error->message);
+ return;
+ }
+
+ self->localed = proxy;
+
+ g_signal_connect_object (self->localed,
+ "g-properties-changed",
+ G_CALLBACK (on_localed_properties_changed),
+ self,
+ 0);
+
+ on_localed_properties_changed (self->localed, NULL, NULL, self);
+}
+
+static void
+setup_login_permission (CcRegionPanel *self)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+ g_autoptr(GError) error = NULL;
+ gboolean can_acquire;
+ gboolean loaded;
+
+ self->permission = polkit_permission_new_sync ("org.freedesktop.locale1.set-locale", NULL, NULL, &error);
+ if (self->permission == NULL) {
+ g_warning ("Could not get 'org.freedesktop.locale1.set-locale' permission: %s",
+ error->message);
+ return;
+ }
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
+ g_dbus_proxy_new (bus,
+ G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
+ NULL,
+ "org.freedesktop.locale1",
+ "/org/freedesktop/locale1",
+ "org.freedesktop.locale1",
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ (GAsyncReadyCallback) localed_proxy_ready,
+ self);
+
+ g_object_get (self->user_manager, "is-loaded", &loaded, NULL);
+ if (loaded)
+ set_login_button_visibility (self);
+ else
+ g_signal_connect_object (self->user_manager, "notify::is-loaded",
+ G_CALLBACK (set_login_button_visibility), self, G_CONNECT_SWAPPED);
+
+ can_acquire = self->permission &&
+ (g_permission_get_allowed (self->permission) ||
+ g_permission_get_can_acquire (self->permission));
+ gtk_widget_set_sensitive (self->login_group, can_acquire);
+}
+
+static void
+session_proxy_ready (GObject *source,
+ GAsyncResult *res,
+ gpointer data)
+{
+ CcRegionPanel *self = data;
+ GDBusProxy *proxy;
+ g_autoptr(GError) error = NULL;
+
+ proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+
+ if (!proxy) {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to contact gnome-session: %s\n", error->message);
+ return;
+ }
+
+ self->session = proxy;
+}
+
+static void
+on_login_formats_row_activated_cb (GtkListBoxRow *row,
+ CcRegionPanel *self)
+{
+ if (g_permission_get_allowed (self->permission)) {
+ show_region_chooser (self, SYSTEM);
+ } else if (g_permission_get_can_acquire (self->permission)) {
+ g_permission_acquire_async (self->permission,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ choose_region_permission_cb,
+ self);
+ }
+}
+
+static void
+on_login_language_row_activated_cb (GtkListBoxRow *row,
+ CcRegionPanel *self)
+{
+ if (g_permission_get_allowed (self->permission)) {
+ show_language_chooser (self, SYSTEM);
+ } else if (g_permission_get_can_acquire (self->permission)) {
+ g_permission_acquire_async (self->permission,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ choose_language_permission_cb,
+ self);
+ }
+}
+
+static void
+on_user_formats_row_activated_cb (GtkListBoxRow *row,
+ CcRegionPanel *self)
+{
+ show_region_chooser (self, USER);
+}
+
+static void
+on_user_language_row_activated_cb (GtkListBoxRow *row,
+ CcRegionPanel *self)
+{
+ show_language_chooser (self, USER);
+}
+
+/* CcPanel overrides */
+
+static const char *
+cc_region_panel_get_help_uri (CcPanel *panel)
+{
+ return "help:gnome-help/prefs-language";
+}
+
+/* GObject overrides */
+
+static void
+cc_region_panel_finalize (GObject *object)
+{
+ CcRegionPanel *self = CC_REGION_PANEL (object);
+ GtkWidget *chooser;
+
+ if (self->user_manager) {
+ g_signal_handlers_disconnect_by_data (self->user_manager, self);
+ self->user_manager = NULL;
+ }
+
+ if (self->user) {
+ g_signal_handlers_disconnect_by_data (self->user, self);
+ self->user = NULL;
+ }
+
+ g_clear_object (&self->permission);
+ g_clear_object (&self->localed);
+ g_clear_object (&self->session);
+ g_clear_object (&self->locale_settings);
+ g_free (self->language);
+ g_free (self->region);
+ g_free (self->system_language);
+ g_free (self->system_region);
+
+ chooser = g_object_get_data (G_OBJECT (self), "input-chooser");
+ if (chooser)
+ gtk_window_destroy (GTK_WINDOW (chooser));
+
+ G_OBJECT_CLASS (cc_region_panel_parent_class)->finalize (object);
+}
+
+static void
+cc_region_panel_class_init (CcRegionPanelClass * klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+
+ panel_class->get_help_uri = cc_region_panel_get_help_uri;
+
+ object_class->finalize = cc_region_panel_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/region/cc-region-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcRegionPanel, formats_row);
+ gtk_widget_class_bind_template_child (widget_class, CcRegionPanel, infobar);
+ gtk_widget_class_bind_template_child (widget_class, CcRegionPanel, login_formats_row);
+ gtk_widget_class_bind_template_child (widget_class, CcRegionPanel, login_group);
+ gtk_widget_class_bind_template_child (widget_class, CcRegionPanel, login_language_row);
+ gtk_widget_class_bind_template_child (widget_class, CcRegionPanel, language_row);
+ gtk_widget_class_bind_template_child (widget_class, CcRegionPanel, restart_button);
+
+ gtk_widget_class_bind_template_callback (widget_class, on_login_formats_row_activated_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_login_language_row_activated_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_user_formats_row_activated_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_user_language_row_activated_cb);
+ gtk_widget_class_bind_template_callback (widget_class, restart_now);
+}
+
+static void
+cc_region_panel_init (CcRegionPanel *self)
+{
+ g_autoptr(GFile) needs_restart_file = NULL;
+
+ g_resources_register (cc_region_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->user_manager = act_user_manager_get_default ();
+
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.gnome.SessionManager",
+ "/org/gnome/SessionManager",
+ "org.gnome.SessionManager",
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ session_proxy_ready,
+ self);
+
+ setup_login_permission (self);
+ setup_language_section (self);
+
+ needs_restart_file = get_needs_restart_file ();
+ if (g_file_query_exists (needs_restart_file, NULL))
+ set_restart_notification_visible (self, NULL, TRUE);
+}
diff --git a/panels/region/cc-region-panel.h b/panels/region/cc-region-panel.h
new file mode 100644
index 0000000..c0c8dac
--- /dev/null
+++ b/panels/region/cc-region-panel.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2010 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Sergey Udaltsov <svu@gnome.org>
+ *
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_REGION_PANEL (cc_region_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcRegionPanel, cc_region_panel, CC, REGION_PANEL, CcPanel)
+
+G_END_DECLS
diff --git a/panels/region/cc-region-panel.ui b/panels/region/cc-region-panel.ui
new file mode 100644
index 0000000..b66de90
--- /dev/null
+++ b/panels/region/cc-region-panel.ui
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcRegionPanel" parent="CcPanel">
+
+ <child type="content">
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+
+ <child>
+ <object class="GtkInfoBar" id="infobar">
+ <property name="revealed">False</property>
+ <property name="message-type">info</property>
+
+ <child>
+ <object class="GtkLabel">
+ <property name="hexpand">True</property>
+ <property name="wrap">True</property>
+ <property name="xalign">0.0</property>
+ <property name="label" translatable="yes">Language and format will be changed after next login</property>
+ <style>
+ <class name="heading" />
+ </style>
+ </object>
+ </child>
+
+ <child type="action">
+ <object class="GtkButton" id="restart_button">
+ <property name="valign">center</property>
+ <property name="label" translatable="yes">Logout…</property>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ <signal name="clicked" handler="restart_now" object="CcRegionPanel" swapped="yes"/>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesPage">
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="description" translatable="yes">The language setting is used for interface text and web pages. Formats are used for numbers, dates, and currencies.</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Your Account</property>
+
+ <child>
+ <object class="AdwActionRow" id="language_row">
+ <property name="use-underline">True</property>
+ <property name="title" translatable="yes">_Language</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="on_user_language_row_activated_cb" object="CcRegionPanel" swapped="no" />
+
+ <child>
+ <object class="GtkImage">
+ <property name="valign">center</property>
+ <property name="icon-name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow" id="formats_row">
+ <property name="use-underline">True</property>
+ <property name="title" translatable="yes">_Formats</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="on_user_formats_row_activated_cb" object="CcRegionPanel" swapped="no" />
+
+ <child>
+ <object class="GtkImage">
+ <property name="valign">center</property>
+ <property name="icon-name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup" id="login_group">
+ <property name="title" translatable="yes">Login Screen</property>
+
+ <child>
+ <object class="AdwActionRow" id="login_language_row">
+ <property name="use-underline">True</property>
+ <property name="title" translatable="yes">_Language</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="on_login_language_row_activated_cb" object="CcRegionPanel" swapped="no" />
+
+ <child>
+ <object class="GtkImage">
+ <property name="valign">center</property>
+ <property name="icon-name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow" id="login_formats_row">
+ <property name="use-underline">True</property>
+ <property name="title" translatable="yes">_Formats</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="on_login_formats_row_activated_cb" object="CcRegionPanel" swapped="no" />
+
+ <child>
+ <object class="GtkImage">
+ <property name="valign">center</property>
+ <property name="icon-name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/region/gnome-region-panel.desktop.in.in b/panels/region/gnome-region-panel.desktop.in.in
new file mode 100644
index 0000000..0bdc8ff
--- /dev/null
+++ b/panels/region/gnome-region-panel.desktop.in.in
@@ -0,0 +1,18 @@
+[Desktop Entry]
+Name=Region & Language
+Comment=Select your display language and formats
+Exec=gnome-control-center region
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-region-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-DetailsSettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=region
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: Search terms to find the Region and Language panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=Language;Layout;Keyboard;Input;
diff --git a/panels/region/icons/meson.build b/panels/region/icons/meson.build
new file mode 100644
index 0000000..a2c3888
--- /dev/null
+++ b/panels/region/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-region-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/region/icons/scalable/org.gnome.Settings-region-symbolic.svg b/panels/region/icons/scalable/org.gnome.Settings-region-symbolic.svg
new file mode 100644
index 0000000..11ac471
--- /dev/null
+++ b/panels/region/icons/scalable/org.gnome.Settings-region-symbolic.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <path d="m 3 0 c -0.550781 0 -1 0.449219 -1 1 v 15 h 2 v -8 h 2.382812 l 0.722657 1.449219 c 0.167969 0.335937 0.515625 0.550781 0.894531 0.550781 h 5 c 0.550781 0 1 -0.449219 1 -1 v -6 c 0 -0.550781 -0.449219 -1 -1 -1 h -3.382812 l -0.722657 -1.449219 c -0.167969 -0.335937 -0.515625 -0.550781 -0.894531 -0.550781 z m 0 0" fill="#2e3436"/>
+</svg>
diff --git a/panels/region/meson.build b/panels/region/meson.build
new file mode 100644
index 0000000..71f9a62
--- /dev/null
+++ b/panels/region/meson.build
@@ -0,0 +1,59 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+sources = files(
+ 'cc-region-panel.c',
+ 'cc-format-chooser.c',
+ 'cc-format-preview.c',
+)
+
+resource_data = files(
+ 'cc-format-chooser.ui',
+ 'cc-format-preview.ui',
+ 'cc-region-panel.ui',
+ 'view-layout-symbolic.svg',
+)
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname,
+ dependencies: resource_data,
+ export: true
+)
+
+deps = common_deps + [
+ accounts_dep,
+ gnome_desktop_dep,
+ liblanguage_dep,
+ polkit_gobject_dep
+]
+
+if enable_ibus
+ deps += ibus_dep
+endif
+
+panels_libs += static_library(
+ cappletname,
+ sources: sources,
+ include_directories: top_inc,
+ dependencies: deps,
+ c_args: cflags
+)
+
+subdir('icons')
diff --git a/panels/region/region.gresource.xml b/panels/region/region.gresource.xml
new file mode 100644
index 0000000..e3bff86
--- /dev/null
+++ b/panels/region/region.gresource.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/region">
+ <file preprocess="xml-stripblanks">cc-format-chooser.ui</file>
+ <file preprocess="xml-stripblanks">cc-region-panel.ui</file>
+ <file preprocess="xml-stripblanks">cc-format-preview.ui</file>
+ </gresource>
+ <gresource prefix="/org/gnome/Settings/icons/scalable/actions">
+ <file>view-layout-symbolic.svg</file>
+ </gresource>
+</gresources>
diff --git a/panels/region/view-layout-symbolic.svg b/panels/region/view-layout-symbolic.svg
new file mode 100644
index 0000000..cfc561a
--- /dev/null
+++ b/panels/region/view-layout-symbolic.svg
@@ -0,0 +1 @@
+<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><path d="M8 2A8 8 0 0 0 .262 8.01 8 8 0 0 0 8 14a8 8 0 0 0 7.738-6.01A8 8 0 0 0 8 2zm0 2a4 4 0 0 1 4 4 4 4 0 0 1-4 4 4 4 0 0 1-4-4 4 4 0 0 1 4-4zm0 2a2 2 0 0 0-2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0-2-2z" style="fill:#3d3846"/></svg> \ No newline at end of file
diff --git a/panels/removable-media/cc-removable-media-panel.c b/panels/removable-media/cc-removable-media-panel.c
new file mode 100644
index 0000000..6ce238e
--- /dev/null
+++ b/panels/removable-media/cc-removable-media-panel.c
@@ -0,0 +1,511 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2017 Mohammed Sadiq <sadiq@sadiqpk.org>
+ * Copyright (C) 2010 Red Hat, Inc
+ * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include "cc-removable-media-panel.h"
+#include "cc-removable-media-resources.h"
+
+/* Autorun options */
+#define PREF_MEDIA_AUTORUN_NEVER "autorun-never"
+#define PREF_MEDIA_AUTORUN_X_CONTENT_START_APP "autorun-x-content-start-app"
+#define PREF_MEDIA_AUTORUN_X_CONTENT_IGNORE "autorun-x-content-ignore"
+#define PREF_MEDIA_AUTORUN_X_CONTENT_OPEN_FOLDER "autorun-x-content-open-folder"
+
+#define CUSTOM_ITEM_ASK "cc-item-ask"
+#define CUSTOM_ITEM_DO_NOTHING "cc-item-do-nothing"
+#define CUSTOM_ITEM_OPEN_FOLDER "cc-item-open-folder"
+
+#define MEDIA_HANDLING_SCHEMA "org.gnome.desktop.media-handling"
+
+struct _CcRemovableMediaPanel
+{
+ CcPanel parent_instance;
+
+ GtkAppChooserButton *audio_cdda_chooser;
+ GtkCheckButton *autorun_never_checkbutton;
+ GtkAppChooserButton *dcf_chooser;
+ GtkButton *extra_options_button;
+ GtkBox *handlers_box;
+ GtkAppChooserButton *music_player_chooser;
+ GtkDialog *other_type_dialog;
+ GtkLabel *other_action_label;
+ GtkBox *other_action_box;
+ GtkComboBox *other_type_combo_box;
+ GtkListStore *other_type_list_store;
+ GtkAppChooserButton *software_chooser;
+ GtkAppChooserButton *video_dvd_chooser;
+
+ GtkAppChooserButton *other_application_chooser;
+ GSettings *settings;
+};
+
+
+G_DEFINE_TYPE (CcRemovableMediaPanel, cc_removable_media_panel, CC_TYPE_PANEL)
+
+static char **
+remove_elem_from_str_array (char **v,
+ const char *s)
+{
+ GPtrArray *array;
+ guint idx;
+
+ array = g_ptr_array_new ();
+
+ for (idx = 0; v[idx] != NULL; idx++) {
+ if (g_strcmp0 (v[idx], s) == 0) {
+ continue;
+ }
+
+ g_ptr_array_add (array, v[idx]);
+ }
+
+ g_ptr_array_add (array, NULL);
+
+ g_free (v);
+
+ return (char **) g_ptr_array_free (array, FALSE);
+}
+
+static char **
+add_elem_to_str_array (char **v,
+ const char *s)
+{
+ GPtrArray *array;
+ guint idx;
+
+ array = g_ptr_array_new ();
+
+ for (idx = 0; v[idx] != NULL; idx++) {
+ g_ptr_array_add (array, v[idx]);
+ }
+
+ g_ptr_array_add (array, g_strdup (s));
+ g_ptr_array_add (array, NULL);
+
+ g_free (v);
+
+ return (char **) g_ptr_array_free (array, FALSE);
+}
+
+static void
+autorun_get_preferences (CcRemovableMediaPanel *self,
+ const char *x_content_type,
+ gboolean *pref_start_app,
+ gboolean *pref_ignore,
+ gboolean *pref_open_folder)
+{
+ g_auto(GStrv) x_content_start_app = NULL;
+ g_auto(GStrv) x_content_ignore = NULL;
+ g_auto(GStrv) x_content_open_folder = NULL;
+
+ g_return_if_fail (pref_start_app != NULL);
+ g_return_if_fail (pref_ignore != NULL);
+ g_return_if_fail (pref_open_folder != NULL);
+
+ *pref_start_app = FALSE;
+ *pref_ignore = FALSE;
+ *pref_open_folder = FALSE;
+ x_content_start_app = g_settings_get_strv (self->settings,
+ PREF_MEDIA_AUTORUN_X_CONTENT_START_APP);
+ x_content_ignore = g_settings_get_strv (self->settings,
+ PREF_MEDIA_AUTORUN_X_CONTENT_IGNORE);
+ x_content_open_folder = g_settings_get_strv (self->settings,
+ PREF_MEDIA_AUTORUN_X_CONTENT_OPEN_FOLDER);
+ if (x_content_start_app != NULL) {
+ *pref_start_app = g_strv_contains ((const gchar * const *) x_content_start_app, x_content_type);
+ }
+ if (x_content_ignore != NULL) {
+ *pref_ignore = g_strv_contains ((const gchar * const *) x_content_ignore, x_content_type);
+ }
+ if (x_content_open_folder != NULL) {
+ *pref_open_folder = g_strv_contains ((const gchar * const *) x_content_open_folder, x_content_type);
+ }
+}
+
+static void
+autorun_set_preferences (CcRemovableMediaPanel *self,
+ const char *x_content_type,
+ gboolean pref_start_app,
+ gboolean pref_ignore,
+ gboolean pref_open_folder)
+{
+ g_auto(GStrv) x_content_start_app = NULL;
+ g_auto(GStrv) x_content_ignore = NULL;
+ g_auto(GStrv) x_content_open_folder = NULL;
+
+ g_assert (x_content_type != NULL);
+
+ x_content_start_app = g_settings_get_strv (self->settings,
+ PREF_MEDIA_AUTORUN_X_CONTENT_START_APP);
+ x_content_ignore = g_settings_get_strv (self->settings,
+ PREF_MEDIA_AUTORUN_X_CONTENT_IGNORE);
+ x_content_open_folder = g_settings_get_strv (self->settings,
+ PREF_MEDIA_AUTORUN_X_CONTENT_OPEN_FOLDER);
+
+ x_content_start_app = remove_elem_from_str_array (x_content_start_app, x_content_type);
+ if (pref_start_app) {
+ x_content_start_app = add_elem_to_str_array (x_content_start_app, x_content_type);
+ }
+ g_settings_set_strv (self->settings,
+ PREF_MEDIA_AUTORUN_X_CONTENT_START_APP, (const gchar * const*) x_content_start_app);
+
+ x_content_ignore = remove_elem_from_str_array (x_content_ignore, x_content_type);
+ if (pref_ignore) {
+ x_content_ignore = add_elem_to_str_array (x_content_ignore, x_content_type);
+ }
+ g_settings_set_strv (self->settings,
+ PREF_MEDIA_AUTORUN_X_CONTENT_IGNORE, (const gchar * const*) x_content_ignore);
+
+ x_content_open_folder = remove_elem_from_str_array (x_content_open_folder, x_content_type);
+ if (pref_open_folder) {
+ x_content_open_folder = add_elem_to_str_array (x_content_open_folder, x_content_type);
+ }
+ g_settings_set_strv (self->settings,
+ PREF_MEDIA_AUTORUN_X_CONTENT_OPEN_FOLDER, (const gchar * const*) x_content_open_folder);
+
+}
+
+static void
+on_custom_item_activated_cb (CcRemovableMediaPanel *self,
+ const gchar *item,
+ GtkAppChooser *app_chooser)
+{
+ g_autofree gchar *content_type = NULL;
+
+ content_type = gtk_app_chooser_get_content_type (app_chooser);
+
+ if (g_strcmp0 (item, CUSTOM_ITEM_ASK) == 0) {
+ autorun_set_preferences (self, content_type,
+ FALSE, FALSE, FALSE);
+ } else if (g_strcmp0 (item, CUSTOM_ITEM_OPEN_FOLDER) == 0) {
+ autorun_set_preferences (self, content_type,
+ FALSE, FALSE, TRUE);
+ } else if (g_strcmp0 (item, CUSTOM_ITEM_DO_NOTHING) == 0) {
+ autorun_set_preferences (self, content_type,
+ FALSE, TRUE, FALSE);
+ }
+}
+
+static void
+on_chooser_changed_cb (CcRemovableMediaPanel *self,
+ GtkAppChooser *chooser)
+{
+ g_autoptr(GAppInfo) info = NULL;
+ g_autofree gchar *content_type = NULL;
+
+ info = gtk_app_chooser_get_app_info (chooser);
+
+ if (info == NULL)
+ return;
+
+ content_type = gtk_app_chooser_get_content_type (chooser);
+ autorun_set_preferences (self, content_type,
+ TRUE, FALSE, FALSE);
+ g_app_info_set_as_default_for_type (info, content_type, NULL);
+}
+
+static void
+prepare_chooser (CcRemovableMediaPanel *self,
+ GtkAppChooserButton *button,
+ const gchar *heading)
+{
+ gboolean pref_ask;
+ gboolean pref_start_app;
+ gboolean pref_ignore;
+ gboolean pref_open_folder;
+ g_autoptr(GAppInfo) info = NULL;
+ g_autofree gchar *content_type = NULL;
+
+ content_type = gtk_app_chooser_get_content_type (GTK_APP_CHOOSER (button));
+
+ /* fetch preferences for this content type */
+ autorun_get_preferences (self, content_type,
+ &pref_start_app, &pref_ignore, &pref_open_folder);
+ pref_ask = !pref_start_app && !pref_ignore && !pref_open_folder;
+
+ info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (button));
+
+ /* append the separator only if we have >= 1 apps in the chooser */
+ if (info != NULL) {
+ gtk_app_chooser_button_append_separator (button);
+ }
+
+ gtk_app_chooser_button_append_custom_item (button, CUSTOM_ITEM_ASK,
+ _("Ask what to do"),
+ NULL);
+
+ gtk_app_chooser_button_append_custom_item (button, CUSTOM_ITEM_DO_NOTHING,
+ _("Do nothing"),
+ NULL);
+
+ gtk_app_chooser_button_append_custom_item (button, CUSTOM_ITEM_OPEN_FOLDER,
+ _("Open folder"),
+ NULL);
+
+ gtk_app_chooser_button_set_show_dialog_item (button, TRUE);
+
+ if (heading)
+ gtk_app_chooser_button_set_heading (button, _(heading));
+
+ if (pref_ask) {
+ gtk_app_chooser_button_set_active_custom_item (button, CUSTOM_ITEM_ASK);
+ } else if (pref_ignore) {
+ gtk_app_chooser_button_set_active_custom_item (button, CUSTOM_ITEM_DO_NOTHING);
+ } else if (pref_open_folder) {
+ gtk_app_chooser_button_set_active_custom_item (button, CUSTOM_ITEM_OPEN_FOLDER);
+ }
+
+ g_signal_connect_object (button, "changed",
+ G_CALLBACK (on_chooser_changed_cb), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (button, "custom-item-activated",
+ G_CALLBACK (on_custom_item_activated_cb), self, G_CONNECT_SWAPPED);
+}
+
+static void
+on_other_type_combo_box_changed (CcRemovableMediaPanel *self)
+{
+ GtkTreeIter iter;
+ g_autofree gchar *x_content_type = NULL;
+
+ if (!gtk_combo_box_get_active_iter (self->other_type_combo_box, &iter)) {
+ return;
+ }
+
+ gtk_tree_model_get (GTK_TREE_MODEL (self->other_type_list_store), &iter,
+ 1, &x_content_type,
+ -1);
+
+ if (self->other_application_chooser != NULL) {
+ gtk_box_remove (self->other_action_box, GTK_WIDGET (self->other_application_chooser));
+ self->other_application_chooser = NULL;
+ }
+
+ self->other_application_chooser = GTK_APP_CHOOSER_BUTTON (gtk_app_chooser_button_new (x_content_type));
+ gtk_box_append (self->other_action_box, GTK_WIDGET (self->other_application_chooser));
+ prepare_chooser (self, self->other_application_chooser, NULL);
+
+ gtk_label_set_mnemonic_widget (self->other_action_label, GTK_WIDGET (self->other_application_chooser));
+}
+
+static void
+on_extra_options_dialog_response (CcRemovableMediaPanel *self)
+{
+ gtk_widget_hide (GTK_WIDGET (self->other_type_dialog));
+
+ if (self->other_application_chooser != NULL) {
+ gtk_box_remove (self->other_action_box, GTK_WIDGET (self->other_application_chooser));
+ self->other_application_chooser = NULL;
+ }
+}
+
+static void
+on_extra_options_button_clicked (CcRemovableMediaPanel *self)
+{
+ CcShell *shell = cc_panel_get_shell (CC_PANEL (self));
+ GtkWidget *toplevel = cc_shell_get_toplevel (shell);
+
+ gtk_window_set_transient_for (GTK_WINDOW (self->other_type_dialog), GTK_WINDOW (toplevel));
+ gtk_window_set_modal (GTK_WINDOW (self->other_type_dialog), TRUE);
+ gtk_window_set_title (GTK_WINDOW (self->other_type_dialog), _("Other Media"));
+ /* update other_application_chooser */
+ on_other_type_combo_box_changed (self);
+ gtk_window_present (GTK_WINDOW (self->other_type_dialog));
+}
+
+#define OFFSET(x) (G_STRUCT_OFFSET (CcRemovableMediaPanel, x))
+#define WIDGET_FROM_OFFSET(x) (G_STRUCT_MEMBER (GtkWidget*, self, x))
+
+static void
+info_panel_setup_media (CcRemovableMediaPanel *self)
+{
+ guint n;
+ GList *l, *content_types;
+ GtkTreeIter iter;
+
+ struct {
+ gint widget_offset;
+ const gchar *content_type;
+ const gchar *heading;
+ } const defs[] = {
+ { OFFSET (audio_cdda_chooser), "x-content/audio-cdda", N_("Select an application for audio CDs") },
+ { OFFSET (video_dvd_chooser), "x-content/video-dvd", N_("Select an application for video DVDs") },
+ { OFFSET (music_player_chooser), "x-content/audio-player", N_("Select an application to run when a music player is connected") },
+ { OFFSET (dcf_chooser), "x-content/image-dcf", N_("Select an application to run when a camera is connected") },
+ { OFFSET (software_chooser), "x-content/unix-software", N_("Select an application for software CDs") },
+ };
+
+ struct {
+ const gchar *content_type;
+ const gchar *description;
+ } const other_defs[] = {
+ /* translators: these strings are duplicates of shared-mime-info
+ * strings, just here to fix capitalization of the English originals.
+ * If the shared-mime-info translation works for your language,
+ * simply leave these untranslated.
+ */
+ { "x-content/audio-dvd", N_("audio DVD") },
+ { "x-content/blank-bd", N_("blank Blu-ray disc") },
+ { "x-content/blank-cd", N_("blank CD disc") },
+ { "x-content/blank-dvd", N_("blank DVD disc") },
+ { "x-content/blank-hddvd", N_("blank HD DVD disc") },
+ { "x-content/video-bluray", N_("Blu-ray video disc") },
+ { "x-content/ebook-reader", N_("e-book reader") },
+ { "x-content/video-hddvd", N_("HD DVD video disc") },
+ { "x-content/image-picturecd", N_("Picture CD") },
+ { "x-content/video-svcd", N_("Super Video CD") },
+ { "x-content/video-vcd", N_("Video CD") },
+ { "x-content/win32-software", N_("Windows software") },
+ };
+
+ for (n = 0; n < G_N_ELEMENTS (defs); n++) {
+ prepare_chooser (self,
+ GTK_APP_CHOOSER_BUTTON (WIDGET_FROM_OFFSET (defs[n].widget_offset)),
+ defs[n].heading);
+ }
+
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (self->other_type_list_store),
+ 1, GTK_SORT_ASCENDING);
+
+
+ content_types = g_content_types_get_registered ();
+
+ for (l = content_types; l != NULL; l = l->next) {
+ char *content_type = l->data;
+ g_autofree char *description = NULL;
+
+ if (!g_str_has_prefix (content_type, "x-content/"))
+ continue;
+
+ for (n = 0; n < G_N_ELEMENTS (defs); n++) {
+ if (g_content_type_is_a (content_type, defs[n].content_type)) {
+ goto skip;
+ }
+ }
+
+ for (n = 0; n < G_N_ELEMENTS (other_defs); n++) {
+ if (strcmp (content_type, other_defs[n].content_type) == 0) {
+ const gchar *s = other_defs[n].description;
+ if (s == _(s))
+ description = g_content_type_get_description (content_type);
+ else
+ description = g_strdup (_(s));
+
+ break;
+ }
+ }
+
+ if (description == NULL) {
+ g_debug ("Content type '%s' is missing from the info panel", content_type);
+ description = g_content_type_get_description (content_type);
+ }
+
+ gtk_list_store_append (self->other_type_list_store, &iter);
+
+ gtk_list_store_set (self->other_type_list_store, &iter,
+ 0, description,
+ 1, content_type,
+ -1);
+ skip:
+ ;
+ }
+
+ g_list_free_full (content_types, g_free);
+
+ gtk_combo_box_set_active (self->other_type_combo_box, 0);
+
+ g_settings_bind (self->settings,
+ PREF_MEDIA_AUTORUN_NEVER,
+ self->autorun_never_checkbutton,
+ "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind (self->settings,
+ PREF_MEDIA_AUTORUN_NEVER,
+ self->handlers_box,
+ "sensitive",
+ G_SETTINGS_BIND_INVERT_BOOLEAN);
+}
+
+
+static void
+cc_removable_media_panel_finalize (GObject *object)
+{
+ CcRemovableMediaPanel *self = CC_REMOVABLE_MEDIA_PANEL (object);
+
+ g_clear_object (&self->settings);
+
+ G_OBJECT_CLASS (cc_removable_media_panel_parent_class)->finalize (object);
+}
+
+static void
+cc_removable_media_panel_dispose (GObject *object)
+{
+ CcRemovableMediaPanel *self = CC_REMOVABLE_MEDIA_PANEL (object);
+
+ g_clear_pointer ((GtkWindow **) &self->other_type_dialog, gtk_window_destroy);
+
+ G_OBJECT_CLASS (cc_removable_media_panel_parent_class)->dispose (object);
+}
+
+static void
+cc_removable_media_panel_class_init (CcRemovableMediaPanelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = cc_removable_media_panel_finalize;
+ object_class->dispose = cc_removable_media_panel_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/removable-media/cc-removable-media-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaPanel, audio_cdda_chooser);
+ gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaPanel, autorun_never_checkbutton);
+ gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaPanel, dcf_chooser);
+ gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaPanel, extra_options_button);
+ gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaPanel, handlers_box);
+ gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaPanel, music_player_chooser);
+ gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaPanel, other_type_dialog);
+ gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaPanel, other_action_box);
+ gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaPanel, other_action_label);
+ gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaPanel, other_type_combo_box);
+ gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaPanel, other_type_list_store);
+ gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaPanel, software_chooser);
+ gtk_widget_class_bind_template_child (widget_class, CcRemovableMediaPanel, video_dvd_chooser);
+
+ gtk_widget_class_bind_template_callback (widget_class, on_extra_options_dialog_response);
+ gtk_widget_class_bind_template_callback (widget_class, on_extra_options_button_clicked);
+ gtk_widget_class_bind_template_callback (widget_class, on_other_type_combo_box_changed);
+}
+
+static void
+cc_removable_media_panel_init (CcRemovableMediaPanel *self)
+{
+ g_resources_register (cc_removable_media_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+ self->settings = g_settings_new (MEDIA_HANDLING_SCHEMA);
+
+ info_panel_setup_media (self);
+}
diff --git a/panels/removable-media/cc-removable-media-panel.h b/panels/removable-media/cc-removable-media-panel.h
new file mode 100644
index 0000000..f6d4b53
--- /dev/null
+++ b/panels/removable-media/cc-removable-media-panel.h
@@ -0,0 +1,29 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2017 Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_REMOVABLE_MEDIA_PANEL (cc_removable_media_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcRemovableMediaPanel, cc_removable_media_panel, CC, REMOVABLE_MEDIA_PANEL, CcPanel)
+
+G_END_DECLS
diff --git a/panels/removable-media/cc-removable-media-panel.ui b/panels/removable-media/cc-removable-media-panel.ui
new file mode 100644
index 0000000..899956e
--- /dev/null
+++ b/panels/removable-media/cc-removable-media-panel.ui
@@ -0,0 +1,304 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcRemovableMediaPanel" parent="CcPanel">
+ <child type="content">
+ <object class="AdwClamp">
+ <child>
+ <object class="GtkBox">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="margin_top">32</property>
+ <property name="margin_bottom">32</property>
+ <property name="margin_start">24</property>
+ <property name="margin_end">24</property>
+ <property name="spacing">18</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox" id="handlers_box">
+ <property name="spacing">10</property>
+ <property name="valign">start</property>
+ <property name="vexpand">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">10</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="halign">center</property>
+ <property name="justify">center</property>
+ <property name="wrap">True</property>
+ <property name="label" translatable="yes">Select how media should be handled</property>
+ <property name="margin_bottom">12</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">18</property>
+ <property name="margin-start">12</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="hexpand">True</property>
+ <property name="column-spacing">6</property>
+ <property name="row-spacing">12</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">CD _audio</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">audio_cdda_chooser</property>
+ <layout>
+ <property name="row">0</property>
+ <property name="column">0</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_DVD video</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">video_dvd_chooser</property>
+ <layout>
+ <property name="row">1</property>
+ <property name="column">0</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkAppChooserButton" id="audio_cdda_chooser">
+ <property name="hexpand">True</property>
+ <property name="content_type">x-content/audio-cdda</property>
+ <layout>
+ <property name="row">0</property>
+ <property name="column">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkAppChooserButton" id="video_dvd_chooser">
+ <property name="hexpand">True</property>
+ <property name="content_type">x-content/video-dvd</property>
+ <layout>
+ <property name="row">1</property>
+ <property name="column">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Music player</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">music_player_chooser</property>
+ <layout>
+ <property name="row">2</property>
+ <property name="column">0</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkAppChooserButton" id="music_player_chooser">
+ <property name="hexpand">True</property>
+ <property name="content_type">x-content/audio-player</property>
+ <layout>
+ <property name="row">2</property>
+ <property name="column">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Photos</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">dcf_chooser</property>
+ <layout>
+ <property name="row">3</property>
+ <property name="column">0</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkAppChooserButton" id="dcf_chooser">
+ <property name="hexpand">True</property>
+ <property name="content_type">x-content/image-dcf</property>
+ <layout>
+ <property name="row">3</property>
+ <property name="column">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Software</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">software_chooser</property>
+ <layout>
+ <property name="row">4</property>
+ <property name="column">0</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkAppChooserButton" id="software_chooser">
+ <property name="hexpand">True</property>
+ <property name="content_type">x-content/unix-software</property>
+ <layout>
+ <property name="row">4</property>
+ <property name="column">1</property>
+ </layout>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="extra_options_button">
+ <property name="label" translatable="yes">_Other Media…</property>
+ <property name="halign">end</property>
+ <property name="use_underline">True</property>
+ <signal name="clicked" handler="on_extra_options_button_clicked" object="CcRemovableMediaPanel" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="autorun_never_checkbutton">
+ <property name="valign">end</property>
+ <property name="vexpand">False</property>
+ <property name="use_underline">True</property>
+ <property name="label" translatable="yes">_Never prompt or start programs on media insertion</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+
+ <object class="GtkDialog" id="other_type_dialog">
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="use_header_bar">1</property>
+ <property name="hide-on-close">True</property>
+ <signal name="response" handler="on_extra_options_dialog_response" object="CcRemovableMediaPanel" swapped="yes"/>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">18</property>
+ <property name="margin-bottom">18</property>
+ <property name="margin-start">18</property>
+ <property name="margin-end">18</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">10</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Select how other media should be handled</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">10</property>
+ <child>
+ <object class="GtkComboBox" id="other_type_combo_box">
+ <property name="model">other_type_list_store</property>
+ <signal name="changed" handler="on_other_type_combo_box_changed" object="CcRemovableMediaPanel" swapped="yes"/>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ <child>
+ <object class="GtkCellRendererText"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="other_action_label">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Action:</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="other_action_box">
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Type:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">other_type_combo_box</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <object class="GtkListStore" id="other_type_list_store">
+ <columns>
+ <!-- column-name description -->
+ <column type="gchararray"/>
+ <!-- column-name content-type -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+</interface>
diff --git a/panels/removable-media/gnome-removable-media-panel.desktop.in.in b/panels/removable-media/gnome-removable-media-panel.desktop.in.in
new file mode 100644
index 0000000..0f5a6d1
--- /dev/null
+++ b/panels/removable-media/gnome-removable-media-panel.desktop.in.in
@@ -0,0 +1,18 @@
+[Desktop Entry]
+Name=Removable Media
+Comment=Configure Removable Media settings
+Exec=gnome-control-center removable-media
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-removable-media-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;X-GNOME-Settings-Panel;X-GNOME-DevicesSettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=info
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: Search terms to find the Removable Media panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=device;system;default;application;preferred;cd;dvd;usb;audio;video;disc;removable;media;autorun;
diff --git a/panels/removable-media/icons/meson.build b/panels/removable-media/icons/meson.build
new file mode 100644
index 0000000..b03db66
--- /dev/null
+++ b/panels/removable-media/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-removable-media-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/removable-media/icons/scalable/org.gnome.Settings-removable-media-symbolic.svg b/panels/removable-media/icons/scalable/org.gnome.Settings-removable-media-symbolic.svg
new file mode 100644
index 0000000..1e31db3
--- /dev/null
+++ b/panels/removable-media/icons/scalable/org.gnome.Settings-removable-media-symbolic.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <path d="m 12 6 v 5 c 0 2.210938 -1.789062 4 -4 4 s -4 -1.789062 -4 -4 v -5 c 0 -0.550781 0.449219 -1 1 -1 h 6 c 0.550781 0 1 0.449219 1 1 z m -7 -5.5 v 3.5 h 6 v -3.5 c 0 -0.277344 -0.222656 -0.5 -0.5 -0.5 h -5 c -0.277344 0 -0.5 0.222656 -0.5 0.5 z m 1 0.5 h 1 v 1 h -1 z m 3 0 h 1 v 1 h -1 z m 0 0" fill="#474747"/>
+</svg>
diff --git a/panels/removable-media/meson.build b/panels/removable-media/meson.build
new file mode 100644
index 0000000..6475659
--- /dev/null
+++ b/panels/removable-media/meson.build
@@ -0,0 +1,47 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+sources = files(
+ 'cc-removable-media-panel.c'
+)
+
+resource_data = files(
+ 'cc-removable-media-panel.ui'
+)
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname.underscorify (),
+ dependencies: resource_data,
+ export: true
+)
+
+deps = common_deps + [
+ dependency('libgtop-2.0')
+]
+
+panels_libs += static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [ top_inc, common_inc ],
+ dependencies: deps,
+ c_args: cflags
+)
+
+subdir('icons')
diff --git a/panels/removable-media/removable-media.gresource.xml b/panels/removable-media/removable-media.gresource.xml
new file mode 100644
index 0000000..330dbf2
--- /dev/null
+++ b/panels/removable-media/removable-media.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/removable-media">
+ <file preprocess="xml-stripblanks">cc-removable-media-panel.ui</file>
+ </gresource>
+</gresources>
diff --git a/panels/screen/cc-screen-panel.c b/panels/screen/cc-screen-panel.c
new file mode 100644
index 0000000..05bd11d
--- /dev/null
+++ b/panels/screen/cc-screen-panel.c
@@ -0,0 +1,387 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2018 Red Hat, Inc
+ * Copyright (C) 2020 Collabora Ltd.
+ * Copyright (C) 2021-2022 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#include "cc-screen-panel.h"
+#include "cc-screen-panel-enums.h"
+#include "cc-screen-resources.h"
+#include "cc-util.h"
+
+#include "panels/display/cc-display-config-manager-dbus.h"
+
+#include <adwaita.h>
+
+#include <gio/gdesktopappinfo.h>
+#include <glib/gi18n.h>
+
+struct _CcScreenPanel
+{
+ CcPanel parent_instance;
+
+ CcDisplayConfigManager *display_config_manager;
+
+ GSettings *lock_settings;
+ GSettings *notification_settings;
+ GSettings *privacy_settings;
+ GSettings *session_settings;
+
+ GCancellable *cancellable;
+
+ AdwComboRow *blank_screen_row;
+ AdwComboRow *lock_after_row;
+ AdwPreferencesGroup *screen_privacy_group;
+ GDBusProxy *usb_proxy;
+ GtkListBoxRow *usb_protection_row;
+ GtkSwitch *automatic_screen_lock_switch;
+ GtkSwitch *privacy_screen_switch;
+ GtkSwitch *show_notifications_switch;
+ GtkSwitch *usb_protection_switch;
+};
+
+CC_PANEL_REGISTER (CcScreenPanel, cc_screen_panel)
+
+static char *
+lock_after_name_cb (AdwEnumListItem *item,
+ gpointer user_data)
+{
+
+ switch (adw_enum_list_item_get_value (item))
+ {
+ case CC_SCREEN_PANEL_LOCK_AFTER_SCREEN_OFF:
+ /* Translators: Option for "Lock screen after blank" in "Screen Lock" panel */
+ return g_strdup(C_("lock_screen", "Screen Turns Off"));
+ case CC_SCREEN_PANEL_LOCK_AFTER_30_SEC:
+ /* Translators: Option for "Lock screen after blank" in "Screen Lock" panel */
+ return g_strdup (C_("lock_screen", "30 seconds"));
+ case CC_SCREEN_PANEL_LOCK_AFTER_1_MIN:
+ /* Translators: Option for "Lock screen after blank" in "Screen Lock" panel */
+ return g_strdup (C_("lock_screen", "1 minute"));
+ case CC_SCREEN_PANEL_LOCK_AFTER_2_MIN:
+ /* Translators: Option for "Lock screen after blank" in "Screen Lock" panel */
+ return g_strdup (C_("lock_screen", "2 minutes"));
+ case CC_SCREEN_PANEL_LOCK_AFTER_3_MIN:
+ /* Translators: Option for "Lock screen after blank" in "Screen Lock" panel */
+ return g_strdup (C_("lock_screen", "3 minutes"));
+ case CC_SCREEN_PANEL_LOCK_AFTER_5_MIN:
+ /* Translators: Option for "Lock screen after blank" in "Screen Lock" panel */
+ return g_strdup (C_("lock_screen", "5 minutes"));
+ case CC_SCREEN_PANEL_LOCK_AFTER_30_MIN:
+ /* Translators: Option for "Lock screen after blank" in "Screen Lock" panel */
+ return g_strdup (C_("lock_screen", "30 minutes"));
+ case CC_SCREEN_PANEL_LOCK_AFTER_1_HR:
+ /* Translators: Option for "Lock screen after blank" in "Screen Lock" panel */
+ return g_strdup (C_("lock_screen", "1 hour"));
+ default:
+ return NULL;
+ }
+}
+
+static void
+on_lock_combo_changed_cb (AdwComboRow *combo_row,
+ GParamSpec *pspec,
+ CcScreenPanel *self)
+{
+ AdwEnumListItem *item;
+ CcScreenPanelLockAfter delay;
+
+ item = ADW_ENUM_LIST_ITEM (adw_combo_row_get_selected_item (combo_row));
+ delay = adw_enum_list_item_get_value (item);
+
+ g_settings_set (self->lock_settings, "lock-delay", "u", delay);
+}
+
+static void
+set_lock_value_for_combo (AdwComboRow *combo_row,
+ CcScreenPanel *self)
+{
+ AdwEnumListModel *model;
+ guint value;
+
+ model = ADW_ENUM_LIST_MODEL (adw_combo_row_get_model (combo_row));
+
+ g_settings_get (self->lock_settings, "lock-delay", "u", &value);
+ adw_combo_row_set_selected (combo_row,
+ adw_enum_list_model_find_position (model, value));
+}
+
+static char *
+screen_delay_name_cb (AdwEnumListItem *item,
+ gpointer user_data)
+{
+
+ switch (adw_enum_list_item_get_value (item))
+ {
+ case CC_SCREEN_PANEL_BLANK_SCREEN_DELAY_1_MIN:
+ /* Translators: Option for "Blank screen" in "Screen Lock" panel */
+ return g_strdup (C_("blank_screen", "1 minute"));
+ case CC_SCREEN_PANEL_BLANK_SCREEN_DELAY_2_MIN:
+ /* Translators: Option for "Blank screen" in "Screen Lock" panel */
+ return g_strdup (C_("blank_screen", "2 minutes"));
+ case CC_SCREEN_PANEL_BLANK_SCREEN_DELAY_3_MIN:
+ /* Translators: Option for "Blank screen" in "Screen Lock" panel */
+ return g_strdup (C_("blank_screen", "3 minutes"));
+ case CC_SCREEN_PANEL_BLANK_SCREEN_DELAY_4_MIN:
+ /* Translators: Option for "Blank screen" in "Screen Lock" panel */
+ return g_strdup (C_("blank_screen", "4 minutes"));
+ case CC_SCREEN_PANEL_BLANK_SCREEN_DELAY_5_MIN:
+ /* Translators: Option for "Blank screen" in "Screen Lock" panel */
+ return g_strdup (C_("blank_screen", "5 minutes"));
+ case CC_SCREEN_PANEL_BLANK_SCREEN_DELAY_8_MIN:
+ /* Translators: Option for "Blank screen" in "Screen Lock" panel */
+ return g_strdup (C_("blank_screen", "8 minutes"));
+ case CC_SCREEN_PANEL_BLANK_SCREEN_DELAY_10_MIN:
+ /* Translators: Option for "Blank screen" in "Screen Lock" panel */
+ return g_strdup (C_("blank_screen", "10 minutes"));
+ case CC_SCREEN_PANEL_BLANK_SCREEN_DELAY_12_MIN:
+ /* Translators: Option for "Blank screen" in "Screen Lock" panel */
+ return g_strdup (C_("blank_screen", "12 minutes"));
+ case CC_SCREEN_PANEL_BLANK_SCREEN_DELAY_15_MIN:
+ /* Translators: Option for "Blank screen" in "Screen Lock" panel */
+ return g_strdup (C_("blank_screen", "15 minutes"));
+ case CC_SCREEN_PANEL_BLANK_SCREEN_DELAY_NEVER:
+ /* Translators: Option for "Blank screen" in "Screen Lock" panel */
+ return g_strdup (C_("blank_screen", "Never"));
+ default:
+ return NULL;
+ }
+}
+
+static void
+set_blank_screen_delay_value (CcScreenPanel *self,
+ gint value)
+{
+ AdwEnumListModel *model;
+
+ model = ADW_ENUM_LIST_MODEL (adw_combo_row_get_model (self->blank_screen_row));
+
+ adw_combo_row_set_selected (self->blank_screen_row,
+ adw_enum_list_model_find_position (model, value));
+}
+
+static void
+on_blank_screen_delay_changed_cb (AdwComboRow *combo_row,
+ GParamSpec *pspec,
+ CcScreenPanel *self)
+{
+ AdwEnumListItem *item;
+ CcScreenPanelBlankScreenDelay delay;
+
+ item = ADW_ENUM_LIST_ITEM (adw_combo_row_get_selected_item (combo_row));
+ delay = adw_enum_list_item_get_value (item);
+
+ g_settings_set_uint (self->session_settings, "idle-delay", delay);
+}
+
+static void
+on_usb_protection_properties_changed_cb (GDBusProxy *usb_proxy,
+ GVariant *changed_properties,
+ GStrv invalidated_properties,
+ CcScreenPanel *self)
+{
+ gboolean available = FALSE;
+
+ if (self->usb_proxy)
+ {
+ g_autoptr(GVariant) variant = NULL;
+
+ variant = g_dbus_proxy_get_cached_property (self->usb_proxy, "Available");
+ if (variant != NULL)
+ available = g_variant_get_boolean (variant);
+ }
+
+ /* Show the USB protection row only if the required daemon is up and running */
+ gtk_widget_set_visible (GTK_WIDGET (self->usb_protection_row), available);
+}
+
+static void
+on_usb_protection_param_ready (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+ CcScreenPanel *self;
+ GDBusProxy *proxy;
+
+ self = user_data;
+ proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+ if (error)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ g_warning ("Failed to connect to SettingsDaemon.UsbProtection: %s",
+ error->message);
+ }
+
+ gtk_widget_hide (GTK_WIDGET (self->usb_protection_row));
+ return;
+ }
+ self->usb_proxy = proxy;
+
+ g_signal_connect_object (self->usb_proxy,
+ "g-properties-changed",
+ G_CALLBACK (on_usb_protection_properties_changed_cb),
+ self,
+ 0);
+ on_usb_protection_properties_changed_cb (self->usb_proxy, NULL, NULL, self);
+}
+
+static void
+cc_screen_panel_finalize (GObject *object)
+{
+ CcScreenPanel *self = CC_SCREEN_PANEL (object);
+
+ g_cancellable_cancel (self->cancellable);
+ g_clear_object (&self->cancellable);
+ g_clear_object (&self->display_config_manager);
+ g_clear_object (&self->lock_settings);
+ g_clear_object (&self->notification_settings);
+ g_clear_object (&self->session_settings);
+ g_clear_object (&self->usb_proxy);
+
+ G_OBJECT_CLASS (cc_screen_panel_parent_class)->finalize (object);
+}
+
+static void
+cc_screen_panel_class_init (CcScreenPanelClass *klass)
+{
+ GObjectClass *oclass = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ oclass->finalize = cc_screen_panel_finalize;
+
+ g_type_ensure (CC_TYPE_SCREEN_PANEL_LOCK_AFTER);
+ g_type_ensure (CC_TYPE_SCREEN_PANEL_BLANK_SCREEN_DELAY);
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/screen/cc-screen-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcScreenPanel, automatic_screen_lock_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcScreenPanel, blank_screen_row);
+ gtk_widget_class_bind_template_child (widget_class, CcScreenPanel, lock_after_row);
+ gtk_widget_class_bind_template_child (widget_class, CcScreenPanel, privacy_screen_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcScreenPanel, screen_privacy_group);
+ gtk_widget_class_bind_template_child (widget_class, CcScreenPanel, show_notifications_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcScreenPanel, usb_protection_row);
+ gtk_widget_class_bind_template_child (widget_class, CcScreenPanel, usb_protection_switch);
+
+ gtk_widget_class_bind_template_callback (widget_class, lock_after_name_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_blank_screen_delay_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_lock_combo_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, screen_delay_name_cb);
+}
+
+static void
+update_display_config (CcScreenPanel *self)
+{
+ g_autoptr (CcDisplayConfig) config = NULL;
+ gboolean any_privacy_screen = FALSE;
+ gboolean any_configurable_privacy_screen = FALSE;
+ GList *monitors;
+ GList *l;
+
+ config = cc_display_config_manager_get_current (self->display_config_manager);
+ monitors = config ? cc_display_config_get_monitors (config) : NULL;
+
+ for (l = monitors; l; l = l->next)
+ {
+ CcDisplayMonitor *monitor = CC_DISPLAY_MONITOR (l->data);
+ CcDisplayMonitorPrivacy privacy = cc_display_monitor_get_privacy (monitor);
+
+ if (privacy != CC_DISPLAY_MONITOR_PRIVACY_UNSUPPORTED)
+ {
+ any_privacy_screen = TRUE;
+
+ if (!(privacy & CC_DISPLAY_MONITOR_PRIVACY_LOCKED))
+ any_configurable_privacy_screen = TRUE;
+ }
+ }
+
+ gtk_widget_set_visible (GTK_WIDGET (self->screen_privacy_group),
+ any_privacy_screen);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->privacy_screen_switch),
+ any_configurable_privacy_screen);
+}
+
+static void
+cc_screen_panel_init (CcScreenPanel *self)
+{
+ guint value;
+
+ g_resources_register (cc_screen_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->cancellable = g_cancellable_new ();
+
+ self->lock_settings = g_settings_new ("org.gnome.desktop.screensaver");
+ self->privacy_settings = g_settings_new ("org.gnome.desktop.privacy");
+ self->notification_settings = g_settings_new ("org.gnome.desktop.notifications");
+ self->session_settings = g_settings_new ("org.gnome.desktop.session");
+
+ g_settings_bind (self->lock_settings,
+ "lock-enabled",
+ self->automatic_screen_lock_switch,
+ "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind (self->lock_settings,
+ "lock-enabled",
+ self->lock_after_row,
+ "sensitive",
+ G_SETTINGS_BIND_GET);
+
+ set_lock_value_for_combo (self->lock_after_row, self);
+
+ g_settings_bind (self->notification_settings,
+ "show-in-lock-screen",
+ self->show_notifications_switch,
+ "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ value = g_settings_get_uint (self->session_settings, "idle-delay");
+ set_blank_screen_delay_value (self, value);
+
+ g_settings_bind (self->privacy_settings,
+ "usb-protection",
+ self->usb_protection_switch,
+ "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ self->display_config_manager = cc_display_config_manager_dbus_new ();
+ g_signal_connect_object (self->display_config_manager, "changed",
+ G_CALLBACK (update_display_config), self,
+ G_CONNECT_SWAPPED);
+
+ update_display_config (self);
+ g_settings_bind (self->privacy_settings,
+ "privacy-screen",
+ self->privacy_screen_switch,
+ "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.gnome.SettingsDaemon.UsbProtection",
+ "/org/gnome/SettingsDaemon/UsbProtection",
+ "org.gnome.SettingsDaemon.UsbProtection",
+ self->cancellable,
+ on_usb_protection_param_ready,
+ self);
+}
diff --git a/panels/screen/cc-screen-panel.h b/panels/screen/cc-screen-panel.h
new file mode 100644
index 0000000..c1917f9
--- /dev/null
+++ b/panels/screen/cc-screen-panel.h
@@ -0,0 +1,55 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2018 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_LOCK_PANEL (cc_screen_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcScreenPanel, cc_screen_panel, CC, SCREEN_PANEL, CcPanel)
+
+typedef enum {
+ CC_SCREEN_PANEL_LOCK_AFTER_SCREEN_OFF = 0,
+ CC_SCREEN_PANEL_LOCK_AFTER_30_SEC = 30,
+ CC_SCREEN_PANEL_LOCK_AFTER_1_MIN = 60,
+ CC_SCREEN_PANEL_LOCK_AFTER_2_MIN = 120,
+ CC_SCREEN_PANEL_LOCK_AFTER_3_MIN = 180,
+ CC_SCREEN_PANEL_LOCK_AFTER_5_MIN = 300,
+ CC_SCREEN_PANEL_LOCK_AFTER_30_MIN = 1800,
+ CC_SCREEN_PANEL_LOCK_AFTER_1_HR = 3600,
+} CcScreenPanelLockAfter;
+
+typedef enum {
+ CC_SCREEN_PANEL_BLANK_SCREEN_DELAY_1_MIN = 60,
+ CC_SCREEN_PANEL_BLANK_SCREEN_DELAY_2_MIN = 120,
+ CC_SCREEN_PANEL_BLANK_SCREEN_DELAY_3_MIN = 180,
+ CC_SCREEN_PANEL_BLANK_SCREEN_DELAY_4_MIN = 240,
+ CC_SCREEN_PANEL_BLANK_SCREEN_DELAY_5_MIN = 300,
+ CC_SCREEN_PANEL_BLANK_SCREEN_DELAY_8_MIN = 480,
+ CC_SCREEN_PANEL_BLANK_SCREEN_DELAY_10_MIN = 600,
+ CC_SCREEN_PANEL_BLANK_SCREEN_DELAY_12_MIN = 720,
+ CC_SCREEN_PANEL_BLANK_SCREEN_DELAY_15_MIN = 900,
+ CC_SCREEN_PANEL_BLANK_SCREEN_DELAY_NEVER = 0,
+} CcScreenPanelBlankScreenDelay;
+
+
+G_END_DECLS
diff --git a/panels/screen/cc-screen-panel.ui b/panels/screen/cc-screen-panel.ui
new file mode 100644
index 0000000..2d58729
--- /dev/null
+++ b/panels/screen/cc-screen-panel.ui
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcScreenPanel" parent="CcPanel">
+ <child type="content">
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Screen Lock</property>
+ <property name="description" translatable="yes">Automatically locking the screen prevents others from accessing the computer while you're away.</property>
+
+ <!-- Blank Screen Delay row -->
+ <child>
+ <object class="AdwComboRow" id="blank_screen_row">
+ <property name="title" translatable="yes">Blank Screen Delay</property>
+ <property name="subtitle" translatable="yes">Period of inactivity after which the screen will go blank.</property>
+ <property name="subtitle-lines">2</property>
+ <property name="use-underline">true</property>
+ <signal name="notify::selected-item" handler="on_blank_screen_delay_changed_cb"/>
+ <property name="model">
+ <object class="AdwEnumListModel">
+ <property name="enum-type">CcScreenPanelBlankScreenDelay</property>
+ </object>
+ </property>
+ <property name="expression">
+ <closure type="gchararray" function="screen_delay_name_cb"/>
+ </property>
+ </object>
+ </child>
+
+ <!-- Automatic Screen Lock row -->
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Automatic Screen _Lock</property>
+ <property name="activatable-widget">automatic_screen_lock_switch</property>
+ <property name="use-underline">true</property>
+ <child>
+ <object class="GtkSwitch" id="automatic_screen_lock_switch">
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Enabled</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- Automatic Screen Lock Delay row -->
+ <child>
+ <object class="AdwComboRow" id="lock_after_row">
+ <property name="title" translatable="yes">Automatic _Screen Lock Delay</property>
+ <property name="subtitle" translatable="yes">Period after the screen blanks when the screen is automatically locked.</property>
+ <property name="subtitle-lines">2</property>
+ <property name="use-underline">true</property>
+ <signal name="notify::selected-item" handler="on_lock_combo_changed_cb"/>
+ <property name="model">
+ <object class="AdwEnumListModel">
+ <property name="enum-type">CcScreenPanelLockAfter</property>
+ </object>
+ </property>
+ <property name="expression">
+ <closure type="gchararray" function="lock_after_name_cb"/>
+ </property>
+ </object>
+ </child>
+
+ <!-- Show Notifications row -->
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes" comments="Translators: Whether to show notifications on the lock screen">_Lock Screen Notifications</property>
+ <property name="activatable-widget">show_notifications_switch</property>
+ <property name="use-underline">true</property>
+ <child>
+ <object class="GtkSwitch" id="show_notifications_switch">
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Enabled</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- USB protection row -->
+ <child>
+ <object class="AdwActionRow" id="usb_protection_row">
+ <property name="visible">false</property>
+ <property name="title" translatable="yes">Forbid new _USB devices</property>
+ <property name="subtitle" translatable="yes">Prevent new USB devices from interacting with the system when the screen is locked.</property>
+ <property name="subtitle-lines">2</property>
+ <property name="activatable-widget">usb_protection_switch</property>
+ <property name="use-underline">true</property>
+ <child>
+ <object class="GtkSwitch" id="usb_protection_switch">
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Enabled</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup" id="screen_privacy_group">
+ <property name="title" translatable="yes">Screen Privacy</property>
+
+ <!-- Privacy Screen row -->
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Restrict Viewing Angle</property>
+ <property name="activatable-widget">privacy_screen_switch</property>
+ <property name="use-underline">true</property>
+ <child>
+ <object class="GtkSwitch" id="privacy_screen_switch">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/screen/gnome-screen-panel.desktop.in.in b/panels/screen/gnome-screen-panel.desktop.in.in
new file mode 100644
index 0000000..e095264
--- /dev/null
+++ b/panels/screen/gnome-screen-panel.desktop.in.in
@@ -0,0 +1,19 @@
+[Desktop Entry]
+Name=Screen
+Comment=Screen Settings
+Exec=gnome-control-center screen
+# FIXME
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-screen-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-PrivacySettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=screen
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: Search terms to find the Screen panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=screen;lock;private;privacy;
diff --git a/panels/screen/icons/meson.build b/panels/screen/icons/meson.build
new file mode 100644
index 0000000..f0e4593
--- /dev/null
+++ b/panels/screen/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-screen-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/screen/icons/scalable/org.gnome.Settings-screen-symbolic.svg b/panels/screen/icons/scalable/org.gnome.Settings-screen-symbolic.svg
new file mode 100644
index 0000000..b27a2bc
--- /dev/null
+++ b/panels/screen/icons/scalable/org.gnome.Settings-screen-symbolic.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <path d="m 3 0 c -1.660156 0 -3 1.339844 -3 3 v 7 c 0 1.660156 1.339844 3 3 3 h 10 c 1.660156 0 3 -1.339844 3 -3 v -7 c 0 -1.660156 -1.339844 -3 -3 -3 z m 0 2 h 10 c 0.554688 0 1 0.445312 1 1 v 7 c 0 0.554688 -0.445312 1 -1 1 h -10 c -0.554688 0 -1 -0.445312 -1 -1 v -7 c 0 -0.554688 0.445312 -1 1 -1 z m 2 12 c -1.105469 0 -2 0.894531 -2 2 h 10 c 0 -1.105469 -0.894531 -2 -2 -2 z m 0 0" fill="#2e3436"/>
+</svg>
diff --git a/panels/screen/meson.build b/panels/screen/meson.build
new file mode 100644
index 0000000..48482b8
--- /dev/null
+++ b/panels/screen/meson.build
@@ -0,0 +1,46 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+sources = files('cc-screen-panel.c')
+
+resource_data = files('cc-screen-panel.ui')
+
+sources += gnome.mkenums_simple(
+ 'cc-screen-panel-enums',
+ sources: ['cc-screen-panel.h'],
+)
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname,
+ dependencies: resource_data,
+ export: true
+)
+
+cflags += '-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir)
+
+panels_libs += static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [top_inc, common_inc],
+ dependencies: common_deps,
+ c_args: cflags
+)
+
+subdir('icons')
diff --git a/panels/screen/screen.gresource.xml b/panels/screen/screen.gresource.xml
new file mode 100644
index 0000000..9d1500f
--- /dev/null
+++ b/panels/screen/screen.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/screen">
+ <file preprocess="xml-stripblanks">cc-screen-panel.ui</file>
+ </gresource>
+</gresources>
diff --git a/panels/search/cc-search-locations-dialog.c b/panels/search/cc-search-locations-dialog.c
new file mode 100644
index 0000000..9a0e437
--- /dev/null
+++ b/panels/search/cc-search-locations-dialog.c
@@ -0,0 +1,787 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Cosimo Cecchi <cosimoc@gnome.org>
+ */
+
+#include "cc-search-locations-dialog.h"
+
+#include <glib/gi18n.h>
+
+#define TRACKER_SCHEMA "org.freedesktop.Tracker.Miner.Files"
+#define TRACKER3_SCHEMA "org.freedesktop.Tracker3.Miner.Files"
+#define TRACKER_KEY_RECURSIVE_DIRECTORIES "index-recursive-directories"
+#define TRACKER_KEY_SINGLE_DIRECTORIES "index-single-directories"
+
+typedef enum {
+ PLACE_XDG,
+ PLACE_BOOKMARKS,
+ PLACE_OTHER
+} PlaceType;
+
+typedef struct {
+ CcSearchLocationsDialog *dialog;
+ GFile *location;
+ gchar *display_name;
+ PlaceType place_type;
+ GCancellable *cancellable;
+ const gchar *settings_key;
+} Place;
+
+typedef struct {
+ GtkWidget *row;
+ GtkWidget *switch_;
+} PlaceRowWidgets;
+
+struct _CcSearchLocationsDialog {
+ AdwPreferencesWindow parent;
+
+ GSettings *tracker_preferences;
+
+ GtkWidget *places_group;
+ GtkWidget *places_list;
+ GtkWidget *bookmarks_group;
+ GtkWidget *bookmarks_list;
+ GtkWidget *others_list;
+ GtkWidget *locations_add;
+};
+
+struct _CcSearchLocationsDialogClass {
+ AdwPreferencesWindowClass parent_class;
+};
+
+G_DEFINE_TYPE (CcSearchLocationsDialog, cc_search_locations_dialog, ADW_TYPE_PREFERENCES_WINDOW)
+
+static gboolean
+keynav_failed_cb (CcSearchLocationsDialog *self,
+ GtkDirectionType direction)
+{
+ GtkWidget *toplevel = GTK_WIDGET (gtk_widget_get_root (GTK_WIDGET (self)));
+
+ if (!toplevel)
+ return FALSE;
+
+ if (direction != GTK_DIR_UP && direction != GTK_DIR_DOWN)
+ return FALSE;
+
+ return gtk_widget_child_focus (toplevel, direction == GTK_DIR_UP ?
+ GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD);
+}
+
+static void
+cc_search_locations_dialog_finalize (GObject *object)
+{
+ CcSearchLocationsDialog *self = CC_SEARCH_LOCATIONS_DIALOG (object);
+
+ g_clear_object (&self->tracker_preferences);
+
+ G_OBJECT_CLASS (cc_search_locations_dialog_parent_class)->finalize (object);
+}
+
+static void
+cc_search_locations_dialog_init (CcSearchLocationsDialog *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static Place *
+place_new (CcSearchLocationsDialog *dialog,
+ GFile *location,
+ gchar *display_name,
+ PlaceType place_type)
+{
+ Place *new_place = g_new0 (Place, 1);
+
+ new_place->dialog = dialog;
+ new_place->location = location;
+ if (display_name != NULL)
+ new_place->display_name = display_name;
+ else
+ new_place->display_name = g_file_get_basename (location);
+ if (g_strcmp0 (g_file_get_path (location), g_get_home_dir ()) == 0)
+ new_place->settings_key = TRACKER_KEY_SINGLE_DIRECTORIES;
+ else
+ new_place->settings_key = TRACKER_KEY_RECURSIVE_DIRECTORIES;
+ new_place->place_type = place_type;
+
+ return new_place;
+}
+
+static void
+place_free (Place * p)
+{
+ g_cancellable_cancel (p->cancellable);
+ g_clear_object (&p->cancellable);
+
+ g_object_unref (p->location);
+ g_free (p->display_name);
+
+ g_free (p);
+}
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (Place, place_free)
+
+static GList *
+get_bookmarks (CcSearchLocationsDialog *self)
+{
+ g_autoptr(GFile) file = NULL;
+ g_autofree gchar *contents = NULL;
+ g_autofree gchar *path = NULL;
+ GList *bookmarks = NULL;
+ GError *error = NULL;
+
+ path = g_build_filename (g_get_user_config_dir (), "gtk-3.0",
+ "bookmarks", NULL);
+ file = g_file_new_for_path (path);
+ if (g_file_load_contents (file, NULL, &contents, NULL, NULL, &error))
+ {
+ gint idx;
+ g_auto(GStrv) lines = NULL;
+
+ lines = g_strsplit (contents, "\n", -1);
+ for (idx = 0; lines[idx]; idx++)
+ {
+ /* Ignore empty or invalid lines that cannot be parsed properly */
+ if (lines[idx][0] != '\0' && lines[idx][0] != ' ')
+ {
+ /* gtk 2.7/2.8 might have labels appended to bookmarks which are separated by a space */
+ /* we must seperate the bookmark uri and the potential label */
+ char *space, *label;
+ Place *bookmark;
+
+ label = NULL;
+ space = strchr (lines[idx], ' ');
+ if (space)
+ {
+ *space = '\0';
+ label = g_strdup (space + 1);
+ }
+
+ bookmark = place_new (self,
+ g_file_new_for_uri (lines[idx]),
+ label,
+ PLACE_BOOKMARKS);
+
+ bookmarks = g_list_prepend (bookmarks, bookmark);
+ }
+ }
+ }
+
+ return g_list_reverse (bookmarks);
+}
+
+static const gchar *
+get_user_special_dir_if_not_home (GUserDirectory idx)
+{
+ const gchar *path;
+ path = g_get_user_special_dir (idx);
+ if (g_strcmp0 (path, g_get_home_dir ()) == 0)
+ return NULL;
+
+ return path;
+}
+
+static GList *
+get_xdg_dirs (CcSearchLocationsDialog *self)
+{
+ GList *xdg_dirs = NULL;
+ gint idx;
+ const gchar *path;
+ Place *xdg_dir;
+
+ for (idx = 0; idx < G_USER_N_DIRECTORIES; idx++)
+ {
+ path = get_user_special_dir_if_not_home (idx);
+ if (path == NULL)
+ continue;
+
+ if (idx == G_USER_DIRECTORY_TEMPLATES ||
+ idx == G_USER_DIRECTORY_PUBLIC_SHARE ||
+ idx == G_USER_DIRECTORY_DESKTOP)
+ continue;
+
+ xdg_dir = place_new (self,
+ g_file_new_for_path (path),
+ NULL,
+ PLACE_XDG);
+
+ xdg_dirs = g_list_prepend (xdg_dirs, xdg_dir);
+ }
+
+ return g_list_reverse (xdg_dirs);
+}
+
+static const gchar *
+path_to_tracker_dir (const gchar *path)
+{
+ const gchar *value;
+
+ if (g_strcmp0 (path, get_user_special_dir_if_not_home (G_USER_DIRECTORY_DESKTOP)) == 0)
+ value = "&DESKTOP";
+ else if (g_strcmp0 (path, get_user_special_dir_if_not_home (G_USER_DIRECTORY_DOCUMENTS)) == 0)
+ value = "&DOCUMENTS";
+ else if (g_strcmp0 (path, get_user_special_dir_if_not_home (G_USER_DIRECTORY_DOWNLOAD)) == 0)
+ value = "&DOWNLOAD";
+ else if (g_strcmp0 (path, get_user_special_dir_if_not_home (G_USER_DIRECTORY_MUSIC)) == 0)
+ value = "&MUSIC";
+ else if (g_strcmp0 (path, get_user_special_dir_if_not_home (G_USER_DIRECTORY_PICTURES)) == 0)
+ value = "&PICTURES";
+ else if (g_strcmp0 (path, get_user_special_dir_if_not_home (G_USER_DIRECTORY_PUBLIC_SHARE)) == 0)
+ value = "&PUBLIC_SHARE";
+ else if (g_strcmp0 (path, get_user_special_dir_if_not_home (G_USER_DIRECTORY_TEMPLATES)) == 0)
+ value = "&TEMPLATES";
+ else if (g_strcmp0 (path, get_user_special_dir_if_not_home (G_USER_DIRECTORY_VIDEOS)) == 0)
+ value = "&VIDEOS";
+ else if (g_strcmp0 (path, g_get_home_dir ()) == 0)
+ value = "$HOME";
+ else
+ value = path;
+
+ return value;
+}
+
+static const gchar *
+path_from_tracker_dir (const gchar *value)
+{
+ const gchar *path;
+
+ if (g_strcmp0 (value, "&DESKTOP") == 0)
+ path = get_user_special_dir_if_not_home (G_USER_DIRECTORY_DESKTOP);
+ else if (g_strcmp0 (value, "&DOCUMENTS") == 0)
+ path = get_user_special_dir_if_not_home (G_USER_DIRECTORY_DOCUMENTS);
+ else if (g_strcmp0 (value, "&DOWNLOAD") == 0)
+ path = get_user_special_dir_if_not_home (G_USER_DIRECTORY_DOWNLOAD);
+ else if (g_strcmp0 (value, "&MUSIC") == 0)
+ path = get_user_special_dir_if_not_home (G_USER_DIRECTORY_MUSIC);
+ else if (g_strcmp0 (value, "&PICTURES") == 0)
+ path = get_user_special_dir_if_not_home (G_USER_DIRECTORY_PICTURES);
+ else if (g_strcmp0 (value, "&PUBLIC_SHARE") == 0)
+ path = get_user_special_dir_if_not_home (G_USER_DIRECTORY_PUBLIC_SHARE);
+ else if (g_strcmp0 (value, "&TEMPLATES") == 0)
+ path = get_user_special_dir_if_not_home (G_USER_DIRECTORY_TEMPLATES);
+ else if (g_strcmp0 (value, "&VIDEOS") == 0)
+ path = get_user_special_dir_if_not_home (G_USER_DIRECTORY_VIDEOS);
+ else if (g_strcmp0 (value, "$HOME") == 0)
+ path = g_get_home_dir ();
+ else
+ path = value;
+
+ return path;
+}
+
+static GPtrArray *
+place_get_new_settings_values (CcSearchLocationsDialog *self,
+ Place *place,
+ gboolean remove)
+{
+ g_auto(GStrv) values = NULL;
+ g_autofree gchar *path = NULL;
+ GPtrArray *new_values;
+ const gchar *tracker_dir;
+ gboolean found;
+ gint idx;
+
+ new_values = g_ptr_array_new_with_free_func (g_free);
+ values = g_settings_get_strv (self->tracker_preferences, place->settings_key);
+ path = g_file_get_path (place->location);
+ tracker_dir = path_to_tracker_dir (path);
+
+ found = FALSE;
+
+ for (idx = 0; values[idx] != NULL; idx++)
+ {
+ if (g_strcmp0 (values[idx], tracker_dir) == 0)
+ {
+ found = TRUE;
+
+ if (remove)
+ continue;
+ }
+
+ g_ptr_array_add (new_values, g_strdup (values[idx]));
+ }
+
+ if (!found && !remove)
+ g_ptr_array_add (new_values, g_strdup (tracker_dir));
+
+ g_ptr_array_add (new_values, NULL);
+
+ return new_values;
+}
+
+
+static GList *
+get_tracker_locations (CcSearchLocationsDialog *self)
+{
+ g_auto(GStrv) locations = NULL;
+ GFile *file;
+ GList *list;
+ gint idx;
+ Place *location;
+ const gchar *path;
+
+ locations = g_settings_get_strv (self->tracker_preferences, TRACKER_KEY_RECURSIVE_DIRECTORIES);
+ list = NULL;
+
+ for (idx = 0; locations[idx] != NULL; idx++)
+ {
+ path = path_from_tracker_dir (locations[idx]);
+
+ file = g_file_new_for_commandline_arg (path);
+ location = place_new (self,
+ file,
+ NULL,
+ PLACE_OTHER);
+
+ if (file != NULL && g_file_query_exists (file, NULL))
+ {
+ list = g_list_prepend (list, location);
+ }
+ else
+ {
+ g_autoptr(GPtrArray) new_values = NULL;
+
+ new_values = place_get_new_settings_values (self, location, TRUE);
+ g_settings_set_strv (self->tracker_preferences,
+ TRACKER_KEY_RECURSIVE_DIRECTORIES,
+ (const gchar **) new_values->pdata);
+ }
+ }
+
+ return g_list_reverse (list);
+}
+
+static GList *
+get_places_list (CcSearchLocationsDialog *self)
+{
+ g_autoptr(GList) xdg_list = NULL;
+ g_autoptr(GList) tracker_list = NULL;
+ g_autoptr(GList) bookmark_list = NULL;
+ GList *l;
+ g_autoptr(GHashTable) places = NULL;
+ Place *place, *old_place;
+ GList *places_list;
+
+ places = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, NULL, (GDestroyNotify) place_free);
+
+ /* add home */
+ place = place_new (self,
+ g_file_new_for_path (g_get_home_dir ()),
+ g_strdup (_("Home")),
+ PLACE_XDG);
+ g_hash_table_insert (places, place->location, place);
+
+ /* first, load the XDG dirs */
+ xdg_list = get_xdg_dirs (self);
+ for (l = xdg_list; l != NULL; l = l->next)
+ {
+ place = l->data;
+ g_hash_table_insert (places, place->location, place);
+ }
+
+ /* then, insert all the tracker locations that are not XDG dirs */
+ tracker_list = get_tracker_locations (self);
+ for (l = tracker_list; l != NULL; l = l->next)
+ {
+ g_autoptr(Place) p = l->data;
+ old_place = g_hash_table_lookup (places, p->location);
+ if (old_place == NULL)
+ {
+ g_hash_table_insert (places, p->location, p);
+ g_steal_pointer (&p);
+ }
+ }
+
+ /* finally, load bookmarks, and possibly update attributes */
+ bookmark_list = get_bookmarks (self);
+ for (l = bookmark_list; l != NULL; l = l->next)
+ {
+ g_autoptr(Place) p = l->data;
+ old_place = g_hash_table_lookup (places, p->location);
+ if (old_place == NULL)
+ {
+ g_hash_table_insert (places, p->location, p);
+ g_steal_pointer (&p);
+ }
+ else
+ {
+ g_free (old_place->display_name);
+ old_place->display_name = g_strdup (p->display_name);
+
+ if (old_place->place_type == PLACE_OTHER)
+ old_place->place_type = PLACE_BOOKMARKS;
+ }
+ }
+
+ places_list = g_hash_table_get_values (places);
+ g_hash_table_steal_all (places);
+
+ return places_list;
+}
+
+static gboolean
+switch_tracker_get_mapping (GValue *value,
+ GVariant *variant,
+ gpointer user_data)
+{
+ Place *place = user_data;
+ g_autofree const gchar **locations = NULL;
+ GFile *location;
+ gint idx;
+ gboolean found;
+
+ found = FALSE;
+ locations = g_variant_get_strv (variant, NULL);
+ for (idx = 0; locations[idx] != NULL; idx++)
+ {
+ location = g_file_new_for_path (path_from_tracker_dir(locations[idx]));
+ found = g_file_equal (location, place->location);
+ g_object_unref (location);
+
+ if (found)
+ break;
+ }
+
+ g_value_set_boolean (value, found);
+ return TRUE;
+}
+
+static GVariant *
+switch_tracker_set_mapping (const GValue *value,
+ const GVariantType *expected_type,
+ gpointer user_data)
+{
+ Place *place = user_data;
+ g_autoptr(GPtrArray) new_values = NULL;
+ gboolean remove;
+
+ remove = !g_value_get_boolean (value);
+ new_values = place_get_new_settings_values (place->dialog, place, remove);
+ return g_variant_new_strv ((const gchar **) new_values->pdata, -1);
+}
+
+static void
+place_query_info_ready (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GFileInfo) info = NULL;
+ PlaceRowWidgets *widgets;
+ Place *place;
+
+ info = g_file_query_info_finish (G_FILE (source), res, NULL);
+ if (!info)
+ return;
+
+ widgets = user_data;
+ place = g_object_get_data (G_OBJECT (widgets->row), "place");
+ g_clear_object (&place->cancellable);
+
+ gtk_widget_set_visible (widgets->switch_, TRUE);
+ g_settings_bind_with_mapping (place->dialog->tracker_preferences, place->settings_key,
+ widgets->switch_, "active",
+ G_SETTINGS_BIND_DEFAULT,
+ switch_tracker_get_mapping,
+ switch_tracker_set_mapping,
+ place, NULL);
+
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (widgets->row),
+ place->display_name);
+}
+
+static void
+remove_button_clicked (CcSearchLocationsDialog *self,
+ GtkWidget *button)
+{
+ g_autoptr(GPtrArray) new_values = NULL;
+ Place *place;
+
+ place = g_object_get_data (G_OBJECT (button), "place");
+ new_values = place_get_new_settings_values (self, place, TRUE);
+ g_settings_set_strv (self->tracker_preferences, place->settings_key, (const gchar **) new_values->pdata);
+}
+
+static gint
+place_compare_func (gconstpointer a,
+ gconstpointer b,
+ gpointer user_data)
+{
+ GtkWidget *child_a, *child_b;
+ Place *place_a, *place_b;
+ g_autofree gchar *path = NULL;
+ gboolean is_home;
+
+ child_a = GTK_WIDGET (a);
+ child_b = GTK_WIDGET (b);
+
+ place_a = g_object_get_data (G_OBJECT (child_a), "place");
+ place_b = g_object_get_data (G_OBJECT (child_b), "place");
+
+ path = g_file_get_path (place_a->location);
+ is_home = (g_strcmp0 (path, g_get_home_dir ()) == 0);
+
+ if (is_home)
+ return -1;
+
+ if (place_a->place_type == place_b->place_type)
+ return g_utf8_collate (place_a->display_name, place_b->display_name);
+
+ if (place_a->place_type == PLACE_XDG)
+ return -1;
+
+ if ((place_a->place_type == PLACE_BOOKMARKS) && (place_b->place_type == PLACE_OTHER))
+ return -1;
+
+ return 1;
+}
+
+static GtkWidget *
+create_row_for_place (CcSearchLocationsDialog *self, Place *place)
+{
+ PlaceRowWidgets *widgets;
+ GtkWidget *remove_button, *separator;
+
+ widgets = g_new0 (PlaceRowWidgets, 1);
+
+ widgets->row = adw_action_row_new ();
+ widgets->switch_ = gtk_switch_new ();
+
+ gtk_widget_set_visible (widgets->switch_, FALSE);
+ gtk_widget_set_valign (widgets->switch_, GTK_ALIGN_CENTER);
+ adw_action_row_add_suffix (ADW_ACTION_ROW (widgets->row), widgets->switch_);
+ adw_action_row_set_activatable_widget (ADW_ACTION_ROW (widgets->row), widgets->switch_);
+
+ g_object_set_data_full (G_OBJECT (widgets->row), "place", place, (GDestroyNotify) place_free);
+
+ if (place->place_type == PLACE_OTHER)
+ {
+ separator = gtk_separator_new (GTK_ORIENTATION_VERTICAL);
+ gtk_widget_set_margin_top (separator, 12);
+ gtk_widget_set_margin_bottom (separator, 12);
+ adw_action_row_add_suffix (ADW_ACTION_ROW (widgets->row), separator);
+
+ remove_button = gtk_button_new_from_icon_name ("window-close-symbolic");
+ g_object_set_data (G_OBJECT (remove_button), "place", place);
+ gtk_widget_set_valign (remove_button, GTK_ALIGN_CENTER);
+ gtk_style_context_add_class (gtk_widget_get_style_context (remove_button), "flat");
+ adw_action_row_add_suffix (ADW_ACTION_ROW (widgets->row), remove_button);
+
+ g_signal_connect_swapped (remove_button, "clicked",
+ G_CALLBACK (remove_button_clicked), self);
+ }
+
+ place->cancellable = g_cancellable_new ();
+ g_file_query_info_async (place->location, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
+ G_FILE_QUERY_INFO_NONE, G_PRIORITY_DEFAULT,
+ place->cancellable, place_query_info_ready, widgets);
+
+ return widgets->row;
+}
+
+static void
+update_list_visibility (CcSearchLocationsDialog *self)
+{
+ gtk_widget_set_visible (self->places_group,
+ gtk_list_box_get_row_at_index (GTK_LIST_BOX (self->places_list), 0)
+ != NULL);
+ gtk_widget_set_visible (self->bookmarks_group,
+ gtk_list_box_get_row_at_index (GTK_LIST_BOX (self->bookmarks_list), 0)
+ != NULL);
+ gtk_widget_set_visible (self->others_list,
+ gtk_list_box_get_row_at_index (GTK_LIST_BOX (self->others_list), 0)
+ != NULL);
+}
+
+static void
+populate_list_boxes (CcSearchLocationsDialog *self)
+{
+ g_autoptr(GList) places = NULL;
+ GList *l;
+ Place *place;
+ GtkWidget *row;
+
+ places = get_places_list (self);
+ for (l = places; l != NULL; l = l->next)
+ {
+ place = l->data;
+ row = create_row_for_place (self, place);
+
+ switch (place->place_type)
+ {
+ case PLACE_XDG:
+ gtk_list_box_append (GTK_LIST_BOX (self->places_list), row);
+ break;
+ case PLACE_BOOKMARKS:
+ gtk_list_box_append (GTK_LIST_BOX (self->bookmarks_list), row);
+ break;
+ case PLACE_OTHER:
+ gtk_list_box_append (GTK_LIST_BOX (self->others_list), row);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ }
+
+ update_list_visibility (self);
+}
+
+static void
+add_file_chooser_response (CcSearchLocationsDialog *self,
+ GtkResponseType response,
+ GtkWidget *widget)
+{
+ g_autoptr(Place) place = NULL;
+ g_autoptr(GPtrArray) new_values = NULL;
+
+ if (response != GTK_RESPONSE_OK)
+ {
+ gtk_window_destroy (GTK_WINDOW (widget));
+ return;
+ }
+
+ place = place_new (self,
+ gtk_file_chooser_get_file (GTK_FILE_CHOOSER (widget)),
+ NULL,
+ 0);
+
+ place->settings_key = TRACKER_KEY_RECURSIVE_DIRECTORIES;
+
+ new_values = place_get_new_settings_values (self, place, FALSE);
+ g_settings_set_strv (self->tracker_preferences, place->settings_key, (const gchar **) new_values->pdata);
+
+ gtk_window_destroy (GTK_WINDOW (widget));
+}
+
+static void
+add_button_clicked (CcSearchLocationsDialog *self)
+{
+ GtkWidget *file_chooser;
+
+ file_chooser = gtk_file_chooser_dialog_new (_("Select Location"),
+ GTK_WINDOW (self),
+ GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_OK"), GTK_RESPONSE_OK,
+ NULL);
+ gtk_window_set_modal (GTK_WINDOW (file_chooser), TRUE);
+ g_signal_connect_swapped (file_chooser, "response",
+ G_CALLBACK (add_file_chooser_response), self);
+ gtk_window_present (GTK_WINDOW (file_chooser));
+}
+
+static void
+other_places_refresh (CcSearchLocationsDialog *self)
+{
+ g_autoptr(GList) places = NULL;
+ GList *l;
+ GtkListBoxRow *widget;
+
+ while ((widget = gtk_list_box_get_row_at_index (GTK_LIST_BOX (self->others_list), 0)))
+ gtk_list_box_remove (GTK_LIST_BOX (self->others_list), GTK_WIDGET (widget));
+
+ places = get_places_list (self);
+ for (l = places; l != NULL; l = l->next)
+ {
+ GtkWidget *row;
+ Place *place;
+
+ place = l->data;
+ if (place->place_type != PLACE_OTHER)
+ continue;
+
+ row = create_row_for_place (self, place);
+ gtk_list_box_append (GTK_LIST_BOX (self->others_list), row);
+ }
+
+ update_list_visibility (self);
+}
+
+CcSearchLocationsDialog *
+cc_search_locations_dialog_new (CcSearchPanel *panel)
+{
+ CcSearchLocationsDialog *self;
+ GSettingsSchemaSource *source;
+ g_autoptr(GSettingsSchema) schema = NULL;
+ GtkWidget *toplevel;
+ CcShell *shell;
+
+ self = g_object_new (CC_SEARCH_LOCATIONS_DIALOG_TYPE, NULL);
+
+ source = g_settings_schema_source_get_default ();
+ schema = g_settings_schema_source_lookup (source, TRACKER3_SCHEMA, TRUE);
+ if (schema)
+ self->tracker_preferences = g_settings_new (TRACKER3_SCHEMA);
+ else
+ self->tracker_preferences = g_settings_new (TRACKER_SCHEMA);
+
+ populate_list_boxes (self);
+
+ gtk_list_box_set_sort_func (GTK_LIST_BOX (self->others_list),
+ (GtkListBoxSortFunc)place_compare_func, NULL, NULL);
+
+ g_signal_connect_swapped (self->tracker_preferences, "changed::" TRACKER_KEY_RECURSIVE_DIRECTORIES,
+ G_CALLBACK (other_places_refresh), self);
+
+ shell = cc_panel_get_shell (CC_PANEL (panel));
+ toplevel = cc_shell_get_toplevel (shell);
+ gtk_window_set_transient_for (GTK_WINDOW (self), GTK_WINDOW (toplevel));
+
+ return self;
+}
+
+gboolean
+cc_search_locations_dialog_is_available (void)
+{
+ GSettingsSchemaSource *source;
+ g_autoptr(GSettingsSchema) schema = NULL;
+
+ source = g_settings_schema_source_get_default ();
+ if (!source)
+ return FALSE;
+
+ schema = g_settings_schema_source_lookup (source, TRACKER3_SCHEMA, TRUE);
+ if (schema)
+ return TRUE;
+
+ schema = g_settings_schema_source_lookup (source, TRACKER_SCHEMA, TRUE);
+ if (schema)
+ return TRUE;
+
+ return FALSE;
+}
+
+static void
+cc_search_locations_dialog_class_init (CcSearchLocationsDialogClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = cc_search_locations_dialog_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/control-center/search/cc-search-locations-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcSearchLocationsDialog, places_group);
+ gtk_widget_class_bind_template_child (widget_class, CcSearchLocationsDialog, places_list);
+ gtk_widget_class_bind_template_child (widget_class, CcSearchLocationsDialog, bookmarks_group);
+ gtk_widget_class_bind_template_child (widget_class, CcSearchLocationsDialog, bookmarks_list);
+ gtk_widget_class_bind_template_child (widget_class, CcSearchLocationsDialog, others_list);
+ gtk_widget_class_bind_template_child (widget_class, CcSearchLocationsDialog, locations_add);
+
+ gtk_widget_class_bind_template_callback (widget_class, add_button_clicked);
+ gtk_widget_class_bind_template_callback (widget_class, keynav_failed_cb);
+}
diff --git a/panels/search/cc-search-locations-dialog.h b/panels/search/cc-search-locations-dialog.h
new file mode 100644
index 0000000..4e2b5b3
--- /dev/null
+++ b/panels/search/cc-search-locations-dialog.h
@@ -0,0 +1,30 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Cosimo Cecchi <cosimoc@gnome.org>
+ */
+
+#pragma once
+
+#include "cc-search-panel.h"
+
+#define CC_SEARCH_LOCATIONS_DIALOG_TYPE (cc_search_locations_dialog_get_type ())
+G_DECLARE_FINAL_TYPE (CcSearchLocationsDialog, cc_search_locations_dialog, CC, SEARCH_LOCATIONS_DIALOG, AdwPreferencesWindow)
+
+CcSearchLocationsDialog *cc_search_locations_dialog_new (CcSearchPanel *panel);
+
+gboolean cc_search_locations_dialog_is_available (void);
diff --git a/panels/search/cc-search-locations-dialog.ui b/panels/search/cc-search-locations-dialog.ui
new file mode 100644
index 0000000..20ad732
--- /dev/null
+++ b/panels/search/cc-search-locations-dialog.ui
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcSearchLocationsDialog" parent="AdwPreferencesWindow">
+ <property name="modal">True</property>
+ <property name="hide-on-close">True</property>
+ <property name="search-enabled">False</property>
+ <property name="title" translatable="yes">Search Locations</property>
+ <child>
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="description" translatable="yes">Folders which are searched by system applications, such as Files, Photos and Videos.</property>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup" id="places_group">
+ <property name="title" translatable="yes">Places</property>
+ <child>
+ <object class="GtkListBox" id="places_list">
+ <property name="selection-mode">none</property>
+ <signal name="keynav-failed" handler="keynav_failed_cb" object="CcSearchLocationsDialog" swapped="yes"/>
+ <accessibility>
+ <relation name="labelled-by">places_group</relation>
+ </accessibility>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup" id="bookmarks_group">
+ <property name="title" translatable="yes">Bookmarks</property>
+ <child>
+ <object class="GtkListBox" id="bookmarks_list">
+ <property name="selection-mode">none</property>
+ <signal name="keynav-failed" handler="keynav_failed_cb" object="CcSearchLocationsDialog" swapped="yes"/>
+ <accessibility>
+ <relation name="labelled-by">bookmarks_group</relation>
+ </accessibility>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup" id="others_group">
+ <property name="title" translatable="yes">Others</property>
+ <property name="header-suffix">
+ <object class="GtkButton" id="locations_add">
+ <property name="valign">center</property>
+ <property name="child">
+ <object class="AdwButtonContent">
+ <property name="icon-name">list-add-symbolic</property>
+ <property name="label" translatable="yes">Add Location</property>
+ </object>
+ </property>
+ <signal name="clicked" handler="add_button_clicked" object="CcSearchLocationsDialog" swapped="yes"/>
+ <style>
+ <class name="flat"/>
+ </style>
+ </object>
+ </property>
+ <child>
+ <object class="GtkListBox" id="others_list">
+ <property name="selection-mode">none</property>
+ <signal name="keynav-failed" handler="keynav_failed_cb" object="CcSearchLocationsDialog" swapped="yes"/>
+ <accessibility>
+ <relation name="labelled-by">others_group</relation>
+ </accessibility>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/search/cc-search-panel-row.c b/panels/search/cc-search-panel-row.c
new file mode 100644
index 0000000..7cae2a3
--- /dev/null
+++ b/panels/search/cc-search-panel-row.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright © 2019 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Felipe Borges <felipeborges@gnome.org>
+ */
+
+#include "cc-search-panel-row.h"
+
+struct _CcSearchPanelRow
+{
+ AdwActionRow parent_instance;
+
+ GAppInfo *app_info;
+
+ GtkImage *icon;
+ GtkSwitch *switcher;
+
+ GtkListBox *drag_widget;
+ gdouble drag_x;
+ gdouble drag_y;
+};
+
+G_DEFINE_TYPE (CcSearchPanelRow, cc_search_panel_row, ADW_TYPE_ACTION_ROW)
+
+enum
+{
+ SIGNAL_MOVE_ROW,
+ SIGNAL_LAST
+};
+
+static guint signals[SIGNAL_LAST] = { 0, };
+
+static void
+move_up_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ CcSearchPanelRow *self = CC_SEARCH_PANEL_ROW (user_data);
+ GtkListBox *list_box = GTK_LIST_BOX (gtk_widget_get_parent (GTK_WIDGET (self)));
+ gint previous_idx = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (self)) - 1;
+ GtkListBoxRow *previous_row = gtk_list_box_get_row_at_index (list_box, previous_idx);
+
+ if (previous_row == NULL)
+ return;
+
+ g_signal_emit (self,
+ signals[SIGNAL_MOVE_ROW],
+ 0,
+ previous_row);
+}
+
+static void
+move_down_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ CcSearchPanelRow *self = CC_SEARCH_PANEL_ROW (user_data);
+ GtkListBox *list_box = GTK_LIST_BOX (gtk_widget_get_parent (GTK_WIDGET (self)));
+ gint next_idx = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (self)) + 1;
+ GtkListBoxRow *next_row = gtk_list_box_get_row_at_index (list_box, next_idx);
+
+ if (next_row == NULL)
+ return;
+
+ g_signal_emit (next_row,
+ signals[SIGNAL_MOVE_ROW],
+ 0,
+ self);
+}
+
+static GdkContentProvider *
+drag_prepare_cb (GtkDragSource *source,
+ double x,
+ double y,
+ CcSearchPanelRow *self)
+{
+ self->drag_x = x;
+ self->drag_y = y;
+
+ return gdk_content_provider_new_typed (CC_TYPE_SEARCH_PANEL_ROW, self);
+}
+
+static void
+drag_begin_cb (GtkDragSource *source,
+ GdkDrag *drag,
+ CcSearchPanelRow *self)
+{
+ CcSearchPanelRow *panel_row;
+ GtkAllocation alloc;
+ GtkWidget *drag_icon;
+
+ gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);
+
+ self->drag_widget = GTK_LIST_BOX (gtk_list_box_new ());
+ gtk_widget_set_size_request (GTK_WIDGET (self->drag_widget), alloc.width, alloc.height);
+
+ panel_row = cc_search_panel_row_new (self->app_info);
+ gtk_switch_set_active (panel_row->switcher, gtk_switch_get_active (self->switcher));
+
+ gtk_list_box_append (GTK_LIST_BOX (self->drag_widget), GTK_WIDGET (panel_row));
+ gtk_list_box_drag_highlight_row (self->drag_widget, GTK_LIST_BOX_ROW (panel_row));
+
+ drag_icon = gtk_drag_icon_get_for_drag (drag);
+ gtk_drag_icon_set_child (GTK_DRAG_ICON (drag_icon), GTK_WIDGET (self->drag_widget));
+ gdk_drag_set_hotspot (drag, self->drag_x, self->drag_y);
+
+}
+
+static gboolean
+drop_cb (GtkDropTarget *drop_target,
+ const GValue *value,
+ gdouble x,
+ gdouble y,
+ CcSearchPanelRow *self)
+{
+ CcSearchPanelRow *source;
+
+ g_message ("Drop");
+
+ if (!G_VALUE_HOLDS (value, CC_TYPE_SEARCH_PANEL_ROW))
+ return FALSE;
+
+ source = g_value_get_object (value);
+
+ g_signal_emit (source,
+ signals[SIGNAL_MOVE_ROW],
+ 0,
+ self);
+
+ return TRUE;
+}
+
+static void
+cc_search_panel_row_class_init (CcSearchPanelRowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/search/cc-search-panel-row.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcSearchPanelRow, icon);
+ gtk_widget_class_bind_template_child (widget_class, CcSearchPanelRow, switcher);
+
+ signals[SIGNAL_MOVE_ROW] =
+ g_signal_new ("move-row",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE,
+ 1, CC_TYPE_SEARCH_PANEL_ROW);
+}
+
+const GActionEntry row_entries[] = {
+ { "move-up", move_up_cb, NULL, NULL, NULL, { 0 } },
+ { "move-down", move_down_cb, NULL, NULL, NULL, { 0 } }
+};
+
+static void
+cc_search_panel_row_init (CcSearchPanelRow *self)
+{
+ GtkDragSource *drag_source;
+ GtkDropTarget *drop_target;
+ GSimpleActionGroup *group;
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ drag_source = gtk_drag_source_new ();
+ gtk_drag_source_set_actions (drag_source, GDK_ACTION_MOVE);
+ g_signal_connect (drag_source, "prepare", G_CALLBACK (drag_prepare_cb), self);
+ g_signal_connect (drag_source, "drag-begin", G_CALLBACK (drag_begin_cb), self);
+ gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (drag_source));
+
+ drop_target = gtk_drop_target_new (CC_TYPE_SEARCH_PANEL_ROW, GDK_ACTION_MOVE);
+ gtk_drop_target_set_preload (drop_target, TRUE);
+ g_signal_connect (drop_target, "drop", G_CALLBACK (drop_cb), self);
+ gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (drop_target));
+
+ group = g_simple_action_group_new ();
+ g_action_map_add_action_entries (G_ACTION_MAP (group),
+ row_entries,
+ G_N_ELEMENTS (row_entries),
+ self);
+ gtk_widget_insert_action_group (GTK_WIDGET (self), "row", G_ACTION_GROUP (group));
+}
+
+CcSearchPanelRow *
+cc_search_panel_row_new (GAppInfo *app_info)
+{
+ CcSearchPanelRow *self;
+ g_autoptr(GIcon) gicon = NULL;
+
+ self = g_object_new (CC_TYPE_SEARCH_PANEL_ROW, NULL);
+ self->app_info = g_object_ref (app_info);
+
+ gicon = g_app_info_get_icon (app_info);
+ if (gicon == NULL)
+ gicon = g_themed_icon_new ("application-x-executable");
+ else
+ g_object_ref (gicon);
+ gtk_image_set_from_gicon (self->icon, gicon);
+
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self),
+ g_app_info_get_name (app_info));
+
+ return self;
+}
+
+GAppInfo *
+cc_search_panel_row_get_app_info (CcSearchPanelRow *self)
+{
+ return self->app_info;
+}
+
+GtkWidget *
+cc_search_panel_row_get_switch (CcSearchPanelRow *self)
+{
+ return GTK_WIDGET (self->switcher);
+}
diff --git a/panels/search/cc-search-panel-row.h b/panels/search/cc-search-panel-row.h
new file mode 100644
index 0000000..f7bae83
--- /dev/null
+++ b/panels/search/cc-search-panel-row.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2019 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Felipe Borges <felipeborges@gnome.org>
+ */
+
+#pragma once
+
+#include <gio/gdesktopappinfo.h>
+#include <adwaita.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_SEARCH_PANEL_ROW (cc_search_panel_row_get_type())
+
+G_DECLARE_FINAL_TYPE (CcSearchPanelRow, cc_search_panel_row, CC, SEARCH_PANEL_ROW, AdwActionRow)
+
+
+CcSearchPanelRow *cc_search_panel_row_new (GAppInfo *app_info);
+
+GAppInfo *cc_search_panel_row_get_app_info (CcSearchPanelRow *row);
+
+GtkWidget *cc_search_panel_row_get_switch (CcSearchPanelRow *row);
+
+G_END_DECLS
diff --git a/panels/search/cc-search-panel-row.ui b/panels/search/cc-search-panel-row.ui
new file mode 100644
index 0000000..89e74ae
--- /dev/null
+++ b/panels/search/cc-search-panel-row.ui
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcSearchPanelRow" parent="AdwActionRow">
+ <property name="activatable-widget">switcher</property>
+ <child type="prefix">
+ <object class="GtkImage" id="icon">
+ <property name="icon-size">large</property>
+ <style>
+ <class name="lowres-icon"/>
+ </style>
+ </object>
+ </child>
+ <child type="prefix">
+ <object class="GtkImage">
+ <property name="icon-name">list-drag-handle-symbolic</property>
+ <style>
+ <class name="drag-handle"/>
+ </style>
+ </object>
+ </child>
+ <child type="suffix">
+ <object class="GtkSwitch" id="switcher">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ <child type="suffix">
+ <object class="GtkSeparator">
+ <property name="orientation">vertical</property>
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ </object>
+ </child>
+ <child type="suffix">
+ <object class="GtkMenuButton">
+ <property name="valign">center</property>
+ <property name="icon-name">view-more-symbolic</property>
+ <property name="menu-model">move_row_menu</property>
+ <accessibility>
+ <property name="label" translatable="yes">More options…</property>
+ </accessibility>
+ <style>
+ <class name="flat"/>
+ </style>
+ </object>
+ </child>
+ </template>
+
+ <!-- Move Row Menu -->
+ <menu id="move_row_menu">
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">Move Up</attribute>
+ <attribute name="action">row.move-up</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Move Down</attribute>
+ <attribute name="action">row.move-down</attribute>
+ </item>
+ </section>
+ </menu>
+</interface>
diff --git a/panels/search/cc-search-panel.c b/panels/search/cc-search-panel.c
new file mode 100644
index 0000000..80c8c94
--- /dev/null
+++ b/panels/search/cc-search-panel.c
@@ -0,0 +1,683 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Cosimo Cecchi <cosimoc@gnome.org>
+ */
+
+#include "cc-search-panel.h"
+#include "cc-search-panel-row.h"
+#include "cc-search-locations-dialog.h"
+#include "cc-search-resources.h"
+
+#include <gio/gdesktopappinfo.h>
+#include <glib/gi18n.h>
+
+struct _CcSearchPanel
+{
+ CcPanel parent_instance;
+
+ GtkWidget *list_box;
+ GtkSwitch *main_switch;
+ GtkWidget *search_group;
+ GtkWidget *settings_row;
+ CcSearchPanelRow *selected_row;
+
+ GSettings *search_settings;
+ GHashTable *sort_order;
+
+ CcSearchLocationsDialog *locations_dialog;
+};
+
+CC_PANEL_REGISTER (CcSearchPanel, cc_search_panel)
+
+#define SHELL_PROVIDER_GROUP "Shell Search Provider"
+
+static gboolean
+keynav_failed_cb (CcSearchPanel *self, GtkDirectionType direction, GtkWidget *list)
+{
+ GtkWidget *toplevel = GTK_WIDGET (gtk_widget_get_root (GTK_WIDGET (self)));
+
+ if (!toplevel)
+ return FALSE;
+
+ if (direction != GTK_DIR_UP && direction != GTK_DIR_DOWN)
+ return FALSE;
+
+ return gtk_widget_child_focus (toplevel, direction == GTK_DIR_UP ?
+ GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD);
+}
+
+static gint
+list_sort_func (gconstpointer a,
+ gconstpointer b,
+ gpointer user_data)
+{
+ CcSearchPanel *self = user_data;
+ GAppInfo *app_a, *app_b;
+ const gchar *id_a, *id_b;
+ gint idx_a, idx_b;
+ gpointer lookup;
+
+ app_a = cc_search_panel_row_get_app_info (CC_SEARCH_PANEL_ROW ((gpointer*)a));
+ app_b = cc_search_panel_row_get_app_info (CC_SEARCH_PANEL_ROW ((gpointer*)b));
+
+ id_a = g_app_info_get_id (app_a);
+ id_b = g_app_info_get_id (app_b);
+
+ /* find the index of the application in the GSettings preferences */
+ idx_a = -1;
+ idx_b = -1;
+
+ lookup = g_hash_table_lookup (self->sort_order, id_a);
+ if (lookup)
+ idx_a = GPOINTER_TO_INT (lookup) - 1;
+
+ lookup = g_hash_table_lookup (self->sort_order, id_b);
+ if (lookup)
+ idx_b = GPOINTER_TO_INT (lookup) - 1;
+
+ /* if neither app is found, use alphabetical order */
+ if ((idx_a == -1) && (idx_b == -1))
+ return g_utf8_collate (g_app_info_get_name (app_a), g_app_info_get_name (app_b));
+
+ /* if app_a isn't found, it's sorted after app_b */
+ if (idx_a == -1)
+ return 1;
+
+ /* if app_b isn't found, it's sorted after app_a */
+ if (idx_b == -1)
+ return -1;
+
+ /* finally, if both apps are found, return their order in the list */
+ return (idx_a - idx_b);
+}
+
+static void
+search_panel_invalidate_sort_order (CcSearchPanel *self)
+{
+ g_auto(GStrv) sort_order = NULL;
+ gint idx;
+
+ g_hash_table_remove_all (self->sort_order);
+ sort_order = g_settings_get_strv (self->search_settings, "sort-order");
+
+ for (idx = 0; sort_order[idx] != NULL; idx++)
+ g_hash_table_insert (self->sort_order, g_strdup (sort_order[idx]), GINT_TO_POINTER (idx + 1));
+
+ gtk_list_box_invalidate_sort (GTK_LIST_BOX (self->list_box));
+}
+
+static gint
+propagate_compare_func (gconstpointer a,
+ gconstpointer b,
+ gpointer user_data)
+{
+ CcSearchPanel *self = user_data;
+ const gchar *key_a = a, *key_b = b;
+ gint idx_a, idx_b;
+
+ idx_a = GPOINTER_TO_INT (g_hash_table_lookup (self->sort_order, key_a));
+ idx_b = GPOINTER_TO_INT (g_hash_table_lookup (self->sort_order, key_b));
+
+ return (idx_a - idx_b);
+}
+
+static void
+search_panel_propagate_sort_order (CcSearchPanel *self)
+{
+ g_autoptr(GList) keys = NULL;
+ GList *l;
+ g_autoptr(GPtrArray) sort_order = NULL;
+
+ sort_order = g_ptr_array_new ();
+ keys = g_hash_table_get_keys (self->sort_order);
+ keys = g_list_sort_with_data (keys, propagate_compare_func, self);
+
+ for (l = keys; l != NULL; l = l->next)
+ g_ptr_array_add (sort_order, l->data);
+
+ g_ptr_array_add (sort_order, NULL);
+ g_settings_set_strv (self->search_settings, "sort-order",
+ (const gchar **) sort_order->pdata);
+}
+
+static void
+search_panel_set_no_providers (CcSearchPanel *self)
+{
+ /* center the list box in the scrolled window */
+ gtk_widget_set_valign (self->list_box, GTK_ALIGN_CENTER);
+
+ gtk_list_box_append (GTK_LIST_BOX (self->list_box),
+ gtk_label_new (_("No applications found")));
+}
+
+static void
+search_panel_move_selected (CcSearchPanel *self,
+ gboolean down)
+{
+ GtkListBoxRow *other_row;
+ GAppInfo *app_info, *other_app_info;
+ const gchar *app_id, *other_app_id;
+ const gchar *last_good_app, *target_app;
+ GtkWidget *aux;
+ gint idx, other_idx;
+ gpointer idx_ptr;
+ gboolean found;
+
+ app_info = cc_search_panel_row_get_app_info (self->selected_row);
+ app_id = g_app_info_get_id (app_info);
+
+ /* The assertions are valid only as long as we don't move the first
+ or the last item. */
+
+ aux = GTK_WIDGET (self->selected_row);
+ other_row = down ? GTK_LIST_BOX_ROW (gtk_widget_get_next_sibling (aux)) :
+ GTK_LIST_BOX_ROW (gtk_widget_get_prev_sibling (aux));
+
+ other_app_info = cc_search_panel_row_get_app_info (CC_SEARCH_PANEL_ROW (other_row));
+ other_app_id = g_app_info_get_id (other_app_info);
+
+ g_assert (other_app_id != NULL);
+
+ /* Check if we're moving one of the unsorted providers at the end of
+ the list; in that case, the value we obtain from the sort order table
+ is garbage.
+ We need to find the last app with a valid sort order, and
+ then set the sort order on all intermediate apps until we find the
+ one we want to move, if moving up, or the neighbor, if moving down.
+ */
+ last_good_app = target_app = app_id;
+ found = g_hash_table_lookup_extended (self->sort_order, last_good_app, NULL, &idx_ptr);
+ while (!found)
+ {
+ GAppInfo *tmp;
+ const char *tmp_id;
+
+ aux = gtk_widget_get_prev_sibling (aux);
+ if (aux == NULL)
+ {
+ last_good_app = NULL;
+ break;
+ }
+
+ tmp = cc_search_panel_row_get_app_info (CC_SEARCH_PANEL_ROW (aux));
+ tmp_id = g_app_info_get_id (tmp);
+
+ last_good_app = tmp_id;
+ found = g_hash_table_lookup_extended (self->sort_order, tmp_id, NULL, &idx_ptr);
+ }
+
+ /* For simplicity's sake, set all sort orders to the previously visible state
+ first, and only then do the modification requested.
+
+ The loop actually sets the sort order on last_good_app even if we found a
+ valid one already, but I preferred to keep the logic simple, at the expense
+ of a small performance penalty.
+ */
+ if (found)
+ {
+ idx = GPOINTER_TO_INT (idx_ptr);
+ }
+ else
+ {
+ /* If not found, there is no configured app that has a sort order, so we start
+ from the first position and walk the entire list.
+ Sort orders are 1 based, so that 0 (NULL) is not a valid value.
+ */
+ idx = 1;
+ aux = gtk_widget_get_first_child (GTK_WIDGET (self->list_box));
+ }
+
+ while (last_good_app != target_app)
+ {
+ GAppInfo *tmp;
+ const char *tmp_id;
+
+ tmp = cc_search_panel_row_get_app_info (CC_SEARCH_PANEL_ROW (aux));
+ tmp_id = g_app_info_get_id (tmp);
+
+ g_hash_table_replace (self->sort_order, g_strdup (tmp_id), GINT_TO_POINTER (idx));
+
+ aux = gtk_widget_get_next_sibling (aux);
+ idx++;
+ last_good_app = tmp_id;
+ }
+
+ other_idx = GPOINTER_TO_INT (g_hash_table_lookup (self->sort_order, app_id));
+ idx = down ? (other_idx + 1) : (other_idx - 1);
+
+ g_hash_table_replace (self->sort_order, g_strdup (other_app_id), GINT_TO_POINTER (other_idx));
+ g_hash_table_replace (self->sort_order, g_strdup (app_id), GINT_TO_POINTER (idx));
+
+ search_panel_propagate_sort_order (self);
+}
+
+static void
+row_moved_cb (CcSearchPanel *self,
+ CcSearchPanelRow *dest_row,
+ CcSearchPanelRow *row)
+{
+ gint source_idx = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (row));
+ gint dest_idx = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (dest_row));
+ gboolean down;
+
+ self->selected_row = row;
+
+ down = (source_idx - dest_idx) < 0;
+ for (int i = 0; i < ABS (source_idx - dest_idx); i++)
+ search_panel_move_selected (self, down);
+}
+
+static void
+settings_row_activated (GtkWidget *widget,
+ gpointer user_data)
+{
+ CcSearchPanel *self = user_data;
+
+ if (self->locations_dialog == NULL)
+ {
+ self->locations_dialog = cc_search_locations_dialog_new (self);
+ g_object_add_weak_pointer (G_OBJECT (self->locations_dialog),
+ (gpointer *) &self->locations_dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (self->locations_dialog));
+}
+
+static GVariant *
+switch_settings_mapping_set_generic (const GValue *value,
+ const GVariantType *expected_type,
+ GtkWidget *row,
+ gboolean default_enabled)
+{
+ CcSearchPanel *self = g_object_get_data (G_OBJECT (row), "self");
+ GAppInfo *app_info = cc_search_panel_row_get_app_info (CC_SEARCH_PANEL_ROW (row));
+ g_auto(GStrv) apps = NULL;
+ g_autoptr(GPtrArray) new_apps = NULL;
+ gint idx;
+ gboolean remove, found;
+
+ remove = !!g_value_get_boolean (value) == !!default_enabled;
+ found = FALSE;
+ new_apps = g_ptr_array_new_with_free_func (g_free);
+ apps = g_settings_get_strv (self->search_settings,
+ default_enabled ? "disabled" : "enabled");
+
+ for (idx = 0; apps[idx] != NULL; idx++)
+ {
+ if (g_strcmp0 (apps[idx], g_app_info_get_id (app_info)) == 0)
+ {
+ found = TRUE;
+
+ if (remove)
+ continue;
+ }
+
+ g_ptr_array_add (new_apps, g_strdup (apps[idx]));
+ }
+
+ if (!found && !remove)
+ g_ptr_array_add (new_apps, g_strdup (g_app_info_get_id (app_info)));
+
+ g_ptr_array_add (new_apps, NULL);
+
+ return g_variant_new_strv ((const gchar **) new_apps->pdata, -1);
+}
+
+static GVariant *
+switch_settings_mapping_set_default_enabled (const GValue *value,
+ const GVariantType *expected_type,
+ gpointer user_data)
+{
+ return switch_settings_mapping_set_generic (value, expected_type,
+ user_data, TRUE);
+}
+
+static GVariant *
+switch_settings_mapping_set_default_disabled (const GValue *value,
+ const GVariantType *expected_type,
+ gpointer user_data)
+{
+ return switch_settings_mapping_set_generic (value, expected_type,
+ user_data, FALSE);
+}
+
+static gboolean
+switch_settings_mapping_get_generic (GValue *value,
+ GVariant *variant,
+ GtkWidget *row,
+ gboolean default_enabled)
+{
+ GAppInfo *app_info = cc_search_panel_row_get_app_info (CC_SEARCH_PANEL_ROW (row));
+ g_autofree const gchar **apps = NULL;
+ gint idx;
+ gboolean found;
+
+ found = FALSE;
+ apps = g_variant_get_strv (variant, NULL);
+
+ for (idx = 0; apps[idx] != NULL; idx++)
+ {
+ if (g_strcmp0 (apps[idx], g_app_info_get_id (app_info)) == 0)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+
+ g_value_set_boolean (value, !!default_enabled != !!found);
+
+ return TRUE;
+}
+
+static gboolean
+switch_settings_mapping_get_default_enabled (GValue *value,
+ GVariant *variant,
+ gpointer user_data)
+{
+ return switch_settings_mapping_get_generic (value, variant,
+ user_data, TRUE);
+}
+
+static gboolean
+switch_settings_mapping_get_default_disabled (GValue *value,
+ GVariant *variant,
+ gpointer user_data)
+{
+ return switch_settings_mapping_get_generic (value, variant,
+ user_data, FALSE);
+}
+
+static void
+search_panel_add_one_app_info (CcSearchPanel *self,
+ GAppInfo *app_info,
+ gboolean default_enabled)
+{
+ CcSearchPanelRow *row;
+
+ /* gnome-control-center is special cased in the shell,
+ and is not configurable */
+ if (g_strcmp0 (g_app_info_get_id (app_info),
+ "gnome-control-center.desktop") == 0)
+ return;
+
+ /* reset valignment of the list box */
+ gtk_widget_set_valign (self->list_box, GTK_ALIGN_FILL);
+
+ row = cc_search_panel_row_new (app_info);
+ g_signal_connect_object (row, "move-row",
+ G_CALLBACK (row_moved_cb), self,
+ G_CONNECT_SWAPPED);
+ g_object_set_data (G_OBJECT (row), "self", self);
+ gtk_list_box_append (GTK_LIST_BOX (self->list_box), GTK_WIDGET (row));
+
+ if (default_enabled)
+ {
+ g_settings_bind_with_mapping (self->search_settings, "disabled",
+ cc_search_panel_row_get_switch (row), "active",
+ G_SETTINGS_BIND_DEFAULT,
+ switch_settings_mapping_get_default_enabled,
+ switch_settings_mapping_set_default_enabled,
+ row, NULL);
+ }
+ else
+ {
+ g_settings_bind_with_mapping (self->search_settings, "enabled",
+ cc_search_panel_row_get_switch (row), "active",
+ G_SETTINGS_BIND_DEFAULT,
+ switch_settings_mapping_get_default_disabled,
+ switch_settings_mapping_set_default_disabled,
+ row, NULL);
+ }
+}
+
+static void
+search_panel_add_one_provider (CcSearchPanel *self,
+ GFile *provider)
+{
+ g_autofree gchar *path = NULL;
+ g_autofree gchar *desktop_id = NULL;
+ g_autoptr(GKeyFile) keyfile = NULL;
+ g_autoptr(GAppInfo) app_info = NULL;
+ g_autoptr(GError) error = NULL;
+ gboolean default_disabled;
+
+ path = g_file_get_path (provider);
+ keyfile = g_key_file_new ();
+ g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, &error);
+
+ if (error != NULL)
+ {
+ g_warning ("Error loading %s: %s - search provider will be ignored",
+ path, error->message);
+ return;
+ }
+
+ if (!g_key_file_has_group (keyfile, SHELL_PROVIDER_GROUP))
+ {
+ g_debug ("Shell search provider group missing from '%s', ignoring", path);
+ return;
+ }
+
+ desktop_id = g_key_file_get_string (keyfile, SHELL_PROVIDER_GROUP,
+ "DesktopId", &error);
+
+ if (error != NULL)
+ {
+ g_warning ("Unable to read desktop ID from %s: %s - search provider will be ignored",
+ path, error->message);
+ return;
+ }
+
+ app_info = G_APP_INFO (g_desktop_app_info_new (desktop_id));
+
+ if (app_info == NULL)
+ {
+ g_debug ("Could not find application with desktop ID '%s' referenced in '%s', ignoring",
+ desktop_id, path);
+ return;
+ }
+
+ default_disabled = g_key_file_get_boolean (keyfile, SHELL_PROVIDER_GROUP,
+ "DefaultDisabled", NULL);
+ search_panel_add_one_app_info (self, app_info, !default_disabled);
+}
+
+static void
+search_providers_discover_ready (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(GList) providers = NULL;
+ GList *l;
+ CcSearchPanel *self = CC_SEARCH_PANEL (source);
+ g_autoptr(GError) error = NULL;
+
+ providers = g_task_propagate_pointer (G_TASK (result), &error);
+
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
+ if (providers == NULL)
+ {
+ search_panel_set_no_providers (self);
+ return;
+ }
+
+ for (l = providers; l != NULL; l = l->next)
+ {
+ g_autoptr(GFile) provider = l->data;
+ search_panel_add_one_provider (self, provider);
+ }
+
+ /* propagate a write to GSettings, to make sure we always have
+ * all the providers in the list.
+ */
+ search_panel_propagate_sort_order (self);
+}
+
+static GList *
+search_providers_discover_one_directory (const gchar *system_dir,
+ GCancellable *cancellable)
+{
+ GList *providers = NULL;
+ g_autofree gchar *providers_path = NULL;
+ g_autoptr(GFile) providers_location = NULL;
+ g_autoptr(GFileEnumerator) enumerator = NULL;
+ g_autoptr(GError) error = NULL;
+
+ providers_path = g_build_filename (system_dir, "gnome-shell", "search-providers", NULL);
+ providers_location = g_file_new_for_path (providers_path);
+
+ enumerator = g_file_enumerate_children (providers_location,
+ "standard::type,standard::name,standard::content-type",
+ G_FILE_QUERY_INFO_NONE,
+ cancellable, &error);
+
+ if (error != NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) &&
+ !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Error opening %s: %s - search provider configuration won't be possible",
+ providers_path, error->message);
+
+ return NULL;
+ }
+
+ while (TRUE)
+ {
+ g_autoptr(GFileInfo) info = NULL;
+ GFile *provider;
+
+ info = g_file_enumerator_next_file (enumerator, cancellable, &error);
+ if (info == NULL)
+ {
+ if (error != NULL && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Error reading from %s: %s - search providers might be missing from the panel",
+ providers_path, error->message);
+ return providers;
+ }
+ provider = g_file_get_child (providers_location, g_file_info_get_name (info));
+ providers = g_list_prepend (providers, provider);
+ }
+}
+
+static void
+search_providers_discover_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ GList *providers = NULL;
+ const gchar * const *system_data_dirs;
+ int idx;
+
+ system_data_dirs = g_get_system_data_dirs ();
+ for (idx = 0; system_data_dirs[idx] != NULL; idx++)
+ {
+ providers = g_list_concat (search_providers_discover_one_directory (system_data_dirs[idx], cancellable),
+ providers);
+
+ if (g_task_return_error_if_cancelled (task))
+ {
+ g_list_free_full (providers, g_object_unref);
+ return;
+ }
+ }
+
+ g_task_return_pointer (task, providers, NULL);
+}
+
+static void
+populate_search_providers (CcSearchPanel *self)
+{
+ g_autoptr(GTask) task = NULL;
+
+ task = g_task_new (self, cc_panel_get_cancellable (CC_PANEL (self)),
+ search_providers_discover_ready, self);
+ g_task_run_in_thread (task, search_providers_discover_thread);
+}
+
+static void
+cc_search_panel_finalize (GObject *object)
+{
+ CcSearchPanel *self = CC_SEARCH_PANEL (object);
+
+ g_clear_object (&self->search_settings);
+ g_hash_table_destroy (self->sort_order);
+
+ if (self->locations_dialog)
+ gtk_window_destroy (GTK_WINDOW (self->locations_dialog));
+
+ G_OBJECT_CLASS (cc_search_panel_parent_class)->finalize (object);
+}
+
+static void
+cc_search_panel_init (CcSearchPanel *self)
+{
+ g_resources_register (cc_search_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ gtk_list_box_set_sort_func (GTK_LIST_BOX (self->list_box),
+ (GtkListBoxSortFunc)list_sort_func, self, NULL);
+
+ gtk_widget_set_sensitive (self->settings_row, cc_search_locations_dialog_is_available ());
+
+ self->search_settings = g_settings_new ("org.gnome.desktop.search-providers");
+ g_settings_bind (self->search_settings,
+ "disable-external",
+ self->main_switch,
+ "active",
+ G_SETTINGS_BIND_DEFAULT |
+ G_SETTINGS_BIND_INVERT_BOOLEAN);
+
+ g_object_bind_property (self->main_switch,
+ "active",
+ self->search_group,
+ "sensitive",
+ G_BINDING_DEFAULT |
+ G_BINDING_SYNC_CREATE);
+
+ self->sort_order = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, NULL);
+ g_signal_connect_swapped (self->search_settings, "changed::sort-order",
+ G_CALLBACK (search_panel_invalidate_sort_order), self);
+ search_panel_invalidate_sort_order (self);
+
+ populate_search_providers (self);
+}
+
+static void
+cc_search_panel_class_init (CcSearchPanelClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *oclass = G_OBJECT_CLASS (klass);
+
+ oclass->finalize = cc_search_panel_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/control-center/search/cc-search-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcSearchPanel, list_box);
+ gtk_widget_class_bind_template_child (widget_class, CcSearchPanel, main_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcSearchPanel, search_group);
+ gtk_widget_class_bind_template_child (widget_class, CcSearchPanel, settings_row);
+
+ gtk_widget_class_bind_template_callback (widget_class, settings_row_activated);
+ gtk_widget_class_bind_template_callback (widget_class, keynav_failed_cb);
+}
diff --git a/panels/search/cc-search-panel.h b/panels/search/cc-search-panel.h
new file mode 100644
index 0000000..34d75a5
--- /dev/null
+++ b/panels/search/cc-search-panel.h
@@ -0,0 +1,30 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Cosimo Cecchi <cosimoc@gnome.org>
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_SEARCH_PANEL (cc_search_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcSearchPanel, cc_search_panel, CC, SEARCH_PANEL, CcPanel)
+
+G_END_DECLS
diff --git a/panels/search/cc-search-panel.ui b/panels/search/cc-search-panel.ui
new file mode 100644
index 0000000..7876fe8
--- /dev/null
+++ b/panels/search/cc-search-panel.ui
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcSearchPanel" parent="CcPanel">
+ <child type="content">
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Application Search</property>
+ <property name="subtitle" translatable="yes">Include application-provided search results.</property>
+ <property name="activatable-widget">main_switch</property>
+ <child type="suffix">
+ <object class="GtkSwitch" id="main_switch">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="settings_row">
+ <property name="title" translatable="yes">Search Locations</property>
+ <property name="subtitle" translatable="yes">Folders which are searched by system applications.</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="settings_row_activated" object="CcSearchPanel" swapped="no"/>
+ <child type="suffix">
+ <object class="GtkImage">
+ <property name="icon-name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup" id="search_group">
+ <property name="title" translatable="yes">Search Results</property>
+ <property name="description" translatable="yes">Results are displayed according to the list order.</property>
+ <child>
+ <object class="GtkListBox" id="list_box">
+ <property name="selection-mode">none</property>
+ <signal name="keynav-failed" handler="keynav_failed_cb" object="CcSearchPanel" swapped="yes"/>
+ <accessibility>
+ <relation name="labelled-by">search_group</relation>
+ </accessibility>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+
+</interface>
diff --git a/panels/search/gnome-search-panel.desktop.in.in b/panels/search/gnome-search-panel.desktop.in.in
new file mode 100644
index 0000000..5df64e4
--- /dev/null
+++ b/panels/search/gnome-search-panel.desktop.in.in
@@ -0,0 +1,18 @@
+[Desktop Entry]
+Name=Search
+Comment=Control which applications show search results in the Activities Overview
+Exec=gnome-control-center search
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-search-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-PersonalizationSettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=search
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=Search;Find;Index;Hide;Privacy;Results;
diff --git a/panels/search/icons/meson.build b/panels/search/icons/meson.build
new file mode 100644
index 0000000..d2d33e2
--- /dev/null
+++ b/panels/search/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-search-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/search/icons/scalable/org.gnome.Settings-search-symbolic.svg b/panels/search/icons/scalable/org.gnome.Settings-search-symbolic.svg
new file mode 100644
index 0000000..3bc527b
--- /dev/null
+++ b/panels/search/icons/scalable/org.gnome.Settings-search-symbolic.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <path d="m 6.5 0 c -3.578125 0 -6.5 2.921875 -6.5 6.5 s 2.921875 6.496094 6.5 6.496094 c 1.429688 0 2.753906 -0.464844 3.828125 -1.253906 l 3.945313 3.945312 c 0.957031 0.9375 2.363281 -0.5 1.40625 -1.4375 l -3.929688 -3.929688 c 0.785156 -1.074218 1.25 -2.394531 1.25 -3.820312 c 0 -3.578125 -2.921875 -6.5 -6.5 -6.5 z m 0 2 c 2.496094 0 4.5 2.003906 4.5 4.5 s -2.003906 4.496094 -4.5 4.496094 s -4.5 -2 -4.5 -4.496094 s 2.003906 -4.5 4.5 -4.5 z m 0 0" fill="#2e3436"/>
+</svg>
diff --git a/panels/search/meson.build b/panels/search/meson.build
new file mode 100644
index 0000000..3b66562
--- /dev/null
+++ b/panels/search/meson.build
@@ -0,0 +1,50 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+sources = files(
+ 'cc-search-panel.c',
+ 'cc-search-locations-dialog.c',
+ 'cc-search-panel-row.c'
+)
+
+resource_data = files(
+ 'cc-search-locations-dialog.ui',
+ 'cc-search-panel.ui',
+)
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname,
+ dependencies: resource_data,
+ export: true
+)
+
+cflags += [
+ '-DDATADIR="@0@"'.format(control_center_datadir)
+]
+
+panels_libs += static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [ top_inc, common_inc ],
+ dependencies: common_deps,
+ c_args: cflags
+)
+
+subdir('icons')
diff --git a/panels/search/search.gresource.xml b/panels/search/search.gresource.xml
new file mode 100644
index 0000000..60c403e
--- /dev/null
+++ b/panels/search/search.gresource.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/search">
+ <file preprocess="xml-stripblanks">cc-search-locations-dialog.ui</file>
+ <file preprocess="xml-stripblanks">cc-search-panel.ui</file>
+ <file preprocess="xml-stripblanks">cc-search-panel-row.ui</file>
+ </gresource>
+</gresources>
diff --git a/panels/sharing/cc-gnome-remote-desktop.c b/panels/sharing/cc-gnome-remote-desktop.c
new file mode 100644
index 0000000..ef7bc53
--- /dev/null
+++ b/panels/sharing/cc-gnome-remote-desktop.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2018 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include "config.h"
+
+#include "cc-gnome-remote-desktop.h"
+
+const SecretSchema *
+cc_grd_rdp_credentials_get_schema (void)
+{
+ static const SecretSchema grd_rdp_credentials_schema = {
+ .name = "org.gnome.RemoteDesktop.RdpCredentials",
+ .flags = SECRET_SCHEMA_NONE,
+ .attributes = {
+ { "credentials", SECRET_SCHEMA_ATTRIBUTE_STRING },
+ { "NULL", 0 },
+ },
+ };
+
+ return &grd_rdp_credentials_schema;
+}
+
+void
+cc_grd_store_rdp_credentials (const gchar *username,
+ const gchar *password,
+ GCancellable *cancellable)
+{
+ GVariantBuilder builder;
+ char *credentials;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (&builder, "{sv}", "username", g_variant_new_string (username));
+ g_variant_builder_add (&builder, "{sv}", "password", g_variant_new_string (password));
+ credentials = g_variant_print (g_variant_builder_end (&builder), TRUE);
+
+ secret_password_store_sync (CC_GRD_RDP_CREDENTIALS_SCHEMA,
+ SECRET_COLLECTION_DEFAULT,
+ "GNOME Remote Desktop RDP credentials",
+ credentials,
+ NULL, NULL,
+ NULL);
+
+ g_free (credentials);
+}
+
+gchar *
+cc_grd_lookup_rdp_username (GCancellable *cancellable)
+{
+ g_autoptr(GError) error = NULL;
+ gchar *username = NULL;
+ g_autofree gchar *secret;
+ GVariant *variant = NULL;
+
+ secret = secret_password_lookup_sync (CC_GRD_RDP_CREDENTIALS_SCHEMA,
+ cancellable, &error,
+ NULL);
+ if (error) {
+ g_warning ("Failed to get username: %s", error->message);
+ return NULL;
+ }
+
+ if (secret == NULL) {
+ g_debug ("No RDP credentials available");
+ return NULL;
+ }
+
+ variant = g_variant_parse (NULL, secret, NULL, NULL, &error);
+ if (variant == NULL) {
+ g_warning ("Invalid credentials format in the keyring: %s", error->message);
+ return NULL;
+ }
+
+ g_variant_lookup (variant, "username", "&s", &username);
+
+ return username;
+}
+
+gchar *
+cc_grd_lookup_rdp_password (GCancellable *cancellable)
+{
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *secret;
+ gchar *password = NULL;
+ GVariant *variant = NULL;
+
+ secret = secret_password_lookup_sync (CC_GRD_RDP_CREDENTIALS_SCHEMA,
+ cancellable, &error,
+ NULL);
+ if (error) {
+ g_warning ("Failed to get password: %s", error->message);
+ return NULL;
+ }
+
+ if (secret == NULL) {
+ g_debug ("No RDP credentials available");
+ return NULL;
+ }
+
+ variant = g_variant_parse (NULL, secret, NULL, NULL, &error);
+ if (variant == NULL) {
+ g_warning ("Invalid credentials format in the keyring: %s", error->message);
+ return NULL;
+ }
+
+ g_variant_lookup (variant, "password", "&s", &password);
+
+ return password;
+}
diff --git a/panels/sharing/cc-gnome-remote-desktop.h b/panels/sharing/cc-gnome-remote-desktop.h
new file mode 100644
index 0000000..592da34
--- /dev/null
+++ b/panels/sharing/cc-gnome-remote-desktop.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2018 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#pragma once
+
+#include <libsecret/secret.h>
+
+G_BEGIN_DECLS
+
+const SecretSchema * cc_grd_rdp_credentials_get_schema (void);
+#define CC_GRD_RDP_CREDENTIALS_SCHEMA cc_grd_rdp_credentials_get_schema ()
+
+void cc_grd_store_rdp_credentials (const gchar *username,
+ const gchar *password,
+ GCancellable *cancellable);
+
+gchar * cc_grd_lookup_rdp_username (GCancellable *cancellable);
+gchar * cc_grd_lookup_rdp_password (GCancellable *cancellable);
+
+G_END_DECLS
diff --git a/panels/sharing/cc-media-sharing.c b/panels/sharing/cc-media-sharing.c
new file mode 100644
index 0000000..d0f12aa
--- /dev/null
+++ b/panels/sharing/cc-media-sharing.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2013 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ *
+ */
+
+#include "cc-media-sharing.h"
+
+#include <gio/gio.h>
+#include <gio/gdesktopappinfo.h>
+#include <glib/gstdio.h>
+
+static GKeyFile*
+cc_media_sharing_open_key_file (void)
+{
+ g_autofree gchar *path = NULL;
+ GKeyFile *file;
+
+ file = g_key_file_new ();
+
+ path = g_build_filename (g_get_user_config_dir (), "rygel.conf", NULL);
+
+ if (!g_key_file_load_from_file (file, path,
+ G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS,
+ NULL))
+ {
+ g_autofree gchar *sysconf_path = NULL;
+ sysconf_path = g_build_filename (SYSCONFDIR, "rygel.conf", NULL);
+ g_key_file_load_from_file (file, sysconf_path,
+ G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS,
+ NULL);
+ }
+
+ return file;
+}
+
+void
+cc_media_sharing_get_preferences (gchar ***folders)
+{
+ g_autoptr(GKeyFile) file = NULL;
+
+ file = cc_media_sharing_open_key_file ();
+
+ if (folders)
+ {
+ gsize length;
+ GPtrArray *array;
+ GStrv str_list;
+ g_auto(GStrv) orig_list = NULL;
+
+ str_list = g_key_file_get_string_list (file, "MediaExport", "uris",
+ &length, NULL);
+ orig_list = str_list;
+ array = g_ptr_array_new ();
+
+ while (str_list && *str_list)
+ {
+ const char *dir;
+
+ if (g_str_equal (*str_list, "@MUSIC@"))
+ dir = g_get_user_special_dir (G_USER_DIRECTORY_MUSIC);
+ else if (g_str_equal (*str_list, "@VIDEOS@"))
+ dir = g_get_user_special_dir (G_USER_DIRECTORY_VIDEOS);
+ else if (g_str_equal (*str_list, "@PICTURES@"))
+ dir = g_get_user_special_dir (G_USER_DIRECTORY_PICTURES);
+ else
+ dir = g_strdup (*str_list);
+
+ if (dir != NULL)
+ g_ptr_array_add (array, g_strdup (dir));
+
+ str_list++;
+ }
+
+ g_ptr_array_add (array, NULL);
+
+ *folders = (char **) g_ptr_array_free (array, FALSE);
+ }
+}
+
+void
+cc_media_sharing_set_preferences (gchar **folders)
+{
+ g_autoptr(GKeyFile) file = NULL;
+ gchar **str_list;
+ g_autofree gchar *path = NULL;
+ gsize length;
+ g_autofree gchar *data = NULL;
+
+ file = cc_media_sharing_open_key_file ();
+
+ g_key_file_set_boolean (file, "general", "upnp-enabled", TRUE);
+ g_key_file_set_boolean (file, "Tracker", "enabled", FALSE);
+ g_key_file_set_boolean (file, "Tracker3", "enabled", FALSE);
+ g_key_file_set_boolean (file, "MediaExport", "enabled", TRUE);
+
+ str_list = folders;
+ length = 0;
+
+ while (str_list && *str_list)
+ {
+ if (g_strcmp0 (*str_list, g_get_user_special_dir (G_USER_DIRECTORY_MUSIC)) == 0)
+ {
+ g_free (*str_list);
+ *str_list = g_strdup ("@MUSIC@");
+ }
+
+ if (g_strcmp0 (*str_list, g_get_user_special_dir (G_USER_DIRECTORY_VIDEOS)) == 0)
+ {
+ g_free (*str_list);
+ *str_list = g_strdup ("@VIDEOS@");
+ }
+
+ if (g_strcmp0 (*str_list, g_get_user_special_dir (G_USER_DIRECTORY_PICTURES)) == 0)
+ {
+ g_free (*str_list);
+ *str_list = g_strdup ("@PICTURES@");
+ }
+
+ str_list++;
+ length++;
+ }
+
+ g_key_file_set_string_list (file, "MediaExport", "uris", (const gchar**) folders, length);
+
+ data = g_key_file_to_data (file, NULL, NULL);
+
+ path = g_build_filename (g_get_user_config_dir (), "rygel.conf", NULL);
+
+ g_file_set_contents (path, data, -1, NULL);
+}
diff --git a/panels/sharing/cc-media-sharing.h b/panels/sharing/cc-media-sharing.h
new file mode 100644
index 0000000..7923db0
--- /dev/null
+++ b/panels/sharing/cc-media-sharing.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2013 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ *
+ */
+
+#pragma once
+
+#include <glib.h>
+
+void cc_media_sharing_get_preferences (gchar ***folders);
+void cc_media_sharing_set_preferences (gchar **folders);
diff --git a/panels/sharing/cc-remote-login-helper.c b/panels/sharing/cc-remote-login-helper.c
new file mode 100644
index 0000000..26e527f
--- /dev/null
+++ b/panels/sharing/cc-remote-login-helper.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2013 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ *
+ */
+
+#include "cc-systemd-service.h"
+
+#ifndef SSHD_SERVICE
+#define SSHD_SERVICE "sshd.service"
+#endif
+
+int
+main (int argc,
+ char **argv)
+{
+ if (argc < 2)
+ return 1;
+
+ if (argv[1] == NULL)
+ return 1;
+
+ if (g_str_equal (argv[1], "enable"))
+ {
+ g_autoptr(GError) error = NULL;
+
+ if (!cc_enable_service (SSHD_SERVICE, G_BUS_TYPE_SYSTEM, &error))
+ {
+ g_critical ("Failed to enable %s: %s", SSHD_SERVICE, error->message);
+ return EXIT_FAILURE;
+ }
+ else
+ {
+ return EXIT_SUCCESS;
+ }
+ }
+ else if (g_str_equal (argv[1], "disable"))
+ {
+ g_autoptr(GError) error = NULL;
+
+ if (!cc_disable_service (SSHD_SERVICE, G_BUS_TYPE_SYSTEM, &error))
+ {
+ g_critical ("Failed to enable %s: %s", SSHD_SERVICE, error->message);
+ return EXIT_FAILURE;
+ }
+ else
+ {
+ return EXIT_SUCCESS;
+ }
+ }
+
+ return 1;
+}
diff --git a/panels/sharing/cc-remote-login.c b/panels/sharing/cc-remote-login.c
new file mode 100644
index 0000000..d185f7d
--- /dev/null
+++ b/panels/sharing/cc-remote-login.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2013 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ *
+ */
+#include "cc-remote-login.h"
+#include <gio/gio.h>
+
+#ifndef SSHD_SERVICE
+#define SSHD_SERVICE "sshd.service"
+#endif
+
+typedef struct
+{
+ GtkSwitch *gtkswitch;
+ GtkWidget *button;
+ GCancellable *cancellable;
+} CallbackData;
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (CallbackData, g_free)
+
+static void
+set_switch_state (GtkSwitch *gtkswitch,
+ gboolean active)
+{
+ if (gtk_switch_get_active (gtkswitch) != active)
+ {
+ g_object_set_data (G_OBJECT (gtkswitch), "set-from-dbus",
+ GINT_TO_POINTER (1));
+ gtk_switch_set_active (gtkswitch, active);
+ }
+ gtk_widget_set_sensitive (GTK_WIDGET (gtkswitch), TRUE);
+}
+
+static void
+active_state_ready_callback (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(CallbackData) callback_data = user_data;
+ g_autoptr(GVariant) active_variant = NULL;
+ g_autoptr(GVariant) child_variant = NULL;
+ g_autoptr(GVariant) tmp_variant = NULL;
+ const gchar *active_state;
+ gboolean active;
+ g_autoptr(GError) error = NULL;
+
+ active_variant = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ result, &error);
+
+ if (!active_variant)
+ {
+ /* print a warning if there was an error but the operation was not
+ * cancelled */
+ if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Error getting remote login state: %s", error->message);
+
+ /* the switch will be remain insensitive, since the current state could
+ * not be determined */
+ return;
+ }
+
+ child_variant = g_variant_get_child_value (active_variant, 0);
+ tmp_variant = g_variant_get_variant (child_variant);
+ active_state = g_variant_get_string (tmp_variant, NULL);
+
+ active = g_str_equal (active_state, "active");
+
+ /* set the switch to the correct state */
+ if (callback_data->gtkswitch)
+ set_switch_state (callback_data->gtkswitch, active);
+}
+
+static void
+path_ready_callback (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(CallbackData) callback_data = user_data;
+ g_autoptr(GVariant) path_variant = NULL;
+ g_autoptr(GVariant) child_variant = NULL;
+ const gchar *object_path;
+ g_autoptr(GError) error = NULL;
+
+ path_variant = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ result, &error);
+
+ if (!path_variant)
+ {
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
+ /* this may fail if systemd or remote login service is not available */
+ g_debug ("Error getting remote login state: %s", error->message);
+
+ /* hide the remote login button, since the service is not available */
+ if (callback_data->button)
+ gtk_widget_hide (callback_data->button);
+
+ return;
+ }
+
+ child_variant = g_variant_get_child_value (path_variant, 0);
+ object_path = g_variant_get_string (child_variant, NULL);
+
+ g_dbus_connection_call (G_DBUS_CONNECTION (source_object),
+ "org.freedesktop.systemd1",
+ object_path,
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ g_variant_new ("(ss)",
+ "org.freedesktop.systemd1.Unit",
+ "ActiveState"),
+ (GVariantType*) "(v)",
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ callback_data->cancellable,
+ active_state_ready_callback,
+ callback_data);
+ g_steal_pointer (&callback_data);
+}
+
+static void
+state_ready_callback (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(CallbackData) callback_data = user_data;
+ g_autoptr(GVariant) state_variant = NULL;
+ g_autoptr(GVariant) child_variant = NULL;
+ const gchar *state_string;
+ g_autoptr(GError) error = NULL;
+
+ state_variant = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ result, &error);
+ if (!state_variant)
+ {
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
+ /* this may fail if systemd or remote login service is not available */
+ g_debug ("Error getting remote login state: %s", error->message);
+
+ /* hide the remote login button, since the service is not available */
+ if (callback_data->button)
+ gtk_widget_hide (callback_data->button);
+
+ return;
+ }
+
+ child_variant = g_variant_get_child_value (state_variant, 0);
+ state_string = g_variant_get_string (child_variant, NULL);
+
+ if (g_str_equal (state_string, "enabled"))
+ {
+ /* service is enabled, so check whether it is running or not */
+ g_dbus_connection_call (G_DBUS_CONNECTION (source_object),
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "GetUnit",
+ g_variant_new ("(s)", SSHD_SERVICE),
+ (GVariantType*) "(o)",
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ callback_data->cancellable,
+ path_ready_callback,
+ callback_data);
+ g_steal_pointer (&callback_data);
+ }
+ else if (g_str_equal (state_string, "disabled"))
+ {
+ /* service is available, but is currently disabled */
+ set_switch_state (callback_data->gtkswitch, FALSE);
+ }
+ else
+ {
+ /* unknown state */
+ g_warning ("Unknown state %s for %s", state_string, SSHD_SERVICE);
+ }
+}
+
+static void
+bus_ready_callback (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(CallbackData) callback_data = user_data;
+ g_autoptr(GDBusConnection) connection = NULL;
+ g_autoptr(GError) error = NULL;
+
+ connection = g_bus_get_finish (result, &error);
+
+ if (!connection)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Error getting remote login state: %s", error->message);
+
+ return;
+ }
+
+ g_dbus_connection_call (connection,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "GetUnitFileState",
+ g_variant_new ("(s)", SSHD_SERVICE),
+ (GVariantType*) "(s)",
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ callback_data->cancellable,
+ state_ready_callback,
+ callback_data);
+ g_steal_pointer (&callback_data);
+}
+
+void
+cc_remote_login_get_enabled (GCancellable *cancellable,
+ GtkSwitch *gtkswitch,
+ GtkWidget *button)
+{
+ CallbackData *callback_data;
+
+ /* disable the switch until the current state is known */
+ gtk_widget_set_sensitive (GTK_WIDGET (gtkswitch), FALSE);
+
+ callback_data = g_new (CallbackData, 1);
+ callback_data->gtkswitch = gtkswitch;
+ callback_data->button = button;
+ callback_data->cancellable = cancellable;
+
+ g_bus_get (G_BUS_TYPE_SYSTEM, callback_data->cancellable,
+ bus_ready_callback, callback_data);
+}
+
+static gint std_err;
+
+static void
+child_watch_func (GPid pid,
+ gint status,
+ gpointer user_data)
+{
+ g_autoptr(CallbackData) callback_data = user_data;
+ if (status != 0)
+ {
+ g_warning ("Error enabling or disabling remote login service");
+
+ /* make sure the switch reflects the current status */
+ cc_remote_login_get_enabled (callback_data->cancellable, callback_data->gtkswitch, NULL);
+ }
+ g_spawn_close_pid (pid);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (callback_data->gtkswitch), TRUE);
+}
+
+void
+cc_remote_login_set_enabled (GCancellable *cancellable,
+ GtkSwitch *gtkswitch)
+{
+ gchar *command[] = { "pkexec", LIBEXECDIR "/cc-remote-login-helper", NULL,
+ NULL };
+ g_autoptr(GError) error = NULL;
+ GPid pid;
+ CallbackData *callback_data;
+
+ if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (gtkswitch), "set-from-dbus")) == 1)
+ {
+ g_object_set_data (G_OBJECT (gtkswitch), "set-from-dbus", NULL);
+ return;
+ }
+
+ if (gtk_switch_get_active (gtkswitch))
+ command[2] = "enable";
+ else
+ command[2] = "disable";
+
+ gtk_widget_set_sensitive (GTK_WIDGET (gtkswitch), FALSE);
+
+ g_spawn_async_with_pipes (NULL, command, NULL,
+ G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, NULL,
+ NULL, &pid, NULL, NULL, &std_err, &error);
+
+ callback_data = g_new0 (CallbackData, 1);
+ callback_data->gtkswitch = gtkswitch;
+ callback_data->cancellable = cancellable;
+
+ g_child_watch_add (pid, child_watch_func, callback_data);
+
+ if (error)
+ g_error ("Error running cc-remote-login-helper: %s", error->message);
+}
diff --git a/panels/sharing/cc-remote-login.h b/panels/sharing/cc-remote-login.h
new file mode 100644
index 0000000..c23ddcf
--- /dev/null
+++ b/panels/sharing/cc-remote-login.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2013 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ *
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+void cc_remote_login_get_enabled (GCancellable *cancellable,
+ GtkSwitch *gtkswitch,
+ GtkWidget *button);
+void cc_remote_login_set_enabled (GCancellable *cancellable,
+ GtkSwitch *gtkswitch);
diff --git a/panels/sharing/cc-sharing-networks.c b/panels/sharing/cc-sharing-networks.c
new file mode 100644
index 0000000..0ebbbfe
--- /dev/null
+++ b/panels/sharing/cc-sharing-networks.c
@@ -0,0 +1,520 @@
+/*
+ * Copyright (C) 2014 Bastien Nocera <hadess@hadess.net>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include "config.h"
+
+#include <adwaita.h>
+#include <gio/gio.h>
+#include <glib/gi18n.h>
+
+#include "cc-sharing-networks.h"
+#include "org.gnome.SettingsDaemon.Sharing.h"
+#include "gsd-sharing-enums.h"
+
+struct _CcSharingNetworks {
+ GtkBox parent_instance;
+
+ GtkWidget *listbox;
+
+ GtkWidget *current_row;
+ GtkWidget *current_icon;
+ GtkWidget *current_switch;
+
+ GtkWidget *no_network_row;
+
+ char *service_name;
+ GsdSharing *proxy;
+ CcSharingStatus status;
+
+ GList *networks; /* list of CcSharingNetwork */
+};
+
+
+G_DEFINE_TYPE (CcSharingNetworks, cc_sharing_networks, GTK_TYPE_BOX)
+
+enum {
+ PROP_0,
+ PROP_PROXY,
+ PROP_SERVICE_NAME,
+ PROP_STATUS
+};
+
+static void cc_sharing_networks_class_init (CcSharingNetworksClass *klass);
+static void cc_sharing_networks_init (CcSharingNetworks *self);
+static void cc_sharing_networks_finalize (GObject *object);
+
+static void cc_sharing_update_networks_box (CcSharingNetworks *self);
+
+typedef struct {
+ char *uuid;
+ char *network_name;
+ char *carrier_type;
+} CcSharingNetwork;
+
+static void
+cc_sharing_network_free (gpointer data)
+{
+ CcSharingNetwork *net = data;
+
+ g_free (net->uuid);
+ g_free (net->network_name);
+ g_free (net->carrier_type);
+ g_free (net);
+}
+
+static void
+cc_sharing_networks_update_status (CcSharingNetworks *self)
+{
+ CcSharingStatus status;
+
+ if (self->networks == NULL)
+ status = CC_SHARING_STATUS_OFF;
+ else if (gtk_widget_is_visible (self->current_switch) &&
+ gtk_switch_get_active (GTK_SWITCH (self->current_switch)))
+ status = CC_SHARING_STATUS_ACTIVE;
+ else
+ status = CC_SHARING_STATUS_ENABLED;
+
+ if (status != self->status) {
+ self->status = status;
+ g_object_notify (G_OBJECT (self), "status");
+ }
+}
+
+static void
+cc_sharing_update_networks (CcSharingNetworks *self)
+{
+ g_autoptr(GVariant) networks = NULL;
+ char *uuid, *network_name, *carrier_type;
+ GVariantIter iter;
+ g_autoptr(GError) error = NULL;
+
+ g_list_free_full (self->networks, cc_sharing_network_free);
+ self->networks = NULL;
+
+ if (!gsd_sharing_call_list_networks_sync (self->proxy, self->service_name, &networks, NULL, &error)) {
+ g_warning ("couldn't list networks: %s", error->message);
+ g_dbus_proxy_set_cached_property (G_DBUS_PROXY (self->proxy),
+ "SharingStatus",
+ g_variant_new_uint32 (GSD_SHARING_STATUS_OFFLINE));
+ return;
+ }
+
+ g_variant_iter_init (&iter, networks);
+ while (g_variant_iter_next (&iter, "(sss)", &uuid, &network_name, &carrier_type)) {
+ CcSharingNetwork *net;
+
+ net = g_new0 (CcSharingNetwork, 1);
+ net->uuid = uuid;
+ net->network_name = network_name;
+ net->carrier_type = carrier_type;
+ self->networks = g_list_prepend (self->networks, net);
+ }
+ self->networks = g_list_reverse (self->networks);
+}
+
+static void
+cc_sharing_networks_remove_network (CcSharingNetworks *self,
+ GtkWidget *button)
+{
+ GtkWidget *row;
+ g_autoptr(GError) error = NULL;
+ gboolean ret;
+ const char *uuid;
+
+ row = g_object_get_data (G_OBJECT (button), "row");
+ uuid = g_object_get_data (G_OBJECT (row), "uuid");
+
+ ret = gsd_sharing_call_disable_service_sync (self->proxy,
+ self->service_name,
+ uuid,
+ NULL,
+ &error);
+ if (!ret)
+ g_warning ("Failed to remove service %s: %s",
+ self->service_name, error->message);
+
+ cc_sharing_update_networks (self);
+ cc_sharing_update_networks_box (self);
+}
+
+static gboolean
+cc_sharing_networks_enable_network (CcSharingNetworks *self,
+ gboolean state,
+ GtkSwitch *widget)
+{
+ g_autoptr(GError) error = NULL;
+ gboolean ret;
+
+ if (state) {
+ ret = gsd_sharing_call_enable_service_sync (self->proxy,
+ self->service_name,
+ NULL,
+ &error);
+ } else {
+ ret = gsd_sharing_call_disable_service_sync (self->proxy,
+ self->service_name,
+ gsd_sharing_get_current_network (self->proxy),
+ NULL,
+ &error);
+ }
+
+ if (ret) {
+ gtk_switch_set_state (widget, state);
+ } else {
+ g_warning ("Failed to %s service %s: %s", state ? "enable" : "disable",
+ self->service_name, error->message);
+ g_signal_handlers_block_by_func (widget,
+ cc_sharing_networks_enable_network, self);
+ gtk_switch_set_active (widget, !state);
+ g_signal_handlers_unblock_by_func (widget,
+ cc_sharing_networks_enable_network, self);
+ }
+
+ cc_sharing_update_networks (self);
+ cc_sharing_networks_update_status (self);
+
+ return TRUE;
+}
+
+static GtkWidget *
+cc_sharing_networks_new_row (const char *uuid,
+ const char *network_name,
+ const char *carrier_type,
+ CcSharingNetworks *self)
+{
+ GtkWidget *row, *w;
+ const char *icon_name;
+
+ row = adw_action_row_new ();
+
+ if (g_strcmp0 (carrier_type, "802-11-wireless") == 0) {
+ icon_name = "network-wireless-offline-symbolic";
+ } else if (g_strcmp0 (carrier_type, "802-3-ethernet") == 0) {
+ icon_name = "network-wired-disconnected-symbolic";
+ } else {
+ icon_name = "network-wired-symbolic";
+ }
+
+ adw_action_row_set_icon_name (ADW_ACTION_ROW (row), icon_name);
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self->current_row), network_name);
+
+ /* Remove button */
+ w = gtk_button_new_from_icon_name ("window-close-symbolic");
+ gtk_widget_add_css_class (w, "flat");
+ gtk_widget_set_valign (w, GTK_ALIGN_CENTER);
+ gtk_accessible_update_property (GTK_ACCESSIBLE (w),
+ GTK_ACCESSIBLE_PROPERTY_LABEL, _("Remove"),
+ -1);
+ adw_action_row_add_suffix (ADW_ACTION_ROW (row), w);
+ g_signal_connect_object (G_OBJECT (w), "clicked",
+ G_CALLBACK (cc_sharing_networks_remove_network), self, G_CONNECT_SWAPPED);
+ g_object_set_data (G_OBJECT (w), "row", row);
+
+ g_object_set_data_full (G_OBJECT (row), "uuid", g_strdup (uuid), g_free);
+
+ return row;
+}
+
+static GtkWidget *
+cc_sharing_networks_new_current_row (CcSharingNetworks *self)
+{
+ GtkWidget *row, *w;
+
+ row = adw_action_row_new ();
+
+ /* Icon */
+ w = gtk_image_new_from_icon_name ("image-missing");
+ adw_action_row_add_prefix (ADW_ACTION_ROW (row), w);
+ self->current_icon = w;
+
+ w = gtk_switch_new ();
+ gtk_widget_set_valign (w, GTK_ALIGN_CENTER);
+ adw_action_row_add_suffix (ADW_ACTION_ROW (row), w);
+ g_signal_connect_object (G_OBJECT (w), "state-set",
+ G_CALLBACK (cc_sharing_networks_enable_network), self, G_CONNECT_SWAPPED);
+ self->current_switch = w;
+ g_object_set_data (G_OBJECT (w), "row", row);
+
+ return row;
+}
+
+static GtkWidget *
+cc_sharing_networks_new_no_network_row (CcSharingNetworks *self)
+{
+ GtkWidget *row, *box, *w;
+
+ row = gtk_list_box_row_new ();
+ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), box);
+
+ /* Label */
+ w = gtk_label_new (_("No networks selected for sharing"));
+ gtk_widget_set_hexpand (w, TRUE);
+ gtk_widget_set_halign (w, GTK_ALIGN_CENTER);
+ gtk_style_context_add_class (gtk_widget_get_style_context (w), "dim-label");
+ gtk_box_append (GTK_BOX (box), w);
+
+ return row;
+}
+
+static void
+cc_sharing_update_networks_box (CcSharingNetworks *self)
+{
+ GtkWidget *child;
+ gboolean current_visible;
+ const char *current_network;
+ GList *l;
+
+ child = gtk_widget_get_first_child (self->listbox);
+ while (child) {
+ GtkWidget *next = gtk_widget_get_next_sibling (child);
+ if (child != self->current_row && child != self->no_network_row)
+ gtk_list_box_remove (GTK_LIST_BOX (self->listbox), child);
+ child = next;
+ }
+
+ current_network = gsd_sharing_get_current_network (self->proxy);
+
+ if (current_network != NULL &&
+ !g_str_equal (current_network, "")) {
+ gboolean available;
+ const char *carrier_type, *icon_name, *current_network_name;
+
+ gtk_widget_show (self->current_row);
+ current_visible = TRUE;
+
+ /* Network name */
+ g_object_set_data_full (G_OBJECT (self->current_row),
+ "uuid", g_strdup (current_network), g_free);
+ current_network_name = gsd_sharing_get_current_network_name (self->proxy);
+ if (ADW_IS_PREFERENCES_ROW (self->current_row))
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self->current_row), current_network_name);
+
+ /* Icon */
+ carrier_type = gsd_sharing_get_carrier_type (self->proxy);
+ if (g_strcmp0 (carrier_type, "802-11-wireless") == 0) {
+ icon_name = "network-wireless-signal-excellent-symbolic";
+ } else if (g_strcmp0 (carrier_type, "802-3-ethernet") == 0) {
+ icon_name = "network-wired-symbolic";
+ } else {
+ icon_name = "network-wired-symbolic";
+ }
+ gtk_image_set_from_icon_name (GTK_IMAGE (self->current_icon), icon_name);
+
+ /* State */
+ available = gsd_sharing_get_sharing_status (self->proxy) == GSD_SHARING_STATUS_AVAILABLE;
+ gtk_widget_set_sensitive (self->current_switch, available);
+ //FIXME add a subtitle explaining why it's disabled
+ } else {
+ gtk_widget_hide (self->current_row);
+ current_visible = FALSE;
+ }
+
+ for (l = self->networks; l != NULL; l = l->next) {
+ CcSharingNetwork *net = l->data;
+ GtkWidget *row;
+
+ if (g_strcmp0 (net->uuid, current_network) == 0) {
+ g_signal_handlers_block_by_func (self->current_switch,
+ cc_sharing_networks_enable_network, self);
+ gtk_switch_set_state (GTK_SWITCH (self->current_switch), TRUE);
+ g_signal_handlers_unblock_by_func (self->current_switch,
+ cc_sharing_networks_enable_network, self);
+ continue;
+ }
+
+ row = cc_sharing_networks_new_row (net->uuid,
+ net->network_name,
+ net->carrier_type,
+ self);
+ gtk_widget_show (row);
+ gtk_list_box_insert (GTK_LIST_BOX (self->listbox), row, -1);
+ }
+
+ if (self->networks == NULL &&
+ !current_visible) {
+ gtk_widget_show (self->no_network_row);
+ } else {
+ gtk_widget_hide (self->no_network_row);
+ }
+
+ cc_sharing_networks_update_status (self);
+}
+
+static void
+current_network_changed (CcSharingNetworks *self)
+{
+ cc_sharing_update_networks (self);
+ cc_sharing_update_networks_box (self);
+}
+
+static void
+cc_sharing_networks_constructed (GObject *object)
+{
+ CcSharingNetworks *self;
+
+ G_OBJECT_CLASS (cc_sharing_networks_parent_class)->constructed (object);
+
+ self = CC_SHARING_NETWORKS (object);
+
+ self->current_row = cc_sharing_networks_new_current_row (self);
+ gtk_list_box_insert (GTK_LIST_BOX (self->listbox), self->current_row, -1);
+ g_object_set_data (G_OBJECT (self), "switch", self->current_switch);
+
+ self->no_network_row = cc_sharing_networks_new_no_network_row (self);
+ gtk_list_box_insert (GTK_LIST_BOX (self->listbox), self->no_network_row, -1);
+
+ cc_sharing_update_networks (self);
+ cc_sharing_update_networks_box (self);
+
+ g_signal_connect_object (self->proxy, "notify::current-network",
+ G_CALLBACK (current_network_changed), self, G_CONNECT_SWAPPED);
+}
+
+static void
+cc_sharing_networks_init (CcSharingNetworks *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+GtkWidget *
+cc_sharing_networks_new (GDBusProxy *proxy,
+ const char *service_name)
+{
+ g_return_val_if_fail (GSD_IS_SHARING (proxy), NULL);
+ g_return_val_if_fail (service_name != NULL, NULL);
+
+ return GTK_WIDGET (g_object_new (CC_TYPE_SHARING_NETWORKS,
+ "proxy", proxy,
+ "service-name", service_name,
+ NULL));
+}
+
+static void
+cc_sharing_networks_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcSharingNetworks *self;
+
+ self = CC_SHARING_NETWORKS (object);
+
+ switch (prop_id) {
+ case PROP_SERVICE_NAME:
+ self->service_name = g_value_dup_string (value);
+ break;
+ case PROP_PROXY:
+ self->proxy = g_value_dup_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_sharing_networks_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcSharingNetworks *self;
+
+ self = CC_SHARING_NETWORKS (object);
+
+ switch (prop_id) {
+ case PROP_STATUS:
+ g_value_set_uint (value, self->status);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_sharing_networks_finalize (GObject *object)
+{
+ CcSharingNetworks *self;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (CC_IS_SHARING_NETWORKS (object));
+
+ self = CC_SHARING_NETWORKS (object);
+
+ g_return_if_fail (self != NULL);
+
+ g_clear_object (&self->proxy);
+ g_clear_pointer (&self->service_name, g_free);
+
+ if (self->networks != NULL) {
+ g_list_free_full (self->networks, cc_sharing_network_free);
+ self->networks = NULL;
+ }
+
+ G_OBJECT_CLASS (cc_sharing_networks_parent_class)->finalize (object);
+}
+
+
+static void
+cc_sharing_networks_class_init (CcSharingNetworksClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->set_property = cc_sharing_networks_set_property;
+ object_class->get_property = cc_sharing_networks_get_property;
+ object_class->finalize = cc_sharing_networks_finalize;
+ object_class->constructed = cc_sharing_networks_constructed;
+
+ g_object_class_install_property (object_class,
+ PROP_PROXY,
+ g_param_spec_object ("proxy",
+ "proxy",
+ "proxy",
+ GSD_TYPE_SHARING_PROXY,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_SERVICE_NAME,
+ g_param_spec_string ("service-name",
+ "service-name",
+ "service-name",
+ NULL,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_STATUS,
+ g_param_spec_uint ("status",
+ "status",
+ "status",
+ CC_SHARING_STATUS_UNSET, CC_SHARING_STATUS_ACTIVE + 1, CC_SHARING_STATUS_OFF,
+ G_PARAM_READABLE));
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/control-center/sharing/cc-sharing-networks.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcSharingNetworks, listbox);
+}
+
+/*
+ * vim: sw=2 ts=8 cindent noai bs=2
+ */
diff --git a/panels/sharing/cc-sharing-networks.h b/panels/sharing/cc-sharing-networks.h
new file mode 100644
index 0000000..f44567e
--- /dev/null
+++ b/panels/sharing/cc-sharing-networks.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2014 Bastien Nocera <hadess@hadess.net>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_SHARING_NETWORKS (cc_sharing_networks_get_type ())
+G_DECLARE_FINAL_TYPE (CcSharingNetworks, cc_sharing_networks, CC, SHARING_NETWORKS, GtkBox)
+
+typedef enum {
+ CC_SHARING_STATUS_UNSET,
+ CC_SHARING_STATUS_OFF,
+ CC_SHARING_STATUS_ENABLED,
+ CC_SHARING_STATUS_ACTIVE
+} CcSharingStatus;
+
+GtkWidget * cc_sharing_networks_new (GDBusProxy *proxy,
+ const char *service_name);
+
+G_END_DECLS
diff --git a/panels/sharing/cc-sharing-networks.ui b/panels/sharing/cc-sharing-networks.ui
new file mode 100644
index 0000000..5703441
--- /dev/null
+++ b/panels/sharing/cc-sharing-networks.ui
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.18.1 -->
+<interface>
+ <requires lib="gtk+" version="3.10"/>
+ <template class="CcSharingNetworks" parent="GtkBox">
+ <property name="margin_start">0</property>
+ <property name="margin_end">0</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="spacing">12</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label15">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Networks</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkFrame" id="shared-networks-frame">
+ <property name="hexpand">True</property>
+ <child>
+ <object class="GtkListBox" id="listbox">
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/sharing/cc-sharing-panel.c b/panels/sharing/cc-sharing-panel.c
new file mode 100644
index 0000000..1ac744c
--- /dev/null
+++ b/panels/sharing/cc-sharing-panel.c
@@ -0,0 +1,1600 @@
+/*
+ * Copyright (C) 2013 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ *
+ */
+
+#include "cc-sharing-panel.h"
+#include "cc-hostname-entry.h"
+#include "cc-list-row.h"
+
+#include "cc-sharing-resources.h"
+#include "cc-remote-login.h"
+#include "file-share-properties.h"
+#include "cc-media-sharing.h"
+#include "cc-sharing-networks.h"
+#include "cc-gnome-remote-desktop.h"
+#include "cc-tls-certificate.h"
+#include "cc-systemd-service.h"
+#include "org.gnome.SettingsDaemon.Sharing.h"
+
+#ifdef GDK_WINDOWING_WAYLAND
+#include <gdk/wayland/gdkwayland.h>
+#endif
+#include <glib/gi18n.h>
+
+#define GCR_API_SUBJECT_TO_CHANGE
+#include <gcr/gcr-base.h>
+
+#include <pwquality.h>
+
+#include <config.h>
+
+#include <unistd.h>
+#include <pwd.h>
+
+static void cc_sharing_panel_setup_label_with_hostname (CcSharingPanel *self, GtkWidget *label);
+static GtkWidget *cc_sharing_panel_new_media_sharing_row (const char *uri_or_path,
+ CcSharingPanel *self);
+
+#define FILE_SHARING_SCHEMA_ID "org.gnome.desktop.file-sharing"
+#define GNOME_REMOTE_DESKTOP_SCHEMA_ID "org.gnome.desktop.remote-desktop"
+#define GNOME_REMOTE_DESKTOP_RDP_SCHEMA_ID "org.gnome.desktop.remote-desktop.rdp"
+
+#define REMOTE_DESKTOP_STORE_CREDENTIALS_TIMEOUT_S 1
+
+#define REMOTE_DESKTOP_SERVICE "gnome-remote-desktop.service"
+
+struct _CcSharingPanel
+{
+ CcPanel parent_instance;
+
+ GtkWidget *hostname_entry;
+ GtkWidget *main_list_box;
+ GtkWidget *master_switch;
+ GtkWidget *media_sharing_dialog;
+ GtkWidget *media_sharing_headerbar;
+ GtkWidget *media_sharing_row;
+ GtkWidget *media_sharing_switch;
+ GtkWidget *personal_file_sharing_dialog;
+ GtkWidget *personal_file_sharing_grid;
+ GtkWidget *personal_file_sharing_headerbar;
+ GtkWidget *personal_file_sharing_label;
+ GtkWidget *personal_file_sharing_password_entry;
+ GtkWidget *personal_file_sharing_password_label;
+ GtkWidget *personal_file_sharing_require_password_switch;
+ GtkWidget *personal_file_sharing_row;
+ GtkWidget *personal_file_sharing_switch;
+ GtkWidget *remote_login_dialog;
+ GtkWidget *remote_login_label;
+ GtkWidget *remote_login_row;
+ GtkWidget *remote_login_switch;
+
+ GtkWidget *remote_control_switch;
+ GtkWidget *remote_control_checkbutton;
+ GtkWidget *remote_desktop_toast_overlay;
+ GtkWidget *remote_desktop_password_entry;
+ GtkWidget *remote_desktop_password_copy;
+ GtkWidget *remote_desktop_username_entry;
+ GtkWidget *remote_desktop_username_copy;
+ GtkWidget *remote_desktop_dialog;
+ GtkWidget *remote_desktop_device_name_label;
+ GtkWidget *remote_desktop_device_name_copy;
+ GtkWidget *remote_desktop_address_label;
+ GtkWidget *remote_desktop_address_copy;
+ GtkWidget *remote_desktop_row;
+ GtkWidget *remote_desktop_switch;
+ GtkWidget *remote_desktop_verify_encryption;
+ GtkWidget *remote_desktop_fingerprint_dialog;
+ GtkWidget *remote_desktop_fingerprint_left;
+ GtkWidget *remote_desktop_fingerprint_right;
+
+ GtkWidget *shared_folders_grid;
+ GtkWidget *shared_folders_listbox;
+
+ GDBusProxy *sharing_proxy;
+
+ guint remote_desktop_name_watch;
+ guint remote_desktop_store_credentials_id;
+ GTlsCertificate *remote_desktop_certificate;
+};
+
+CC_PANEL_REGISTER (CcSharingPanel, cc_sharing_panel)
+
+#define OFF_IF_VISIBLE(x, y) { if (gtk_widget_is_visible(x) && (y) != NULL && gtk_widget_is_sensitive(y)) gtk_switch_set_active (GTK_SWITCH(y), FALSE); }
+
+static gboolean store_remote_desktop_credentials_timeout (gpointer user_data);
+
+static void
+cc_sharing_panel_master_switch_notify (CcSharingPanel *self)
+{
+ gboolean active;
+
+ active = gtk_switch_get_active (GTK_SWITCH (self->master_switch));
+
+ if (!active)
+ {
+ /* disable all services if the master switch is not active */
+ OFF_IF_VISIBLE(self->media_sharing_row, self->media_sharing_switch);
+ OFF_IF_VISIBLE(self->personal_file_sharing_row, self->personal_file_sharing_switch);
+ OFF_IF_VISIBLE(self->remote_desktop_row, self->remote_desktop_switch);
+
+ gtk_switch_set_active (GTK_SWITCH (self->remote_login_switch), FALSE);
+ }
+
+ gtk_widget_set_sensitive (self->main_list_box, active);
+}
+
+static void
+cc_sharing_panel_dispose (GObject *object)
+{
+ CcSharingPanel *self = CC_SHARING_PANEL (object);
+
+ if (self->remote_desktop_name_watch)
+ g_bus_unwatch_name (self->remote_desktop_name_watch);
+ self->remote_desktop_name_watch = 0;
+
+ if (self->media_sharing_dialog)
+ {
+ gtk_window_destroy (GTK_WINDOW (self->media_sharing_dialog));
+ self->media_sharing_dialog = NULL;
+ }
+
+ if (self->personal_file_sharing_dialog)
+ {
+ gtk_window_destroy (GTK_WINDOW (self->personal_file_sharing_dialog));
+ self->personal_file_sharing_dialog = NULL;
+ }
+
+ if (self->remote_login_dialog)
+ {
+ gtk_window_destroy (GTK_WINDOW (self->remote_login_dialog));
+ self->remote_login_dialog = NULL;
+ }
+
+ if (self->remote_desktop_dialog)
+ {
+ gtk_window_destroy (GTK_WINDOW (self->remote_desktop_dialog));
+ self->remote_desktop_dialog = NULL;
+ }
+
+ g_clear_object (&self->sharing_proxy);
+
+ if (self->remote_desktop_store_credentials_id)
+ {
+ g_clear_handle_id (&self->remote_desktop_store_credentials_id,
+ g_source_remove);
+ store_remote_desktop_credentials_timeout (self);
+ }
+
+ G_OBJECT_CLASS (cc_sharing_panel_parent_class)->dispose (object);
+}
+
+static const char *
+cc_sharing_panel_get_help_uri (CcPanel *panel)
+{
+ return "help:gnome-help/prefs-sharing";
+}
+
+static void
+remote_desktop_show_encryption_fingerprint (CcSharingPanel *self)
+{
+ g_autoptr(GByteArray) der = NULL;
+ g_autoptr(GcrCertificate) gcr_cert = NULL;
+ g_autofree char *fingerprint = NULL;
+ g_auto(GStrv) fingerprintv = NULL;
+ g_autofree char *left_string = NULL;
+ g_autofree char *right_string = NULL;
+
+ g_return_if_fail (self->remote_desktop_certificate);
+
+ g_object_get (self->remote_desktop_certificate,
+ "certificate", &der, NULL);
+ gcr_cert = gcr_simple_certificate_new (der->data, der->len);
+ if (!gcr_cert)
+ {
+ g_warning ("Failed to load GCR TLS certificate representation");
+ return;
+ }
+
+ fingerprint = gcr_certificate_get_fingerprint_hex (gcr_cert, G_CHECKSUM_SHA256);
+
+ fingerprintv = g_strsplit (fingerprint, " ", -1);
+ g_return_if_fail (g_strv_length (fingerprintv) == 32);
+
+ left_string = g_strdup_printf (
+ "%s:%s:%s:%s\n"
+ "%s:%s:%s:%s\n"
+ "%s:%s:%s:%s\n"
+ "%s:%s:%s:%s\n",
+ fingerprintv[0], fingerprintv[1], fingerprintv[2], fingerprintv[3],
+ fingerprintv[8], fingerprintv[9], fingerprintv[10], fingerprintv[11],
+ fingerprintv[16], fingerprintv[17], fingerprintv[18], fingerprintv[19],
+ fingerprintv[24], fingerprintv[25], fingerprintv[26], fingerprintv[27]);
+
+ right_string = g_strdup_printf (
+ "%s:%s:%s:%s\n"
+ "%s:%s:%s:%s\n"
+ "%s:%s:%s:%s\n"
+ "%s:%s:%s:%s\n",
+ fingerprintv[4], fingerprintv[5], fingerprintv[6], fingerprintv[7],
+ fingerprintv[12], fingerprintv[13], fingerprintv[14], fingerprintv[15],
+ fingerprintv[20], fingerprintv[21], fingerprintv[22], fingerprintv[23],
+ fingerprintv[28], fingerprintv[29], fingerprintv[30], fingerprintv[31]);
+
+ gtk_label_set_label (GTK_LABEL (self->remote_desktop_fingerprint_left),
+ left_string);
+ gtk_label_set_label (GTK_LABEL (self->remote_desktop_fingerprint_right),
+ right_string);
+
+ gtk_window_set_transient_for (GTK_WINDOW (self->remote_desktop_fingerprint_dialog),
+ GTK_WINDOW (self->remote_desktop_dialog));
+ gtk_window_present (GTK_WINDOW (self->remote_desktop_fingerprint_dialog));
+}
+
+static void
+cc_sharing_panel_class_init (CcSharingPanelClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+
+ object_class->dispose = cc_sharing_panel_dispose;
+
+ panel_class->get_help_uri = cc_sharing_panel_get_help_uri;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/sharing/cc-sharing-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, hostname_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, shared_folders_grid);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, master_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, main_list_box);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, media_sharing_dialog);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, media_sharing_headerbar);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, media_sharing_row);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, personal_file_sharing_dialog);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, personal_file_sharing_grid);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, personal_file_sharing_headerbar);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, personal_file_sharing_label);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, personal_file_sharing_password_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, personal_file_sharing_password_label);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, personal_file_sharing_require_password_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, personal_file_sharing_row);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_login_dialog);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_login_label);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_login_row);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_login_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_desktop_dialog);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_desktop_toast_overlay);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_desktop_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_control_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_desktop_username_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_desktop_username_copy);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_desktop_password_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_desktop_password_copy);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_desktop_device_name_label);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_desktop_device_name_copy);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_desktop_address_label);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_desktop_address_copy);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_desktop_verify_encryption);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_desktop_fingerprint_dialog);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_desktop_row);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_desktop_fingerprint_left);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_desktop_fingerprint_right);
+ gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, shared_folders_listbox);
+
+ gtk_widget_class_bind_template_callback (widget_class, remote_desktop_show_encryption_fingerprint);
+
+ g_type_ensure (CC_TYPE_LIST_ROW);
+ g_type_ensure (CC_TYPE_HOSTNAME_ENTRY);
+}
+
+static void
+cc_sharing_panel_run_dialog (CcSharingPanel *self,
+ GtkWidget *dialog)
+{
+ GtkWidget *parent;
+
+ /* ensure labels with the hostname are updated if the hostname has changed */
+ cc_sharing_panel_setup_label_with_hostname (self,
+ self->remote_desktop_address_label);
+ cc_sharing_panel_setup_label_with_hostname (self, self->remote_login_label);
+ cc_sharing_panel_setup_label_with_hostname (self,
+ self->personal_file_sharing_label);
+
+
+ parent = cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (self)));
+
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent));
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+static void
+cc_sharing_panel_main_list_box_row_activated (CcSharingPanel *self,
+ GtkListBoxRow *row)
+{
+ GtkWidget *dialog;
+
+ if (row == GTK_LIST_BOX_ROW (self->media_sharing_row))
+ dialog = self->media_sharing_dialog;
+ else if (row == GTK_LIST_BOX_ROW (self->personal_file_sharing_row))
+ dialog = self->personal_file_sharing_dialog;
+ else if (row == GTK_LIST_BOX_ROW (self->remote_login_row))
+ dialog = self->remote_login_dialog;
+ else if (row == GTK_LIST_BOX_ROW (self->remote_desktop_row))
+ dialog = self->remote_desktop_dialog;
+ else
+ return;
+
+ gtk_list_box_select_row (GTK_LIST_BOX (self->main_list_box), NULL);
+
+ cc_sharing_panel_run_dialog (self, dialog);
+}
+
+static gboolean
+cc_sharing_panel_switch_to_label_transform_func (GBinding *binding,
+ const GValue *source_value,
+ GValue *target_value,
+ CcSharingPanel *self)
+{
+ gboolean active;
+
+ if (!G_VALUE_HOLDS_BOOLEAN (source_value))
+ return FALSE;
+
+ if (!G_VALUE_HOLDS_STRING (target_value))
+ return FALSE;
+
+ active = g_value_get_boolean (source_value);
+
+ if (active)
+ g_value_set_string (target_value, C_("service is enabled", "On"));
+ else
+ g_value_set_string (target_value, C_("service is disabled", "Off"));
+
+ /* ensure the master switch is active if one of the services is active */
+ if (active)
+ gtk_switch_set_active (GTK_SWITCH (self->master_switch), TRUE);
+
+ return TRUE;
+}
+
+static gboolean
+cc_sharing_panel_networks_to_label_transform_func (GBinding *binding,
+ const GValue *source_value,
+ GValue *target_value,
+ CcSharingPanel *self)
+{
+ CcSharingStatus status;
+
+ if (!G_VALUE_HOLDS_UINT (source_value))
+ return FALSE;
+
+ if (!G_VALUE_HOLDS_STRING (target_value))
+ return FALSE;
+
+ status = g_value_get_uint (source_value);
+
+ switch (status) {
+ case CC_SHARING_STATUS_OFF:
+ g_value_set_string (target_value, C_("service is disabled", "Off"));
+ break;
+ case CC_SHARING_STATUS_ENABLED:
+ g_value_set_string (target_value, C_("service is enabled", "Enabled"));
+ break;
+ case CC_SHARING_STATUS_ACTIVE:
+ g_value_set_string (target_value, C_("service is active", "Active"));
+ break;
+ default:
+ return FALSE;
+ }
+
+ /* ensure the master switch is active if one of the services is active */
+ if (status != CC_SHARING_STATUS_OFF)
+ gtk_switch_set_active (GTK_SWITCH (self->master_switch), TRUE);
+
+ return TRUE;
+}
+
+static void
+cc_sharing_panel_bind_switch_to_label (CcSharingPanel *self,
+ GtkWidget *gtkswitch,
+ GtkWidget *row)
+{
+ g_object_bind_property_full (gtkswitch, "active", row, "secondary-label",
+ G_BINDING_SYNC_CREATE,
+ (GBindingTransformFunc) cc_sharing_panel_switch_to_label_transform_func,
+ NULL, self, NULL);
+}
+
+static void
+cc_sharing_panel_bind_networks_to_label (CcSharingPanel *self,
+ GtkWidget *networks,
+ GtkWidget *list_row)
+{
+ g_object_bind_property_full (networks, "status", list_row, "secondary-label",
+ G_BINDING_SYNC_CREATE,
+ (GBindingTransformFunc) cc_sharing_panel_networks_to_label_transform_func,
+ NULL, self, NULL);
+}
+
+static void
+cc_sharing_panel_bind_switch_to_widgets (GtkWidget *gtkswitch,
+ GtkWidget *first_widget,
+ ...)
+{
+ va_list w;
+ GtkWidget *widget;
+
+ va_start (w, first_widget);
+
+ g_object_bind_property (gtkswitch, "active", first_widget,
+ "sensitive", G_BINDING_SYNC_CREATE);
+
+ while ((widget = va_arg (w, GtkWidget*)))
+ {
+ g_object_bind_property (gtkswitch, "active", widget,
+ "sensitive", G_BINDING_SYNC_CREATE);
+ }
+
+ va_end (w);
+}
+
+static void
+on_add_folder_dialog_response_cb (GtkDialog *dialog,
+ gint response,
+ CcSharingPanel *self)
+{
+ g_autofree gchar *folder = NULL;
+ g_autoptr(GFile) file = NULL;
+ GtkWidget *child;
+ gboolean matching = FALSE;
+ gint n_rows = 0;
+
+ if (response != GTK_RESPONSE_ACCEPT)
+ goto bail;
+
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+ folder = g_file_get_uri (file);
+ if (!folder || g_str_equal (folder, ""))
+ goto bail;
+
+ g_debug ("Trying to add %s", folder);
+
+ for (child = gtk_widget_get_first_child (self->shared_folders_listbox);
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ {
+ const char *string;
+
+ string = g_object_get_data (G_OBJECT (child), "path");
+ matching = (g_strcmp0 (string, folder) == 0);
+
+ if (matching)
+ {
+ g_debug ("Found a duplicate for %s", folder);
+ break;
+ }
+
+ n_rows++;
+ }
+
+ if (!matching)
+ {
+ GtkWidget *row = cc_sharing_panel_new_media_sharing_row (folder, self);
+
+ gtk_list_box_insert (GTK_LIST_BOX (self->shared_folders_listbox),
+ row,
+ n_rows - 1);
+ }
+
+bail:
+ gtk_window_destroy (GTK_WINDOW (dialog));
+}
+
+static void
+cc_sharing_panel_add_folder (CcSharingPanel *self,
+ GtkListBoxRow *row)
+{
+ GtkWidget *dialog;
+
+ if (!GPOINTER_TO_INT (g_object_get_data (G_OBJECT (row), "is-add")))
+ return;
+
+ dialog = gtk_file_chooser_dialog_new (_("Choose a Folder"),
+ GTK_WINDOW (self->media_sharing_dialog),
+ GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Open"), GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ g_signal_connect_object (dialog,
+ "response",
+ G_CALLBACK (on_add_folder_dialog_response_cb),
+ self,
+ 0);
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+static void
+cc_sharing_panel_remove_folder (CcSharingPanel *self,
+ GtkButton *button)
+{
+ GtkWidget *row;
+
+ row = g_object_get_data (G_OBJECT (button), "row");
+ gtk_list_box_remove (GTK_LIST_BOX (self->shared_folders_listbox), row);
+}
+
+static void
+cc_sharing_panel_media_sharing_dialog_response (CcSharingPanel *self,
+ gint reponse_id)
+{
+ g_autoptr(GPtrArray) folders = NULL;
+ GtkWidget *child;
+
+ folders = g_ptr_array_new_with_free_func (g_free);
+
+ for (child = gtk_widget_get_first_child (self->shared_folders_listbox);
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ {
+ const char *folder;
+
+ folder = g_object_get_data (G_OBJECT (child), "path");
+ if (folder == NULL)
+ continue;
+ g_ptr_array_add (folders, g_strdup (folder));
+ }
+
+ g_ptr_array_add (folders, NULL);
+
+ cc_media_sharing_set_preferences ((gchar **) folders->pdata);
+}
+
+#define ICON_NAME_FOLDER "folder-symbolic"
+#define ICON_NAME_FOLDER_DESKTOP "user-desktop-symbolic"
+#define ICON_NAME_FOLDER_DOCUMENTS "folder-documents-symbolic"
+#define ICON_NAME_FOLDER_DOWNLOAD "folder-download-symbolic"
+#define ICON_NAME_FOLDER_MUSIC "folder-music-symbolic"
+#define ICON_NAME_FOLDER_PICTURES "folder-pictures-symbolic"
+#define ICON_NAME_FOLDER_PUBLIC_SHARE "folder-publicshare-symbolic"
+#define ICON_NAME_FOLDER_TEMPLATES "folder-templates-symbolic"
+#define ICON_NAME_FOLDER_VIDEOS "folder-videos-symbolic"
+#define ICON_NAME_FOLDER_SAVED_SEARCH "folder-saved-search-symbolic"
+
+static GIcon *
+special_directory_get_gicon (GUserDirectory directory)
+{
+#define ICON_CASE(x) \
+ case G_USER_DIRECTORY_ ## x: \
+ return g_themed_icon_new_with_default_fallbacks (ICON_NAME_FOLDER_ ## x);
+
+ switch (directory)
+ {
+ ICON_CASE (DESKTOP);
+ ICON_CASE (DOCUMENTS);
+ ICON_CASE (DOWNLOAD);
+ ICON_CASE (MUSIC);
+ ICON_CASE (PICTURES);
+ ICON_CASE (PUBLIC_SHARE);
+ ICON_CASE (TEMPLATES);
+ ICON_CASE (VIDEOS);
+
+ default:
+ return g_themed_icon_new_with_default_fallbacks (ICON_NAME_FOLDER);
+ }
+
+#undef ICON_CASE
+}
+
+static GtkWidget *
+cc_sharing_panel_new_media_sharing_row (const char *uri_or_path,
+ CcSharingPanel *self)
+{
+ GtkWidget *row, *w;
+ GUserDirectory dir = G_USER_N_DIRECTORIES;
+ g_autoptr(GIcon) icon = NULL;
+ guint i;
+ g_autofree gchar *basename = NULL;
+ g_autofree gchar *path = NULL;
+ g_autoptr(GFile) file = NULL;
+
+ file = g_file_new_for_commandline_arg (uri_or_path);
+ path = g_file_get_path (file);
+
+ row = adw_action_row_new ();
+
+ /* Find the icon and create it */
+ for (i = 0; i < G_USER_N_DIRECTORIES; i++)
+ {
+ if (g_strcmp0 (path, g_get_user_special_dir (i)) == 0)
+ {
+ dir = i;
+ break;
+ }
+ }
+
+ icon = special_directory_get_gicon (dir);
+ adw_action_row_add_prefix (ADW_ACTION_ROW (row),
+ gtk_image_new_from_gicon (icon));
+
+ /* Label */
+ basename = g_filename_display_basename (path);
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row), basename);
+
+ /* Remove button */
+ w = gtk_button_new_from_icon_name ("window-close-symbolic");
+ gtk_widget_add_css_class (w, "flat");
+ gtk_widget_set_valign (w, GTK_ALIGN_CENTER);
+ gtk_accessible_update_property (GTK_ACCESSIBLE (w),
+ GTK_ACCESSIBLE_PROPERTY_LABEL, _("Remove"),
+ -1);
+ adw_action_row_add_suffix (ADW_ACTION_ROW (row), w);
+ g_signal_connect_object (G_OBJECT (w), "clicked",
+ G_CALLBACK (cc_sharing_panel_remove_folder), self, G_CONNECT_SWAPPED);
+ g_object_set_data (G_OBJECT (w), "row", row);
+
+ g_object_set_data_full (G_OBJECT (row), "path", g_steal_pointer (&path), g_free);
+
+ return row;
+}
+
+static GtkWidget *
+cc_sharing_panel_new_add_media_sharing_row (CcSharingPanel *self)
+{
+ GtkWidget *row, *box, *w;
+
+ row = gtk_list_box_row_new ();
+ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), box);
+
+ w = gtk_image_new_from_icon_name ("list-add-symbolic");
+ gtk_widget_set_hexpand (w, TRUE);
+ gtk_widget_set_margin_top (w, 12);
+ gtk_widget_set_margin_bottom (w, 12);
+ gtk_accessible_update_property (GTK_ACCESSIBLE (w),
+ GTK_ACCESSIBLE_PROPERTY_LABEL, _("Add"),
+ -1);
+ gtk_box_append (GTK_BOX (box), w);
+
+ g_object_set_data (G_OBJECT (w), "row", row);
+
+ g_object_set_data (G_OBJECT (row), "is-add", GINT_TO_POINTER (1));
+
+ return row;
+}
+
+static GtkWidget *
+create_switch_with_bindings (GtkSwitch *from)
+{
+ GtkWidget *new_switch = gtk_switch_new ();
+
+ g_object_bind_property (from, "visible", new_switch, "visible", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+ g_object_bind_property (from, "state", new_switch, "state", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+ g_object_bind_property (from, "active", new_switch, "active", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+ g_object_bind_property (from, "sensitive", new_switch, "sensitive", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+
+ return new_switch;
+}
+
+static void
+cc_sharing_panel_setup_media_sharing_dialog (CcSharingPanel *self)
+{
+ g_auto(GStrv) folders = NULL;
+ GStrv list;
+ GtkWidget *row, *networks, *w;
+ g_autofree gchar *path = NULL;
+
+ path = g_find_program_in_path ("rygel");
+ if (path == NULL)
+ {
+ gtk_widget_hide (self->media_sharing_row);
+ return;
+ }
+
+ g_signal_connect_object (self->media_sharing_dialog, "response",
+ G_CALLBACK (cc_sharing_panel_media_sharing_dialog_response),
+ self, G_CONNECT_SWAPPED);
+
+ cc_media_sharing_get_preferences (&folders);
+
+ list = folders;
+ while (list && *list)
+ {
+ row = cc_sharing_panel_new_media_sharing_row (*list, self);
+ gtk_list_box_insert (GTK_LIST_BOX (self->shared_folders_listbox), row, -1);
+ list++;
+ }
+
+ row = cc_sharing_panel_new_add_media_sharing_row (self);
+ gtk_list_box_append (GTK_LIST_BOX (self->shared_folders_listbox), row);
+
+ g_signal_connect_object (self->shared_folders_listbox, "row-activated",
+ G_CALLBACK (cc_sharing_panel_add_folder), self, G_CONNECT_SWAPPED);
+
+ networks = cc_sharing_networks_new (self->sharing_proxy, "rygel");
+ gtk_grid_attach (GTK_GRID (self->shared_folders_grid), networks, 0, 4, 2, 1);
+
+ w = create_switch_with_bindings (GTK_SWITCH (g_object_get_data (G_OBJECT (networks), "switch")));
+ gtk_accessible_update_property (GTK_ACCESSIBLE (w),
+ GTK_ACCESSIBLE_PROPERTY_LABEL, _("Enable media sharing"),
+ -1);
+ gtk_header_bar_pack_start (GTK_HEADER_BAR (self->media_sharing_headerbar), w);
+ self->media_sharing_switch = w;
+
+ cc_sharing_panel_bind_networks_to_label (self, networks,
+ self->media_sharing_row);
+}
+
+static void
+cc_sharing_panel_setup_label (CcSharingPanel *self,
+ GtkWidget *label,
+ const gchar *hostname)
+{
+ g_autofree gchar *text = NULL;
+
+ if (label == self->personal_file_sharing_label)
+ {
+ g_autofree gchar *url = g_strdup_printf ("<a href=\"dav://%s\">dav://%s</a>", hostname, hostname);
+ /* TRANSLATORS: %s is replaced with a link to a dav://<hostname> URL */
+ text = g_strdup_printf (_("File Sharing allows you to share your Public folder with others on your current network using: %s"), url);
+ }
+ else if (label == self->remote_login_label)
+ {
+ g_autofree gchar *command = g_strdup_printf ("<a href=\"ssh %s\">ssh %s</a>", hostname, hostname);
+ /* TRANSLATORS: %s is replaced with a link to a "ssh <hostname>" command to run */
+ text = g_strdup_printf (_("When remote login is enabled, remote users can connect using the Secure Shell command:\n%s"), command);
+ }
+ else if (label == self->remote_desktop_address_label)
+ {
+ text = g_strdup_printf ("ms-rd://%s", hostname);
+ }
+ else
+ g_assert_not_reached ();
+
+ gtk_label_set_label (GTK_LABEL (label), text);
+}
+
+typedef struct
+{
+ CcSharingPanel *panel;
+ GtkWidget *label;
+} GetHostNameData;
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (GetHostNameData, g_free);
+
+static void
+cc_sharing_panel_get_host_name_fqdn_done (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GDBusConnection *connection = G_DBUS_CONNECTION (object);
+ g_autoptr(GetHostNameData) data = user_data;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) variant = NULL;
+ const gchar *fqdn;
+
+ variant = g_dbus_connection_call_finish (connection, res, &error);
+
+ if (variant == NULL)
+ {
+ /* Avahi service may not be available */
+ g_debug ("Error calling GetHostNameFqdn: %s", error->message);
+
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ g_autofree gchar *hostname = NULL;
+
+ hostname = cc_hostname_entry_get_hostname (CC_HOSTNAME_ENTRY (data->panel->hostname_entry));
+
+ cc_sharing_panel_setup_label (data->panel, data->label, hostname);
+ }
+
+ return;
+ }
+
+ g_variant_get (variant, "(&s)", &fqdn);
+
+ cc_sharing_panel_setup_label (data->panel, data->label, fqdn);
+}
+
+static void
+cc_sharing_panel_bus_ready (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GDBusConnection) connection = NULL;
+ g_autoptr(GetHostNameData) data = user_data;
+ g_autoptr(GError) error = NULL;
+
+ connection = g_bus_get_finish (res, &error);
+
+ if (connection == NULL)
+ {
+ g_warning ("Could not connect to system bus: %s", error->message);
+
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ g_autofree gchar *hostname = NULL;
+
+ hostname = cc_hostname_entry_get_hostname (CC_HOSTNAME_ENTRY (data->panel->hostname_entry));
+
+ cc_sharing_panel_setup_label (data->panel, data->label, hostname);
+ }
+
+ return;
+ }
+
+ g_dbus_connection_call (connection,
+ "org.freedesktop.Avahi",
+ "/",
+ "org.freedesktop.Avahi.Server",
+ "GetHostNameFqdn",
+ NULL,
+ (GVariantType*)"(s)",
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cc_panel_get_cancellable (CC_PANEL (data->panel)),
+ cc_sharing_panel_get_host_name_fqdn_done,
+ data);
+ g_steal_pointer (&data);
+}
+
+
+static void
+cc_sharing_panel_setup_label_with_hostname (CcSharingPanel *self,
+ GtkWidget *label)
+
+{
+ GetHostNameData *get_hostname_data;
+
+ /* set the hostname */
+ get_hostname_data = g_new (GetHostNameData, 1);
+ get_hostname_data->panel = self;
+ get_hostname_data->label = label;
+ g_bus_get (G_BUS_TYPE_SYSTEM,
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ cc_sharing_panel_bus_ready,
+ get_hostname_data);
+}
+
+static gboolean
+file_sharing_get_require_password (GValue *value,
+ GVariant *variant,
+ gpointer user_data)
+{
+ if (g_str_equal (g_variant_get_string (variant, NULL), "always"))
+ g_value_set_boolean (value, TRUE);
+ else
+ g_value_set_boolean (value, FALSE);
+
+ return TRUE;
+}
+
+static GVariant *
+file_sharing_set_require_password (const GValue *value,
+ const GVariantType *type,
+ gpointer user_data)
+{
+ if (g_value_get_boolean (value))
+ return g_variant_new_string ("always");
+ else
+ return g_variant_new_string ("never");
+}
+
+static void
+file_sharing_password_changed (GtkEntry *entry)
+{
+ file_share_write_out_password (gtk_editable_get_text (GTK_EDITABLE (entry)));
+}
+
+static void
+cc_sharing_panel_setup_personal_file_sharing_dialog (CcSharingPanel *self)
+{
+ GSettings *settings;
+ GtkWidget *networks, *w;
+
+ cc_sharing_panel_bind_switch_to_widgets (self->personal_file_sharing_require_password_switch,
+ self->personal_file_sharing_password_entry,
+ self->personal_file_sharing_password_label,
+ NULL);
+
+ cc_sharing_panel_setup_label_with_hostname (self,
+ self->personal_file_sharing_label);
+
+ /* the password cannot be read, so just make sure the entry is not empty */
+ gtk_editable_set_text (GTK_EDITABLE (self->personal_file_sharing_password_entry),
+ "password");
+
+ settings = g_settings_new (FILE_SHARING_SCHEMA_ID);
+ g_settings_bind_with_mapping (settings, "require-password",
+ self->personal_file_sharing_require_password_switch,
+ "active",
+ G_SETTINGS_BIND_DEFAULT,
+ file_sharing_get_require_password,
+ file_sharing_set_require_password, NULL, NULL);
+
+ g_signal_connect (self->personal_file_sharing_password_entry,
+ "notify::text", G_CALLBACK (file_sharing_password_changed),
+ NULL);
+
+ networks = cc_sharing_networks_new (self->sharing_proxy, "gnome-user-share-webdav");
+ gtk_grid_attach (GTK_GRID (self->personal_file_sharing_grid), networks, 0, 3, 2, 1);
+
+ w = create_switch_with_bindings (GTK_SWITCH (g_object_get_data (G_OBJECT (networks), "switch")));
+ gtk_accessible_update_property (GTK_ACCESSIBLE (w),
+ GTK_ACCESSIBLE_PROPERTY_LABEL, _("Enable personal media sharing"),
+ -1);
+ gtk_header_bar_pack_start (GTK_HEADER_BAR (self->personal_file_sharing_headerbar), w);
+ self->personal_file_sharing_switch = w;
+
+ cc_sharing_panel_bind_networks_to_label (self,
+ networks,
+ self->personal_file_sharing_row);
+}
+
+static void
+remote_login_switch_activate (CcSharingPanel *self)
+{
+ cc_remote_login_set_enabled (cc_panel_get_cancellable (CC_PANEL (self)), GTK_SWITCH (self->remote_login_switch));
+}
+
+static void
+cc_sharing_panel_setup_remote_login_dialog (CcSharingPanel *self)
+{
+ cc_sharing_panel_bind_switch_to_label (self, self->remote_login_switch,
+ self->remote_login_row);
+
+ cc_sharing_panel_setup_label_with_hostname (self, self->remote_login_label);
+
+ g_signal_connect_object (self->remote_login_switch, "notify::active",
+ G_CALLBACK (remote_login_switch_activate), self, G_CONNECT_SWAPPED);
+ gtk_widget_set_sensitive (self->remote_login_switch, FALSE);
+
+ cc_remote_login_get_enabled (cc_panel_get_cancellable (CC_PANEL (self)),
+ GTK_SWITCH (self->remote_login_switch),
+ self->remote_login_row);
+}
+
+static gboolean
+cc_sharing_panel_check_schema_available (CcSharingPanel *self,
+ const gchar *schema_id)
+{
+ GSettingsSchemaSource *source;
+ g_autoptr(GSettingsSchema) schema = NULL;
+
+ source = g_settings_schema_source_get_default ();
+ if (!source)
+ return FALSE;
+
+ schema = g_settings_schema_source_lookup (source, schema_id, TRUE);
+ if (!schema)
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+store_remote_desktop_credentials_timeout (gpointer user_data)
+{
+ CcSharingPanel *self = CC_SHARING_PANEL (user_data);
+ const char *username, *password;
+
+ username = gtk_editable_get_text (GTK_EDITABLE (self->remote_desktop_username_entry));
+ password = gtk_editable_get_text (GTK_EDITABLE (self->remote_desktop_password_entry));
+
+ if (username && password)
+ {
+ cc_grd_store_rdp_credentials (username, password,
+ cc_panel_get_cancellable (CC_PANEL (self)));
+ }
+
+ self->remote_desktop_store_credentials_id = 0;
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+remote_desktop_credentials_changed (CcSharingPanel *self)
+{
+ g_clear_handle_id (&self->remote_desktop_store_credentials_id,
+ g_source_remove);
+
+ self->remote_desktop_store_credentials_id =
+ g_timeout_add_seconds (REMOTE_DESKTOP_STORE_CREDENTIALS_TIMEOUT_S,
+ store_remote_desktop_credentials_timeout,
+ self);
+}
+
+static gboolean
+is_remote_desktop_enabled (CcSharingPanel *self)
+{
+ g_autoptr(GSettings) rdp_settings = NULL;
+
+ rdp_settings = g_settings_new (GNOME_REMOTE_DESKTOP_RDP_SCHEMA_ID);
+
+ if (!g_settings_get_boolean (rdp_settings, "enable"))
+ return FALSE;
+
+ return cc_is_service_active (REMOTE_DESKTOP_SERVICE, G_BUS_TYPE_SESSION);
+}
+
+static void
+enable_gnome_remote_desktop_service (CcSharingPanel *self)
+{
+ g_autoptr(GError) error = NULL;
+
+ if (is_remote_desktop_enabled (self))
+ return;
+
+ if (!cc_enable_service (REMOTE_DESKTOP_SERVICE,
+ G_BUS_TYPE_SESSION,
+ &error))
+ g_warning ("Failed to enable remote desktop service: %s", error->message);
+}
+
+static void
+disable_gnome_remote_desktop_service (CcSharingPanel *self)
+{
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GSettings) rdp_settings = NULL;
+
+ rdp_settings = g_settings_new (GNOME_REMOTE_DESKTOP_RDP_SCHEMA_ID);
+
+ g_settings_set_boolean (rdp_settings, "enable", FALSE);
+
+ if (!cc_disable_service (REMOTE_DESKTOP_SERVICE,
+ G_BUS_TYPE_SESSION,
+ &error))
+ g_warning ("Failed to enable remote desktop service: %s", error->message);
+}
+
+static void
+calc_default_tls_paths (char **out_dir_path,
+ char **out_cert_path,
+ char **out_key_path)
+{
+ g_autofree char *dir_path = NULL;
+
+ dir_path = g_strdup_printf ("%s/gnome-remote-desktop",
+ g_get_user_data_dir ());
+
+ if (out_cert_path)
+ *out_cert_path = g_strdup_printf ("%s/rdp-tls.crt", dir_path);
+ if (out_key_path)
+ *out_key_path = g_strdup_printf ("%s/rdp-tls.key", dir_path);
+
+ if (out_dir_path)
+ *out_dir_path = g_steal_pointer (&dir_path);
+}
+
+static void
+set_tls_certificate (CcSharingPanel *self,
+ GTlsCertificate *tls_certificate)
+{
+ g_set_object (&self->remote_desktop_certificate,
+ tls_certificate);
+ gtk_widget_set_sensitive (self->remote_desktop_verify_encryption, TRUE);
+}
+
+static void
+on_certificate_generated (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcSharingPanel *self;
+ g_autoptr(GTlsCertificate) tls_certificate = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autofree char *cert_path = NULL;
+ g_autofree char *key_path = NULL;
+ g_autoptr(GSettings) rdp_settings = NULL;
+
+ tls_certificate = bonsai_tls_certificate_new_generate_finish (res, &error);
+ if (!tls_certificate)
+ {
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
+ g_warning ("Failed to generate TLS certificate: %s", error->message);
+ return;
+ }
+
+ self = CC_SHARING_PANEL (user_data);
+
+ calc_default_tls_paths (NULL, &cert_path, &key_path);
+
+ rdp_settings = g_settings_new (GNOME_REMOTE_DESKTOP_RDP_SCHEMA_ID);
+
+ g_settings_set_string (rdp_settings, "tls-cert", cert_path);
+ g_settings_set_string (rdp_settings, "tls-key", key_path);
+
+ set_tls_certificate (self, tls_certificate);
+
+ enable_gnome_remote_desktop_service (self);
+}
+
+static void
+enable_gnome_remote_desktop (CcSharingPanel *self)
+{
+ g_autofree char *dir_path = NULL;
+ g_autofree char *cert_path = NULL;
+ g_autofree char *key_path = NULL;
+ g_autoptr(GFile) dir = NULL;
+ g_autoptr(GFile) cert_file = NULL;
+ g_autoptr(GFile) key_file = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GSettings) rdp_settings = NULL;
+
+ rdp_settings = g_settings_new (GNOME_REMOTE_DESKTOP_RDP_SCHEMA_ID);
+
+ g_settings_set_boolean (rdp_settings, "enable", TRUE);
+
+ cert_path = g_settings_get_string (rdp_settings, "tls-cert");
+ key_path = g_settings_get_string (rdp_settings, "tls-key");
+ if (strlen (cert_path) > 0 &&
+ strlen (key_path) > 0)
+ {
+ g_autoptr(GTlsCertificate) tls_certificate = NULL;
+
+ tls_certificate = g_tls_certificate_new_from_file (cert_path, &error);
+ if (tls_certificate)
+ {
+ set_tls_certificate (self, tls_certificate);
+
+ enable_gnome_remote_desktop_service (self);
+ return;
+ }
+
+ g_warning ("Configured TLS certificate invalid: %s", error->message);
+ return;
+ }
+
+ calc_default_tls_paths (&dir_path, &cert_path, &key_path);
+
+ dir = g_file_new_for_path (dir_path);
+ if (!g_file_query_exists (dir, NULL))
+ {
+ if (!g_file_make_directory_with_parents (dir, NULL, &error))
+ {
+ g_warning ("Failed to create remote desktop certificate directory: %s",
+ error->message);
+ return;
+ }
+ }
+
+ cert_file = g_file_new_for_path (cert_path);
+ key_file = g_file_new_for_path (key_path);
+
+ if (g_file_query_exists (cert_file, NULL) &&
+ g_file_query_exists (key_file, NULL))
+ {
+ g_autoptr(GTlsCertificate) tls_certificate = NULL;
+
+ tls_certificate = g_tls_certificate_new_from_file (cert_path, &error);
+ if (tls_certificate)
+ {
+ g_settings_set_string (rdp_settings, "tls-cert", cert_path);
+ g_settings_set_string (rdp_settings, "tls-key", key_path);
+
+ set_tls_certificate (self, tls_certificate);
+
+ enable_gnome_remote_desktop_service (self);
+ return;
+ }
+
+ g_warning ("Existing TLS certificate invalid: %s", error->message);
+ return;
+ }
+
+ bonsai_tls_certificate_new_generate_async (cert_path,
+ key_path,
+ "US",
+ "GNOME",
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ on_certificate_generated,
+ self);
+}
+
+static void
+on_remote_desktop_state_changed (GtkWidget *widget,
+ GParamSpec *pspec,
+ CcSharingPanel *self)
+{
+ if (gtk_switch_get_active (GTK_SWITCH (widget)))
+ enable_gnome_remote_desktop (self);
+ else
+ disable_gnome_remote_desktop_service (self);
+}
+
+static char *
+get_hostname (void)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+ g_autoptr(GVariant) res = NULL;
+ g_autoptr(GVariant) inner = NULL;
+ g_autoptr(GError) error = NULL;
+ const char *hostname;
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (bus == NULL)
+ {
+ g_warning ("Failed to get system bus connection: %s", error->message);
+ return NULL;
+ }
+ res = g_dbus_connection_call_sync (bus,
+ "org.freedesktop.hostname1",
+ "/org/freedesktop/hostname1",
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ g_variant_new ("(ss)",
+ "org.freedesktop.hostname1",
+ "PrettyHostname"),
+ (GVariantType*)"(v)",
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if (res == NULL)
+ {
+ g_warning ("Getting pretty hostname failed: %s", error->message);
+ return NULL;
+ }
+
+ g_variant_get (res, "(v)", &inner);
+ hostname = g_variant_get_string (inner, NULL);
+ if (g_strcmp0 (hostname, "") != 0)
+ return g_strdup (hostname);
+
+ g_clear_pointer (&inner, g_variant_unref);
+ g_clear_pointer (&res, g_variant_unref);
+
+ res = g_dbus_connection_call_sync (bus,
+ "org.freedesktop.hostname1",
+ "/org/freedesktop/hostname1",
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ g_variant_new ("(ss)",
+ "org.freedesktop.hostname1",
+ "Hostname"),
+ (GVariantType*)"(v)",
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if (res == NULL)
+ {
+ g_warning ("Getting hostname failed: %s", error->message);
+ return NULL;
+ }
+
+ g_variant_get (res, "(v)", &inner);
+ return g_variant_dup_string (inner, NULL);
+}
+
+static void
+add_toast (CcSharingPanel *self,
+ const char *message)
+{
+ adw_toast_overlay_add_toast (ADW_TOAST_OVERLAY (self->remote_desktop_toast_overlay),
+ adw_toast_new (message));
+}
+
+static void
+on_device_name_copy_clicked (GtkButton *button,
+ CcSharingPanel *self)
+{
+ GtkLabel *label = GTK_LABEL (self->remote_desktop_device_name_label);
+
+ gdk_clipboard_set_text (gtk_widget_get_clipboard (GTK_WIDGET (button)),
+ gtk_label_get_text (label));
+ add_toast (self, _("Device name copied"));
+}
+
+static void
+on_device_address_copy_clicked (GtkButton *button,
+ CcSharingPanel *self)
+{
+ GtkLabel *label = GTK_LABEL (self->remote_desktop_address_label);
+
+ gdk_clipboard_set_text (gtk_widget_get_clipboard (GTK_WIDGET (button)),
+ gtk_label_get_text (label));
+ add_toast (self, _("Device address copied"));
+}
+
+static void
+on_username_copy_clicked (GtkButton *button,
+ CcSharingPanel *self)
+{
+ GtkEditable *editable = GTK_EDITABLE (self->remote_desktop_username_entry);
+
+ gdk_clipboard_set_text (gtk_widget_get_clipboard (GTK_WIDGET (button)),
+ gtk_editable_get_text (editable));
+ add_toast (self, _("Username copied"));
+}
+
+static void
+on_password_copy_clicked (GtkButton *button,
+ CcSharingPanel *self)
+{
+ GtkEditable *editable = GTK_EDITABLE (self->remote_desktop_password_entry);
+
+ gdk_clipboard_set_text (gtk_widget_get_clipboard (GTK_WIDGET (button)),
+ gtk_editable_get_text (editable));
+ add_toast (self, _("Password copied"));
+}
+
+static pwquality_settings_t *
+get_pwq (void)
+{
+ static pwquality_settings_t *settings;
+
+ if (settings == NULL)
+ {
+ gchar *err = NULL;
+ gint rv = 0;
+
+ settings = pwquality_default_settings ();
+ pwquality_set_int_value (settings, PWQ_SETTING_MAX_SEQUENCE, 4);
+
+ rv = pwquality_read_config (settings, NULL, (gpointer)&err);
+ if (rv < 0)
+ {
+ g_warning ("Failed to read pwquality configuration: %s\n",
+ pwquality_strerror (NULL, 0, rv, err));
+ pwquality_free_settings (settings);
+
+ /* Load just default settings in case of failure. */
+ settings = pwquality_default_settings ();
+ pwquality_set_int_value (settings, PWQ_SETTING_MAX_SEQUENCE, 4);
+ }
+ }
+
+ return settings;
+}
+
+static char *
+pw_generate (void)
+{
+ char *res;
+ int rv;
+
+ rv = pwquality_generate (get_pwq (), 0, &res);
+
+ if (rv < 0) {
+ g_warning ("Password generation failed: %s\n",
+ pwquality_strerror (NULL, 0, rv, NULL));
+ return NULL;
+ }
+
+ return res;
+}
+
+static void
+cc_sharing_panel_setup_remote_desktop_dialog (CcSharingPanel *self)
+{
+ const gchar *username = NULL;
+ const gchar *password = NULL;
+ g_autoptr(GSettings) rdp_settings = NULL;
+ g_autofree char *hostname = NULL;
+
+ cc_sharing_panel_bind_switch_to_label (self, self->remote_desktop_switch,
+ self->remote_desktop_row);
+
+ cc_sharing_panel_setup_label_with_hostname (self, self->remote_desktop_address_label);
+
+ rdp_settings = g_settings_new (GNOME_REMOTE_DESKTOP_RDP_SCHEMA_ID);
+
+ g_settings_bind (rdp_settings,
+ "view-only",
+ self->remote_control_switch,
+ "active",
+ G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_INVERT_BOOLEAN);
+ g_object_bind_property (self->remote_desktop_switch, "state",
+ self->remote_control_switch, "sensitive",
+ G_BINDING_SYNC_CREATE);
+
+ hostname = get_hostname ();
+ gtk_label_set_label (GTK_LABEL (self->remote_desktop_device_name_label),
+ hostname);
+
+ username = cc_grd_lookup_rdp_username (cc_panel_get_cancellable (CC_PANEL (self)));
+ password = cc_grd_lookup_rdp_password (cc_panel_get_cancellable (CC_PANEL (self)));
+ if (username != NULL)
+ gtk_editable_set_text (GTK_EDITABLE (self->remote_desktop_username_entry), username);
+ if (password != NULL)
+ gtk_editable_set_text (GTK_EDITABLE (self->remote_desktop_password_entry), password);
+
+ g_signal_connect_swapped (self->remote_desktop_username_entry,
+ "notify::text",
+ G_CALLBACK (remote_desktop_credentials_changed),
+ self);
+ g_signal_connect_swapped (self->remote_desktop_password_entry,
+ "notify::text",
+ G_CALLBACK (remote_desktop_credentials_changed),
+ self);
+ if (username == NULL)
+ {
+ struct passwd *pw = getpwuid (getuid ());
+ if (pw != NULL)
+ {
+ gtk_editable_set_text (GTK_EDITABLE (self->remote_desktop_username_entry),
+ pw->pw_name);
+ }
+ else
+ {
+ g_warning ("Failed to get username: %s", g_strerror (errno));
+ }
+ }
+
+ if (password == NULL)
+ {
+ char * pw = pw_generate ();
+ if (pw)
+ gtk_editable_set_text (GTK_EDITABLE (self->remote_desktop_password_entry),
+ pw );
+ }
+ g_signal_connect (self->remote_desktop_device_name_copy,
+ "clicked", G_CALLBACK (on_device_name_copy_clicked),
+ self);
+ g_signal_connect (self->remote_desktop_address_copy,
+ "clicked", G_CALLBACK (on_device_address_copy_clicked),
+ self);
+ g_signal_connect (self->remote_desktop_username_copy,
+ "clicked", G_CALLBACK (on_username_copy_clicked),
+ self);
+ g_signal_connect (self->remote_desktop_password_copy,
+ "clicked", G_CALLBACK (on_password_copy_clicked),
+ self);
+
+ g_signal_connect (self->remote_desktop_switch, "notify::state",
+ G_CALLBACK (on_remote_desktop_state_changed), self);
+
+ if (is_remote_desktop_enabled (self))
+ {
+ gtk_switch_set_active (GTK_SWITCH (self->remote_desktop_switch),
+ TRUE);
+ }
+}
+
+static void
+remote_desktop_name_appeared (GDBusConnection *connection,
+ const gchar *name,
+ const gchar *name_owner,
+ gpointer user_data)
+{
+ CcSharingPanel *self = CC_SHARING_PANEL (user_data);
+
+ g_bus_unwatch_name (self->remote_desktop_name_watch);
+ self->remote_desktop_name_watch = 0;
+
+ cc_sharing_panel_setup_remote_desktop_dialog (self);
+ gtk_widget_show (self->remote_desktop_row);
+}
+
+static void
+check_remote_desktop_available (CcSharingPanel *self)
+{
+ if (!cc_sharing_panel_check_schema_available (self, GNOME_REMOTE_DESKTOP_SCHEMA_ID))
+ return;
+
+ if (!cc_sharing_panel_check_schema_available (self, GNOME_REMOTE_DESKTOP_RDP_SCHEMA_ID))
+ return;
+
+ self->remote_desktop_name_watch = g_bus_watch_name (G_BUS_TYPE_SESSION,
+ "org.gnome.Mutter.RemoteDesktop",
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ remote_desktop_name_appeared,
+ NULL,
+ self,
+ NULL);
+}
+
+static void
+sharing_proxy_ready (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcSharingPanel *self;
+ GDBusProxy *proxy;
+ g_autoptr(GError) error = NULL;
+
+ proxy = G_DBUS_PROXY (gsd_sharing_proxy_new_for_bus_finish (res, &error));
+ if (!proxy) {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to get sharing proxy: %s", error->message);
+ return;
+ }
+
+ self = CC_SHARING_PANEL (user_data);
+ self->sharing_proxy = proxy;
+
+ /* media sharing */
+ cc_sharing_panel_setup_media_sharing_dialog (self);
+
+ /* personal file sharing */
+ if (cc_sharing_panel_check_schema_available (self, FILE_SHARING_SCHEMA_ID))
+ cc_sharing_panel_setup_personal_file_sharing_dialog (self);
+ else
+ gtk_widget_hide (self->personal_file_sharing_row);
+
+ /* remote login */
+ cc_sharing_panel_setup_remote_login_dialog (self);
+
+ /* screen sharing */
+ check_remote_desktop_available (self);
+ gtk_widget_hide (self->remote_desktop_row);
+}
+
+static void
+cc_sharing_panel_init (CcSharingPanel *self)
+{
+ g_autoptr(GtkCssProvider) provider = NULL;
+
+ g_resources_register (cc_sharing_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ g_signal_connect_object (self->main_list_box, "row-activated",
+ G_CALLBACK (cc_sharing_panel_main_list_box_row_activated), self, G_CONNECT_SWAPPED);
+
+ g_signal_connect (self->media_sharing_dialog, "response",
+ G_CALLBACK (gtk_widget_hide), NULL);
+ g_signal_connect (self->personal_file_sharing_dialog, "response",
+ G_CALLBACK (gtk_widget_hide), NULL);
+ g_signal_connect (self->remote_login_dialog, "response",
+ G_CALLBACK (gtk_widget_hide), NULL);
+ g_signal_connect (self->remote_desktop_dialog, "response",
+ G_CALLBACK (gtk_widget_hide), NULL);
+
+ gtk_list_box_set_activate_on_single_click (GTK_LIST_BOX (self->main_list_box),
+ TRUE);
+
+ /* start the panel in the disabled state */
+ gtk_switch_set_active (GTK_SWITCH (self->master_switch), FALSE);
+ gtk_widget_set_sensitive (self->main_list_box, FALSE);
+ g_signal_connect_object (self->master_switch, "notify::active",
+ G_CALLBACK (cc_sharing_panel_master_switch_notify), self, G_CONNECT_SWAPPED);
+
+ gsd_sharing_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "org.gnome.SettingsDaemon.Sharing",
+ "/org/gnome/SettingsDaemon/Sharing",
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ sharing_proxy_ready,
+ self);
+
+ /* make sure the hostname entry isn't focused by default */
+ g_signal_connect_swapped (self, "map", G_CALLBACK (gtk_widget_grab_focus),
+ self->main_list_box);
+
+ provider = gtk_css_provider_new ();
+ gtk_css_provider_load_from_resource (provider,
+ "/org/gnome/control-center/sharing/sharing.css");
+ gtk_style_context_add_provider_for_display (gdk_display_get_default (),
+ GTK_STYLE_PROVIDER (provider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+}
+
+CcSharingPanel *
+cc_sharing_panel_new (void)
+{
+ return g_object_new (CC_TYPE_SHARING_PANEL, NULL);
+}
diff --git a/panels/sharing/cc-sharing-panel.h b/panels/sharing/cc-sharing-panel.h
new file mode 100644
index 0000000..b8b69ab
--- /dev/null
+++ b/panels/sharing/cc-sharing-panel.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2013 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ *
+ */
+
+#pragma once
+
+#include <shell/cc-shell.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_SHARING_PANEL (cc_sharing_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcSharingPanel, cc_sharing_panel, CC, SHARING_PANEL, CcPanel)
+
+CcSharingPanel *cc_sharing_panel_new (void);
+
+G_END_DECLS
diff --git a/panels/sharing/cc-sharing-panel.ui b/panels/sharing/cc-sharing-panel.ui
new file mode 100644
index 0000000..e02ca68
--- /dev/null
+++ b/panels/sharing/cc-sharing-panel.ui
@@ -0,0 +1,537 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcSharingPanel" parent="CcPanel">
+
+ <child type="titlebar-end">
+ <object class="GtkSwitch" id="master_switch">
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Sharing</property>
+ </accessibility>
+ </object>
+ </child>
+
+ <child type="content">
+ <object class="GtkScrolledWindow" id="sharing_panel">
+ <property name="hscrollbar-policy">never</property>
+ <child>
+ <object class="AdwClamp">
+ <property name="margin_top">32</property>
+ <property name="margin_bottom">32</property>
+ <property name="margin_start">12</property>
+ <property name="margin_end">12</property>
+ <child>
+ <object class="GtkBox">
+ <property name="hexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label6">
+ <property name="margin_bottom">12</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Computer Name</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">hostname_entry</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="CcHostnameEntry" id="hostname_entry">
+ <property name="margin_bottom">32</property>
+ <property name="invisible_char">●</property>
+ <accessibility>
+ <relation name="labelled-by">label6</relation>
+ </accessibility>
+ </object>
+ </child>
+ <child>
+ <object class="GtkListBox" id="main_list_box">
+ <property name="selection-mode">none</property>
+ <style>
+ <class name="boxed-list" />
+ </style>
+ <child>
+ <object class="CcListRow" id="personal_file_sharing_row">
+ <property name="show-arrow">True</property>
+ <property name="use-underline">True</property>
+ <property name="title" translatable="yes">_File Sharing</property>
+ </object>
+ </child>
+ <child>
+ <object class="CcListRow" id="remote_desktop_row">
+ <property name="show-arrow">True</property>
+ <property name="use-underline">True</property>
+ <property name="title" translatable="yes">Remote _Desktop</property>
+ </object>
+ </child>
+ <child>
+ <object class="CcListRow" id="media_sharing_row">
+ <property name="show-arrow">True</property>
+ <property name="use-underline">True</property>
+ <property name="title" translatable="yes">_Media Sharing</property>
+ </object>
+ </child>
+ <child>
+ <object class="CcListRow" id="remote_login_row">
+ <property name="show-arrow">True</property>
+ <property name="use-underline">True</property>
+ <property name="title" translatable="yes">_Remote Login</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GtkDialog" id="personal_file_sharing_dialog">
+ <property name="title" translatable="yes">File Sharing</property>
+ <property name="resizable">False</property>
+ <property name="use_header_bar">1</property>
+ <property name="modal">True</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="spacing">12</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkGrid" id="personal_file_sharing_grid">
+ <property name="margin_start">12</property>
+ <property name="margin_end">6</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="row_spacing">12</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="personal_file_sharing_label">
+ <property name="xalign">0</property>
+ <property name="label">File Sharing allows you to share your Public folder with others on your current network using: &lt;a href="dav://%s"&gt;dav://%s&lt;/a&gt;</property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ <property name="max-width-chars">36</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ <property name="column-span">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkGrid" id="require_password_grid">
+ <property name="row_spacing">12</property>
+ <property name="column_spacing">6</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ <property name="column-span">2</property>
+ </layout>
+ <child>
+ <object class="GtkLabel" id="label17">
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">_Require Password</property>
+ <property name="use_markup">True</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">personal_file_sharing_require_password_switch</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="personal_file_sharing_password_label">
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">_Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">personal_file_sharing_password_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="personal_file_sharing_require_password_switch">
+ <property name="halign">end</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="personal_file_sharing_password_entry">
+ <property name="visibility">False</property>
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ <property name="input_purpose">password</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="titlebar">
+ <object class="GtkHeaderBar" id="personal_file_sharing_headerbar">
+ <property name="show_title_buttons">True</property>
+ </object>
+ </child>
+ </object>
+ <object class="GtkDialog" id="remote_login_dialog">
+ <property name="title" translatable="yes">Remote Login</property>
+ <property name="resizable">False</property>
+ <property name="use_header_bar">1</property>
+ <property name="modal">True</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="spacing">12</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="remote_login_label">
+ <property name="xalign">0</property>
+ <property name="label">When remote login is enabled, remote users can connect using the Secure Shell command:
+&lt;a href="ssh %s"&gt;ssh %s&lt;/a&gt;</property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ <property name="max-width-chars">36</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <style>
+ <class name="frame"/>
+ <class name="view"/>
+ </style>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Remote Login</property>
+ <property name="hexpand">True</property>
+ <property name="xalign">0</property>
+ <property name="mnemonic_widget">remote_login_switch</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="remote_login_switch">
+ <property name="halign">end</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ <object class="GtkDialog" id="remote_desktop_dialog">
+ <property name="title" translatable="yes">Remote Desktop</property>
+ <property name="modal">True</property>
+ <property name="default-width">640</property>
+ <child type="titlebar">
+ <object class="GtkHeaderBar">
+ <property name="show_title_buttons">True</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwToastOverlay" id="remote_desktop_toast_overlay">
+ <child>
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="description" translatable="yes">Remote desktop allows viewing and controlling your desktop from another computer.</property>
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Remote Desktop</property>
+ <property name="subtitle" translatable="yes">Enable or disable remote desktop connections to this computer.</property>
+ <property name="activatable_widget">remote_desktop_switch</property>
+ <child type="suffix">
+ <object class="GtkSwitch" id="remote_desktop_switch">
+ <property name="state">False</property>
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Remote Control</property>
+ <property name="subtitle" translatable="yes">Allows remote connections to control the screen.</property>
+ <property name="activatable_widget">remote_control_switch</property>
+ <child type="suffix">
+ <object class="GtkSwitch" id="remote_control_switch">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">How to Connect</property>
+ <property name="description" translatable="yes">Connect to this computer using the device name or remote desktop address.</property>
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Device Name</property>
+ <child type="suffix">
+ <object class="GtkBox">
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkLabel" id="remote_desktop_device_name_label">
+ <property name="selectable">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="remote_desktop_device_name_copy">
+ <property name="valign">center</property>
+ <property name="icon-name">edit-copy-symbolic</property>
+ <accessibility>
+ <property name="label" translatable="yes">Copy</property>
+ </accessibility>
+ <style>
+ <class name="flat"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Remote Desktop Address</property>
+ <child type="suffix">
+ <object class="GtkBox">
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkLabel" id="remote_desktop_address_label">
+ <property name="selectable">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="remote_desktop_address_copy">
+ <property name="valign">center</property>
+ <property name="icon-name">edit-copy-symbolic</property>
+ <accessibility>
+ <property name="label" translatable="yes">Copy</property>
+ </accessibility>
+ <style>
+ <class name="flat"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Authentication</property>
+ <property name="description" translatable="yes">The user name and password are required to connect to this computer.</property>
+
+ <child>
+ <object class="AdwEntryRow" id="remote_desktop_username_entry">
+ <property name="title" translatable="yes">User Name</property>
+ <child type="suffix">
+ <object class="GtkButton" id="remote_desktop_username_copy">
+ <property name="valign">center</property>
+ <property name="icon-name">edit-copy-symbolic</property>
+ <accessibility>
+ <property name="label" translatable="yes">Copy</property>
+ </accessibility>
+ <style>
+ <class name="flat"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPasswordEntryRow" id="remote_desktop_password_entry">
+ <property name="title" translatable="yes">Password</property>
+ <child type="suffix">
+ <object class="GtkButton" id="remote_desktop_password_copy">
+ <property name="valign">center</property>
+ <property name="icon-name">edit-copy-symbolic</property>
+ <accessibility>
+ <property name="label" translatable="yes">Copy</property>
+ </accessibility>
+ <style>
+ <class name="flat"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkButton" id="remote_desktop_verify_encryption">
+ <property name="sensitive">False</property>
+ <property name="halign">end</property>
+ <property name="margin-top">12</property>
+ <property name="label" translatable="yes">Verify Encryption</property>
+ <signal name="clicked" handler="remote_desktop_show_encryption_fingerprint" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+
+ <object class="AdwWindow" id="remote_desktop_fingerprint_dialog">
+ <property name="default-width">360</property>
+ <property name="default-height">360</property>
+ <property name="hide-on-close">True</property>
+ <property name="modal">True</property>
+
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkWindowControls">
+ <property name="halign">end</property>
+ <property name="side">end</property>
+ </object>
+ </child>
+ <child>
+ <object class="AdwStatusPage">
+ <property name="title" translatable="yes">Encryption Fingerprint</property>
+ <property name="description" translatable="yes">The encryption fingerprint can be seen in connecting clients and should be identical.</property>
+ <property name="vexpand">True</property>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <property name="halign">center</property>
+ <style>
+ <class name="tls-cert-verification" />
+ </style>
+ <child>
+ <object class="GtkLabel" id="remote_desktop_fingerprint_left">
+ <style>
+ <class name="tls-cert-fingerprint" />
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="remote_desktop_fingerprint_right">
+ <style>
+ <class name="tls-cert-fingerprint" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+
+ <object class="GtkDialog" id="media_sharing_dialog">
+ <property name="title" translatable="yes">Media Sharing</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="spacing">12</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkGrid" id="shared_folders_grid">
+ <property name="margin_start">12</property>
+ <property name="margin_end">6</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="row_spacing">12</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label13">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Share music, photos and videos over the network.</property>
+ <property name="max-width-chars">36</property>
+ <property name="wrap">True</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ <property name="column-span">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label15">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Folders</property>
+ <property name="mnemonic_widget">shared_folders_listbox</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ <property name="column-span">2</property>
+ </layout>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkListBox" id="shared_folders_listbox">
+ <property name="selection-mode">none</property>
+ <style>
+ <class name="boxed-list" />
+ </style>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ <property name="column-span">2</property>
+ </layout>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="titlebar">
+ <object class="GtkHeaderBar" id="media_sharing_headerbar">
+ <property name="show_title_buttons">True</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/panels/sharing/cc-systemd-service.c b/panels/sharing/cc-systemd-service.c
new file mode 100644
index 0000000..d2b6346
--- /dev/null
+++ b/panels/sharing/cc-systemd-service.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2013 Intel, Inc
+ * Copyright (C) 2022 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ *
+ */
+
+#include "cc-systemd-service.h"
+
+gboolean
+cc_is_service_active (const char *service,
+ GBusType bus_type)
+{
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GDBusConnection) connection = NULL;
+ g_autoptr(GVariant) unit_path_variant = NULL;
+ g_autofree char *unit_path = NULL;
+ g_autoptr(GVariant) active_state_prop = NULL;
+ g_autoptr(GVariant) active_state_variant = NULL;
+ const char *active_state = NULL;
+ g_autoptr(GVariant) unit_state_prop = NULL;
+ g_autoptr(GVariant) unit_state_variant = NULL;
+ const char *unit_state = NULL;
+
+ connection = g_bus_get_sync (bus_type, NULL, &error);
+ if (!connection)
+ {
+ g_warning ("Failed connecting to D-Bus system bus: %s", error->message);
+ return FALSE;
+ }
+
+ unit_path_variant =
+ g_dbus_connection_call_sync (connection,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "GetUnit",
+ g_variant_new ("(s)",
+ service),
+ (GVariantType *) "(o)",
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ NULL);
+
+ if (!unit_path_variant)
+ return FALSE;
+ g_variant_get_child (unit_path_variant, 0, "o", &unit_path);
+
+ active_state_prop =
+ g_dbus_connection_call_sync (connection,
+ "org.freedesktop.systemd1",
+ unit_path,
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ g_variant_new ("(ss)",
+ "org.freedesktop.systemd1.Unit",
+ "ActiveState"),
+ (GVariantType *) "(v)",
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if (!active_state_prop)
+ {
+ g_warning ("Failed to get service active state: %s", error->message);
+ return FALSE;
+ }
+ g_variant_get_child (active_state_prop, 0, "v", &active_state_variant);
+ active_state = g_variant_get_string (active_state_variant, NULL);
+
+ if (g_strcmp0 (active_state, "active") != 0 &&
+ g_strcmp0 (active_state, "activating") != 0)
+ return FALSE;
+
+ unit_state_prop =
+ g_dbus_connection_call_sync (connection,
+ "org.freedesktop.systemd1",
+ unit_path,
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ g_variant_new ("(ss)",
+ "org.freedesktop.systemd1.Unit",
+ "UnitFileState"),
+ (GVariantType *) "(v)",
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if (!unit_state_prop)
+ {
+ g_warning ("Failed to get service active state: %s", error->message);
+ return FALSE;
+ }
+ g_variant_get_child (unit_state_prop, 0, "v", &unit_state_variant);
+ unit_state = g_variant_get_string (unit_state_variant, NULL);
+
+ if (g_strcmp0 (unit_state, "enabled") == 0 ||
+ g_strcmp0 (unit_state, "static") == 0)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+gboolean
+cc_enable_service (const char *service,
+ GBusType bus_type,
+ GError **error)
+{
+ g_autoptr(GDBusConnection) connection = NULL;
+ g_autoptr(GVariant) start_result = NULL;
+ g_autoptr(GVariant) enable_result = NULL;
+ const char *service_list[] = { service, NULL };
+
+ connection = g_bus_get_sync (bus_type, NULL, error);
+ if (!connection)
+ {
+ g_prefix_error_literal (error, "Failed connecting to D-Bus system bus: ");
+ return FALSE;
+ }
+
+ start_result = g_dbus_connection_call_sync (connection,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "StartUnit",
+ g_variant_new ("(ss)",
+ service,
+ "replace"),
+ (GVariantType *) "(o)",
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ error);
+
+ if (!start_result)
+ {
+ g_prefix_error_literal (error, "Failed to start service: ");
+ return FALSE;
+ }
+
+ enable_result = g_dbus_connection_call_sync (connection,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "EnableUnitFiles",
+ g_variant_new ("(^asbb)",
+ service_list,
+ FALSE, FALSE),
+ (GVariantType *) "(ba(sss))",
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ error);
+
+ if (!enable_result)
+ {
+ g_prefix_error_literal (error, "Failed to enable service: ");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+cc_disable_service (const char *service,
+ GBusType bus_type,
+ GError **error)
+{
+ g_autoptr(GDBusConnection) connection = NULL;
+ g_autoptr(GVariant) stop_result = NULL;
+ g_autoptr(GVariant) disable_result = NULL;
+ const char *service_list[] = { service, NULL };
+
+ connection = g_bus_get_sync (bus_type, NULL, error);
+ if (!connection)
+ {
+ g_prefix_error_literal (error, "Failed connecting to D-Bus system bus: ");
+ return FALSE;
+ }
+
+ stop_result = g_dbus_connection_call_sync (connection,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "StopUnit",
+ g_variant_new ("(ss)", service, "replace"),
+ (GVariantType *) "(o)",
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ error);
+ if (!stop_result)
+ {
+ g_prefix_error_literal (error, "Failed to stop service: ");
+ return FALSE;
+ }
+
+ disable_result = g_dbus_connection_call_sync (connection,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "DisableUnitFiles",
+ g_variant_new ("(^asb)", service_list, FALSE,
+ FALSE),
+ (GVariantType *) "(a(sss))",
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ error);
+
+ if (!stop_result)
+ {
+ g_prefix_error_literal (error, "Failed to disable service: ");
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/panels/sharing/cc-systemd-service.h b/panels/sharing/cc-systemd-service.h
new file mode 100644
index 0000000..89b1d9a
--- /dev/null
+++ b/panels/sharing/cc-systemd-service.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#pragma once
+
+#include <gio/gio.h>
+
+gboolean cc_is_service_active (const char *service,
+ GBusType bus_type);
+
+gboolean cc_enable_service (const char *service,
+ GBusType bus_type,
+ GError **error);
+
+gboolean cc_disable_service (const char *service,
+ GBusType bus_type,
+ GError **error);
diff --git a/panels/sharing/cc-tls-certificate.c b/panels/sharing/cc-tls-certificate.c
new file mode 100644
index 0000000..3b616f8
--- /dev/null
+++ b/panels/sharing/cc-tls-certificate.c
@@ -0,0 +1,511 @@
+/* cc-tls-certificate.c
+ *
+ * Copyright 2018 Christian Hergert <chergert@redhat.com>
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This file 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-3.0-or-later
+ */
+
+#include "config.h"
+
+#include <errno.h>
+#include <string.h>
+#include <glib/gstdio.h>
+#include <gnutls/x509.h>
+
+#include "cc-tls-certificate.h"
+
+#define DEFAULT_KEY_SIZE 4096
+#define DEFAULT_EXPIRATION (60L*60L*24L*2L*365L)
+
+static void
+_gnutls_datum_clear (gnutls_datum_t *datum)
+{
+ if (datum->data != NULL)
+ gnutls_free (datum->data);
+}
+
+static void
+_gnutls_crt_free (gnutls_x509_crt_t *cert)
+{
+ if (cert != NULL)
+ gnutls_x509_crt_deinit (*cert);
+}
+
+static void
+_gnutls_privkey_free (gnutls_x509_privkey_t *privkey)
+{
+ if (privkey != NULL)
+ gnutls_x509_privkey_deinit (*privkey);
+}
+
+G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC (gnutls_datum_t, _gnutls_datum_clear)
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (gnutls_x509_crt_t, _gnutls_crt_free)
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (gnutls_x509_privkey_t, _gnutls_privkey_free)
+
+typedef struct
+{
+ gchar *public_key_path;
+ gchar *private_key_path;
+ gchar *c;
+ gchar *cn;
+} GenerateData;
+
+static void
+generate_data_free (GenerateData *data)
+{
+ g_clear_pointer (&data->public_key_path, g_free);
+ g_clear_pointer (&data->private_key_path, g_free);
+ g_clear_pointer (&data->c, g_free);
+ g_clear_pointer (&data->cn, g_free);
+ g_slice_free (GenerateData, data);
+}
+
+static gboolean
+make_directory_parent (const gchar *path,
+ GError **error)
+{
+ g_autofree gchar *dir = NULL;
+
+ g_assert (path != NULL);
+ g_assert (error != NULL);
+
+ dir = g_path_get_dirname (path);
+
+ if (g_mkdir_with_parents (dir, 0750) == -1)
+ {
+ g_set_error_literal (error,
+ G_IO_ERROR,
+ g_io_error_from_errno (errno),
+ g_strerror (errno));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+bonsai_tls_certificate_generate_worker (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ GenerateData *data = task_data;
+ g_autoptr(GTlsCertificate) certificate = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(gnutls_x509_crt_t) certptr = NULL;
+ g_autoptr(gnutls_x509_privkey_t) privkeyptr = NULL;
+ g_auto(gnutls_datum_t) pubkey_data = {0};
+ g_auto(gnutls_datum_t) privkey_data = {0};
+ g_autofree char *dn = NULL;
+ gnutls_x509_privkey_t privkey;
+ gnutls_x509_crt_t cert;
+ guint32 serial = 1;
+ int gtlsret = 0;
+
+ g_assert (G_IS_TASK (task));
+ g_assert (source_object == NULL);
+ g_assert (data != NULL);
+ g_assert (data->public_key_path != NULL);
+ g_assert (data->private_key_path != NULL);
+ g_assert (data->c != NULL);
+ g_assert (data->cn != NULL);
+
+ if (!make_directory_parent (data->public_key_path, &error) ||
+ !make_directory_parent (data->private_key_path, &error))
+ {
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ /*
+ * From the GnuTLS documentation:
+ *
+ * To be consistent with the X.509/PKIX specifications the provided serial
+ * should be a big-endian positive number (i.e. it's leftmost bit should be
+ * zero).
+ */
+ serial = GUINT32_TO_BE (serial);
+
+#define HANDLE_FAILURE(x) \
+ G_STMT_START { \
+ gtlsret = x; \
+ if (gtlsret != GNUTLS_E_SUCCESS) \
+ goto failure; \
+ } G_STMT_END
+
+ HANDLE_FAILURE (gnutls_x509_crt_init (&cert));
+ certptr = &cert;
+ HANDLE_FAILURE (gnutls_x509_crt_set_version (cert, 3));
+ HANDLE_FAILURE (gnutls_x509_crt_set_activation_time (cert, time (NULL)));
+ dn = g_strdup_printf ("C=%s,CN=%s", data->c, data->cn);
+ HANDLE_FAILURE (gnutls_x509_crt_set_dn (cert, dn, NULL));
+ HANDLE_FAILURE (gnutls_x509_crt_set_serial (cert, &serial, sizeof serial));
+ /* 5 years. We'll figure out key rotation in that time... */
+ HANDLE_FAILURE (gnutls_x509_crt_set_expiration_time (cert, time (NULL) + DEFAULT_EXPIRATION));
+ HANDLE_FAILURE (gnutls_x509_privkey_init (&privkey));
+ privkeyptr = &privkey;
+ HANDLE_FAILURE (gnutls_x509_privkey_generate (privkey, GNUTLS_PK_RSA, DEFAULT_KEY_SIZE, 0));
+ HANDLE_FAILURE (gnutls_x509_crt_set_key (cert, privkey));
+ HANDLE_FAILURE (gnutls_x509_crt_sign (cert, cert, privkey));
+ HANDLE_FAILURE (gnutls_x509_crt_export2 (cert, GNUTLS_X509_FMT_PEM, &pubkey_data));
+ if (!g_file_set_contents (data->public_key_path, (char *)pubkey_data.data, pubkey_data.size, &error))
+ goto failure;
+
+ HANDLE_FAILURE (gnutls_x509_privkey_export2 (privkey, GNUTLS_X509_FMT_PEM, &privkey_data));
+ if (!g_file_set_contents (data->private_key_path, (char*)privkey_data.data, privkey_data.size, &error))
+ goto failure;
+
+#undef HANDLE_FAILURE
+
+ if ((certificate = g_tls_certificate_new_from_files (data->public_key_path, data->private_key_path, &error)))
+ {
+ g_task_return_pointer (task, g_steal_pointer (&certificate), g_object_unref);
+ return;
+ }
+
+failure:
+
+ if (error != NULL)
+ g_task_return_error (task, g_steal_pointer (&error));
+ else if (gtlsret != 0)
+ g_task_return_new_error (task,
+ G_TLS_ERROR,
+ G_TLS_ERROR_MISC,
+ "GnuTLS Error: %s",
+ gnutls_strerror (gtlsret));
+ else
+ g_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Failed to generate TLS certificate pair");
+}
+
+void
+bonsai_tls_certificate_new_generate_async (const gchar *public_key_path,
+ const gchar *private_key_path,
+ const gchar *c,
+ const gchar *cn,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+ GenerateData *data;
+
+ g_return_if_fail (public_key_path != NULL);
+ g_return_if_fail (private_key_path != NULL);
+ g_return_if_fail (c != NULL);
+ g_return_if_fail (cn != NULL);
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = g_task_new (NULL, cancellable, callback, user_data);
+ g_task_set_source_tag (task, bonsai_tls_certificate_new_generate_async);
+
+ data = g_slice_new0 (GenerateData);
+ data->public_key_path = g_strdup (public_key_path);
+ data->private_key_path = g_strdup (private_key_path);
+ data->c = g_strdup (c);
+ data->cn = g_strdup (cn);
+ g_task_set_task_data (task, data, (GDestroyNotify)generate_data_free);
+
+ g_task_run_in_thread (task, bonsai_tls_certificate_generate_worker);
+}
+
+GTlsCertificate *
+bonsai_tls_certificate_new_generate_finish (GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (G_IS_TASK (result), NULL);
+
+ return g_task_propagate_pointer (G_TASK (result), error);
+}
+
+GTlsCertificate *
+bonsai_tls_certificate_new_generate (const gchar *public_key_path,
+ const gchar *private_key_path,
+ const gchar *c,
+ const gchar *cn,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(GTask) task = NULL;
+ GenerateData *data;
+
+ g_return_val_if_fail (public_key_path != NULL, NULL);
+ g_return_val_if_fail (private_key_path != NULL, NULL);
+ g_return_val_if_fail (c != NULL, NULL);
+ g_return_val_if_fail (cn != NULL, NULL);
+ g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), NULL);
+
+ task = g_task_new (NULL, cancellable, NULL, NULL);
+ g_task_set_source_tag (task, bonsai_tls_certificate_new_generate);
+
+ data = g_slice_new0 (GenerateData);
+ data->public_key_path = g_strdup (public_key_path);
+ data->private_key_path = g_strdup (private_key_path);
+ data->c = g_strdup (c);
+ data->cn = g_strdup (cn);
+ g_task_set_task_data (task, data, (GDestroyNotify)generate_data_free);
+
+ bonsai_tls_certificate_generate_worker (task, NULL, data, cancellable);
+
+ return g_task_propagate_pointer (task, error);
+}
+
+gchar *
+bonsai_tls_certificate_get_hash (GTlsCertificate *cert)
+{
+ g_autoptr(GByteArray) bytesarray = NULL;
+ g_autoptr(GChecksum) checksum = NULL;
+
+ g_return_val_if_fail (G_IS_TLS_CERTIFICATE (cert), NULL);
+
+ g_object_get (cert, "certificate", &bytesarray, NULL);
+
+ checksum = g_checksum_new (G_CHECKSUM_SHA256);
+ g_checksum_update (checksum, bytesarray->data, bytesarray->len);
+
+ return g_ascii_strdown (g_checksum_get_string (checksum), -1);
+}
+
+typedef struct
+{
+ gchar *public_key_path;
+ gchar *private_key_path;
+ gchar *c;
+ gchar *cn;
+} NewFromFilesOrGenerate;
+
+static void
+new_from_files_or_generate_free (gpointer data)
+{
+ NewFromFilesOrGenerate *state = data;
+
+ g_clear_pointer (&state->public_key_path, g_free);
+ g_clear_pointer (&state->private_key_path, g_free);
+ g_clear_pointer (&state->c, g_free);
+ g_clear_pointer (&state->cn, g_free);
+ g_free (state);
+}
+
+static void
+bonsai_tls_certificate_new_from_files_or_generate_worker (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ NewFromFilesOrGenerate *state = task_data;
+ g_autoptr(GTlsCertificate) certificate = NULL;
+ g_autoptr(GError) error = NULL;
+
+ g_assert (G_IS_TASK (task));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+ g_assert (state != NULL);
+ g_assert (state->public_key_path != NULL);
+ g_assert (state->private_key_path != NULL);
+
+ /* Generate new public/private key for server if we need one.
+ * Ideally, we would generate something signed by a real CA
+ * for the user. But since this is "private cloud" oriented,
+ * we should be fine for now.
+ */
+ if (!g_file_test (state->public_key_path, G_FILE_TEST_EXISTS) ||
+ !g_file_test (state->private_key_path, G_FILE_TEST_EXISTS))
+ certificate = bonsai_tls_certificate_new_generate (state->public_key_path,
+ state->private_key_path,
+ state->c,
+ state->cn,
+ cancellable,
+ &error);
+ else
+ certificate = g_tls_certificate_new_from_files (state->public_key_path,
+ state->private_key_path,
+ &error);
+
+ if (certificate == NULL)
+ g_task_return_error (task, g_steal_pointer (&error));
+ else
+ g_task_return_pointer (task, g_steal_pointer (&certificate), g_object_unref);
+}
+
+/**
+ * bonsai_tls_certificate_new_from_files_or_generate_async:
+ * @public_key_path: the path to the public key file
+ * @private_key_path: the path to the private key file
+ * @cancellable: (nullable): a #GCancellable or %NULL
+ * @callback: a callback to execute upon completion
+ * @user_data: closure data for @callback
+ *
+ * Asynchronously requests that a certificate is loaded, or generate one if it
+ * does not yet exist. The generated certificate is a self-signed certificate.
+ *
+ * Since: 0.2
+ */
+void
+bonsai_tls_certificate_new_from_files_or_generate_async (const gchar *public_key_path,
+ const gchar *private_key_path,
+ const gchar *c,
+ const gchar *cn,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+ NewFromFilesOrGenerate state;
+
+ g_assert (public_key_path != NULL);
+ g_assert (private_key_path != NULL);
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ state.public_key_path = g_strdup (public_key_path);
+ state.private_key_path = g_strdup (private_key_path);
+ state.c = g_strdup (c);
+ state.cn = g_strdup (cn);
+
+ task = g_task_new (NULL, cancellable, callback, user_data);
+ g_task_set_source_tag (task, bonsai_tls_certificate_new_from_files_or_generate_async);
+ g_task_set_task_data (task, g_memdup2 (&state, sizeof state), new_from_files_or_generate_free);
+ g_task_run_in_thread (task, bonsai_tls_certificate_new_from_files_or_generate_worker);
+}
+
+/**
+ * bonsai_tls_certificate_new_from_files_or_generate_finish:
+ * @result: a #GAsyncResult provided to callback
+ * @error: a location for a #GError, or %NULL
+ *
+ * Completes a request to
+ * bonsai_tls_certificate_new_from_files_or_generate_async() which will
+ * either load a #GTlsCertificate for the files if they exist, or generate
+ * a new self-signed certificate in their place.
+ *
+ * Returns: (transfer none): a #GTlsCertificate or %NULL and @error is set.
+ *
+ * Since: 0.2
+ */
+GTlsCertificate *
+bonsai_tls_certificate_new_from_files_or_generate_finish (GAsyncResult *result,
+ GError **error)
+{
+ g_assert (G_IS_TASK (result));
+
+ return g_task_propagate_pointer (G_TASK (result), error);
+}
+
+/**
+ * bonsai_tls_certificate_new_from_files_or_generate:
+ * @public_key_path: the path to the public key
+ * @private_key_path: the path to the private key
+ * @c: the C for the certificate
+ * @cn: the CN for the certificate
+ * @cancellable: (nullable): a #GCancellable or %NULL
+ * @error: the location for the error
+ *
+ * Loads a certificate or generates a new self-signed certificate in
+ * it's place.
+ *
+ * Returns: (transfer full): a #GTlsCertificate or %NULL and @error is set
+ *
+ * Since: 0.2
+ */
+GTlsCertificate *
+bonsai_tls_certificate_new_from_files_or_generate (const gchar *public_key_path,
+ const gchar *private_key_path,
+ const gchar *c,
+ const gchar *cn,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GTlsCertificate *ret;
+
+ g_return_val_if_fail (public_key_path != NULL, NULL);
+ g_return_val_if_fail (private_key_path != NULL, NULL);
+ g_return_val_if_fail (c != NULL, NULL);
+ g_return_val_if_fail (cn != NULL, NULL);
+ g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), NULL);
+
+ if (!(ret = g_tls_certificate_new_from_files (public_key_path, private_key_path, NULL)))
+ ret = bonsai_tls_certificate_new_generate (public_key_path,
+ private_key_path,
+ c,
+ cn,
+ cancellable,
+ error);
+
+ return g_steal_pointer (&ret);
+}
+
+/**
+ * bonsai_tls_certificate_new_for_user:
+ * @public_key_path: the path to the public key
+ * @private_key_path: the path to the private key
+ *
+ * This is a simplified form to create a new certificate or load a previously
+ * created certificate for the current user.
+ *
+ * Returns: (transfer none): a #GTlsCertificate or %NULL and @error is set.
+ *
+ * Since: 0.2
+ */
+GTlsCertificate *
+bonsai_tls_certificate_new_for_user (GCancellable *cancellable,
+ GError **error)
+{
+ g_autofree gchar *public_key_path = NULL;
+ g_autofree gchar *private_key_path = NULL;
+
+ g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), NULL);
+
+ public_key_path = g_build_filename (g_get_user_config_dir (), "bonsai", "public.key", NULL);
+ private_key_path = g_build_filename (g_get_user_config_dir (), "bonsai", "private.key", NULL);
+
+ return bonsai_tls_certificate_new_from_files_or_generate (public_key_path,
+ private_key_path,
+ "US",
+ "GNOME",
+ cancellable,
+ error);
+}
+
+gboolean
+bonsai_is_tls_hash (const gchar *hash)
+{
+ guint len = 0;
+
+ if (hash == NULL)
+ return FALSE;
+
+ for (; *hash; hash++)
+ {
+ if (len == 64)
+ return FALSE;
+
+ switch (*hash)
+ {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ len++;
+ break;
+
+ default:
+ return FALSE;
+ }
+ }
+
+ return len == 64;
+}
+
diff --git a/panels/sharing/cc-tls-certificate.h b/panels/sharing/cc-tls-certificate.h
new file mode 100644
index 0000000..9b9a8d5
--- /dev/null
+++ b/panels/sharing/cc-tls-certificate.h
@@ -0,0 +1,63 @@
+/* cc-tls-certificate.h
+ *
+ * Copyright 2018 Christian Hergert <chergert@redhat.com>
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This file 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+gboolean bonsai_is_tls_hash (const gchar *hash);
+GTlsCertificate *bonsai_tls_certificate_new_generate (const gchar *public_key_path,
+ const gchar *private_key_path,
+ const gchar *c,
+ const gchar *cn,
+ GCancellable *cancellable,
+ GError **error);
+void bonsai_tls_certificate_new_generate_async (const gchar *public_key_path,
+ const gchar *private_key_path,
+ const gchar *c,
+ const gchar *cn,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GTlsCertificate *bonsai_tls_certificate_new_generate_finish (GAsyncResult *result,
+ GError **error);
+gchar *bonsai_tls_certificate_get_hash (GTlsCertificate *cert);
+GTlsCertificate *bonsai_tls_certificate_new_from_files_or_generate (const gchar *public_key_path,
+ const gchar *private_key_path,
+ const gchar *c,
+ const gchar *cn,
+ GCancellable *cancellable,
+ GError **error);
+void bonsai_tls_certificate_new_from_files_or_generate_async (const gchar *public_key_path,
+ const gchar *private_key_path,
+ const gchar *c,
+ const gchar *cn,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GTlsCertificate *bonsai_tls_certificate_new_from_files_or_generate_finish (GAsyncResult *result,
+ GError **error);
+GTlsCertificate *bonsai_tls_certificate_new_for_user (GCancellable *cancellable,
+ GError **error);
+
+G_END_DECLS
+
diff --git a/panels/sharing/file-share-properties.c b/panels/sharing/file-share-properties.c
new file mode 100644
index 0000000..dcf741c
--- /dev/null
+++ b/panels/sharing/file-share-properties.c
@@ -0,0 +1,55 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+
+/*
+ * Copyright (C) 2004 Red Hat, Inc.
+ *
+ * Nautilus 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.
+ *
+ * Nautilus 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors: Alexander Larsson <alexl@redhat.com>
+ *
+ */
+
+#include "file-share-properties.h"
+
+#include <string.h>
+#include <stdio.h>
+
+#include <glib.h>
+
+
+#define REALM "Please log in as the user guest"
+#define USER "guest"
+
+void
+file_share_write_out_password (const char *password)
+{
+ g_autofree gchar *to_hash = NULL;
+ g_autofree gchar *ascii_digest = NULL;
+ g_autofree gchar *line = NULL;
+ g_autofree gchar *filename = NULL;
+ FILE *file;
+
+ to_hash = g_strdup_printf ("%s:%s:%s", USER, REALM, password);
+ ascii_digest = g_compute_checksum_for_string (G_CHECKSUM_MD5, to_hash, strlen (to_hash));
+ line = g_strdup_printf ("%s:%s:%s\n", USER, REALM, ascii_digest);
+
+ filename = g_build_filename (g_get_user_config_dir (), "user-share", "passwd", NULL);
+
+ file = fopen (filename, "w");
+ if (file != NULL) {
+ fwrite (line, strlen (line), 1, file);
+ fclose (file);
+ }
+}
diff --git a/panels/sharing/file-share-properties.h b/panels/sharing/file-share-properties.h
new file mode 100644
index 0000000..b29d23f
--- /dev/null
+++ b/panels/sharing/file-share-properties.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2013 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#pragma once
+
+void file_share_write_out_password (const char *password);
diff --git a/panels/sharing/gnome-sharing-panel.desktop.in.in b/panels/sharing/gnome-sharing-panel.desktop.in.in
new file mode 100644
index 0000000..8dc340c
--- /dev/null
+++ b/panels/sharing/gnome-sharing-panel.desktop.in.in
@@ -0,0 +1,15 @@
+[Desktop Entry]
+Name=Sharing
+Comment=Control what you want to share with others
+Exec=gnome-control-center sharing
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-sharing-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-AccountSettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Settings-Panel=sharing
+# Translators: Search terms to find the Sharing panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=share;sharing;ssh;host;name;remote;desktop;media;audio;video;pictures;photos;movies;server;renderer;
diff --git a/panels/sharing/gsd-sharing-enums.h b/panels/sharing/gsd-sharing-enums.h
new file mode 100644
index 0000000..d117845
--- /dev/null
+++ b/panels/sharing/gsd-sharing-enums.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2014 Bastien Nocera <hadess@hadess.net>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+G_BEGIN_DECLS
+
+typedef enum {
+ GSD_SHARING_STATUS_OFFLINE,
+ GSD_SHARING_STATUS_DISABLED_MOBILE_BROADBAND,
+ GSD_SHARING_STATUS_DISABLED_LOW_SECURITY,
+ GSD_SHARING_STATUS_AVAILABLE
+} GsdSharingStatus;
+
+G_END_DECLS
diff --git a/panels/sharing/icons/meson.build b/panels/sharing/icons/meson.build
new file mode 100644
index 0000000..4ee7e38
--- /dev/null
+++ b/panels/sharing/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-sharing-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/sharing/icons/scalable/org.gnome.Settings-sharing-symbolic.svg b/panels/sharing/icons/scalable/org.gnome.Settings-sharing-symbolic.svg
new file mode 100644
index 0000000..acd455b
--- /dev/null
+++ b/panels/sharing/icons/scalable/org.gnome.Settings-sharing-symbolic.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <g fill="#2e3436">
+ <path d="m 6 8 c 0 1.65625 -1.34375 3 -3 3 s -3 -1.34375 -3 -3 s 1.34375 -3 3 -3 s 3 1.34375 3 3 z m 0 0"/>
+ <path d="m 12.554688 2.105469 l -11.789063 5.894531 l 11.789063 5.894531 l 0.894531 -1.789062 l -8.210938 -4.105469 l 8.210938 -4.105469 z m 0 0"/>
+ <path d="m 16 3 c 0 1.65625 -1.34375 3 -3 3 s -3 -1.34375 -3 -3 s 1.34375 -3 3 -3 s 3 1.34375 3 3 z m 0 0"/>
+ <path d="m 16 13 c 0 1.65625 -1.34375 3 -3 3 s -3 -1.34375 -3 -3 s 1.34375 -3 3 -3 s 3 1.34375 3 3 z m 0 0"/>
+ </g>
+</svg>
diff --git a/panels/sharing/meson.build b/panels/sharing/meson.build
new file mode 100644
index 0000000..c674cfb
--- /dev/null
+++ b/panels/sharing/meson.build
@@ -0,0 +1,114 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+polkit_conf = configuration_data()
+polkit_conf.set('libexecdir', control_center_libexecdir)
+
+polkit = 'org.gnome.controlcenter.remote-login-helper.policy'
+
+polkit_in = configure_file(
+ input: polkit + '.in.in',
+ output: polkit + '.in',
+ configuration: polkit_conf
+)
+
+i18n.merge_file(
+ input: polkit_in,
+ output: polkit,
+ po_dir: po_dir,
+ install: true,
+ install_dir: join_paths(control_center_datadir, 'polkit-1', 'actions')
+)
+
+sources = files(
+ 'cc-sharing-panel.c',
+ 'cc-media-sharing.c',
+ 'cc-remote-login.c',
+ 'cc-sharing-networks.c',
+ 'cc-gnome-remote-desktop.c',
+ 'cc-tls-certificate.c',
+ 'cc-systemd-service.c',
+ 'file-share-properties.c',
+)
+
+resource_data = files(
+ 'cc-sharing-panel.ui',
+ 'cc-sharing-networks.ui',
+)
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname,
+ dependencies: resource_data,
+ export: true
+)
+
+settings_daemon = 'org.gnome.SettingsDaemon'
+gdbus = settings_daemon + '.Sharing'
+
+sources += gnome.gdbus_codegen(
+ gdbus,
+ gdbus + '.xml',
+ interface_prefix: settings_daemon + '.',
+ namespace: 'Gsd'
+)
+
+cflags += [
+ '-DLIBEXECDIR="@0@"'.format(control_center_libexecdir),
+ '-DSYSCONFDIR="@0@"'.format(control_center_sysconfdir)
+]
+
+libsecret_dep = dependency('libsecret-1')
+gnutls_dep = dependency('gnutls')
+
+panels_libs += static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [ top_inc, common_inc ],
+ dependencies: [
+ common_deps,
+ libsecret_dep,
+ gnutls_dep,
+ gcr_dep,
+ pwquality_dep,
+ ],
+ c_args: cflags
+)
+
+name = 'cc-remote-login-helper'
+
+deps = [
+ gio_dep,
+ glib_dep,
+]
+
+executable(
+ name,
+ sources: [
+ name + '.c',
+ 'cc-systemd-service.c',
+ ],
+ include_directories: top_inc,
+ dependencies: deps,
+ c_args: cflags,
+ install: true,
+ install_dir: control_center_libexecdir
+)
+
+subdir('icons')
diff --git a/panels/sharing/org.gnome.SettingsDaemon.Sharing.xml b/panels/sharing/org.gnome.SettingsDaemon.Sharing.xml
new file mode 100644
index 0000000..1710c3e
--- /dev/null
+++ b/panels/sharing/org.gnome.SettingsDaemon.Sharing.xml
@@ -0,0 +1,19 @@
+<node name="/org/gnome/SettingsDaemon/Sharing">
+ <interface name='org.gnome.SettingsDaemon.Sharing'>
+ <property name='CurrentNetworkName' type='s' access='read'/>
+ <property name='CurrentNetwork' type='s' access='read'/>
+ <property name='CarrierType' type='s' access='read'/>
+ <property name='SharingStatus' type='u' access='read'/>
+ <method name='EnableService'>
+ <arg name='service_name' direction='in' type='s'/>
+ </method>
+ <method name='DisableService'>
+ <arg name='service_name' direction='in' type='s'/>
+ <arg name='network' direction='in' type='s'/>
+ </method>
+ <method name='ListNetworks'>
+ <arg name='service_name' direction='in' type='s'/>
+ <arg name='networks' direction='out' type='a(sss)'/>
+ </method>
+ </interface>
+</node>
diff --git a/panels/sharing/org.gnome.controlcenter.remote-login-helper.policy.in.in b/panels/sharing/org.gnome.controlcenter.remote-login-helper.policy.in.in
new file mode 100644
index 0000000..7fabac2
--- /dev/null
+++ b/panels/sharing/org.gnome.controlcenter.remote-login-helper.policy.in.in
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE policyconfig PUBLIC
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
+<policyconfig>
+
+ <vendor>The GNOME Project</vendor>
+ <vendor_url>http://www.gnome.org/</vendor_url>
+
+ <action id="org.gnome.controlcenter.remote-login-helper">
+ <description>Enable or disable remote login</description>
+ <message>Authentication is required to enable or disable remote login</message>
+ <defaults>
+ <allow_any>no</allow_any>
+ <allow_inactive>no</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ <annotate key="org.freedesktop.policykit.exec.path">@libexecdir@/cc-remote-login-helper</annotate>
+ </action>
+
+</policyconfig>
+
diff --git a/panels/sharing/sharing.css b/panels/sharing/sharing.css
new file mode 100644
index 0000000..cf18ab3
--- /dev/null
+++ b/panels/sharing/sharing.css
@@ -0,0 +1,4 @@
+.tls-cert-fingerprint {
+ font-family: monospace;
+ margin: 10px;
+}
diff --git a/panels/sharing/sharing.gresource.xml b/panels/sharing/sharing.gresource.xml
new file mode 100644
index 0000000..275f884
--- /dev/null
+++ b/panels/sharing/sharing.gresource.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/sharing">
+ <file preprocess="xml-stripblanks">cc-sharing-panel.ui</file>
+ <file preprocess="xml-stripblanks">cc-sharing-networks.ui</file>
+ <file>sharing.css</file>
+ </gresource>
+</gresources>
diff --git a/panels/sound/cc-alert-chooser.c b/panels/sound/cc-alert-chooser.c
new file mode 100644
index 0000000..686d8c6
--- /dev/null
+++ b/panels/sound/cc-alert-chooser.c
@@ -0,0 +1,306 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib/gi18n.h>
+#include <gsound.h>
+
+#include "config.h"
+#include "cc-alert-chooser.h"
+#include "cc-sound-resources.h"
+
+#define KEY_SOUNDS_SCHEMA "org.gnome.desktop.sound"
+
+struct _CcAlertChooser
+{
+ GtkBox parent_instance;
+
+ GtkToggleButton *click_button;
+ GtkToggleButton *hum_button;
+ GtkToggleButton *string_button;
+ GtkToggleButton *swing_button;
+
+ GSoundContext *context;
+ GSettings *sound_settings;
+};
+
+static void clicked_cb (CcAlertChooser *self,
+ GtkToggleButton *button);
+
+G_DEFINE_TYPE (CcAlertChooser, cc_alert_chooser, GTK_TYPE_BOX)
+
+#define CUSTOM_THEME_NAME "__custom"
+
+static gchar *
+get_theme_dir (void)
+{
+ return g_build_filename (g_get_user_data_dir (), "sounds", CUSTOM_THEME_NAME, NULL);
+}
+
+static gchar *
+get_sound_path (const gchar *name)
+{
+ g_autofree gchar *filename = NULL;
+
+ filename = g_strdup_printf ("%s.ogg", name);
+ return g_build_filename (SOUND_DATA_DIR, "gnome", "default", "alerts", filename, NULL);
+}
+
+static gchar *
+get_alert_name (void)
+{
+ g_autofree gchar *dir = NULL;
+ g_autofree gchar *path = NULL;
+ g_autoptr(GFile) file = NULL;
+ g_autoptr(GFileInfo) info = NULL;
+ const gchar *target;
+ g_autofree gchar *basename = NULL;
+ g_autoptr(GError) error = NULL;
+
+ dir = get_theme_dir ();
+ path = g_build_filename (dir, "bell-terminal.ogg", NULL);
+ file = g_file_new_for_path (path);
+
+ info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ &error);
+ if (info == NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+ g_warning ("Failed to get sound theme symlink %s: %s", path, error->message);
+ return NULL;
+ }
+ target = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET);
+ if (target == NULL)
+ return NULL;
+
+ basename = g_path_get_basename (target);
+ if (g_str_has_suffix (basename, ".ogg"))
+ basename[strlen (basename) - 4] = '\0';
+
+ return g_steal_pointer (&basename);
+}
+
+static void
+set_sound_symlink (const gchar *alert_name,
+ const gchar *name)
+{
+ g_autofree gchar *dir = NULL;
+ g_autofree gchar *source_filename = NULL;
+ g_autofree gchar *source_path = NULL;
+ g_autofree gchar *target_path = NULL;
+ g_autoptr(GFile) file = NULL;
+ g_autoptr(GError) error = NULL;
+
+ dir = get_theme_dir ();
+ source_filename = g_strdup_printf ("%s.ogg", alert_name);
+ source_path = g_build_filename (dir, source_filename, NULL);
+ target_path = get_sound_path (name);
+
+ file = g_file_new_for_path (source_path);
+ if (!g_file_delete (file, NULL, &error))
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+ g_warning ("Failed to remove existing sound symbolic link %s: %s", source_path, error->message);
+ }
+ if (!g_file_make_symbolic_link (file, target_path, NULL, &error))
+ g_warning ("Failed to make sound theme symbolic link %s->%s: %s", source_path, target_path, error->message);
+}
+
+static void
+set_custom_theme (CcAlertChooser *self,
+ const gchar *name)
+{
+ g_autofree gchar *dir_path = NULL;
+ g_autofree gchar *theme_path = NULL;
+ g_autoptr(GDateTime) now = NULL;
+ g_autoptr(GFile) dir = NULL;
+ g_autoptr(GKeyFile) theme_file = NULL;
+ g_autoptr(GVariant) default_theme = NULL;
+ g_autoptr(GError) load_error = NULL;
+ g_autoptr(GError) save_error = NULL;
+ g_autoptr(GError) mtime_error = NULL;
+
+ dir_path = get_theme_dir ();
+ g_mkdir_with_parents (dir_path, USER_DIR_MODE);
+
+ theme_path = g_build_filename (dir_path, "index.theme", NULL);
+
+ default_theme = g_settings_get_default_value (self->sound_settings, "theme-name");
+
+ theme_file = g_key_file_new ();
+ if (!g_key_file_load_from_file (theme_file, theme_path, G_KEY_FILE_KEEP_COMMENTS, &load_error))
+ {
+ if (!g_error_matches (load_error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
+ g_printerr ("Failed to load theme file %s: %s", theme_path, load_error->message);
+ }
+ g_key_file_set_string (theme_file, "Sound Theme", "Name", _("Custom"));
+ if (default_theme != NULL)
+ g_key_file_set_string (theme_file, "Sound Theme", "Inherits", g_variant_get_string (default_theme, NULL));
+ g_key_file_set_string (theme_file, "Sound Theme", "Directories", ".");
+
+ if (!g_key_file_save_to_file (theme_file, theme_path, &save_error))
+ {
+ g_warning ("Failed to save theme file %s: %s", theme_path, save_error->message);
+ }
+
+ set_sound_symlink ("bell-terminal", name);
+ set_sound_symlink ("bell-window-system", name);
+
+ /* Ensure the g-s-d sound plugin which does non-recursive monitoring
+ * notices the change even if the theme directory already existed.
+ */
+ now = g_date_time_new_now_utc ();
+ dir = g_file_new_for_path (dir_path);
+ if (!g_file_set_attribute_uint64 (dir,
+ G_FILE_ATTRIBUTE_TIME_MODIFIED,
+ g_date_time_to_unix (now),
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ &mtime_error))
+ {
+ g_warning ("Failed to update theme directory modification time for %s: %s",
+ dir_path, mtime_error->message);
+ }
+
+ g_settings_set_boolean (self->sound_settings, "event-sounds", TRUE);
+ g_settings_set_string (self->sound_settings, "theme-name", CUSTOM_THEME_NAME);
+}
+
+static void
+select_sound (CcAlertChooser *self,
+ const gchar *name)
+{
+ g_autofree gchar *path = NULL;
+ g_autoptr(GError) error = NULL;
+
+ path = get_sound_path (name);
+ if (!gsound_context_play_simple (self->context, NULL, &error,
+ GSOUND_ATTR_MEDIA_FILENAME, path,
+ NULL))
+ {
+ g_warning ("Failed to play alert sound %s: %s", path, error->message);
+ }
+
+ set_custom_theme (self, name);
+}
+
+static void
+set_button (CcAlertChooser *self,
+ GtkToggleButton *button,
+ gboolean active)
+{
+ g_signal_handlers_block_by_func (button, clicked_cb, self);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), active);
+ g_signal_handlers_unblock_by_func (button, clicked_cb, self);
+}
+
+static void
+clicked_cb (CcAlertChooser *self,
+ GtkToggleButton *button)
+{
+ if (button == self->click_button)
+ select_sound (self, "click");
+ else if (button == self->hum_button)
+ select_sound (self, "hum");
+ else if (button == self->string_button)
+ select_sound (self, "string");
+ else if (button == self->swing_button)
+ select_sound (self, "swing");
+
+ set_button (self, button, TRUE);
+ if (button != self->click_button)
+ set_button (self, self->click_button, FALSE);
+ if (button != self->hum_button)
+ set_button (self, self->hum_button, FALSE);
+ if (button != self->string_button)
+ set_button (self, self->string_button, FALSE);
+ if (button != self->swing_button)
+ set_button (self, self->swing_button, FALSE);
+}
+
+static void
+cc_alert_chooser_dispose (GObject *object)
+{
+ CcAlertChooser *self = CC_ALERT_CHOOSER (object);
+
+ g_clear_object (&self->context);
+ g_clear_object (&self->sound_settings);
+
+ G_OBJECT_CLASS (cc_alert_chooser_parent_class)->dispose (object);
+}
+
+void
+cc_alert_chooser_class_init (CcAlertChooserClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_alert_chooser_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/sound/cc-alert-chooser.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcAlertChooser, click_button);
+ gtk_widget_class_bind_template_child (widget_class, CcAlertChooser, hum_button);
+ gtk_widget_class_bind_template_child (widget_class, CcAlertChooser, string_button);
+ gtk_widget_class_bind_template_child (widget_class, CcAlertChooser, swing_button);
+
+ gtk_widget_class_bind_template_callback (widget_class, clicked_cb);
+}
+
+void
+cc_alert_chooser_init (CcAlertChooser *self)
+{
+ g_autofree gchar *alert_name = NULL;
+ g_autoptr(GError) error = NULL;
+
+ g_resources_register (cc_sound_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->context = gsound_context_new (NULL, &error);
+ if (self->context == NULL)
+ g_error ("Failed to make sound context: %s", error->message);
+
+ self->sound_settings = g_settings_new (KEY_SOUNDS_SCHEMA);
+
+ alert_name = get_alert_name ();
+
+ /* If user has selected an old sound alert, migrate them to click. */
+ if (g_strcmp0 (alert_name, "click") != 0 &&
+ g_strcmp0 (alert_name, "hum") != 0 &&
+ g_strcmp0 (alert_name, "string") != 0 &&
+ g_strcmp0 (alert_name, "swing") != 0)
+ {
+ set_custom_theme (self, "click");
+ g_free (alert_name);
+ alert_name = g_strdup ("click");
+ }
+
+ if (g_strcmp0 (alert_name, "click") == 0)
+ set_button (self, self->click_button, TRUE);
+ else if (g_strcmp0 (alert_name, "hum") == 0)
+ set_button (self, self->hum_button, TRUE);
+ else if (g_strcmp0 (alert_name, "string") == 0)
+ set_button (self, self->string_button, TRUE);
+ else if (g_strcmp0 (alert_name, "swing") == 0)
+ set_button (self, self->swing_button, TRUE);
+ else if (alert_name != NULL)
+ g_warning ("Current alert sound has unknown name %s", alert_name);
+}
diff --git a/panels/sound/cc-alert-chooser.h b/panels/sound/cc-alert-chooser.h
new file mode 100644
index 0000000..c6f4b87
--- /dev/null
+++ b/panels/sound/cc-alert-chooser.h
@@ -0,0 +1,28 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_ALERT_CHOOSER (cc_alert_chooser_get_type ())
+G_DECLARE_FINAL_TYPE (CcAlertChooser, cc_alert_chooser, CC, ALERT_CHOOSER, GtkBox)
+
+G_END_DECLS
diff --git a/panels/sound/cc-alert-chooser.ui b/panels/sound/cc-alert-chooser.ui
new file mode 100644
index 0000000..603aff9
--- /dev/null
+++ b/panels/sound/cc-alert-chooser.ui
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcAlertChooser" parent="GtkBox">
+ <property name="homogeneous">True</property>
+ <style>
+ <class name="linked"/>
+ </style>
+ <child>
+ <object class="GtkToggleButton" id="click_button">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Click</property>
+ <signal name="clicked" handler="clicked_cb" object="CcAlertChooser" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="string_button">
+ <property name="visible">True</property>
+ <property name="group">click_button</property>
+ <property name="label" translatable="yes">String</property>
+ <signal name="clicked" handler="clicked_cb" object="CcAlertChooser" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="swing_button">
+ <property name="visible">True</property>
+ <property name="group">click_button</property>
+ <property name="label" translatable="yes">Swing</property>
+ <signal name="clicked" handler="clicked_cb" object="CcAlertChooser" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="hum_button">
+ <property name="visible">True</property>
+ <property name="group">click_button</property>
+ <property name="label" translatable="yes">Hum</property>
+ <signal name="clicked" handler="clicked_cb" object="CcAlertChooser" swapped="yes"/>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/sound/cc-balance-slider.c b/panels/sound/cc-balance-slider.c
new file mode 100644
index 0000000..7cb8a04
--- /dev/null
+++ b/panels/sound/cc-balance-slider.c
@@ -0,0 +1,119 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cc-sound-resources.h"
+#include "cc-balance-slider.h"
+#include "gvc-channel-map-private.h"
+
+struct _CcBalanceSlider
+{
+ GtkBox parent_instance;
+
+ GtkAdjustment *adjustment;
+
+ GvcChannelMap *channel_map;
+ guint volume_changed_handler_id;
+};
+
+G_DEFINE_TYPE (CcBalanceSlider, cc_balance_slider, GTK_TYPE_BOX)
+
+static void
+changed_cb (CcBalanceSlider *self)
+{
+ gdouble value;
+ const pa_channel_map *pa_map;
+ pa_cvolume pa_volume;
+
+ if (self->channel_map == NULL)
+ return;
+
+ value = gtk_adjustment_get_value (self->adjustment);
+ pa_map = gvc_channel_map_get_pa_channel_map (self->channel_map);
+ pa_volume = *gvc_channel_map_get_cvolume (self->channel_map);
+ pa_cvolume_set_balance (&pa_volume, pa_map, value);
+ gvc_channel_map_volume_changed (self->channel_map, &pa_volume, TRUE);
+}
+
+static void
+volume_changed_cb (CcBalanceSlider *self)
+{
+ const gdouble *volumes;
+
+ volumes = gvc_channel_map_get_volume (self->channel_map);
+ g_signal_handlers_block_by_func (self->adjustment, volume_changed_cb, self);
+ gtk_adjustment_set_value (self->adjustment, volumes[BALANCE]);
+ g_signal_handlers_unblock_by_func (self->adjustment, volume_changed_cb, self);
+}
+
+static void
+cc_balance_slider_dispose (GObject *object)
+{
+ CcBalanceSlider *self = CC_BALANCE_SLIDER (object);
+
+ g_clear_object (&self->channel_map);
+
+ G_OBJECT_CLASS (cc_balance_slider_parent_class)->dispose (object);
+}
+
+void
+cc_balance_slider_class_init (CcBalanceSliderClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_balance_slider_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/sound/cc-balance-slider.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcBalanceSlider, adjustment);
+
+ gtk_widget_class_bind_template_callback (widget_class, changed_cb);
+}
+
+void
+cc_balance_slider_init (CcBalanceSlider *self)
+{
+ g_resources_register (cc_sound_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+void
+cc_balance_slider_set_channel_map (CcBalanceSlider *self,
+ GvcChannelMap *channel_map)
+{
+ g_return_if_fail (CC_IS_BALANCE_SLIDER (self));
+
+ if (self->channel_map != NULL)
+ {
+ g_signal_handler_disconnect (self->channel_map, self->volume_changed_handler_id);
+ self->volume_changed_handler_id = 0;
+ }
+ g_clear_object (&self->channel_map);
+
+ if (channel_map != NULL)
+ {
+ self->channel_map = g_object_ref (channel_map);
+
+ self->volume_changed_handler_id = g_signal_connect_object (channel_map,
+ "volume-changed",
+ G_CALLBACK (volume_changed_cb),
+ self, G_CONNECT_SWAPPED);
+ volume_changed_cb (self);
+ }
+}
diff --git a/panels/sound/cc-balance-slider.h b/panels/sound/cc-balance-slider.h
new file mode 100644
index 0000000..6a968a7
--- /dev/null
+++ b/panels/sound/cc-balance-slider.h
@@ -0,0 +1,33 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <pulse/pulseaudio.h>
+#include <gvc-channel-map.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_BALANCE_SLIDER (cc_balance_slider_get_type ())
+G_DECLARE_FINAL_TYPE (CcBalanceSlider, cc_balance_slider, CC, BALANCE_SLIDER, GtkBox)
+
+void cc_balance_slider_set_channel_map (CcBalanceSlider *slider,
+ GvcChannelMap *channel_map);
+
+G_END_DECLS
diff --git a/panels/sound/cc-balance-slider.ui b/panels/sound/cc-balance-slider.ui
new file mode 100644
index 0000000..871a915
--- /dev/null
+++ b/panels/sound/cc-balance-slider.ui
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcBalanceSlider" parent="GtkBox">
+ <child>
+ <object class="GtkScale">
+ <property name="visible">True</property>
+ <property name="hexpand">True</property>
+ <property name="draw_value">False</property>
+ <property name="has_origin">False</property>
+ <property name="adjustment">adjustment</property>
+ <accessibility>
+ <property name="label" translatable="yes">Balance</property>
+ </accessibility>
+ <marks>
+ <mark value="-1" translatable="yes">Left</mark>
+ <mark value="0"/>
+ <mark value="1" translatable="yes">Right</mark>
+ </marks>
+ </object>
+ </child>
+ </template>
+ <object class="GtkAdjustment" id="adjustment">
+ <property name="lower">-1.0</property>
+ <property name="upper">1.0</property>
+ <property name="step_increment">0.5</property>
+ <property name="page_increment">0.5</property>
+ <signal name="value_changed" handler="changed_cb" object="CcBalanceSlider" swapped="yes"/>
+ </object>
+</interface>
diff --git a/panels/sound/cc-device-combo-box.c b/panels/sound/cc-device-combo-box.c
new file mode 100644
index 0000000..85537ef
--- /dev/null
+++ b/panels/sound/cc-device-combo-box.c
@@ -0,0 +1,213 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cc-device-combo-box.h"
+#include "cc-sound-resources.h"
+
+struct _CcDeviceComboBox
+{
+ GtkComboBox parent_instance;
+
+ GtkListStore *device_model;
+
+ GvcMixerControl *mixer_control;
+ guint added_handler_id;
+ guint removed_handler_id;
+ guint active_update_handler_id;
+ gboolean is_output;
+};
+
+G_DEFINE_TYPE (CcDeviceComboBox, cc_device_combo_box, GTK_TYPE_COMBO_BOX)
+
+static void
+device_added_cb (CcDeviceComboBox *self,
+ guint id)
+{
+ GvcMixerUIDevice *device = NULL;
+ g_autofree gchar *label = NULL;
+ g_autofree gchar *icon_name = NULL;
+ const gchar *origin;
+ GtkTreeIter iter;
+
+ if (self->is_output)
+ device = gvc_mixer_control_lookup_output_id (self->mixer_control, id);
+ else
+ device = gvc_mixer_control_lookup_input_id (self->mixer_control, id);
+ if (device == NULL)
+ return;
+
+ origin = gvc_mixer_ui_device_get_origin (device);
+ if (origin && origin[0] != '\0')
+ {
+ label = g_strdup_printf ("%s - %s",
+ gvc_mixer_ui_device_get_description (device),
+ origin);
+ }
+ else
+ {
+ label = g_strdup (gvc_mixer_ui_device_get_description (device));
+ }
+
+ if (gvc_mixer_ui_device_get_icon_name (device) != NULL)
+ icon_name = g_strdup_printf ("%s-symbolic", gvc_mixer_ui_device_get_icon_name (device));
+
+ gtk_list_store_append (self->device_model, &iter);
+ gtk_list_store_set (self->device_model, &iter,
+ 0, label,
+ 1, icon_name,
+ 2, id,
+ -1);
+}
+
+static gboolean
+get_iter (CcDeviceComboBox *self,
+ guint id,
+ GtkTreeIter *iter)
+{
+ if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->device_model), iter))
+ return FALSE;
+
+ do
+ {
+ guint i;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (self->device_model), iter, 2, &i, -1);
+ if (i == id)
+ return TRUE;
+ } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->device_model), iter));
+
+ return FALSE;
+}
+
+static void
+device_removed_cb (CcDeviceComboBox *self,
+ guint id)
+{
+ GtkTreeIter iter;
+
+ if (get_iter (self, id, &iter))
+ gtk_list_store_remove (self->device_model, &iter);
+}
+
+static void
+active_device_update_cb (CcDeviceComboBox *self,
+ guint id)
+{
+ GtkTreeIter iter;
+
+ if (get_iter (self, id, &iter))
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (self), &iter);
+}
+
+static void
+cc_device_combo_box_dispose (GObject *object)
+{
+ CcDeviceComboBox *self = CC_DEVICE_COMBO_BOX (object);
+
+ g_clear_object (&self->mixer_control);
+
+ G_OBJECT_CLASS (cc_device_combo_box_parent_class)->dispose (object);
+}
+
+void
+cc_device_combo_box_class_init (CcDeviceComboBoxClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_device_combo_box_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/sound/cc-device-combo-box.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcDeviceComboBox, device_model);
+}
+
+void
+cc_device_combo_box_init (CcDeviceComboBox *self)
+{
+ g_resources_register (cc_sound_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+void
+cc_device_combo_box_set_mixer_control (CcDeviceComboBox *self,
+ GvcMixerControl *mixer_control,
+ gboolean is_output)
+{
+ const gchar *added_signal, *removed_signal, *active_update_signal;
+ g_return_if_fail (CC_IS_DEVICE_COMBO_BOX (self));
+
+ if (self->mixer_control != NULL)
+ {
+ g_signal_handler_disconnect (self->mixer_control, self->added_handler_id);
+ self->added_handler_id = 0;
+ g_signal_handler_disconnect (self->mixer_control, self->removed_handler_id);
+ self->removed_handler_id = 0;
+ g_signal_handler_disconnect (self->mixer_control, self->active_update_handler_id);
+ self->active_update_handler_id = 0;
+ }
+ g_clear_object (&self->mixer_control);
+
+ self->mixer_control = g_object_ref (mixer_control);
+ self->is_output = is_output;
+ if (is_output)
+ {
+ added_signal = "output-added";
+ removed_signal = "output-removed";
+ active_update_signal = "active-output-update";
+ }
+ else
+ {
+ added_signal = "input-added";
+ removed_signal = "input-removed";
+ active_update_signal = "active-input-update";
+ }
+
+ self->added_handler_id = g_signal_connect_object (self->mixer_control,
+ added_signal,
+ G_CALLBACK (device_added_cb),
+ self, G_CONNECT_SWAPPED);
+ self->removed_handler_id = g_signal_connect_object (self->mixer_control,
+ removed_signal,
+ G_CALLBACK (device_removed_cb),
+ self, G_CONNECT_SWAPPED);
+ self->active_update_handler_id = g_signal_connect_object (self->mixer_control,
+ active_update_signal,
+ G_CALLBACK (active_device_update_cb),
+ self, G_CONNECT_SWAPPED);
+}
+
+GvcMixerUIDevice *
+cc_device_combo_box_get_device (CcDeviceComboBox *self)
+{
+ GtkTreeIter iter;
+ guint id;
+
+ g_return_val_if_fail (CC_IS_DEVICE_COMBO_BOX (self), NULL);
+
+ if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (self), &iter))
+ return NULL;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (self->device_model), &iter, 2, &id, -1);
+
+ if (self->is_output)
+ return gvc_mixer_control_lookup_output_id (self->mixer_control, id);
+ else
+ return gvc_mixer_control_lookup_input_id (self->mixer_control, id);
+}
diff --git a/panels/sound/cc-device-combo-box.h b/panels/sound/cc-device-combo-box.h
new file mode 100644
index 0000000..119de59
--- /dev/null
+++ b/panels/sound/cc-device-combo-box.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <pulse/pulseaudio.h>
+#include <gvc-mixer-control.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_DEVICE_COMBO_BOX (cc_device_combo_box_get_type ())
+G_DECLARE_FINAL_TYPE (CcDeviceComboBox, cc_device_combo_box, CC, DEVICE_COMBO_BOX, GtkComboBox)
+
+void cc_device_combo_box_set_mixer_control (CcDeviceComboBox *combo_box,
+ GvcMixerControl *mixer_control,
+ gboolean is_output);
+
+GvcMixerUIDevice *cc_device_combo_box_get_device (CcDeviceComboBox *combo_box);
+
+G_END_DECLS
diff --git a/panels/sound/cc-device-combo-box.ui b/panels/sound/cc-device-combo-box.ui
new file mode 100644
index 0000000..e54f292
--- /dev/null
+++ b/panels/sound/cc-device-combo-box.ui
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcDeviceComboBox" parent="GtkComboBox">
+ <property name="model">device_model</property>
+ <child>
+ <object class="GtkCellRendererPixbuf">
+ <property name="xpad">6</property>
+ </object>
+ <attributes>
+ <attribute name="icon-name">1</attribute>
+ </attributes>
+ </child>
+ <child>
+ <object class="GtkCellRendererText">
+ <property name="ellipsize">end</property>
+ </object>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </template>
+ <object class="GtkListStore" id="device_model">
+ <columns>
+ <!-- column-name title -->
+ <column type="gchararray"/>
+ <!-- column-name icon -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="guint"/>
+ </columns>
+ </object>
+</interface>
diff --git a/panels/sound/cc-fade-slider.c b/panels/sound/cc-fade-slider.c
new file mode 100644
index 0000000..888f214
--- /dev/null
+++ b/panels/sound/cc-fade-slider.c
@@ -0,0 +1,119 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cc-sound-resources.h"
+#include "cc-fade-slider.h"
+#include "gvc-channel-map-private.h"
+
+struct _CcFadeSlider
+{
+ GtkBox parent_instance;
+
+ GtkAdjustment *adjustment;
+
+ GvcChannelMap *channel_map;
+ guint volume_changed_handler_id;
+};
+
+G_DEFINE_TYPE (CcFadeSlider, cc_fade_slider, GTK_TYPE_BOX)
+
+static void
+changed_cb (CcFadeSlider *self)
+{
+ gdouble value;
+ const pa_channel_map *pa_map;
+ pa_cvolume pa_volume;
+
+ if (self->channel_map == NULL)
+ return;
+
+ value = gtk_adjustment_get_value (self->adjustment);
+ pa_map = gvc_channel_map_get_pa_channel_map (self->channel_map);
+ pa_volume = *gvc_channel_map_get_cvolume (self->channel_map);
+ pa_cvolume_set_fade (&pa_volume, pa_map, value);
+ gvc_channel_map_volume_changed (self->channel_map, &pa_volume, TRUE);
+}
+
+static void
+volume_changed_cb (CcFadeSlider *self)
+{
+ const gdouble *volumes;
+
+ volumes = gvc_channel_map_get_volume (self->channel_map);
+ g_signal_handlers_block_by_func (self->adjustment, volume_changed_cb, self);
+ gtk_adjustment_set_value (self->adjustment, volumes[FADE]);
+ g_signal_handlers_unblock_by_func (self->adjustment, volume_changed_cb, self);
+}
+
+static void
+cc_fade_slider_dispose (GObject *object)
+{
+ CcFadeSlider *self = CC_FADE_SLIDER (object);
+
+ g_clear_object (&self->channel_map);
+
+ G_OBJECT_CLASS (cc_fade_slider_parent_class)->dispose (object);
+}
+
+void
+cc_fade_slider_class_init (CcFadeSliderClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_fade_slider_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/sound/cc-fade-slider.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcFadeSlider, adjustment);
+
+ gtk_widget_class_bind_template_callback (widget_class, changed_cb);
+}
+
+void
+cc_fade_slider_init (CcFadeSlider *self)
+{
+ g_resources_register (cc_sound_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+void
+cc_fade_slider_set_channel_map (CcFadeSlider *self,
+ GvcChannelMap *channel_map)
+{
+ g_return_if_fail (CC_IS_FADE_SLIDER (self));
+
+ if (self->channel_map != NULL)
+ {
+ g_signal_handler_disconnect (self->channel_map, self->volume_changed_handler_id);
+ self->volume_changed_handler_id = 0;
+ }
+ g_clear_object (&self->channel_map);
+
+ if (channel_map != NULL)
+ {
+ self->channel_map = g_object_ref (channel_map);
+
+ self->volume_changed_handler_id = g_signal_connect_object (channel_map,
+ "volume-changed",
+ G_CALLBACK (volume_changed_cb),
+ self, G_CONNECT_SWAPPED);
+ volume_changed_cb (self);
+ }
+}
diff --git a/panels/sound/cc-fade-slider.h b/panels/sound/cc-fade-slider.h
new file mode 100644
index 0000000..92b8041
--- /dev/null
+++ b/panels/sound/cc-fade-slider.h
@@ -0,0 +1,33 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <pulse/pulseaudio.h>
+#include <gvc-channel-map.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_FADE_SLIDER (cc_fade_slider_get_type ())
+G_DECLARE_FINAL_TYPE (CcFadeSlider, cc_fade_slider, CC, FADE_SLIDER, GtkBox)
+
+void cc_fade_slider_set_channel_map (CcFadeSlider *slider,
+ GvcChannelMap *channel_map);
+
+G_END_DECLS
diff --git a/panels/sound/cc-fade-slider.ui b/panels/sound/cc-fade-slider.ui
new file mode 100644
index 0000000..97984fb
--- /dev/null
+++ b/panels/sound/cc-fade-slider.ui
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcFadeSlider" parent="GtkBox">
+ <child>
+ <object class="GtkScale">
+ <property name="visible">True</property>
+ <property name="hexpand">True</property>
+ <property name="draw_value">False</property>
+ <property name="has_origin">False</property>
+ <property name="adjustment">adjustment</property>
+ <accessibility>
+ <property name="label" translatable="yes">Fade</property>
+ </accessibility>
+ <marks>
+ <mark value="-1" translatable="yes">Rear</mark>
+ <mark value="0"/>
+ <mark value="1" translatable="yes">Front</mark>
+ </marks>
+ </object>
+ </child>
+ </template>
+ <object class="GtkAdjustment" id="adjustment">
+ <property name="lower">-1.0</property>
+ <property name="upper">1.0</property>
+ <property name="step_increment">0.5</property>
+ <property name="page_increment">0.5</property>
+ <signal name="value_changed" handler="changed_cb" object="CcFadeSlider" swapped="yes"/>
+ </object>
+</interface>
diff --git a/panels/sound/cc-level-bar.c b/panels/sound/cc-level-bar.c
new file mode 100644
index 0000000..8636132
--- /dev/null
+++ b/panels/sound/cc-level-bar.c
@@ -0,0 +1,290 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cc-level-bar.h"
+#include "cc-sound-enums.h"
+#include "gvc-mixer-stream-private.h"
+
+struct _CcLevelBar
+{
+ GtkWidget parent_instance;
+
+ CcStreamType type;
+ pa_stream *level_stream;
+ gdouble last_input_peak;
+
+ gdouble value;
+};
+
+G_DEFINE_TYPE (CcLevelBar, cc_level_bar, GTK_TYPE_WIDGET)
+
+#define LED_WIDTH 12
+#define LED_HEIGHT 3
+#define LED_SPACING 4
+
+#define DECAY_STEP .15
+
+static void
+set_peak (CcLevelBar *self,
+ gdouble value)
+{
+ if (value < 0)
+ value = 0;
+ if (value > 1)
+ value = 1;
+
+ if (self->last_input_peak >= DECAY_STEP &&
+ value < self->last_input_peak - DECAY_STEP)
+ value = self->last_input_peak - DECAY_STEP;
+ self->last_input_peak = value;
+
+ self->value = value;
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+}
+
+static void
+read_cb (pa_stream *stream,
+ size_t length,
+ void *userdata)
+{
+ CcLevelBar *self = userdata;
+ const void *data;
+ gdouble value;
+
+ if (pa_stream_peek (stream, &data, &length) < 0)
+ {
+ g_warning ("Failed to read data from stream");
+ return;
+ }
+
+ if (!data)
+ {
+ pa_stream_drop (stream);
+ return;
+ }
+
+ assert (length > 0);
+ assert (length % sizeof (float) == 0);
+
+ value = ((const float *) data)[length / sizeof (float) -1];
+
+ pa_stream_drop (stream);
+
+ set_peak (self, value);
+}
+
+static void
+suspended_cb (pa_stream *stream,
+ void *userdata)
+{
+ CcLevelBar *self = userdata;
+
+ if (pa_stream_is_suspended (stream))
+ {
+ g_debug ("Stream suspended");
+ self->value = 0.0;
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+ }
+}
+
+static void
+cc_level_bar_measure (GtkWidget *widget,
+ GtkOrientation orientation,
+ int for_size,
+ int *minimum,
+ int *natural,
+ int *minimum_baseline,
+ int *natural_baseline)
+{
+ if (orientation == GTK_ORIENTATION_VERTICAL)
+ {
+ *minimum = *natural = LED_HEIGHT;
+ }
+ else
+ {
+ GTK_WIDGET_CLASS (cc_level_bar_parent_class)->measure (widget,
+ orientation,
+ for_size,
+ minimum,
+ natural,
+ minimum_baseline,
+ natural_baseline);
+ }
+}
+
+static void
+cc_level_bar_snapshot (GtkWidget *widget,
+ GtkSnapshot *snapshot)
+{
+ CcLevelBar *self = CC_LEVEL_BAR (widget);
+ GdkRGBA inactive_color, active_color;
+ int i, n_leds;
+ double level;
+ double spacing, x_offset = 0.0;
+
+ n_leds = gtk_widget_get_width (widget) / (LED_WIDTH + LED_SPACING);
+ spacing = (double) (gtk_widget_get_width (widget) - (n_leds * LED_WIDTH)) / (n_leds - 1);
+ level = self->value * n_leds;
+
+ gdk_rgba_parse (&inactive_color, "#C0C0C0");
+ switch (self->type)
+ {
+ default:
+ case CC_STREAM_TYPE_OUTPUT:
+ gdk_rgba_parse (&active_color, "#4a90d9");
+ break;
+ case CC_STREAM_TYPE_INPUT:
+ gdk_rgba_parse (&active_color, "#ff0000");
+ break;
+ }
+
+ for (i = 0; i < n_leds; i++)
+ {
+ GdkRGBA blended_color;
+ double led_level;
+
+ led_level = level - i;
+ if (led_level < 0.0)
+ led_level = 0.0;
+ else if (led_level > 1.0)
+ led_level = 1.0;
+
+ blended_color = (GdkRGBA) {
+ .red = (1.0 - led_level) * inactive_color.red + led_level * active_color.red,
+ .green = (1.0 - led_level) * inactive_color.green + led_level * active_color.green,
+ .blue = (1.0 - led_level) * inactive_color.blue + led_level * active_color.blue,
+ .alpha = 1.0,
+ };
+
+ gtk_snapshot_append_color (snapshot,
+ &blended_color,
+ &GRAPHENE_RECT_INIT (x_offset, 0,
+ LED_WIDTH,
+ gtk_widget_get_height (widget)));
+ x_offset += LED_WIDTH + spacing;
+ }
+}
+
+static void
+close_stream (pa_stream *stream)
+{
+ if (stream == NULL)
+ return;
+
+ /* Stop receiving data */
+ pa_stream_set_read_callback (stream, NULL, NULL);
+ pa_stream_set_suspended_callback (stream, NULL, NULL);
+
+ /* Disconnect from the stream */
+ pa_stream_disconnect (stream);
+}
+
+static void
+cc_level_bar_dispose (GObject *object)
+{
+ CcLevelBar *self = CC_LEVEL_BAR (object);
+
+ close_stream (self->level_stream);
+ g_clear_pointer (&self->level_stream, pa_stream_unref);
+
+ G_OBJECT_CLASS (cc_level_bar_parent_class)->dispose (object);
+}
+
+void
+cc_level_bar_class_init (CcLevelBarClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_level_bar_dispose;
+
+ widget_class->measure = cc_level_bar_measure;
+ widget_class->snapshot = cc_level_bar_snapshot;
+}
+
+void
+cc_level_bar_init (CcLevelBar *self)
+{
+}
+
+void
+cc_level_bar_set_stream (CcLevelBar *self,
+ GvcMixerStream *stream,
+ CcStreamType type)
+{
+ pa_context *context;
+ pa_sample_spec sample_spec;
+ pa_proplist *proplist;
+ pa_buffer_attr attr;
+ g_autofree gchar *device = NULL;
+
+ g_return_if_fail (CC_IS_LEVEL_BAR (self));
+
+ close_stream (self->level_stream);
+ g_clear_pointer (&self->level_stream, pa_stream_unref);
+
+ self->type = type;
+
+ if (stream == NULL)
+ {
+ self->value = 0.0;
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+ return;
+ }
+
+ context = gvc_mixer_stream_get_pa_context (stream);
+
+ if (pa_context_get_server_protocol_version (context) < 13)
+ {
+ g_warning ("Unsupported version of PulseAudio");
+ return;
+ }
+
+ sample_spec.channels = 1;
+ sample_spec.format = PA_SAMPLE_FLOAT32;
+ sample_spec.rate = 25;
+
+ proplist = pa_proplist_new ();
+ pa_proplist_sets (proplist, PA_PROP_APPLICATION_ID, "org.gnome.VolumeControl");
+ self->level_stream = pa_stream_new_with_proplist (context, "Peak detect", &sample_spec, NULL, proplist);
+ pa_proplist_free (proplist);
+ if (self->level_stream == NULL)
+ {
+ g_warning ("Failed to create monitoring stream");
+ return;
+ }
+
+ pa_stream_set_read_callback (self->level_stream, read_cb, self);
+ pa_stream_set_suspended_callback (self->level_stream, suspended_cb, self);
+
+ memset (&attr, 0, sizeof (attr));
+ attr.fragsize = sizeof (float);
+ attr.maxlength = (uint32_t) -1;
+ device = g_strdup_printf ("%u", gvc_mixer_stream_get_index (stream));
+ if (pa_stream_connect_record (self->level_stream,
+ device,
+ &attr,
+ (pa_stream_flags_t) (PA_STREAM_DONT_MOVE |
+ PA_STREAM_PEAK_DETECT |
+ PA_STREAM_ADJUST_LATENCY)) < 0)
+ {
+ g_warning ("Failed to connect monitoring stream");
+ }
+
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+}
diff --git a/panels/sound/cc-level-bar.h b/panels/sound/cc-level-bar.h
new file mode 100644
index 0000000..34ef1ea
--- /dev/null
+++ b/panels/sound/cc-level-bar.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <pulse/pulseaudio.h>
+#include <gvc-mixer-stream.h>
+
+#include "cc-sound-enums.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_LEVEL_BAR (cc_level_bar_get_type ())
+G_DECLARE_FINAL_TYPE (CcLevelBar, cc_level_bar, CC, LEVEL_BAR, GtkWidget)
+
+void cc_level_bar_set_stream (CcLevelBar *bar,
+ GvcMixerStream *stream,
+ CcStreamType type);
+
+G_END_DECLS
diff --git a/panels/sound/cc-output-test-dialog.c b/panels/sound/cc-output-test-dialog.c
new file mode 100644
index 0000000..b8a518e
--- /dev/null
+++ b/panels/sound/cc-output-test-dialog.c
@@ -0,0 +1,160 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <gsound.h>
+#include <glib/gi18n.h>
+
+#include "cc-output-test-dialog.h"
+#include "cc-sound-resources.h"
+#include "cc-speaker-test-button.h"
+
+struct _CcOutputTestDialog
+{
+ GtkDialog parent_instance;
+
+ CcSpeakerTestButton *front_center_speaker_button;
+ CcSpeakerTestButton *front_left_speaker_button;
+ CcSpeakerTestButton *front_left_of_center_speaker_button;
+ CcSpeakerTestButton *front_right_of_center_speaker_button;
+ CcSpeakerTestButton *front_right_speaker_button;
+ CcSpeakerTestButton *lfe_speaker_button;
+ CcSpeakerTestButton *rear_center_speaker_button;
+ CcSpeakerTestButton *rear_left_speaker_button;
+ CcSpeakerTestButton *rear_right_speaker_button;
+ CcSpeakerTestButton *side_left_speaker_button;
+ CcSpeakerTestButton *side_right_speaker_button;
+
+ GvcMixerUIDevice *device;
+ GSoundContext *context;
+};
+
+G_DEFINE_TYPE (CcOutputTestDialog, cc_output_test_dialog, GTK_TYPE_DIALOG)
+
+static void
+cc_output_test_dialog_dispose (GObject *object)
+{
+ CcOutputTestDialog *self = CC_OUTPUT_TEST_DIALOG (object);
+
+ g_clear_object (&self->device);
+ g_clear_object (&self->context);
+
+ G_OBJECT_CLASS (cc_output_test_dialog_parent_class)->dispose (object);
+}
+
+void
+cc_output_test_dialog_class_init (CcOutputTestDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_output_test_dialog_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/sound/cc-output-test-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcOutputTestDialog, front_center_speaker_button);
+ gtk_widget_class_bind_template_child (widget_class, CcOutputTestDialog, front_left_speaker_button);
+ gtk_widget_class_bind_template_child (widget_class, CcOutputTestDialog, front_left_of_center_speaker_button);
+ gtk_widget_class_bind_template_child (widget_class, CcOutputTestDialog, front_right_of_center_speaker_button);
+ gtk_widget_class_bind_template_child (widget_class, CcOutputTestDialog, front_right_speaker_button);
+ gtk_widget_class_bind_template_child (widget_class, CcOutputTestDialog, lfe_speaker_button);
+ gtk_widget_class_bind_template_child (widget_class, CcOutputTestDialog, rear_center_speaker_button);
+ gtk_widget_class_bind_template_child (widget_class, CcOutputTestDialog, rear_left_speaker_button);
+ gtk_widget_class_bind_template_child (widget_class, CcOutputTestDialog, rear_right_speaker_button);
+ gtk_widget_class_bind_template_child (widget_class, CcOutputTestDialog, side_left_speaker_button);
+ gtk_widget_class_bind_template_child (widget_class, CcOutputTestDialog, side_right_speaker_button);
+
+ g_type_ensure (CC_TYPE_SPEAKER_TEST_BUTTON);
+}
+
+void
+cc_output_test_dialog_init (CcOutputTestDialog *self)
+{
+ GtkSettings *settings;
+ g_autofree gchar *theme_name = NULL;
+
+ g_resources_register (cc_sound_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->context = gsound_context_new (NULL, NULL);
+ gsound_context_set_driver (self->context, "pulse", NULL);
+ gsound_context_set_attributes (self->context, NULL,
+ GSOUND_ATTR_APPLICATION_ID, "org.gnome.VolumeControl",
+ NULL);
+ settings = gtk_settings_get_for_display (gdk_display_get_default ());
+ g_object_get (G_OBJECT (settings),
+ "gtk-sound-theme-name", &theme_name,
+ NULL);
+ if (theme_name != NULL)
+ gsound_context_set_attributes (self->context, NULL,
+ GSOUND_ATTR_CANBERRA_XDG_THEME_NAME, theme_name,
+ NULL);
+
+ cc_speaker_test_button_set_channel_position (self->front_left_speaker_button, self->context, PA_CHANNEL_POSITION_FRONT_LEFT);
+ cc_speaker_test_button_set_channel_position (self->front_left_of_center_speaker_button, self->context, PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER);
+ cc_speaker_test_button_set_channel_position (self->front_center_speaker_button, self->context, PA_CHANNEL_POSITION_FRONT_CENTER);
+ cc_speaker_test_button_set_channel_position (self->front_right_of_center_speaker_button, self->context, PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER);
+ cc_speaker_test_button_set_channel_position (self->front_right_speaker_button, self->context, PA_CHANNEL_POSITION_FRONT_RIGHT);
+ cc_speaker_test_button_set_channel_position (self->side_left_speaker_button, self->context, PA_CHANNEL_POSITION_SIDE_LEFT);
+ cc_speaker_test_button_set_channel_position (self->side_right_speaker_button, self->context, PA_CHANNEL_POSITION_SIDE_RIGHT);
+ cc_speaker_test_button_set_channel_position (self->lfe_speaker_button, self->context, PA_CHANNEL_POSITION_LFE);
+ cc_speaker_test_button_set_channel_position (self->rear_left_speaker_button, self->context, PA_CHANNEL_POSITION_REAR_LEFT);
+ cc_speaker_test_button_set_channel_position (self->rear_center_speaker_button, self->context, PA_CHANNEL_POSITION_REAR_CENTER);
+ cc_speaker_test_button_set_channel_position (self->rear_right_speaker_button, self->context, PA_CHANNEL_POSITION_REAR_RIGHT);
+}
+
+CcOutputTestDialog *
+cc_output_test_dialog_new (GvcMixerUIDevice *device,
+ GvcMixerStream *stream)
+{
+ CcOutputTestDialog *self;
+ const GvcChannelMap *map = NULL;
+ g_autofree gchar *title = NULL;
+
+ self = g_object_new (CC_TYPE_OUTPUT_TEST_DIALOG,
+ "use-header-bar", 1,
+ NULL);
+ self->device = g_object_ref (device);
+
+ title = g_strdup_printf (_("Testing %s"), gvc_mixer_ui_device_get_description (device));
+ gtk_window_set_title (GTK_WINDOW (self), title);
+
+ map = gvc_mixer_stream_get_channel_map (stream);
+ gtk_widget_set_visible (GTK_WIDGET (self->front_left_speaker_button), gvc_channel_map_has_position (map, PA_CHANNEL_POSITION_FRONT_LEFT));
+ gtk_widget_set_visible (GTK_WIDGET (self->front_left_of_center_speaker_button), gvc_channel_map_has_position (map, PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER));
+ gtk_widget_set_visible (GTK_WIDGET (self->front_center_speaker_button), gvc_channel_map_has_position (map, PA_CHANNEL_POSITION_FRONT_CENTER));
+ gtk_widget_set_visible (GTK_WIDGET (self->front_right_of_center_speaker_button), gvc_channel_map_has_position (map, PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER));
+ gtk_widget_set_visible (GTK_WIDGET (self->front_right_speaker_button), gvc_channel_map_has_position (map, PA_CHANNEL_POSITION_FRONT_RIGHT));
+ gtk_widget_set_visible (GTK_WIDGET (self->side_left_speaker_button), gvc_channel_map_has_position (map, PA_CHANNEL_POSITION_SIDE_LEFT));
+ gtk_widget_set_visible (GTK_WIDGET (self->side_right_speaker_button), gvc_channel_map_has_position (map, PA_CHANNEL_POSITION_SIDE_RIGHT));
+ gtk_widget_set_visible (GTK_WIDGET (self->lfe_speaker_button), gvc_channel_map_has_position (map, PA_CHANNEL_POSITION_LFE));
+ gtk_widget_set_visible (GTK_WIDGET (self->rear_left_speaker_button), gvc_channel_map_has_position (map, PA_CHANNEL_POSITION_REAR_LEFT));
+ gtk_widget_set_visible (GTK_WIDGET (self->rear_center_speaker_button), gvc_channel_map_has_position (map, PA_CHANNEL_POSITION_REAR_CENTER));
+ gtk_widget_set_visible (GTK_WIDGET (self->rear_right_speaker_button), gvc_channel_map_has_position (map, PA_CHANNEL_POSITION_REAR_RIGHT));
+
+ /* Replace the center channel with a mono channel */
+ if (gvc_channel_map_has_position (map, PA_CHANNEL_POSITION_MONO))
+ {
+ if (gvc_channel_map_has_position (map, PA_CHANNEL_POSITION_FRONT_CENTER))
+ g_warning ("Testing output with both front center and mono channels - front center is hidden");
+ cc_speaker_test_button_set_channel_position (self->front_center_speaker_button, self->context, PA_CHANNEL_POSITION_MONO);
+ gtk_widget_set_visible (GTK_WIDGET (self->front_center_speaker_button), TRUE);
+ }
+
+ return self;
+}
diff --git a/panels/sound/cc-output-test-dialog.h b/panels/sound/cc-output-test-dialog.h
new file mode 100644
index 0000000..ece6f82
--- /dev/null
+++ b/panels/sound/cc-output-test-dialog.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <gvc-mixer-ui-device.h>
+#include <pulse/pulseaudio.h>
+#include <gvc-mixer-stream.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_OUTPUT_TEST_DIALOG (cc_output_test_dialog_get_type ())
+G_DECLARE_FINAL_TYPE (CcOutputTestDialog, cc_output_test_dialog, CC, OUTPUT_TEST_DIALOG, GtkDialog)
+
+CcOutputTestDialog *cc_output_test_dialog_new (GvcMixerUIDevice *device,
+ GvcMixerStream *stream);
+
+G_END_DECLS
diff --git a/panels/sound/cc-output-test-dialog.ui b/panels/sound/cc-output-test-dialog.ui
new file mode 100644
index 0000000..7ec5b7b
--- /dev/null
+++ b/panels/sound/cc-output-test-dialog.ui
@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcOutputTestDialog" parent="GtkDialog">
+ <property name="modal">True</property>
+ <property name="resizable">False</property>
+ <child>
+ <object class="GtkBox">
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="row_spacing">30</property>
+ <property name="column_spacing">30</property>
+ <property name="margin-top">30</property>
+ <property name="margin-bottom">30</property>
+ <property name="margin-start">30</property>
+ <property name="margin-end">30</property>
+ <child>
+ <object class="CcSpeakerTestButton" id="front_left_speaker_button">
+ <property name="visible">True</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="CcSpeakerTestButton" id="front_left_of_center_speaker_button">
+ <property name="visible">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="CcSpeakerTestButton" id="front_center_speaker_button">
+ <property name="visible">True</property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="CcSpeakerTestButton" id="front_right_of_center_speaker_button">
+ <property name="visible">True</property>
+ <layout>
+ <property name="column">3</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="CcSpeakerTestButton" id="front_right_speaker_button">
+ <property name="visible">True</property>
+ <layout>
+ <property name="column">4</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="CcSpeakerTestButton" id="side_left_speaker_button">
+ <property name="visible">True</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="icon_name">avatar-default-symbolic</property>
+ <property name="pixel_size">64</property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="CcSpeakerTestButton" id="side_right_speaker_button">
+ <property name="visible">True</property>
+ <layout>
+ <property name="column">4</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="CcSpeakerTestButton" id="rear_left_speaker_button">
+ <property name="visible">True</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="CcSpeakerTestButton" id="rear_center_speaker_button">
+ <property name="visible">True</property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="CcSpeakerTestButton" id="lfe_speaker_button">
+ <property name="visible">True</property>
+ <layout>
+ <property name="column">3</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="CcSpeakerTestButton" id="rear_right_speaker_button">
+ <property name="visible">True</property>
+ <layout>
+ <property name="column">4</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Click a speaker to test</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ <property name="column-span">5</property>
+ </layout>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GtkSizeGroup">
+ <property name="mode">both</property>
+ <widgets>
+ <widget name="front_left_speaker_button"/>
+ <widget name="front_left_of_center_speaker_button"/>
+ <widget name="front_center_speaker_button"/>
+ <widget name="front_right_of_center_speaker_button"/>
+ <widget name="front_right_speaker_button"/>
+ <widget name="side_left_speaker_button"/>
+ <widget name="side_right_speaker_button"/>
+ <widget name="rear_left_speaker_button"/>
+ <widget name="rear_center_speaker_button"/>
+ <widget name="lfe_speaker_button"/>
+ <widget name="rear_right_speaker_button"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/panels/sound/cc-profile-combo-box.c b/panels/sound/cc-profile-combo-box.c
new file mode 100644
index 0000000..a328b98
--- /dev/null
+++ b/panels/sound/cc-profile-combo-box.c
@@ -0,0 +1,135 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cc-profile-combo-box.h"
+#include "cc-sound-resources.h"
+
+struct _CcProfileComboBox
+{
+ GtkComboBox parent_instance;
+
+ GtkListStore *profile_model;
+
+ GvcMixerControl *mixer_control;
+ GvcMixerUIDevice *device;
+};
+
+G_DEFINE_TYPE (CcProfileComboBox, cc_profile_combo_box, GTK_TYPE_COMBO_BOX)
+
+static void
+profile_changed_cb (CcProfileComboBox *self)
+{
+ GtkTreeIter iter;
+ g_autofree gchar *profile = NULL;
+
+ if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (self), &iter))
+ return;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (self->profile_model), &iter,
+ 1, &profile,
+ -1);
+
+ if (!gvc_mixer_control_change_profile_on_selected_device (self->mixer_control,
+ self->device,
+ profile))
+ {
+ g_warning ("Failed to change profile on %s", gvc_mixer_ui_device_get_description (self->device));
+ }
+}
+
+static void
+cc_profile_combo_box_dispose (GObject *object)
+{
+ CcProfileComboBox *self = CC_PROFILE_COMBO_BOX (object);
+
+ g_clear_object (&self->device);
+
+ G_OBJECT_CLASS (cc_profile_combo_box_parent_class)->dispose (object);
+}
+
+void
+cc_profile_combo_box_class_init (CcProfileComboBoxClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_profile_combo_box_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/sound/cc-profile-combo-box.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcProfileComboBox, profile_model);
+
+ gtk_widget_class_bind_template_callback (widget_class, profile_changed_cb);
+}
+
+void
+cc_profile_combo_box_init (CcProfileComboBox *self)
+{
+ g_resources_register (cc_sound_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+void
+cc_profile_combo_box_set_device (CcProfileComboBox *self,
+ GvcMixerControl *mixer_control,
+ GvcMixerUIDevice *device)
+{
+ GList *profiles, *link;
+
+ g_return_if_fail (CC_IS_PROFILE_COMBO_BOX (self));
+
+ if (device == self->device)
+ return;
+
+ g_clear_object (&self->mixer_control);
+ self->mixer_control = g_object_ref (mixer_control);
+ g_clear_object (&self->device);
+ gtk_list_store_clear (self->profile_model);
+
+ if (device == NULL)
+ return;
+
+ self->device = g_object_ref (device);
+ profiles = gvc_mixer_ui_device_get_profiles (device);
+ for (link = profiles; link; link = link->next)
+ {
+ GvcMixerCardProfile *profile = link->data;
+ GtkTreeIter iter;
+
+ gtk_list_store_append (self->profile_model, &iter);
+ gtk_list_store_set (self->profile_model, &iter,
+ 0, profile->human_profile,
+ 1, profile->profile,
+ -1);
+
+ if (g_strcmp0 (gvc_mixer_ui_device_get_active_profile (device), profile->profile) == 0)
+ {
+ g_signal_handlers_block_by_func(self, profile_changed_cb, self);
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (self), &iter);
+ g_signal_handlers_unblock_by_func(self, profile_changed_cb, self);
+ }
+ }
+}
+
+gint
+cc_profile_combo_box_get_profile_count (CcProfileComboBox *self)
+{
+ g_return_val_if_fail (CC_IS_PROFILE_COMBO_BOX (self), 0);
+ return gtk_tree_model_iter_n_children (GTK_TREE_MODEL (self->profile_model), NULL);
+}
diff --git a/panels/sound/cc-profile-combo-box.h b/panels/sound/cc-profile-combo-box.h
new file mode 100644
index 0000000..d76becb
--- /dev/null
+++ b/panels/sound/cc-profile-combo-box.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <pulse/pulseaudio.h>
+#include <gvc-mixer-control.h>
+#include <gvc-mixer-ui-device.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_PROFILE_COMBO_BOX (cc_profile_combo_box_get_type ())
+G_DECLARE_FINAL_TYPE (CcProfileComboBox, cc_profile_combo_box, CC, PROFILE_COMBO_BOX, GtkComboBox)
+
+void cc_profile_combo_box_set_device (CcProfileComboBox *combo_box,
+ GvcMixerControl *mixer_control,
+ GvcMixerUIDevice *device);
+
+gint cc_profile_combo_box_get_profile_count (CcProfileComboBox *combo_box);
+
+G_END_DECLS
diff --git a/panels/sound/cc-profile-combo-box.ui b/panels/sound/cc-profile-combo-box.ui
new file mode 100644
index 0000000..58f2d9b
--- /dev/null
+++ b/panels/sound/cc-profile-combo-box.ui
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcProfileComboBox" parent="GtkComboBox">
+ <property name="model">profile_model</property>
+ <signal name="changed" handler="profile_changed_cb" object="CcProfileComboBox" swapped="yes"/>
+ <child>
+ <object class="GtkCellRendererText"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </template>
+ <object class="GtkListStore" id="profile_model">
+ <columns>
+ <!-- column-name title -->
+ <column type="gchararray"/>
+ <!-- column-name profile -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+</interface>
diff --git a/panels/sound/cc-sound-enums.h b/panels/sound/cc-sound-enums.h
new file mode 100644
index 0000000..bf29d27
--- /dev/null
+++ b/panels/sound/cc-sound-enums.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 Jordan Petridis <jpetridis@gnome.org>
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef enum
+{
+ CC_STREAM_TYPE_OUTPUT,
+ CC_STREAM_TYPE_INPUT,
+} CcStreamType;
+
+G_END_DECLS
diff --git a/panels/sound/cc-sound-panel.c b/panels/sound/cc-sound-panel.c
new file mode 100644
index 0000000..0de1ca9
--- /dev/null
+++ b/panels/sound/cc-sound-panel.c
@@ -0,0 +1,318 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <libintl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <glib/gi18n-lib.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <pulse/pulseaudio.h>
+#include <gvc-mixer-control.h>
+
+#include "cc-alert-chooser.h"
+#include "cc-balance-slider.h"
+#include "cc-device-combo-box.h"
+#include "cc-fade-slider.h"
+#include "cc-level-bar.h"
+#include "cc-output-test-dialog.h"
+#include "cc-profile-combo-box.h"
+#include "cc-sound-panel.h"
+#include "cc-sound-resources.h"
+#include "cc-stream-list-box.h"
+#include "cc-subwoofer-slider.h"
+#include "cc-volume-slider.h"
+
+struct _CcSoundPanel
+{
+ CcPanel parent_instance;
+
+ CcBalanceSlider *balance_slider;
+ GtkListBoxRow *fade_row;
+ CcFadeSlider *fade_slider;
+ CcDeviceComboBox *input_device_combo_box;
+ CcLevelBar *input_level_bar;
+ GtkListBox *input_list_box;
+ CcProfileComboBox *input_profile_combo_box;
+ GtkListBoxRow *input_profile_row;
+ CcVolumeSlider *input_volume_slider;
+ GtkSizeGroup *label_size_group;
+ CcDeviceComboBox *output_device_combo_box;
+ GtkListStore *output_device_model;
+ CcLevelBar *output_level_bar;
+ GtkListBox *output_list_box;
+ CcProfileComboBox *output_profile_combo_box;
+ GtkListBoxRow *output_profile_row;
+ CcVolumeSlider *output_volume_slider;
+ CcStreamListBox *stream_list_box;
+ GtkListBoxRow *subwoofer_row;
+ CcSubwooferSlider *subwoofer_slider;
+
+ GvcMixerControl *mixer_control;
+ GSettings *sound_settings;
+};
+
+CC_PANEL_REGISTER (CcSoundPanel, cc_sound_panel)
+
+enum
+{
+ PROP_0,
+ PROP_PARAMETERS
+};
+
+#define KEY_SOUNDS_SCHEMA "org.gnome.desktop.sound"
+
+static void
+allow_amplified_changed_cb (CcSoundPanel *self)
+{
+ cc_volume_slider_set_is_amplified (self->output_volume_slider,
+ g_settings_get_boolean (self->sound_settings, "allow-volume-above-100-percent"));
+}
+
+static void
+set_output_stream (CcSoundPanel *self,
+ GvcMixerStream *stream)
+{
+ GvcChannelMap *map = NULL;
+ gboolean can_fade = FALSE, has_lfe = FALSE;
+
+ cc_volume_slider_set_stream (self->output_volume_slider, stream, CC_STREAM_TYPE_OUTPUT);
+ cc_level_bar_set_stream (self->output_level_bar, stream, CC_STREAM_TYPE_OUTPUT);
+
+ if (stream != NULL)
+ {
+ map = (GvcChannelMap *) gvc_mixer_stream_get_channel_map (stream);
+ can_fade = gvc_channel_map_can_fade (map);
+ has_lfe = gvc_channel_map_has_lfe (map);
+ }
+ cc_fade_slider_set_channel_map (self->fade_slider, map);
+ cc_balance_slider_set_channel_map (self->balance_slider, map);
+ cc_subwoofer_slider_set_channel_map (self->subwoofer_slider, map);
+
+ gtk_widget_set_visible (GTK_WIDGET (self->fade_row), can_fade);
+ gtk_widget_set_visible (GTK_WIDGET (self->subwoofer_row), has_lfe);
+}
+
+static void
+output_device_changed_cb (CcSoundPanel *self)
+{
+ GvcMixerUIDevice *device;
+ GvcMixerStream *stream = NULL;
+
+ device = cc_device_combo_box_get_device (self->output_device_combo_box);
+
+ if (device != NULL)
+ stream = gvc_mixer_control_get_stream_from_device (self->mixer_control, device);
+
+ set_output_stream (self, stream);
+
+ if (device != NULL)
+ gvc_mixer_control_change_output (self->mixer_control, device);
+}
+
+static void
+set_input_stream (CcSoundPanel *self,
+ GvcMixerStream *stream)
+{
+ cc_volume_slider_set_stream (self->input_volume_slider, stream, CC_STREAM_TYPE_INPUT);
+ cc_level_bar_set_stream (self->input_level_bar, stream, CC_STREAM_TYPE_INPUT);
+}
+
+static void
+input_device_changed_cb (CcSoundPanel *self)
+{
+ GvcMixerUIDevice *device;
+ GvcMixerStream *stream = NULL;
+
+ device = cc_device_combo_box_get_device (self->input_device_combo_box);
+
+ if (device != NULL)
+ stream = gvc_mixer_control_get_stream_from_device (self->mixer_control, device);
+
+ set_input_stream (self, stream);
+
+ if (device != NULL)
+ gvc_mixer_control_change_input (self->mixer_control, device);
+}
+
+static void
+output_device_update_cb (CcSoundPanel *self,
+ guint id)
+{
+ GvcMixerUIDevice *device;
+ gboolean has_multi_profiles;
+ GvcMixerStream *stream = NULL;
+
+ device = cc_device_combo_box_get_device (self->output_device_combo_box);
+ cc_profile_combo_box_set_device (self->output_profile_combo_box, self->mixer_control, device);
+ has_multi_profiles = (cc_profile_combo_box_get_profile_count (self->output_profile_combo_box) > 1);
+ gtk_widget_set_visible (GTK_WIDGET (self->output_profile_row),
+ has_multi_profiles);
+
+ if (cc_volume_slider_get_stream (self->output_volume_slider) == NULL)
+ stream = gvc_mixer_control_get_stream_from_device (self->mixer_control, device);
+ if (stream != NULL)
+ set_output_stream (self, stream);
+}
+
+static void
+input_device_update_cb (CcSoundPanel *self,
+ guint id)
+{
+ GvcMixerUIDevice *device;
+ gboolean has_multi_profiles;
+ GvcMixerStream *stream = NULL;
+
+ device = cc_device_combo_box_get_device (self->input_device_combo_box);
+ cc_profile_combo_box_set_device (self->input_profile_combo_box, self->mixer_control, device);
+ has_multi_profiles = (cc_profile_combo_box_get_profile_count (self->input_profile_combo_box) > 1);
+ gtk_widget_set_visible (GTK_WIDGET (self->input_profile_row),
+ has_multi_profiles);
+
+ if (cc_volume_slider_get_stream (self->input_volume_slider) == NULL)
+ stream = gvc_mixer_control_get_stream_from_device (self->mixer_control, device);
+ if (stream != NULL)
+ set_input_stream (self, stream);
+}
+
+static void
+test_output_configuration_button_clicked_cb (CcSoundPanel *self)
+{
+ GvcMixerUIDevice *device;
+ GvcMixerStream *stream = NULL;
+ CcOutputTestDialog *dialog;
+ GtkWidget *toplevel;
+ CcShell *shell;
+
+ device = cc_device_combo_box_get_device (self->output_device_combo_box);
+ if (device != NULL)
+ stream = gvc_mixer_control_get_stream_from_device (self->mixer_control, device);
+
+ shell = cc_panel_get_shell (CC_PANEL (self));
+ toplevel = cc_shell_get_toplevel (shell);
+
+ dialog = cc_output_test_dialog_new (device, stream);
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel));
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+static const char *
+cc_sound_panel_get_help_uri (CcPanel *panel)
+{
+ return "help:gnome-help/media#sound";
+}
+
+static void
+cc_sound_panel_finalize (GObject *object)
+{
+ CcSoundPanel *panel = CC_SOUND_PANEL (object);
+
+ g_clear_object (&panel->mixer_control);
+ g_clear_object (&panel->sound_settings);
+
+ G_OBJECT_CLASS (cc_sound_panel_parent_class)->finalize (object);
+}
+
+static void
+cc_sound_panel_class_init (CcSoundPanelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+
+ panel_class->get_help_uri = cc_sound_panel_get_help_uri;
+
+ object_class->finalize = cc_sound_panel_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/sound/cc-sound-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, balance_slider);
+ gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, fade_row);
+ gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, fade_slider);
+ gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, input_device_combo_box);
+ gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, input_level_bar);
+ gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, input_list_box);
+ gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, input_profile_combo_box);
+ gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, input_profile_row);
+ gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, input_volume_slider);
+ gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, label_size_group);
+ gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, output_device_combo_box);
+ gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, output_level_bar);
+ gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, output_list_box);
+ gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, output_profile_combo_box);
+ gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, output_profile_row);
+ gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, output_volume_slider);
+ gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, stream_list_box);
+ gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, subwoofer_row);
+ gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, subwoofer_slider);
+
+ gtk_widget_class_bind_template_callback (widget_class, input_device_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, output_device_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, test_output_configuration_button_clicked_cb);
+
+ g_type_ensure (CC_TYPE_ALERT_CHOOSER);
+ g_type_ensure (CC_TYPE_BALANCE_SLIDER);
+ g_type_ensure (CC_TYPE_DEVICE_COMBO_BOX);
+ g_type_ensure (CC_TYPE_FADE_SLIDER);
+ g_type_ensure (CC_TYPE_LEVEL_BAR);
+ g_type_ensure (CC_TYPE_PROFILE_COMBO_BOX);
+ g_type_ensure (CC_TYPE_STREAM_LIST_BOX);
+ g_type_ensure (CC_TYPE_SUBWOOFER_SLIDER);
+ g_type_ensure (CC_TYPE_VOLUME_SLIDER);
+}
+
+static void
+cc_sound_panel_init (CcSoundPanel *self)
+{
+ g_resources_register (cc_sound_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->sound_settings = g_settings_new (KEY_SOUNDS_SCHEMA);
+ g_signal_connect_object (self->sound_settings,
+ "changed::allow-volume-above-100-percent",
+ G_CALLBACK (allow_amplified_changed_cb),
+ self,
+ G_CONNECT_SWAPPED);
+ allow_amplified_changed_cb (self);
+
+ self->mixer_control = gvc_mixer_control_new ("GNOME Settings");
+ gvc_mixer_control_open (self->mixer_control);
+
+ cc_stream_list_box_set_mixer_control (self->stream_list_box, self->mixer_control);
+ cc_volume_slider_set_mixer_control (self->input_volume_slider, self->mixer_control);
+ cc_volume_slider_set_mixer_control (self->output_volume_slider, self->mixer_control);
+ cc_subwoofer_slider_set_mixer_control (self->subwoofer_slider, self->mixer_control);
+ cc_device_combo_box_set_mixer_control (self->input_device_combo_box, self->mixer_control, FALSE);
+ cc_device_combo_box_set_mixer_control (self->output_device_combo_box, self->mixer_control, TRUE);
+ g_signal_connect_object (self->mixer_control,
+ "active-output-update",
+ G_CALLBACK (output_device_update_cb),
+ self,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->mixer_control,
+ "active-input-update",
+ G_CALLBACK (input_device_update_cb),
+ self,
+ G_CONNECT_SWAPPED);
+}
diff --git a/panels/sound/cc-sound-panel.h b/panels/sound/cc-sound-panel.h
new file mode 100644
index 0000000..468f2c4
--- /dev/null
+++ b/panels/sound/cc-sound-panel.h
@@ -0,0 +1,28 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_SOUND_PANEL (cc_sound_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcSoundPanel, cc_sound_panel, CC, SOUND_PANEL, CcPanel)
+
+G_END_DECLS
diff --git a/panels/sound/cc-sound-panel.ui b/panels/sound/cc-sound-panel.ui
new file mode 100644
index 0000000..33b6dbb
--- /dev/null
+++ b/panels/sound/cc-sound-panel.ui
@@ -0,0 +1,351 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcSoundPanel" parent="CcPanel">
+ <child type="content">
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">System Volume</property>
+ <child>
+ <object class="AdwPreferencesRow">
+ <accessibility>
+ <property name="label" translatable="yes">Master volume</property>
+ </accessibility>
+ <child>
+ <object class="CcVolumeSlider" id="output_volume_slider">
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Volume Levels</property>
+ <child>
+ <object class="CcStreamListBox" id="stream_list_box">
+ <property name="label-size-group">label_size_group</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Output</property>
+ <child>
+ <object class="GtkListBox" id="output_list_box">
+ <property name="selection_mode">none</property>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ <child>
+ <object class="GtkListBoxRow">
+ <property name="activatable">False</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="output_device_label">
+ <property name="ellipsize">end</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Output Device</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">9</property>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <child>
+ <object class="CcDeviceComboBox" id="output_device_combo_box">
+ <property name="hexpand">True</property>
+ <accessibility>
+ <relation name="labelled-by">output_device_label</relation>
+ </accessibility>
+ <signal name="changed" handler="output_device_changed_cb" object="CcSoundPanel" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="label" translatable="yes">Test</property>
+ <signal name="clicked" handler="test_output_configuration_button_clicked_cb" object="CcSoundPanel" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="CcLevelBar" id="output_level_bar" />
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkListBoxRow" id="output_profile_row">
+ <property name="activatable">False</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="output_configuration_label">
+ <property name="ellipsize">end</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Configuration</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <child>
+ <object class="CcProfileComboBox" id="output_profile_combo_box">
+ <property name="hexpand">True</property>
+ <accessibility>
+ <relation name="labelled-by">output_configuration_label</relation>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkListBoxRow">
+ <property name="activatable">False</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="output_balance_label">
+ <property name="ellipsize">end</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Balance</property>
+ </object>
+ </child>
+ <child>
+ <object class="CcBalanceSlider" id="balance_slider">
+ <property name="hexpand">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkListBoxRow" id="fade_row">
+ <property name="activatable">False</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="output_fade_label">
+ <property name="ellipsize">end</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Fade</property>
+ </object>
+ </child>
+ <child>
+ <object class="CcFadeSlider" id="fade_slider">
+ <property name="hexpand">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkListBoxRow" id="subwoofer_row">
+ <property name="activatable">False</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="output_subwoofer_label">
+ <property name="ellipsize">end</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Subwoofer</property>
+ </object>
+ </child>
+ <child>
+ <object class="CcSubwooferSlider" id="subwoofer_slider">
+ <property name="hexpand">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Input</property>
+ <child>
+ <object class="GtkListBox" id="input_list_box">
+ <property name="selection_mode">none</property>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ <child>
+ <object class="GtkListBoxRow">
+ <property name="activatable">False</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="input_device_label">
+ <property name="ellipsize">end</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Input Device</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">9</property>
+ <child>
+ <object class="CcDeviceComboBox" id="input_device_combo_box">
+ <property name="hexpand">True</property>
+ <accessibility>
+ <relation name="labelled-by">input_device_label</relation>
+ </accessibility>
+ <signal name="changed" handler="input_device_changed_cb" object="CcSoundPanel" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="CcLevelBar" id="input_level_bar" />
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkListBoxRow" id="input_profile_row">
+ <property name="activatable">False</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="input_configuration_label">
+ <property name="ellipsize">end</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Configuration</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <child>
+ <object class="CcProfileComboBox" id="input_profile_combo_box">
+ <property name="hexpand">True</property>
+ <accessibility>
+ <relation name="labelled-by">input_configuration_label</relation>"
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkListBoxRow">
+ <property name="activatable">False</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="input_volume_label">
+ <property name="ellipsize">end</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Volume</property>
+ </object>
+ </child>
+ <child>
+ <object class="CcVolumeSlider" id="input_volume_slider">
+ <property name="hexpand">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Alert Sound</property>
+ <child>
+ <object class="CcAlertChooser">
+ <property name="hexpand">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GtkSizeGroup" id="label_size_group">
+ <property name="mode">horizontal</property>
+ <widgets>
+ <widget name="output_device_label"/>
+ <widget name="output_configuration_label"/>
+ <widget name="output_balance_label"/>
+ <widget name="output_fade_label"/>
+ <widget name="output_subwoofer_label"/>
+ <widget name="input_configuration_label"/>
+ <widget name="input_device_label"/>
+ <widget name="input_volume_label"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/panels/sound/cc-speaker-test-button.c b/panels/sound/cc-speaker-test-button.c
new file mode 100644
index 0000000..71824aa
--- /dev/null
+++ b/panels/sound/cc-speaker-test-button.c
@@ -0,0 +1,241 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <gsound.h>
+#include <pulse/pulseaudio.h>
+
+#include "cc-sound-resources.h"
+#include "cc-speaker-test-button.h"
+
+struct _CcSpeakerTestButton
+{
+ GtkDialog parent_instance;
+
+ GtkImage *image;
+ GtkLabel *label;
+
+ GCancellable *cancellable;
+ GSoundContext *context;
+ pa_channel_position_t position;
+ gboolean playing;
+ gint event_index;
+};
+
+G_DEFINE_TYPE (CcSpeakerTestButton, cc_speaker_test_button, GTK_TYPE_BUTTON)
+
+#define TEST_SOUND_ID 1
+
+static gboolean
+play_sound (CcSpeakerTestButton *self);
+
+static const gchar *
+get_icon_name (CcSpeakerTestButton *self)
+{
+ switch (self->position)
+ {
+ case PA_CHANNEL_POSITION_FRONT_LEFT:
+ return self->playing ? "audio-speaker-left-testing" : "audio-speaker-left";
+ case PA_CHANNEL_POSITION_FRONT_RIGHT:
+ return self->playing ? "audio-speaker-right-testing" : "audio-speaker-right";
+ case PA_CHANNEL_POSITION_FRONT_CENTER:
+ return self->playing ? "audio-speaker-center-testing" : "audio-speaker-center";
+ case PA_CHANNEL_POSITION_REAR_LEFT:
+ return self->playing ? "audio-speaker-left-back-testing" : "audio-speaker-left-back";
+ case PA_CHANNEL_POSITION_REAR_RIGHT:
+ return self->playing ? "audio-speaker-right-back-testing" : "audio-speaker-right-back";
+ case PA_CHANNEL_POSITION_REAR_CENTER:
+ return self->playing ? "audio-speaker-center-back-testing" : "audio-speaker-center-back";
+ case PA_CHANNEL_POSITION_LFE:
+ return self->playing ? "audio-subwoofer-testing" : "audio-subwoofer";
+ case PA_CHANNEL_POSITION_SIDE_LEFT:
+ return self->playing ? "audio-speaker-left-side-testing" : "audio-speaker-left-side";
+ case PA_CHANNEL_POSITION_SIDE_RIGHT:
+ return self->playing ? "audio-speaker-right-side-testing" : "audio-speaker-right-side";
+ case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER:
+ return self->playing ? "audio-speaker-front-left-of-center-testing" : "audio-speaker-front-left-of-center";
+ case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER:
+ return self->playing ? "audio-speaker-front-right-of-center-testing" : "audio-speaker-front-right-of-center";
+ case PA_CHANNEL_POSITION_MONO:
+ return self->playing ? "audio-speaker-mono-testing" : "audio-speaker-mono";
+ default:
+ return "audio-speakers";
+ }
+}
+
+static void
+update_icon (CcSpeakerTestButton *self)
+{
+ gtk_image_set_from_icon_name (self->image, get_icon_name (self));
+}
+
+static GStrv
+get_sound_events (CcSpeakerTestButton *self)
+{
+ switch (self->position)
+ {
+ case PA_CHANNEL_POSITION_FRONT_LEFT:
+ return g_strsplit ("audio-channel-front-left;audio-test-signal;bell", ";", -1);
+ case PA_CHANNEL_POSITION_FRONT_RIGHT:
+ return g_strsplit ("audio-channel-front-right;audio-test-signal;bell", ";", -1);
+ case PA_CHANNEL_POSITION_FRONT_CENTER:
+ return g_strsplit ("audio-channel-front-center;audio-test-signal;bell", ";", -1);
+ case PA_CHANNEL_POSITION_REAR_LEFT:
+ return g_strsplit ("audio-channel-rear-left;audio-test-signal;bell", ";", -1);
+ case PA_CHANNEL_POSITION_REAR_RIGHT:
+ return g_strsplit ("audio-channel-rear-right;audio-test-signal;bell", ";", -1);
+ case PA_CHANNEL_POSITION_REAR_CENTER:
+ return g_strsplit ("audio-channel-rear-center;audio-test-signal;bell", ";", -1);
+ case PA_CHANNEL_POSITION_LFE:
+ return g_strsplit ("audio-channel-lfe;audio-test-signal;bell", ";", -1);
+ case PA_CHANNEL_POSITION_SIDE_LEFT:
+ return g_strsplit ("audio-channel-side-left;audio-test-signal;bell", ";", -1);
+ case PA_CHANNEL_POSITION_SIDE_RIGHT:
+ return g_strsplit ("audio-channel-side-right;audio-test-signal;bell", ";", -1);
+ case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER:
+ return g_strsplit ("audio-channel-front-left-of-center;audio-test-signal;bell", ";", -1);
+ case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER:
+ return g_strsplit ("audio-channel-front-right-of-center;audio-test-signal;bell", ";", -1);
+ case PA_CHANNEL_POSITION_MONO:
+ return g_strsplit ("audio-channel-mono;audio-test-signal;bell", ";", -1);
+ default:
+ return g_strsplit ("audio-test-signal;bell", ";", -1);
+ }
+}
+
+static void
+finish_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer userdata)
+{
+ CcSpeakerTestButton *self = userdata;
+ g_autoptr(GError) error = NULL;
+
+ if (!gsound_context_play_full_finish (GSOUND_CONTEXT (object), result, &error))
+ {
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
+ if (play_sound (self))
+ return;
+
+ g_warning ("Failed to play sound: %s", error->message);
+ }
+
+ self->playing = FALSE;
+ update_icon (self);
+}
+
+static gboolean
+play_sound (CcSpeakerTestButton *self)
+{
+ g_auto(GStrv) events = NULL;
+
+ /* Stop existing sound */
+ g_cancellable_cancel (self->cancellable);
+ g_clear_object (&self->cancellable);
+ self->cancellable = g_cancellable_new ();
+
+ events = get_sound_events (self);
+ if (events[self->event_index] == NULL)
+ return FALSE;
+
+ gsound_context_play_full (self->context, self->cancellable, finish_cb, self,
+ GSOUND_ATTR_MEDIA_ROLE, "test",
+ GSOUND_ATTR_MEDIA_NAME, pa_channel_position_to_pretty_string (self->position),
+ GSOUND_ATTR_CANBERRA_FORCE_CHANNEL, pa_channel_position_to_string (self->position),
+ GSOUND_ATTR_CANBERRA_ENABLE, "1",
+ GSOUND_ATTR_EVENT_ID, events[self->event_index],
+ NULL);
+ self->event_index++;
+
+ return TRUE;
+}
+
+static void
+clicked_cb (CcSpeakerTestButton *self)
+{
+ if (self->context == NULL)
+ return;
+
+ self->playing = TRUE;
+ update_icon (self);
+
+ /* Play the per-channel sound name or a generic sound */
+ self->event_index = 0;
+ play_sound (self);
+}
+
+static void
+cc_speaker_test_button_dispose (GObject *object)
+{
+ CcSpeakerTestButton *self = CC_SPEAKER_TEST_BUTTON (object);
+
+ g_cancellable_cancel (self->cancellable);
+ g_clear_object (&self->cancellable);
+ g_clear_object (&self->context);
+
+ G_OBJECT_CLASS (cc_speaker_test_button_parent_class)->dispose (object);
+}
+
+void
+cc_speaker_test_button_class_init (CcSpeakerTestButtonClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_speaker_test_button_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/sound/cc-speaker-test-button.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcSpeakerTestButton, image);
+ gtk_widget_class_bind_template_child (widget_class, CcSpeakerTestButton, label);
+
+ gtk_widget_class_bind_template_callback (widget_class, clicked_cb);
+}
+
+void
+cc_speaker_test_button_init (CcSpeakerTestButton *self)
+{
+ g_resources_register (cc_sound_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->cancellable = g_cancellable_new ();
+
+ update_icon (self);
+}
+
+CcSpeakerTestButton *
+cc_speaker_test_button_new (void)
+{
+ return g_object_new (CC_TYPE_SPEAKER_TEST_BUTTON, NULL);
+}
+
+void
+cc_speaker_test_button_set_channel_position (CcSpeakerTestButton *self,
+ GSoundContext *context,
+ pa_channel_position_t position)
+{
+ g_return_if_fail (CC_IS_SPEAKER_TEST_BUTTON (self));
+
+ g_clear_object (&self->context);
+ self->context = g_object_ref (context);
+ self->position = position;
+ gtk_label_set_label (self->label, pa_channel_position_to_pretty_string (position));
+ update_icon (self);
+}
diff --git a/panels/sound/cc-speaker-test-button.h b/panels/sound/cc-speaker-test-button.h
new file mode 100644
index 0000000..32c4c31
--- /dev/null
+++ b/panels/sound/cc-speaker-test-button.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gsound.h>
+#include <gtk/gtk.h>
+#include <pulse/pulseaudio.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_SPEAKER_TEST_BUTTON (cc_speaker_test_button_get_type ())
+G_DECLARE_FINAL_TYPE (CcSpeakerTestButton, cc_speaker_test_button, CC, SPEAKER_TEST_BUTTON, GtkButton)
+
+CcSpeakerTestButton *cc_speaker_test_button_new (void);
+
+void cc_speaker_test_button_set_channel_position (CcSpeakerTestButton *button,
+ GSoundContext *context,
+ pa_channel_position_t position);
+
+G_END_DECLS
diff --git a/panels/sound/cc-speaker-test-button.ui b/panels/sound/cc-speaker-test-button.ui
new file mode 100644
index 0000000..2c8bdf8
--- /dev/null
+++ b/panels/sound/cc-speaker-test-button.ui
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcSpeakerTestButton" parent="GtkButton">
+ <signal name="clicked" handler="clicked_cb" object="CcSpeakerTestButton" swapped="yes"/>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <child>
+ <object class="GtkImage" id="image">
+ <property name="visible">True</property>
+ <property name="icon-size">large</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label">
+ <property name="visible">True</property>
+ <property name="wrap">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/sound/cc-stream-list-box.c b/panels/sound/cc-stream-list-box.c
new file mode 100644
index 0000000..d981976
--- /dev/null
+++ b/panels/sound/cc-stream-list-box.c
@@ -0,0 +1,248 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <pulse/pulseaudio.h>
+#include <gvc-mixer-sink.h>
+#include <gvc-mixer-source.h>
+
+#include "cc-stream-list-box.h"
+#include "cc-stream-row.h"
+#include "cc-sound-enums.h"
+#include "cc-sound-resources.h"
+
+struct _CcStreamListBox
+{
+ GtkBox parent_instance;
+
+ GtkListBox *listbox;
+ GtkSizeGroup *label_size_group;
+ GvcMixerControl *mixer_control;
+ CcStreamType stream_type;
+ guint stream_added_handler_id;
+ guint stream_removed_handler_id;
+};
+
+G_DEFINE_TYPE (CcStreamListBox, cc_stream_list_box, GTK_TYPE_BOX)
+
+enum
+{
+ PROP_0,
+ PROP_LABEL_SIZE_GROUP
+};
+
+static gint
+sort_cb (GtkListBoxRow *row1,
+ GtkListBoxRow *row2,
+ gpointer user_data)
+{
+ CcStreamListBox *self = user_data;
+ GvcMixerStream *stream1, *stream2, *event_sink;
+ g_autofree gchar *name1 = NULL;
+ g_autofree gchar *name2 = NULL;
+
+ stream1 = cc_stream_row_get_stream (CC_STREAM_ROW (row1));
+ stream2 = cc_stream_row_get_stream (CC_STREAM_ROW (row2));
+
+ /* Put the system sound events control at the top */
+ event_sink = gvc_mixer_control_get_event_sink_input (self->mixer_control);
+ if (stream1 == event_sink)
+ return -1;
+ else if (stream2 == event_sink)
+ return 1;
+
+ name1 = g_utf8_casefold (gvc_mixer_stream_get_name (stream1), -1);
+ name2 = g_utf8_casefold (gvc_mixer_stream_get_name (stream2), -1);
+
+ return g_strcmp0 (name1, name2);
+}
+
+static void
+stream_added_cb (CcStreamListBox *self,
+ guint id)
+{
+ GvcMixerStream *stream;
+ const gchar *app_id;
+ CcStreamRow *row;
+
+ stream = gvc_mixer_control_lookup_stream_id (self->mixer_control, id);
+ if (stream == NULL)
+ return;
+
+ app_id = gvc_mixer_stream_get_application_id (stream);
+
+ /* Skip master volume controls */
+ if (g_strcmp0 (app_id, "org.gnome.VolumeControl") == 0 ||
+ g_strcmp0 (app_id, "org.PulseAudio.pavucontrol") == 0)
+ {
+ return;
+ }
+
+ /* Skip streams that aren't volume controls */
+ if (GVC_IS_MIXER_SOURCE (stream) ||
+ GVC_IS_MIXER_SINK (stream) ||
+ gvc_mixer_stream_is_virtual (stream) ||
+ gvc_mixer_stream_is_event_stream (stream))
+ {
+ return;
+ }
+
+ row = cc_stream_row_new (self->label_size_group, stream, id, self->stream_type, self->mixer_control);
+ gtk_list_box_append (self->listbox, GTK_WIDGET (row));
+}
+
+static GtkWidget *
+find_row (CcStreamListBox *self,
+ guint id)
+{
+ GtkWidget *child;
+
+ for (child = gtk_widget_get_first_child (GTK_WIDGET (self->listbox));
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ {
+ if (!CC_IS_STREAM_ROW (child))
+ continue;
+
+ if (id == cc_stream_row_get_id (CC_STREAM_ROW (child)))
+ return child;
+ }
+
+ return NULL;
+}
+
+static void
+stream_removed_cb (CcStreamListBox *self,
+ guint id)
+{
+ GtkWidget *row;
+
+ row = find_row (self, id);
+ if (row != NULL)
+ gtk_list_box_remove (self->listbox, row);
+}
+
+static void
+cc_stream_list_box_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcStreamListBox *self = CC_STREAM_LIST_BOX (object);
+
+ switch (property_id) {
+ case PROP_LABEL_SIZE_GROUP:
+ self->label_size_group = g_value_dup_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+cc_stream_list_box_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcStreamListBox *self = CC_STREAM_LIST_BOX (object);
+
+ switch (property_id) {
+ case PROP_LABEL_SIZE_GROUP:
+ g_value_set_object (value, self->label_size_group);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+cc_stream_list_box_dispose (GObject *object)
+{
+ CcStreamListBox *self = CC_STREAM_LIST_BOX (object);
+
+ g_clear_object (&self->mixer_control);
+
+ G_OBJECT_CLASS (cc_stream_list_box_parent_class)->dispose (object);
+}
+
+void
+cc_stream_list_box_class_init (CcStreamListBoxClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->set_property = cc_stream_list_box_set_property;
+ object_class->get_property = cc_stream_list_box_get_property;
+ object_class->dispose = cc_stream_list_box_dispose;
+
+ g_object_class_install_property (object_class, PROP_LABEL_SIZE_GROUP,
+ g_param_spec_object ("label-size-group",
+ NULL,
+ NULL,
+ GTK_TYPE_SIZE_GROUP,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/sound/cc-stream-list-box.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcStreamListBox, listbox);
+}
+
+void
+cc_stream_list_box_init (CcStreamListBox *self)
+{
+ g_resources_register (cc_sound_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ gtk_list_box_set_sort_func (self->listbox, sort_cb, self, NULL);
+}
+
+void
+cc_stream_list_box_set_mixer_control (CcStreamListBox *self,
+ GvcMixerControl *mixer_control)
+{
+ g_return_if_fail (CC_IS_STREAM_LIST_BOX (self));
+
+ if (self->mixer_control != NULL)
+ {
+ g_signal_handler_disconnect (self->mixer_control, self->stream_added_handler_id);
+ self->stream_added_handler_id = 0;
+ g_signal_handler_disconnect (self->mixer_control, self->stream_removed_handler_id);
+ self->stream_removed_handler_id = 0;
+ }
+ g_clear_object (&self->mixer_control);
+
+ self->mixer_control = g_object_ref (mixer_control);
+
+ self->stream_added_handler_id = g_signal_connect_object (self->mixer_control,
+ "stream-added",
+ G_CALLBACK (stream_added_cb),
+ self, G_CONNECT_SWAPPED);
+ self->stream_removed_handler_id = g_signal_connect_object (self->mixer_control,
+ "stream-removed",
+ G_CALLBACK (stream_removed_cb),
+ self, G_CONNECT_SWAPPED);
+}
+
+void cc_stream_list_box_set_stream_type (CcStreamListBox *self,
+ CcStreamType stream_type)
+{
+ g_return_if_fail (CC_IS_STREAM_LIST_BOX (self));
+
+ self->stream_type = stream_type;
+}
diff --git a/panels/sound/cc-stream-list-box.h b/panels/sound/cc-stream-list-box.h
new file mode 100644
index 0000000..f2d3075
--- /dev/null
+++ b/panels/sound/cc-stream-list-box.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <pulse/pulseaudio.h>
+#include <gvc-mixer-control.h>
+
+#include "cc-sound-enums.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_STREAM_LIST_BOX (cc_stream_list_box_get_type ())
+G_DECLARE_FINAL_TYPE (CcStreamListBox, cc_stream_list_box, CC, STREAM_LIST_BOX, GtkBox)
+
+void cc_stream_list_box_set_mixer_control (CcStreamListBox *combo_box,
+ GvcMixerControl *mixer_control);
+
+void cc_stream_list_box_set_stream_type (CcStreamListBox *combo_box,
+ CcStreamType type);
+
+G_END_DECLS
diff --git a/panels/sound/cc-stream-list-box.ui b/panels/sound/cc-stream-list-box.ui
new file mode 100644
index 0000000..6050c2c
--- /dev/null
+++ b/panels/sound/cc-stream-list-box.ui
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcStreamListBox" parent="GtkBox">
+ <child>
+ <object class="GtkListBox" id="listbox">
+ <property name="hexpand">True</property>
+ <property name="selection-mode">none</property>
+ <style>
+ <class name="boxed-list" />
+ </style>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/sound/cc-stream-row.c b/panels/sound/cc-stream-row.c
new file mode 100644
index 0000000..8322df7
--- /dev/null
+++ b/panels/sound/cc-stream-row.c
@@ -0,0 +1,142 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cc-sound-resources.h"
+#include "cc-stream-row.h"
+#include "cc-volume-slider.h"
+#include "cc-sound-enums.h"
+
+#define SPEECH_DISPATCHER_PREFIX "speech-dispatcher-"
+
+struct _CcStreamRow
+{
+ GtkListBoxRow parent_instance;
+
+ GtkBox *label_box;
+ GtkLabel *name_label;
+ GtkImage *icon_image;
+ CcVolumeSlider *volume_slider;
+
+ GvcMixerStream *stream;
+ guint id;
+};
+
+G_DEFINE_TYPE (CcStreamRow, cc_stream_row, GTK_TYPE_LIST_BOX_ROW)
+
+static void
+cc_stream_row_dispose (GObject *object)
+{
+ CcStreamRow *self = CC_STREAM_ROW (object);
+
+ g_clear_object (&self->stream);
+
+ G_OBJECT_CLASS (cc_stream_row_parent_class)->dispose (object);
+}
+
+void
+cc_stream_row_class_init (CcStreamRowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_stream_row_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/sound/cc-stream-row.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcStreamRow, label_box);
+ gtk_widget_class_bind_template_child (widget_class, CcStreamRow, icon_image);
+ gtk_widget_class_bind_template_child (widget_class, CcStreamRow, name_label);
+ gtk_widget_class_bind_template_child (widget_class, CcStreamRow, volume_slider);
+}
+
+void
+cc_stream_row_init (CcStreamRow *self)
+{
+ g_resources_register (cc_sound_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+CcStreamRow *
+cc_stream_row_new (GtkSizeGroup *size_group,
+ GvcMixerStream *stream,
+ guint id,
+ CcStreamType stream_type,
+ GvcMixerControl *mixer_control)
+{
+ CcStreamRow *self;
+ g_autoptr(GtkIconPaintable) icon_paintable = NULL;
+ g_autoptr(GIcon) gicon = NULL;
+ const gchar *stream_name;
+ const gchar *icon_name;
+ g_autofree gchar *symbolic_icon_name = NULL;
+
+ self = g_object_new (CC_TYPE_STREAM_ROW, NULL);
+ self->stream = g_object_ref (stream);
+ self->id = id;
+
+ icon_name = gvc_mixer_stream_get_icon_name (stream);
+ stream_name = gvc_mixer_stream_get_name (stream);
+
+ if (g_str_has_suffix (icon_name, "-symbolic"))
+ symbolic_icon_name = strdup (icon_name);
+ else
+ symbolic_icon_name = g_strconcat (icon_name, "-symbolic", NULL);
+
+ /* Explicitly lookup for the icon, since some streams may give us an
+ * icon name (e.g. "audio") that doesn't really exist in the theme.
+ */
+ icon_paintable = gtk_icon_theme_lookup_icon (gtk_icon_theme_get_for_display (gdk_display_get_default ()),
+ icon_name,
+ NULL,
+ 24,
+ gtk_widget_get_scale_factor (GTK_WIDGET (self)),
+ GTK_TEXT_DIR_RTL,
+ 0);
+
+ if (icon_paintable)
+ gicon = g_themed_icon_new_with_default_fallbacks (symbolic_icon_name);
+ else if (g_str_has_prefix (stream_name, SPEECH_DISPATCHER_PREFIX))
+ gicon = g_themed_icon_new_with_default_fallbacks ("org.gnome.Settings-accessibility-symbolic");
+ else
+ gicon = g_themed_icon_new_with_default_fallbacks ("application-x-executable-symbolic");
+
+ gtk_image_set_from_gicon (self->icon_image, gicon);
+
+ gtk_label_set_label (self->name_label, gvc_mixer_stream_get_name (stream));
+ cc_volume_slider_set_stream (self->volume_slider, stream, stream_type);
+ cc_volume_slider_set_mixer_control (self->volume_slider, mixer_control);
+
+ gtk_size_group_add_widget (size_group, GTK_WIDGET (self->label_box));
+
+ return self;
+}
+
+GvcMixerStream *
+cc_stream_row_get_stream (CcStreamRow *self)
+{
+ g_return_val_if_fail (CC_IS_STREAM_ROW (self), NULL);
+ return self->stream;
+}
+
+guint
+cc_stream_row_get_id (CcStreamRow *self)
+{
+ g_return_val_if_fail (CC_IS_STREAM_ROW (self), 0);
+ return self->id;
+}
diff --git a/panels/sound/cc-stream-row.h b/panels/sound/cc-stream-row.h
new file mode 100644
index 0000000..9e4de9b
--- /dev/null
+++ b/panels/sound/cc-stream-row.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <pulse/pulseaudio.h>
+#include <gvc-mixer-control.h>
+#include <gvc-mixer-stream.h>
+
+#include "cc-sound-enums.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_STREAM_ROW (cc_stream_row_get_type ())
+G_DECLARE_FINAL_TYPE (CcStreamRow, cc_stream_row, CC, STREAM_ROW, GtkListBoxRow)
+
+CcStreamRow *cc_stream_row_new (GtkSizeGroup *size_group,
+ GvcMixerStream *stream,
+ guint id,
+ CcStreamType stream_type,
+ GvcMixerControl *mixer_control);
+
+GvcMixerStream *cc_stream_row_get_stream (CcStreamRow *row);
+
+guint cc_stream_row_get_id (CcStreamRow *row);
+
+G_END_DECLS
diff --git a/panels/sound/cc-stream-row.ui b/panels/sound/cc-stream-row.ui
new file mode 100644
index 0000000..756f6bb
--- /dev/null
+++ b/panels/sound/cc-stream-row.ui
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcStreamRow" parent="GtkListBoxRow">
+ <property name="activatable">False</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkBox" id="label_box">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkImage" id="icon_image">
+ <style>
+ <class name="lowres-icon"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="name_label">
+ <property name="ellipsize">end</property>
+ <property name="xalign">0</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="CcVolumeSlider" id="volume_slider">
+ <property name="hexpand">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/sound/cc-subwoofer-slider.c b/panels/sound/cc-subwoofer-slider.c
new file mode 100644
index 0000000..f209ec2
--- /dev/null
+++ b/panels/sound/cc-subwoofer-slider.c
@@ -0,0 +1,135 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <pulse/pulseaudio.h>
+#include <gvc-mixer-control.h>
+
+#include "cc-sound-resources.h"
+#include "cc-subwoofer-slider.h"
+#include "gvc-channel-map-private.h"
+
+struct _CcSubwooferSlider
+{
+ GtkBox parent_instance;
+
+ GtkAdjustment *adjustment;
+
+ GvcChannelMap *channel_map;
+ guint volume_changed_handler_id;
+};
+
+G_DEFINE_TYPE (CcSubwooferSlider, cc_subwoofer_slider, GTK_TYPE_BOX)
+
+static void
+changed_cb (CcSubwooferSlider *self)
+{
+ gdouble value;
+ const pa_channel_map *pa_map;
+ pa_cvolume pa_volume;
+
+ if (self->channel_map == NULL)
+ return;
+
+ value = gtk_adjustment_get_value (self->adjustment);
+ pa_map = gvc_channel_map_get_pa_channel_map (self->channel_map);
+ pa_volume = *gvc_channel_map_get_cvolume (self->channel_map);
+ pa_cvolume_set_position (&pa_volume, pa_map, PA_CHANNEL_POSITION_LFE, value);
+ gvc_channel_map_volume_changed (self->channel_map, &pa_volume, TRUE);
+}
+
+static void
+volume_changed_cb (CcSubwooferSlider *self)
+{
+ const gdouble *volumes;
+
+ volumes = gvc_channel_map_get_volume (self->channel_map);
+ g_signal_handlers_block_by_func (self->adjustment, volume_changed_cb, self);
+ gtk_adjustment_set_value (self->adjustment, volumes[LFE]);
+ g_signal_handlers_unblock_by_func (self->adjustment, volume_changed_cb, self);
+}
+
+static void
+cc_subwoofer_slider_dispose (GObject *object)
+{
+ CcSubwooferSlider *self = CC_SUBWOOFER_SLIDER (object);
+
+ g_clear_object (&self->channel_map);
+
+ G_OBJECT_CLASS (cc_subwoofer_slider_parent_class)->dispose (object);
+}
+
+void
+cc_subwoofer_slider_class_init (CcSubwooferSliderClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_subwoofer_slider_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/sound/cc-subwoofer-slider.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcSubwooferSlider, adjustment);
+
+ gtk_widget_class_bind_template_callback (widget_class, changed_cb);
+}
+
+void
+cc_subwoofer_slider_init (CcSubwooferSlider *self)
+{
+ g_resources_register (cc_sound_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+void
+cc_subwoofer_slider_set_mixer_control (CcSubwooferSlider *self,
+ GvcMixerControl *mixer_control)
+{
+ gdouble vol_max_norm;
+
+ g_return_if_fail (CC_IS_SUBWOOFER_SLIDER (self));
+
+ vol_max_norm = gvc_mixer_control_get_vol_max_norm (mixer_control);
+ gtk_adjustment_set_upper (self->adjustment, vol_max_norm);
+ gtk_adjustment_set_page_increment (self->adjustment, vol_max_norm / 100.0);
+}
+
+void
+cc_subwoofer_slider_set_channel_map (CcSubwooferSlider *self,
+ GvcChannelMap *channel_map)
+{
+ g_return_if_fail (CC_IS_SUBWOOFER_SLIDER (self));
+
+ if (self->channel_map != NULL)
+ {
+ g_signal_handler_disconnect (self->channel_map, self->volume_changed_handler_id);
+ self->volume_changed_handler_id = 0;
+ }
+ g_clear_object (&self->channel_map);
+
+ if (channel_map != NULL)
+ {
+ self->channel_map = g_object_ref (channel_map);
+
+ self->volume_changed_handler_id = g_signal_connect_object (channel_map,
+ "volume-changed",
+ G_CALLBACK (volume_changed_cb),
+ self, G_CONNECT_SWAPPED);
+ volume_changed_cb (self);
+ }
+}
diff --git a/panels/sound/cc-subwoofer-slider.h b/panels/sound/cc-subwoofer-slider.h
new file mode 100644
index 0000000..8b462dc
--- /dev/null
+++ b/panels/sound/cc-subwoofer-slider.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <pulse/pulseaudio.h>
+#include <gvc-channel-map.h>
+#include <gvc-mixer-control.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_SUBWOOFER_SLIDER (cc_subwoofer_slider_get_type ())
+G_DECLARE_FINAL_TYPE (CcSubwooferSlider, cc_subwoofer_slider, CC, SUBWOOFER_SLIDER, GtkBox)
+
+void cc_subwoofer_slider_set_mixer_control (CcSubwooferSlider *slider,
+ GvcMixerControl *mixer_control);
+
+void cc_subwoofer_slider_set_channel_map (CcSubwooferSlider *slider,
+ GvcChannelMap *channel_map);
+
+G_END_DECLS
diff --git a/panels/sound/cc-subwoofer-slider.ui b/panels/sound/cc-subwoofer-slider.ui
new file mode 100644
index 0000000..057da4b
--- /dev/null
+++ b/panels/sound/cc-subwoofer-slider.ui
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcSubwooferSlider" parent="GtkBox">
+ <child>
+ <object class="GtkScale">
+ <property name="visible">True</property>
+ <property name="hexpand">True</property>
+ <property name="draw_value">False</property>
+ <property name="has_origin">False</property>
+ <property name="adjustment">adjustment</property>
+ <accessibility>
+ <property name="label" translatable="yes">Subwoofer</property>
+ </accessibility>
+ </object>
+ </child>
+ </template>
+ <object class="GtkAdjustment" id="adjustment">
+ <signal name="value_changed" handler="changed_cb" object="CcSubwooferSlider" swapped="yes"/>
+ </object>
+</interface>
diff --git a/panels/sound/cc-volume-slider.c b/panels/sound/cc-volume-slider.c
new file mode 100644
index 0000000..5c37765
--- /dev/null
+++ b/panels/sound/cc-volume-slider.c
@@ -0,0 +1,263 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib/gi18n.h>
+#include <math.h>
+#include <pulse/pulseaudio.h>
+#include <gvc-mixer-control.h>
+
+#include "cc-sound-resources.h"
+#include "cc-volume-slider.h"
+
+struct _CcVolumeSlider
+{
+ GtkBox parent_instance;
+
+ GtkToggleButton *mute_button;
+ GtkAdjustment *volume_adjustment;
+ GtkScale *volume_scale;
+
+ gboolean is_amplified;
+ GvcMixerControl *mixer_control;
+ GvcMixerStream *stream;
+ guint notify_volume_handler_id;
+ guint notify_is_muted_handler_id;
+};
+
+G_DEFINE_TYPE (CcVolumeSlider, cc_volume_slider, GTK_TYPE_BOX)
+
+static void
+update_volume_icon (CcVolumeSlider *self)
+{
+ const gchar *icon_name = NULL;
+ gdouble volume, fraction;
+
+ volume = gtk_adjustment_get_value (self->volume_adjustment);
+ fraction = (100.0 * volume) / gtk_adjustment_get_upper (self->volume_adjustment);
+
+ if (gtk_toggle_button_get_active (self->mute_button))
+ icon_name = "audio-volume-muted-symbolic";
+ else if (fraction < 30.0)
+ icon_name = "audio-volume-low-symbolic";
+ else if (fraction > 30.0 && fraction < 70.0)
+ icon_name = "audio-volume-medium-symbolic";
+ else
+ icon_name = "audio-volume-high-symbolic";
+
+ gtk_button_set_icon_name (GTK_BUTTON (self->mute_button), icon_name);
+}
+
+static void
+volume_changed_cb (CcVolumeSlider *self)
+{
+ gdouble volume, rounded;
+
+ if (self->stream == NULL)
+ return;
+
+ volume = gtk_adjustment_get_value (self->volume_adjustment);
+ rounded = round (volume);
+
+ gtk_toggle_button_set_active (self->mute_button, volume == 0.0);
+
+ if (gvc_mixer_stream_set_volume (self->stream, (pa_volume_t) rounded))
+ gvc_mixer_stream_push_volume (self->stream);
+
+ update_volume_icon (self);
+}
+
+static void
+notify_volume_cb (CcVolumeSlider *self)
+{
+ g_signal_handlers_block_by_func (self->volume_adjustment, volume_changed_cb, self);
+
+ if (gtk_toggle_button_get_active (self->mute_button))
+ gtk_adjustment_set_value (self->volume_adjustment, 0.0);
+ else
+ gtk_adjustment_set_value (self->volume_adjustment, gvc_mixer_stream_get_volume (self->stream));
+
+ update_volume_icon (self);
+
+ g_signal_handlers_unblock_by_func (self->volume_adjustment, volume_changed_cb, self);
+}
+
+static void
+update_ranges (CcVolumeSlider *self)
+{
+ gdouble vol_max_norm;
+
+ if (self->mixer_control == NULL)
+ return;
+
+ vol_max_norm = gvc_mixer_control_get_vol_max_norm (self->mixer_control);
+
+ gtk_scale_clear_marks (self->volume_scale);
+ if (self->is_amplified)
+ {
+ gtk_adjustment_set_upper (self->volume_adjustment, gvc_mixer_control_get_vol_max_amplified (self->mixer_control));
+ gtk_scale_add_mark (self->volume_scale,
+ vol_max_norm,
+ GTK_POS_BOTTOM,
+ C_("volume", "100%"));
+ }
+ else
+ {
+ gtk_adjustment_set_upper (self->volume_adjustment, vol_max_norm);
+ }
+ gtk_adjustment_set_page_increment (self->volume_adjustment, vol_max_norm / 100.0);
+
+ if (self->stream)
+ notify_volume_cb (self);
+}
+
+static void
+mute_button_toggled_cb (CcVolumeSlider *self)
+{
+ if (self->stream == NULL)
+ return;
+
+ gvc_mixer_stream_change_is_muted (self->stream, gtk_toggle_button_get_active (self->mute_button));
+
+ update_volume_icon (self);
+}
+
+static void
+notify_is_muted_cb (CcVolumeSlider *self)
+{
+ g_signal_handlers_block_by_func (self->mute_button, mute_button_toggled_cb, self);
+ gtk_toggle_button_set_active (self->mute_button, gvc_mixer_stream_get_is_muted (self->stream));
+ g_signal_handlers_unblock_by_func (self->mute_button, mute_button_toggled_cb, self);
+ notify_volume_cb (self);
+}
+
+static void
+cc_volume_slider_dispose (GObject *object)
+{
+ CcVolumeSlider *self = CC_VOLUME_SLIDER (object);
+
+ g_clear_object (&self->mixer_control);
+ g_clear_object (&self->stream);
+
+ G_OBJECT_CLASS (cc_volume_slider_parent_class)->dispose (object);
+}
+
+void
+cc_volume_slider_class_init (CcVolumeSliderClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_volume_slider_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/sound/cc-volume-slider.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcVolumeSlider, mute_button);
+ gtk_widget_class_bind_template_child (widget_class, CcVolumeSlider, volume_adjustment);
+ gtk_widget_class_bind_template_child (widget_class, CcVolumeSlider, volume_scale);
+
+ gtk_widget_class_bind_template_callback (widget_class, mute_button_toggled_cb);
+ gtk_widget_class_bind_template_callback (widget_class, volume_changed_cb);
+}
+
+void
+cc_volume_slider_init (CcVolumeSlider *self)
+{
+ g_resources_register (cc_sound_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+void
+cc_volume_slider_set_mixer_control (CcVolumeSlider *self,
+ GvcMixerControl *mixer_control)
+{
+ g_return_if_fail (CC_IS_VOLUME_SLIDER (self));
+
+ g_set_object (&self->mixer_control, mixer_control);
+
+ update_ranges (self);
+}
+
+void
+cc_volume_slider_set_stream (CcVolumeSlider *self,
+ GvcMixerStream *stream,
+ CcStreamType type)
+{
+ g_return_if_fail (CC_IS_VOLUME_SLIDER (self));
+
+ if (self->stream != NULL)
+ {
+ g_signal_handler_disconnect (self->stream, self->notify_volume_handler_id);
+ self->notify_volume_handler_id = 0;
+ g_signal_handler_disconnect (self->stream, self->notify_is_muted_handler_id);
+ self->notify_is_muted_handler_id = 0;
+ }
+ g_clear_object (&self->stream);
+
+ switch (type)
+ {
+ case CC_STREAM_TYPE_INPUT:
+ gtk_button_set_icon_name (GTK_BUTTON (self->mute_button),
+ "microphone-sensitivity-muted-symbolic");
+ break;
+
+ case CC_STREAM_TYPE_OUTPUT:
+ gtk_button_set_icon_name (GTK_BUTTON (self->mute_button),
+ "audio-volume-muted-symbolic");
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ if (stream != NULL)
+ {
+ self->stream = g_object_ref (stream);
+
+ self->notify_volume_handler_id = g_signal_connect_object (stream,
+ "notify::volume",
+ G_CALLBACK (notify_volume_cb),
+ self, G_CONNECT_SWAPPED);
+ self->notify_is_muted_handler_id = g_signal_connect_object (stream,
+ "notify::is-muted",
+ G_CALLBACK (notify_is_muted_cb),
+ self, G_CONNECT_SWAPPED);
+ notify_volume_cb (self);
+ notify_is_muted_cb (self);
+ }
+}
+
+GvcMixerStream *
+cc_volume_slider_get_stream (CcVolumeSlider *self)
+{
+ g_return_val_if_fail (CC_IS_VOLUME_SLIDER (self), NULL);
+
+ return self->stream;
+}
+
+void
+cc_volume_slider_set_is_amplified (CcVolumeSlider *self,
+ gboolean is_amplified)
+{
+ g_return_if_fail (CC_IS_VOLUME_SLIDER (self));
+
+ self->is_amplified = is_amplified;
+
+ update_ranges (self);
+}
diff --git a/panels/sound/cc-volume-slider.h b/panels/sound/cc-volume-slider.h
new file mode 100644
index 0000000..b038590
--- /dev/null
+++ b/panels/sound/cc-volume-slider.h
@@ -0,0 +1,45 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <pulse/pulseaudio.h>
+#include <gvc-mixer-control.h>
+#include <gvc-mixer-stream.h>
+
+#include "cc-sound-enums.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_VOLUME_SLIDER (cc_volume_slider_get_type ())
+G_DECLARE_FINAL_TYPE (CcVolumeSlider, cc_volume_slider, CC, VOLUME_SLIDER, GtkBox)
+
+void cc_volume_slider_set_mixer_control (CcVolumeSlider *slider,
+ GvcMixerControl *mixer_control);
+
+void cc_volume_slider_set_stream (CcVolumeSlider *slider,
+ GvcMixerStream *stream,
+ CcStreamType type);
+
+void cc_volume_slider_set_is_amplified (CcVolumeSlider *slider,
+ gboolean is_amplified);
+
+GvcMixerStream *cc_volume_slider_get_stream (CcVolumeSlider *slider);
+
+G_END_DECLS
diff --git a/panels/sound/cc-volume-slider.ui b/panels/sound/cc-volume-slider.ui
new file mode 100644
index 0000000..a3de463
--- /dev/null
+++ b/panels/sound/cc-volume-slider.ui
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcVolumeSlider" parent="GtkBox">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkScale" id="volume_scale">
+ <property name="visible">True</property>
+ <property name="adjustment">volume_adjustment</property>
+ <property name="draw_value">False</property>
+ <property name="hexpand">True</property>
+ <accessibility>
+ <property name="label" translatable="yes">Volume</property>
+ </accessibility>
+ </object>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="mute_button">
+ <property name="visible">True</property>
+ <property name="icon_name">audio-volume-muted-symbolic</property>
+ <accessibility>
+ <property name="label" translatable="yes">Mute</property>
+ </accessibility>
+ <signal name="toggled" handler="mute_button_toggled_cb" object="CcVolumeSlider" swapped="yes"/>
+ <style>
+ <class name="flat" />
+ </style>
+ </object>
+ </child>
+ </template>
+ <object class="GtkAdjustment" id="volume_adjustment">
+ <signal name="value_changed" handler="volume_changed_cb" object="CcVolumeSlider" swapped="yes"/>
+ </object>
+</interface>
diff --git a/panels/sound/gnome-sound-panel.desktop.in.in b/panels/sound/gnome-sound-panel.desktop.in.in
new file mode 100644
index 0000000..8b02861
--- /dev/null
+++ b/panels/sound/gnome-sound-panel.desktop.in.in
@@ -0,0 +1,19 @@
+[Desktop Entry]
+Name=Sound
+Comment=Change sound levels, inputs, outputs, and alert sounds
+Exec=gnome-control-center sound
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-sound-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;X-GNOME-Settings-Panel;X-GNOME-DevicesSettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=sound
+X-GNOME-Bugzilla-Version=@VERSION@
+X-GNOME-Settings-Panel=sound
+# Translators: Search terms to find the Sound panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=Card;Microphone;Volume;Fade;Balance;Bluetooth;Headset;Audio;Output;Input;
diff --git a/panels/sound/gvc-mixer-stream-private.h b/panels/sound/gvc-mixer-stream-private.h
new file mode 100644
index 0000000..e9b1552
--- /dev/null
+++ b/panels/sound/gvc-mixer-stream-private.h
@@ -0,0 +1,30 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <glib-object.h>
+
+#include "gvc-channel-map.h"
+
+G_BEGIN_DECLS
+
+pa_context * gvc_mixer_stream_get_pa_context (GvcMixerStream *stream);
+
+G_END_DECLS
diff --git a/panels/sound/icons/audio-speaker-center-back-testing.svg b/panels/sound/icons/audio-speaker-center-back-testing.svg
new file mode 100644
index 0000000..d704b47
--- /dev/null
+++ b/panels/sound/icons/audio-speaker-center-back-testing.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" version="1.0"><defs><linearGradient id="c"><stop style="stop-color:#555753;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient><linearGradient id="b"><stop offset="0" style="stop-color:#2e3436;stop-opacity:1"/><stop style="stop-color:#eeeeec;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="a"><stop style="stop-color:#babdb6;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient></defs><g style="display:inline;stroke-width:.5"><path d="M41 202h2.485l2.968-3 .547.016v12h-.475L43.485 208H41Z" style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:.50000005;marker:none;font-variant-east_asian:normal;opacity:1;vector-effect:none;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0" transform="matrix(0 -2 -2 0 434.063 122)"/><path style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:.1;fill:none;stroke:none;stroke-width:.5;marker:none" d="M41 197h16v16H41z" transform="matrix(0 -2 -2 0 434.063 122)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;fill-rule:nonzero;stroke:none;stroke-width:.50000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M56 205c0-2.814-1-5.172-2.585-7H52v1.48c1.265 1.52 2 3.22 2 5.52 0 2.3-.78 4-2 5.52V212h1.381c1.466-1.64 2.62-4.186 2.62-7z" transform="matrix(0 -2 -2 0 434.063 122)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;fill-rule:nonzero;stroke:none;stroke-width:.50000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M53 205c0-2.166-.739-4.02-2-5h-1v2c.607.789 1 1.76 1 3 0 1.241-.393 2.22-1 3v2h1c1.223-.995 2-2.873 2-5z" transform="matrix(0 -2 -2 0 434.063 122)"/><path style="color:#000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;stroke:none;stroke-width:.50000005;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0" d="M50 205c0-1.257-.311-2.216-1-3h-1v6h1c.672-.837 1-1.742 1-3z" transform="matrix(0 -2 -2 0 434.063 122)"/></g></svg> \ No newline at end of file
diff --git a/panels/sound/icons/audio-speaker-center-back.svg b/panels/sound/icons/audio-speaker-center-back.svg
new file mode 100644
index 0000000..a776f48
--- /dev/null
+++ b/panels/sound/icons/audio-speaker-center-back.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" version="1.0"><defs><linearGradient id="c"><stop style="stop-color:#555753;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient><linearGradient id="b"><stop offset="0" style="stop-color:#2e3436;stop-opacity:1"/><stop style="stop-color:#eeeeec;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="a"><stop style="stop-color:#babdb6;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient></defs><g style="display:inline;stroke-width:.5"><path d="M41 202h2.485l2.968-3 .547.016v12h-.475L43.485 208H41Z" style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:.5;marker:none" transform="matrix(0 -2 -2 0 434.063 122)"/><path style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:.1;fill:none;stroke:none;stroke-width:.5;marker:none" d="M41 197h16v16H41z" transform="matrix(0 -2 -2 0 434.063 122)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:.23529412;fill-rule:nonzero;stroke:none;stroke-width:1.16391027;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M56 205c0-2.814-1-5.172-2.585-7H52v1.48c1.265 1.52 2 3.22 2 5.52 0 2.3-.78 4-2 5.52V212h1.381c1.466-1.64 2.62-4.186 2.62-7z" transform="matrix(0 -2 -2 0 434.063 122)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:.23529412;fill-rule:nonzero;stroke:none;stroke-width:1.16391027;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M53 205c0-2.166-.739-4.02-2-5h-1v2c.607.789 1 1.76 1 3 0 1.241-.393 2.22-1 3v2h1c1.223-.995 2-2.873 2-5z" transform="matrix(0 -2 -2 0 434.063 122)"/><path style="color:#000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:.23529412;stroke:none;stroke-width:1.16391027;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" d="M50 205c0-1.257-.311-2.216-1-3h-1v6h1c.672-.837 1-1.742 1-3z" transform="matrix(0 -2 -2 0 434.063 122)"/></g></svg> \ No newline at end of file
diff --git a/panels/sound/icons/audio-speaker-center-testing.svg b/panels/sound/icons/audio-speaker-center-testing.svg
new file mode 100644
index 0000000..99b31a2
--- /dev/null
+++ b/panels/sound/icons/audio-speaker-center-testing.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" version="1.0"><defs><linearGradient id="c"><stop style="stop-color:#555753;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient><linearGradient id="b"><stop offset="0" style="stop-color:#2e3436;stop-opacity:1"/><stop style="stop-color:#eeeeec;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="a"><stop style="stop-color:#babdb6;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient></defs><g style="display:inline;stroke-width:.5"><path d="M41 202h2.485l2.968-3 .547.016v12h-.475L43.485 208H41Z" style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:.5;marker:none" transform="matrix(0 2 -2 0 434.063 -74)"/><path style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:.1;fill:none;stroke:none;stroke-width:.5;marker:none" d="M41 197h16v16H41z" transform="matrix(0 2 -2 0 434.063 -74)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;fill-rule:nonzero;stroke:none;stroke-width:.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M56 205c0-2.814-1-5.172-2.585-7H52v1.48c1.265 1.52 2 3.22 2 5.52 0 2.3-.78 4-2 5.52V212h1.381c1.466-1.64 2.62-4.186 2.62-7z" transform="matrix(0 2 -2 0 434.063 -74)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;fill-rule:nonzero;stroke:none;stroke-width:.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M53 205c0-2.166-.739-4.02-2-5h-1v2c.607.789 1 1.76 1 3 0 1.241-.393 2.22-1 3v2h1c1.223-.995 2-2.873 2-5z" transform="matrix(0 2 -2 0 434.063 -74)"/><path style="color:#000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;stroke:none;stroke-width:.5;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0" d="M50 205c0-1.257-.311-2.216-1-3h-1v6h1c.672-.837 1-1.742 1-3z" transform="matrix(0 2 -2 0 434.063 -74)"/></g></svg> \ No newline at end of file
diff --git a/panels/sound/icons/audio-speaker-center.svg b/panels/sound/icons/audio-speaker-center.svg
new file mode 100644
index 0000000..1c2f505
--- /dev/null
+++ b/panels/sound/icons/audio-speaker-center.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" version="1.0"><defs><linearGradient id="c"><stop style="stop-color:#555753;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient><linearGradient id="b"><stop offset="0" style="stop-color:#2e3436;stop-opacity:1"/><stop style="stop-color:#eeeeec;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="a"><stop style="stop-color:#babdb6;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient></defs><g style="display:inline;stroke-width:.5"><path d="M41 202h2.485l2.968-3 .547.016v12h-.475L43.485 208H41Z" style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:.5;marker:none" transform="matrix(0 2 -2 0 434.063 -74)"/><path style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:.1;fill:none;stroke:none;stroke-width:.5;marker:none" d="M41 197h16v16H41z" transform="matrix(0 2 -2 0 434.063 -74)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:.23529412;fill-rule:nonzero;stroke:none;stroke-width:1.16391015;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M56 205c0-2.814-1-5.172-2.585-7H52v1.48c1.265 1.52 2 3.22 2 5.52 0 2.3-.78 4-2 5.52V212h1.381c1.466-1.64 2.62-4.186 2.62-7z" transform="matrix(0 2 -2 0 434.063 -74)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:.23529412;fill-rule:nonzero;stroke:none;stroke-width:1.16391015;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M53 205c0-2.166-.739-4.02-2-5h-1v2c.607.789 1 1.76 1 3 0 1.241-.393 2.22-1 3v2h1c1.223-.995 2-2.873 2-5z" transform="matrix(0 2 -2 0 434.063 -74)"/><path style="color:#000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:.23529412;stroke:none;stroke-width:1.16391015;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" d="M50 205c0-1.257-.311-2.216-1-3h-1v6h1c.672-.837 1-1.742 1-3z" transform="matrix(0 2 -2 0 434.063 -74)"/></g></svg> \ No newline at end of file
diff --git a/panels/sound/icons/audio-speaker-left-back-testing.svg b/panels/sound/icons/audio-speaker-left-back-testing.svg
new file mode 100644
index 0000000..51a5d82
--- /dev/null
+++ b/panels/sound/icons/audio-speaker-left-back-testing.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" version="1.0"><defs><linearGradient id="c"><stop style="stop-color:#555753;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient><linearGradient id="b"><stop offset="0" style="stop-color:#2e3436;stop-opacity:1"/><stop style="stop-color:#eeeeec;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="a"><stop style="stop-color:#babdb6;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient></defs><g style="display:inline;stroke-width:.5"><path d="M41 202h2.485l2.968-3 .547.016v12h-.475L43.485 208H41Z" style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:.5;marker:none" transform="rotate(-45 -404.912 306.25) scale(2)"/><path style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:.1;fill:none;stroke:none;stroke-width:.5;marker:none" d="M41 197h16v16H41z" transform="rotate(-45 -404.912 306.25) scale(2)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;fill-rule:nonzero;stroke:none;stroke-width:.50000004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M56 205c0-2.814-1-5.172-2.585-7H52v1.48c1.265 1.52 2 3.22 2 5.52 0 2.3-.78 4-2 5.52V212h1.381c1.466-1.64 2.62-4.186 2.62-7z" transform="rotate(-45 -404.912 306.25) scale(2)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;fill-rule:nonzero;stroke:none;stroke-width:.50000004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M53 205c0-2.166-.739-4.02-2-5h-1v2c.607.789 1 1.76 1 3 0 1.241-.393 2.22-1 3v2h1c1.223-.995 2-2.873 2-5z" transform="rotate(-45 -404.912 306.25) scale(2)"/><path style="color:#000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;stroke:none;stroke-width:.50000004;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0" d="M50 205c0-1.257-.311-2.216-1-3h-1v6h1c.672-.837 1-1.742 1-3z" transform="rotate(-45 -404.912 306.25) scale(2)"/></g></svg> \ No newline at end of file
diff --git a/panels/sound/icons/audio-speaker-left-back.svg b/panels/sound/icons/audio-speaker-left-back.svg
new file mode 100644
index 0000000..6d06375
--- /dev/null
+++ b/panels/sound/icons/audio-speaker-left-back.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" version="1.0"><defs><linearGradient id="c"><stop style="stop-color:#555753;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient><linearGradient id="b"><stop offset="0" style="stop-color:#2e3436;stop-opacity:1"/><stop style="stop-color:#eeeeec;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="a"><stop style="stop-color:#babdb6;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient></defs><g style="display:inline;stroke-width:.5"><path d="M41 202h2.485l2.968-3 .547.016v12h-.475L43.485 208H41Z" style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:.5;marker:none" transform="rotate(-45 -404.912 306.25) scale(2)"/><path style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:.1;fill:none;stroke:none;stroke-width:.5;marker:none" d="M41 197h16v16H41z" transform="rotate(-45 -404.912 306.25) scale(2)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:.23529412;fill-rule:nonzero;stroke:none;stroke-width:1.16391024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M56 205c0-2.814-1-5.172-2.585-7H52v1.48c1.265 1.52 2 3.22 2 5.52 0 2.3-.78 4-2 5.52V212h1.381c1.466-1.64 2.62-4.186 2.62-7z" transform="rotate(-45 -404.912 306.25) scale(2)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:.23529412;fill-rule:nonzero;stroke:none;stroke-width:1.16391024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M53 205c0-2.166-.739-4.02-2-5h-1v2c.607.789 1 1.76 1 3 0 1.241-.393 2.22-1 3v2h1c1.223-.995 2-2.873 2-5z" transform="rotate(-45 -404.912 306.25) scale(2)"/><path style="color:#000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:.23529412;stroke:none;stroke-width:1.16391024;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" d="M50 205c0-1.257-.311-2.216-1-3h-1v6h1c.672-.837 1-1.742 1-3z" transform="rotate(-45 -404.912 306.25) scale(2)"/></g></svg> \ No newline at end of file
diff --git a/panels/sound/icons/audio-speaker-left-side-testing.svg b/panels/sound/icons/audio-speaker-left-side-testing.svg
new file mode 100644
index 0000000..316557e
--- /dev/null
+++ b/panels/sound/icons/audio-speaker-left-side-testing.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" version="1.0"><defs><linearGradient id="c"><stop style="stop-color:#555753;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient><linearGradient id="b"><stop offset="0" style="stop-color:#2e3436;stop-opacity:1"/><stop style="stop-color:#eeeeec;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="a"><stop style="stop-color:#babdb6;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient></defs><g style="display:inline;stroke-width:.5"><path d="M41 202h2.485l2.968-3 .547.016v12h-.475L43.485 208H41Z" style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:.5;marker:none" transform="matrix(2 0 0 2 -73.938 -386)"/><path style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:.1;fill:none;stroke:none;stroke-width:.5;marker:none" d="M41 197h16v16H41z" transform="matrix(2 0 0 2 -73.938 -386)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;fill-rule:nonzero;stroke:none;stroke-width:.50000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M56 205c0-2.814-1-5.172-2.585-7H52v1.48c1.265 1.52 2 3.22 2 5.52 0 2.3-.78 4-2 5.52V212h1.381c1.466-1.64 2.62-4.186 2.62-7z" transform="matrix(2 0 0 2 -73.938 -386)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;fill-rule:nonzero;stroke:none;stroke-width:.50000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M53 205c0-2.166-.739-4.02-2-5h-1v2c.607.789 1 1.76 1 3 0 1.241-.393 2.22-1 3v2h1c1.223-.995 2-2.873 2-5z" transform="matrix(2 0 0 2 -73.938 -386)"/><path style="color:#000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;stroke:none;stroke-width:.50000002;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0" d="M50 205c0-1.257-.311-2.216-1-3h-1v6h1c.672-.837 1-1.742 1-3z" transform="matrix(2 0 0 2 -73.938 -386)"/></g></svg> \ No newline at end of file
diff --git a/panels/sound/icons/audio-speaker-left-side.svg b/panels/sound/icons/audio-speaker-left-side.svg
new file mode 100644
index 0000000..091f3eb
--- /dev/null
+++ b/panels/sound/icons/audio-speaker-left-side.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" version="1.0"><defs><linearGradient id="c"><stop style="stop-color:#555753;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient><linearGradient id="b"><stop offset="0" style="stop-color:#2e3436;stop-opacity:1"/><stop style="stop-color:#eeeeec;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="a"><stop style="stop-color:#babdb6;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient></defs><g style="display:inline;stroke-width:.5"><path d="M41 202h2.485l2.968-3 .547.016v12h-.475L43.485 208H41Z" style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:.5;marker:none" transform="matrix(2 0 0 2 -73.938 -386)"/><path style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:.1;fill:none;stroke:none;stroke-width:.5;marker:none" d="M41 197h16v16H41z" transform="matrix(2 0 0 2 -73.938 -386)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:.23529412;fill-rule:nonzero;stroke:none;stroke-width:1.16391021;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M56 205c0-2.814-1-5.172-2.585-7H52v1.48c1.265 1.52 2 3.22 2 5.52 0 2.3-.78 4-2 5.52V212h1.381c1.466-1.64 2.62-4.186 2.62-7z" transform="matrix(2 0 0 2 -73.938 -386)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:.23529412;fill-rule:nonzero;stroke:none;stroke-width:1.16391021;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M53 205c0-2.166-.739-4.02-2-5h-1v2c.607.789 1 1.76 1 3 0 1.241-.393 2.22-1 3v2h1c1.223-.995 2-2.873 2-5z" transform="matrix(2 0 0 2 -73.938 -386)"/><path style="color:#000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:.23529412;stroke:none;stroke-width:1.16391021;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" d="M50 205c0-1.257-.311-2.216-1-3h-1v6h1c.672-.837 1-1.742 1-3z" transform="matrix(2 0 0 2 -73.938 -386)"/></g></svg> \ No newline at end of file
diff --git a/panels/sound/icons/audio-speaker-left-testing.svg b/panels/sound/icons/audio-speaker-left-testing.svg
new file mode 100644
index 0000000..a0cbd73
--- /dev/null
+++ b/panels/sound/icons/audio-speaker-left-testing.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" version="1.0"><defs><linearGradient id="c"><stop style="stop-color:#555753;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient><linearGradient id="b"><stop offset="0" style="stop-color:#2e3436;stop-opacity:1"/><stop style="stop-color:#eeeeec;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="a"><stop style="stop-color:#babdb6;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient></defs><g style="display:inline;stroke-width:.5"><path d="M41 202h2.485l2.968-3 .547.016v12h-.475L43.485 208H41Z" style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:.5;marker:none" transform="rotate(45 526.975 127.75) scale(2)"/><path style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:.1;fill:none;stroke:none;stroke-width:.5;marker:none" d="M41 197h16v16H41z" transform="rotate(45 526.975 127.75) scale(2)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;fill-rule:nonzero;stroke:none;stroke-width:.50000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M56 205c0-2.814-1-5.172-2.585-7H52v1.48c1.265 1.52 2 3.22 2 5.52 0 2.3-.78 4-2 5.52V212h1.381c1.466-1.64 2.62-4.186 2.62-7z" transform="rotate(45 526.975 127.75) scale(2)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;fill-rule:nonzero;stroke:none;stroke-width:.50000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M53 205c0-2.166-.739-4.02-2-5h-1v2c.607.789 1 1.76 1 3 0 1.241-.393 2.22-1 3v2h1c1.223-.995 2-2.873 2-5z" transform="rotate(45 526.975 127.75) scale(2)"/><path style="color:#000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;stroke:none;stroke-width:.50000002;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0" d="M50 205c0-1.257-.311-2.216-1-3h-1v6h1c.672-.837 1-1.742 1-3z" transform="rotate(45 526.975 127.75) scale(2)"/></g></svg> \ No newline at end of file
diff --git a/panels/sound/icons/audio-speaker-left.svg b/panels/sound/icons/audio-speaker-left.svg
new file mode 100644
index 0000000..4eef45c
--- /dev/null
+++ b/panels/sound/icons/audio-speaker-left.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" version="1.0"><defs><linearGradient id="c"><stop style="stop-color:#555753;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient><linearGradient id="b"><stop offset="0" style="stop-color:#2e3436;stop-opacity:1"/><stop style="stop-color:#eeeeec;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="a"><stop style="stop-color:#babdb6;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient></defs><g style="display:inline;stroke-width:.5"><path d="M41 202h2.485l2.968-3 .547.016v12h-.475L43.485 208H41Z" style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:.5;marker:none" transform="rotate(45 526.975 127.75) scale(2)"/><path style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:.1;fill:none;stroke:none;stroke-width:.5;marker:none" d="M41 197h16v16H41z" transform="rotate(45 526.975 127.75) scale(2)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:.23529412;fill-rule:nonzero;stroke:none;stroke-width:1.1639102;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M56 205c0-2.814-1-5.172-2.585-7H52v1.48c1.265 1.52 2 3.22 2 5.52 0 2.3-.78 4-2 5.52V212h1.381c1.466-1.64 2.62-4.186 2.62-7z" transform="rotate(45 526.975 127.75) scale(2)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:.23529412;fill-rule:nonzero;stroke:none;stroke-width:1.1639102;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M53 205c0-2.166-.739-4.02-2-5h-1v2c.607.789 1 1.76 1 3 0 1.241-.393 2.22-1 3v2h1c1.223-.995 2-2.873 2-5z" transform="rotate(45 526.975 127.75) scale(2)"/><path style="color:#000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:.23529412;stroke:none;stroke-width:1.1639102;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" d="M50 205c0-1.257-.311-2.216-1-3h-1v6h1c.672-.837 1-1.742 1-3z" transform="rotate(45 526.975 127.75) scale(2)"/></g></svg> \ No newline at end of file
diff --git a/panels/sound/icons/audio-speaker-mono-testing.svg b/panels/sound/icons/audio-speaker-mono-testing.svg
new file mode 100644
index 0000000..ccd86c6
--- /dev/null
+++ b/panels/sound/icons/audio-speaker-mono-testing.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" version="1.0"><defs><linearGradient id="c"><stop style="stop-color:#555753;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient><linearGradient id="b"><stop offset="0" style="stop-color:#2e3436;stop-opacity:1"/><stop style="stop-color:#eeeeec;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="a"><stop style="stop-color:#babdb6;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient></defs><path style="color:#000;display:inline;overflow:visible;visibility:visible;opacity:1;vector-effect:none;fill:#729fcf;fill-opacity:.52697096;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate" d="M48.003 24c0 5.628-2 10.343-5.171 14h-2.83v-2.961c2.53-3.039 4-6.44 4-11.039 0-4.6-1.558-8-4-11.039V10h2.763c2.932 3.28 5.238 8.372 5.238 14z"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;opacity:1;vector-effect:none;fill:#729fcf;fill-opacity:.52697096;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate" d="M42.003 24c0 4.333-1.478 8.04-4 10h-2v-4c1.213-1.578 2-3.518 2-6s-.787-4.439-2-6v-4h2c2.446 1.99 4 5.747 4 10z"/><path style="color:#000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;opacity:1;vector-effect:none;fill:#729fcf;fill-opacity:.52697096;stroke:none;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate" d="M36.003 24c0 2.515-.624 4.431-2 6h-2V18h2c1.344 1.674 2 3.485 2 6z"/><path d="M.065 24c0 5.628 2 10.343 5.171 14h2.83v-2.961c-2.53-3.039-4-6.44-4-11.039 0-4.6 1.558-8 4-11.039V10H5.302C2.37 13.28.065 18.372.065 24Z" style="color:#000;display:inline;overflow:visible;visibility:visible;opacity:1;vector-effect:none;fill:#729fcf;fill-opacity:.52697096;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate"/><path d="M6.065 24c0 4.333 1.478 8.04 4 10h2v-4c-1.213-1.578-2-3.518-2-6s.787-4.439 2-6v-4h-2c-2.446 1.99-4 5.747-4 10z" style="color:#000;display:inline;overflow:visible;visibility:visible;opacity:1;vector-effect:none;fill:#729fcf;fill-opacity:.52697096;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate"/><path d="M12.065 24c0 2.515.624 4.431 2 6h2V18h-2c-1.344 1.674-2 3.485-2 6z" style="color:#000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;opacity:1;vector-effect:none;fill:#729fcf;fill-opacity:.52697096;stroke:none;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate"/><circle style="opacity:1;vector-effect:none;fill:#729fcf;fill-opacity:1;stroke:none;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;paint-order:normal" cx="24.02" cy="24.076" r="6.022"/></svg> \ No newline at end of file
diff --git a/panels/sound/icons/audio-speaker-mono.svg b/panels/sound/icons/audio-speaker-mono.svg
new file mode 100644
index 0000000..1e36297
--- /dev/null
+++ b/panels/sound/icons/audio-speaker-mono.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" version="1.0"><defs><linearGradient id="c"><stop style="stop-color:#555753;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient><linearGradient id="b"><stop offset="0" style="stop-color:#2e3436;stop-opacity:1"/><stop style="stop-color:#eeeeec;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="a"><stop style="stop-color:#babdb6;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient></defs><path style="color:#000;display:inline;overflow:visible;visibility:visible;opacity:1;vector-effect:none;fill:#000;fill-opacity:.23529412;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate" d="M48.003 24c0 5.628-2 10.343-5.171 14h-2.83v-2.961c2.53-3.039 4-6.44 4-11.039 0-4.6-1.558-8-4-11.039V10h2.763c2.932 3.28 5.238 8.372 5.238 14z"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;opacity:1;vector-effect:none;fill:#000;fill-opacity:.23529412;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate" d="M42.003 24c0 4.333-1.478 8.04-4 10h-2v-4c1.213-1.578 2-3.518 2-6s-.787-4.439-2-6v-4h2c2.446 1.99 4 5.747 4 10z"/><path style="color:#000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;opacity:1;vector-effect:none;fill:#000;fill-opacity:.23529412;stroke:none;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate" d="M36.003 24c0 2.515-.624 4.431-2 6h-2V18h2c1.344 1.674 2 3.485 2 6z"/><path d="M.065 24c0 5.628 2 10.343 5.171 14h2.83v-2.961c-2.53-3.039-4-6.44-4-11.039 0-4.6 1.558-8 4-11.039V10H5.302C2.37 13.28.065 18.372.065 24Z" style="color:#000;display:inline;overflow:visible;visibility:visible;opacity:1;vector-effect:none;fill:#000;fill-opacity:.23529412;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate"/><path d="M6.065 24c0 4.333 1.478 8.04 4 10h2v-4c-1.213-1.578-2-3.518-2-6s.787-4.439 2-6v-4h-2c-2.446 1.99-4 5.747-4 10z" style="color:#000;display:inline;overflow:visible;visibility:visible;opacity:1;vector-effect:none;fill:#000;fill-opacity:.23529412;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate"/><path d="M12.065 24c0 2.515.624 4.431 2 6h2V18h-2c-1.344 1.674-2 3.485-2 6z" style="color:#000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;opacity:1;vector-effect:none;fill:#000;fill-opacity:.23529412;stroke:none;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate"/><circle style="opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:none;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;paint-order:normal" cx="24.02" cy="24.076" r="6.022"/></svg> \ No newline at end of file
diff --git a/panels/sound/icons/audio-speaker-right-back-testing.svg b/panels/sound/icons/audio-speaker-right-back-testing.svg
new file mode 100644
index 0000000..62b6056
--- /dev/null
+++ b/panels/sound/icons/audio-speaker-right-back-testing.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" version="1.0"><defs><linearGradient id="c"><stop style="stop-color:#555753;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient><linearGradient id="b"><stop offset="0" style="stop-color:#2e3436;stop-opacity:1"/><stop style="stop-color:#eeeeec;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="a"><stop style="stop-color:#babdb6;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient></defs><g style="display:inline;stroke-width:.5"><path d="M41 202h2.485l2.968-3 .547.016v12h-.475L43.485 208H41Z" style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:.5;marker:none" transform="scale(-2 2) rotate(-45 -214.487 182.171)"/><path style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:.1;fill:none;stroke:none;stroke-width:.5;marker:none" d="M41 197h16v16H41z" transform="scale(-2 2) rotate(-45 -214.487 182.171)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;fill-rule:nonzero;stroke:none;stroke-width:.50000004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M56 205c0-2.814-1-5.172-2.585-7H52v1.48c1.265 1.52 2 3.22 2 5.52 0 2.3-.78 4-2 5.52V212h1.381c1.466-1.64 2.62-4.186 2.62-7z" transform="scale(-2 2) rotate(-45 -214.487 182.171)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;fill-rule:nonzero;stroke:none;stroke-width:.50000004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M53 205c0-2.166-.739-4.02-2-5h-1v2c.607.789 1 1.76 1 3 0 1.241-.393 2.22-1 3v2h1c1.223-.995 2-2.873 2-5z" transform="scale(-2 2) rotate(-45 -214.487 182.171)"/><path style="color:#000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;stroke:none;stroke-width:.50000004;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0" d="M50 205c0-1.257-.311-2.216-1-3h-1v6h1c.672-.837 1-1.742 1-3z" transform="scale(-2 2) rotate(-45 -214.487 182.171)"/></g></svg> \ No newline at end of file
diff --git a/panels/sound/icons/audio-speaker-right-back.svg b/panels/sound/icons/audio-speaker-right-back.svg
new file mode 100644
index 0000000..91fbb27
--- /dev/null
+++ b/panels/sound/icons/audio-speaker-right-back.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" version="1.0"><defs><linearGradient id="c"><stop style="stop-color:#555753;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient><linearGradient id="b"><stop offset="0" style="stop-color:#2e3436;stop-opacity:1"/><stop style="stop-color:#eeeeec;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="a"><stop style="stop-color:#babdb6;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient></defs><g style="display:inline;stroke-width:.5"><path d="M41 202h2.485l2.968-3 .547.016v12h-.475L43.485 208H41Z" style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:.5;marker:none" transform="scale(-2 2) rotate(-45 -214.487 182.171)"/><path style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:.1;fill:none;stroke:none;stroke-width:.5;marker:none" d="M41 197h16v16H41z" transform="scale(-2 2) rotate(-45 -214.487 182.171)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:.23529412;fill-rule:nonzero;stroke:none;stroke-width:1.16391024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M56 205c0-2.814-1-5.172-2.585-7H52v1.48c1.265 1.52 2 3.22 2 5.52 0 2.3-.78 4-2 5.52V212h1.381c1.466-1.64 2.62-4.186 2.62-7z" transform="scale(-2 2) rotate(-45 -214.487 182.171)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:.23529412;fill-rule:nonzero;stroke:none;stroke-width:1.16391024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M53 205c0-2.166-.739-4.02-2-5h-1v2c.607.789 1 1.76 1 3 0 1.241-.393 2.22-1 3v2h1c1.223-.995 2-2.873 2-5z" transform="scale(-2 2) rotate(-45 -214.487 182.171)"/><path style="color:#000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:.23529412;stroke:none;stroke-width:1.16391024;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" d="M50 205c0-1.257-.311-2.216-1-3h-1v6h1c.672-.837 1-1.742 1-3z" transform="scale(-2 2) rotate(-45 -214.487 182.171)"/></g></svg> \ No newline at end of file
diff --git a/panels/sound/icons/audio-speaker-right-side-testing.svg b/panels/sound/icons/audio-speaker-right-side-testing.svg
new file mode 100644
index 0000000..ea28b66
--- /dev/null
+++ b/panels/sound/icons/audio-speaker-right-side-testing.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" version="1.0"><defs><linearGradient id="c"><stop style="stop-color:#555753;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient><linearGradient id="b"><stop offset="0" style="stop-color:#2e3436;stop-opacity:1"/><stop style="stop-color:#eeeeec;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="a"><stop style="stop-color:#babdb6;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient></defs><g style="display:inline;stroke-width:.5"><path d="M41 202h2.485l2.968-3 .547.016v12h-.475L43.485 208H41Z" style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:.5;marker:none" transform="matrix(-2 0 0 2 122.063 -386)"/><path style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:.1;fill:none;stroke:none;stroke-width:.5;marker:none" d="M41 197h16v16H41z" transform="matrix(-2 0 0 2 122.063 -386)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;fill-rule:nonzero;stroke:none;stroke-width:.50000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M56 205c0-2.814-1-5.172-2.585-7H52v1.48c1.265 1.52 2 3.22 2 5.52 0 2.3-.78 4-2 5.52V212h1.381c1.466-1.64 2.62-4.186 2.62-7z" transform="matrix(-2 0 0 2 122.063 -386)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;fill-rule:nonzero;stroke:none;stroke-width:.50000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M53 205c0-2.166-.739-4.02-2-5h-1v2c.607.789 1 1.76 1 3 0 1.241-.393 2.22-1 3v2h1c1.223-.995 2-2.873 2-5z" transform="matrix(-2 0 0 2 122.063 -386)"/><path style="color:#000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;stroke:none;stroke-width:.50000002;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0" d="M50 205c0-1.257-.311-2.216-1-3h-1v6h1c.672-.837 1-1.742 1-3z" transform="matrix(-2 0 0 2 122.063 -386)"/></g></svg> \ No newline at end of file
diff --git a/panels/sound/icons/audio-speaker-right-side.svg b/panels/sound/icons/audio-speaker-right-side.svg
new file mode 100644
index 0000000..295eead
--- /dev/null
+++ b/panels/sound/icons/audio-speaker-right-side.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" version="1.0"><defs><linearGradient id="c"><stop style="stop-color:#555753;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient><linearGradient id="b"><stop offset="0" style="stop-color:#2e3436;stop-opacity:1"/><stop style="stop-color:#eeeeec;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="a"><stop style="stop-color:#babdb6;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient></defs><g style="display:inline;stroke-width:.5"><path d="M41 202h2.485l2.968-3 .547.016v12h-.475L43.485 208H41Z" style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:.5;marker:none" transform="matrix(-2 0 0 2 122.063 -386)"/><path style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:.1;fill:none;stroke:none;stroke-width:.5;marker:none" d="M41 197h16v16H41z" transform="matrix(-2 0 0 2 122.063 -386)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:.23529412;fill-rule:nonzero;stroke:none;stroke-width:1.16391021;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M56 205c0-2.814-1-5.172-2.585-7H52v1.48c1.265 1.52 2 3.22 2 5.52 0 2.3-.78 4-2 5.52V212h1.381c1.466-1.64 2.62-4.186 2.62-7z" transform="matrix(-2 0 0 2 122.063 -386)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:.23529412;fill-rule:nonzero;stroke:none;stroke-width:1.16391021;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M53 205c0-2.166-.739-4.02-2-5h-1v2c.607.789 1 1.76 1 3 0 1.241-.393 2.22-1 3v2h1c1.223-.995 2-2.873 2-5z" transform="matrix(-2 0 0 2 122.063 -386)"/><path style="color:#000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:.23529412;stroke:none;stroke-width:1.16391021;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" d="M50 205c0-1.257-.311-2.216-1-3h-1v6h1c.672-.837 1-1.742 1-3z" transform="matrix(-2 0 0 2 122.063 -386)"/></g></svg> \ No newline at end of file
diff --git a/panels/sound/icons/audio-speaker-right-testing.svg b/panels/sound/icons/audio-speaker-right-testing.svg
new file mode 100644
index 0000000..6449f7b
--- /dev/null
+++ b/panels/sound/icons/audio-speaker-right-testing.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" version="1.0"><defs><linearGradient id="c"><stop style="stop-color:#555753;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient><linearGradient id="b"><stop offset="0" style="stop-color:#2e3436;stop-opacity:1"/><stop style="stop-color:#eeeeec;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="a"><stop style="stop-color:#babdb6;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient></defs><g style="display:inline;stroke-width:.5"><path d="M41 202h2.485l2.968-3 .547.016v12h-.475L43.485 208H41Z" style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:.5;marker:none" transform="scale(-2 2) rotate(45 251.456 34.829)"/><path style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:.1;fill:none;stroke:none;stroke-width:.5;marker:none" d="M41 197h16v16H41z" transform="scale(-2 2) rotate(45 251.456 34.829)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;fill-rule:nonzero;stroke:none;stroke-width:.50000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M56 205c0-2.814-1-5.172-2.585-7H52v1.48c1.265 1.52 2 3.22 2 5.52 0 2.3-.78 4-2 5.52V212h1.381c1.466-1.64 2.62-4.186 2.62-7z" transform="scale(-2 2) rotate(45 251.456 34.829)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;fill-rule:nonzero;stroke:none;stroke-width:.50000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M53 205c0-2.166-.739-4.02-2-5h-1v2c.607.789 1 1.76 1 3 0 1.241-.393 2.22-1 3v2h1c1.223-.995 2-2.873 2-5z" transform="scale(-2 2) rotate(45 251.456 34.829)"/><path style="color:#000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;stroke:none;stroke-width:.50000002;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0" d="M50 205c0-1.257-.311-2.216-1-3h-1v6h1c.672-.837 1-1.742 1-3z" transform="scale(-2 2) rotate(45 251.456 34.829)"/></g></svg> \ No newline at end of file
diff --git a/panels/sound/icons/audio-speaker-right.svg b/panels/sound/icons/audio-speaker-right.svg
new file mode 100644
index 0000000..ce49905
--- /dev/null
+++ b/panels/sound/icons/audio-speaker-right.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" version="1.0"><defs><linearGradient id="c"><stop style="stop-color:#555753;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient><linearGradient id="b"><stop offset="0" style="stop-color:#2e3436;stop-opacity:1"/><stop style="stop-color:#eeeeec;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="a"><stop style="stop-color:#babdb6;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient></defs><g style="display:inline;stroke-width:.5"><path d="M41 202h2.485l2.968-3 .547.016v12h-.475L43.485 208H41Z" style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:.5;marker:none" transform="scale(-2 2) rotate(45 251.456 34.829)"/><path style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:.1;fill:none;stroke:none;stroke-width:.5;marker:none" d="M41 197h16v16H41z" transform="scale(-2 2) rotate(45 251.456 34.829)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:.23529412;fill-rule:nonzero;stroke:none;stroke-width:1.1639102;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M56 205c0-2.814-1-5.172-2.585-7H52v1.48c1.265 1.52 2 3.22 2 5.52 0 2.3-.78 4-2 5.52V212h1.381c1.466-1.64 2.62-4.186 2.62-7z" transform="scale(-2 2) rotate(45 251.456 34.829)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:.23529412;fill-rule:nonzero;stroke:none;stroke-width:1.1639102;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M53 205c0-2.166-.739-4.02-2-5h-1v2c.607.789 1 1.76 1 3 0 1.241-.393 2.22-1 3v2h1c1.223-.995 2-2.873 2-5z" transform="scale(-2 2) rotate(45 251.456 34.829)"/><path style="color:#000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#000;fill-opacity:.23529412;stroke:none;stroke-width:1.1639102;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" d="M50 205c0-1.257-.311-2.216-1-3h-1v6h1c.672-.837 1-1.742 1-3z" transform="scale(-2 2) rotate(45 251.456 34.829)"/></g></svg> \ No newline at end of file
diff --git a/panels/sound/icons/audio-speaker-testing.svg b/panels/sound/icons/audio-speaker-testing.svg
new file mode 100644
index 0000000..6449f7b
--- /dev/null
+++ b/panels/sound/icons/audio-speaker-testing.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" version="1.0"><defs><linearGradient id="c"><stop style="stop-color:#555753;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient><linearGradient id="b"><stop offset="0" style="stop-color:#2e3436;stop-opacity:1"/><stop style="stop-color:#eeeeec;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="a"><stop style="stop-color:#babdb6;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient></defs><g style="display:inline;stroke-width:.5"><path d="M41 202h2.485l2.968-3 .547.016v12h-.475L43.485 208H41Z" style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:.5;marker:none" transform="scale(-2 2) rotate(45 251.456 34.829)"/><path style="color:#bebebe;display:inline;overflow:visible;visibility:visible;opacity:.1;fill:none;stroke:none;stroke-width:.5;marker:none" d="M41 197h16v16H41z" transform="scale(-2 2) rotate(45 251.456 34.829)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;fill-rule:nonzero;stroke:none;stroke-width:.50000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M56 205c0-2.814-1-5.172-2.585-7H52v1.48c1.265 1.52 2 3.22 2 5.52 0 2.3-.78 4-2 5.52V212h1.381c1.466-1.64 2.62-4.186 2.62-7z" transform="scale(-2 2) rotate(45 251.456 34.829)"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;fill-rule:nonzero;stroke:none;stroke-width:.50000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none" d="M53 205c0-2.166-.739-4.02-2-5h-1v2c.607.789 1 1.76 1 3 0 1.241-.393 2.22-1 3v2h1c1.223-.995 2-2.873 2-5z" transform="scale(-2 2) rotate(45 251.456 34.829)"/><path style="color:#000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:.52697096;stroke:none;stroke-width:.50000002;marker:none;enable-background:accumulate;font-variant-east_asian:normal;opacity:1;vector-effect:none;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0" d="M50 205c0-1.257-.311-2.216-1-3h-1v6h1c.672-.837 1-1.742 1-3z" transform="scale(-2 2) rotate(45 251.456 34.829)"/></g></svg> \ No newline at end of file
diff --git a/panels/sound/icons/audio-subwoofer-testing.svg b/panels/sound/icons/audio-subwoofer-testing.svg
new file mode 100644
index 0000000..a161b1e
--- /dev/null
+++ b/panels/sound/icons/audio-subwoofer-testing.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" version="1.0"><defs><linearGradient id="c"><stop style="stop-color:#555753;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient><linearGradient id="b"><stop offset="0" style="stop-color:#2e3436;stop-opacity:1"/><stop style="stop-color:#eeeeec;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="a"><stop style="stop-color:#babdb6;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient></defs><g style="display:inline;stroke-width:.50000006"><path style="fill:#729fcf;fill-opacity:1;stroke:none;stroke-width:.75" d="M9.996 12C8.89 12 8 13.046 8 14.313v15.124C8 30.704 8.832 32 9.938 32h2c0 1.266.948 2 2.054 2h1.992c1.106 0 1.954-.734 1.954-2h11.976c0 1.266.933 2 2.04 2h1.987c1.106 0 1.996-.734 1.996-2h2.004c1.106 0 1.996-1.296 1.996-2.563V14.313c0-1.266-.89-2.312-1.996-2.312Zm9.049 2a4.995 4.995 0 0 1 4.99 5c0 2.761-2.234 5-4.99 5a4.995 4.995 0 0 1-4.99-5c0-2.761 2.234-5 4.99-5zm11.97 1.969a3.016 3.016 0 1 1 0 6.031 3.016 3.016 0 0 1 0-6.031ZM19 16a3 3 0 1 0 0 6 3 3 0 0 0 0-6z" transform="translate(0 12)"/></g><path style="color:#000;display:inline;overflow:visible;visibility:visible;opacity:1;vector-effect:none;fill:#729fcf;fill-opacity:.52697096;fill-rule:nonzero;stroke:none;stroke-width:1.00000006;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate;font-variant-east_asian:normal" d="M25 5c5.628 0 10.343 2 14 5.171V13h-2.961C33 10.47 29.599 9 25 9c-4.6 0-8 1.56-11.039 4H11v-2.763C14.28 7.306 19.372 5 25 5Z"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;opacity:1;vector-effect:none;fill:#729fcf;fill-opacity:.52697096;fill-rule:nonzero;stroke:none;stroke-width:1.00000006;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate;font-variant-east_asian:normal" d="M25 11c4.333 0 8.04 1.478 10 4v2h-4c-1.578-1.213-3.518-2-6-2s-4.439.787-6 2h-4v-2c1.99-2.446 5.747-4 10-4Z"/><path style="color:#000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;opacity:1;vector-effect:none;fill:#729fcf;fill-opacity:.52697096;stroke:none;stroke-width:1.00000006;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;marker:none;enable-background:accumulate;font-variant-east_asian:normal" d="M25 17c2.515 0 4.431.623 6 2v2H19v-2c1.674-1.344 3.485-2 6-2z"/></svg> \ No newline at end of file
diff --git a/panels/sound/icons/audio-subwoofer.svg b/panels/sound/icons/audio-subwoofer.svg
new file mode 100644
index 0000000..8dd0457
--- /dev/null
+++ b/panels/sound/icons/audio-subwoofer.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" version="1.0"><defs><linearGradient id="c"><stop style="stop-color:#555753;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient><linearGradient id="b"><stop offset="0" style="stop-color:#2e3436;stop-opacity:1"/><stop style="stop-color:#eeeeec;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="a"><stop style="stop-color:#babdb6;stop-opacity:1" offset="0"/><stop offset="1" style="stop-color:#eeeeec;stop-opacity:1"/></linearGradient></defs><g style="display:inline;stroke-width:.50000006"><path style="fill:#000;fill-opacity:1;stroke:none;stroke-width:.75" d="M9.996 12C8.89 12 8 13.046 8 14.313v15.124C8 30.704 8.832 32 9.938 32h2c0 1.266.948 2 2.054 2h1.992c1.106 0 1.954-.734 1.954-2h11.976c0 1.266.933 2 2.04 2h1.987c1.106 0 1.996-.734 1.996-2h2.004c1.106 0 1.996-1.296 1.996-2.563V14.313c0-1.266-.89-2.312-1.996-2.312Zm9.049 2a4.995 4.995 0 0 1 4.99 5c0 2.761-2.234 5-4.99 5a4.995 4.995 0 0 1-4.99-5c0-2.761 2.234-5 4.99-5zm11.97 1.969a3.016 3.016 0 1 1 0 6.031 3.016 3.016 0 0 1 0-6.031ZM19 16a3 3 0 1 0 0 6 3 3 0 0 0 0-6z" transform="translate(0 12)"/></g><path style="color:#000;display:inline;overflow:visible;visibility:visible;opacity:1;vector-effect:none;fill:#000;fill-opacity:.23529412;fill-rule:nonzero;stroke:none;stroke-width:2.32782054;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" d="M25 5c5.628 0 10.343 2 14 5.171V13h-2.961C33 10.47 29.599 9 25 9c-4.6 0-8 1.56-11.039 4H11v-2.763C14.28 7.306 19.372 5 25 5Z"/><path style="color:#000;display:inline;overflow:visible;visibility:visible;opacity:1;vector-effect:none;fill:#000;fill-opacity:.23529412;fill-rule:nonzero;stroke:none;stroke-width:2.32782054;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" d="M25 11c4.333 0 8.04 1.478 10 4v2h-4c-1.578-1.213-3.518-2-6-2s-4.439.787-6 2h-4v-2c1.99-2.446 5.747-4 10-4Z"/><path style="color:#000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;opacity:1;vector-effect:none;fill:#000;fill-opacity:.23529412;stroke:none;stroke-width:2.32782054;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" d="M25 17c2.515 0 4.431.623 6 2v2H19v-2c1.674-1.344 3.485-2 6-2z"/></svg> \ No newline at end of file
diff --git a/panels/sound/icons/org.gnome.Settings-sound-symbolic.svg b/panels/sound/icons/org.gnome.Settings-sound-symbolic.svg
new file mode 100644
index 0000000..ddfa354
--- /dev/null
+++ b/panels/sound/icons/org.gnome.Settings-sound-symbolic.svg
@@ -0,0 +1 @@
+<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M12.04.004a.946.946 0 0 0-.727.281L8 3.578V5h1.39l3.305-3.3c.407-.403.36-1.04.032-1.391a1.026 1.026 0 0 0-.688-.305zM7 1.008a.989.989 0 0 0-.77.351L3 5H2C.906 5 0 5.844 0 7v2c0 1.09.91 2 2 2h1l3.23 3.64c.211.255.493.364.77.36zM8 7v2h6c.75 0 1-.5 1-1s-.25-1-1-1zm0 4v1.422l3.324 3.293c.403.41 1.063.347 1.414-.024a1.02 1.02 0 0 0-.031-1.39L9.391 11zm0 0" fill="#2e3436"/></svg> \ No newline at end of file
diff --git a/panels/sound/meson.build b/panels/sound/meson.build
new file mode 100644
index 0000000..458377d
--- /dev/null
+++ b/panels/sound/meson.build
@@ -0,0 +1,112 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+deps = common_deps + [
+ libgvc_dep,
+ libxml_dep,
+ m_dep,
+ pulse_dep,
+ pulse_mainloop_dep,
+ dependency('gsound'),
+]
+
+cflags += [
+ '-DSOUND_DATA_DIR="@0@"'.format(join_paths(control_center_datadir, 'sounds')),
+]
+
+sources = files(
+ 'cc-alert-chooser.c',
+ 'cc-balance-slider.c',
+ 'cc-device-combo-box.c',
+ 'cc-fade-slider.c',
+ 'cc-level-bar.c',
+ 'cc-output-test-dialog.c',
+ 'cc-profile-combo-box.c',
+ 'cc-sound-panel.c',
+ 'cc-speaker-test-button.c',
+ 'cc-stream-list-box.c',
+ 'cc-stream-row.c',
+ 'cc-subwoofer-slider.c',
+ 'cc-volume-slider.c',
+)
+
+resource_data = files(
+ 'icons/audio-speaker-center-back.svg',
+ 'icons/audio-speaker-center-back-testing.svg',
+ 'icons/audio-speaker-center.svg',
+ 'icons/audio-speaker-center-testing.svg',
+ 'icons/audio-speaker-left-back.svg',
+ 'icons/audio-speaker-left-back-testing.svg',
+ 'icons/audio-speaker-left-side.svg',
+ 'icons/audio-speaker-left-side-testing.svg',
+ 'icons/audio-speaker-left.svg',
+ 'icons/audio-speaker-left-testing.svg',
+ 'icons/audio-speaker-mono.svg',
+ 'icons/audio-speaker-mono-testing.svg',
+ 'icons/audio-speaker-right-back.svg',
+ 'icons/audio-speaker-right-back-testing.svg',
+ 'icons/audio-speaker-right-side.svg',
+ 'icons/audio-speaker-right-side-testing.svg',
+ 'icons/audio-speaker-right.svg',
+ 'icons/audio-speaker-right-testing.svg',
+ 'icons/audio-speaker-testing.svg',
+ 'cc-alert-chooser.ui',
+ 'cc-balance-slider.ui',
+ 'cc-device-combo-box.ui',
+ 'cc-fade-slider.ui',
+ 'cc-output-test-dialog.ui',
+ 'cc-profile-combo-box.ui',
+ 'cc-sound-panel.ui',
+ 'cc-speaker-test-button.ui',
+ 'cc-stream-row.ui',
+ 'cc-subwoofer-slider.ui',
+ 'cc-volume-slider.ui',
+)
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname.underscorify (),
+ dependencies: resource_data,
+ export: true
+)
+
+panels_libs += static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [top_inc, common_inc],
+ dependencies: deps,
+ c_args: cflags,
+)
+
+sound_data = files(
+ 'sounds/click.ogg',
+ 'sounds/hum.ogg',
+ 'sounds/string.ogg',
+ 'sounds/swing.ogg'
+)
+
+install_data(
+ sound_data,
+ install_dir: join_paths(control_center_datadir, 'sounds', 'gnome', 'default', 'alerts')
+)
+
+install_data(
+ 'icons/org.gnome.Settings-sound-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/sound/sound.gresource.xml b/panels/sound/sound.gresource.xml
new file mode 100644
index 0000000..cdac713
--- /dev/null
+++ b/panels/sound/sound.gresource.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/sound">
+ <file preprocess="xml-stripblanks">cc-alert-chooser.ui</file>
+ <file preprocess="xml-stripblanks">cc-balance-slider.ui</file>
+ <file preprocess="xml-stripblanks">cc-device-combo-box.ui</file>
+ <file preprocess="xml-stripblanks">cc-fade-slider.ui</file>
+ <file preprocess="xml-stripblanks">cc-output-test-dialog.ui</file>
+ <file preprocess="xml-stripblanks">cc-profile-combo-box.ui</file>
+ <file preprocess="xml-stripblanks">cc-sound-panel.ui</file>
+ <file preprocess="xml-stripblanks">cc-speaker-test-button.ui</file>
+ <file preprocess="xml-stripblanks">cc-stream-list-box.ui</file>
+ <file preprocess="xml-stripblanks">cc-stream-row.ui</file>
+ <file preprocess="xml-stripblanks">cc-subwoofer-slider.ui</file>
+ <file preprocess="xml-stripblanks">cc-volume-slider.ui</file>
+ </gresource>
+ <gresource prefix="/org/gnome/Settings/icons/scalable/devices">
+ <file alias="audio-speaker-center-back.svg">icons/audio-speaker-center-back.svg</file>
+ <file alias="audio-speaker-center-back-testing.svg">icons/audio-speaker-center-back-testing.svg</file>
+ <file alias="audio-speaker-center.svg">icons/audio-speaker-center.svg</file>
+ <file alias="audio-speaker-center-testing.svg">icons/audio-speaker-center-testing.svg</file>
+ <file alias="audio-speaker-left-back.svg">icons/audio-speaker-left-back.svg</file>
+ <file alias="audio-speaker-left-back-testing.svg">icons/audio-speaker-left-back-testing.svg</file>
+ <file alias="audio-speaker-left-side.svg">icons/audio-speaker-left-side.svg</file>
+ <file alias="audio-speaker-left-side-testing.svg">icons/audio-speaker-left-side-testing.svg</file>
+ <file alias="audio-speaker-left.svg">icons/audio-speaker-left.svg</file>
+ <file alias="audio-speaker-left-testing.svg">icons/audio-speaker-left-testing.svg</file>
+ <file alias="audio-speaker-mono.svg">icons/audio-speaker-mono.svg</file>
+ <file alias="audio-speaker-mono-testing.svg">icons/audio-speaker-mono-testing.svg</file>
+ <file alias="audio-speaker-right-back.svg">icons/audio-speaker-right-back.svg</file>
+ <file alias="audio-speaker-right-back-testing.svg">icons/audio-speaker-right-back-testing.svg</file>
+ <file alias="audio-speaker-right-side.svg">icons/audio-speaker-right-side.svg</file>
+ <file alias="audio-speaker-right-side-testing.svg">icons/audio-speaker-right-side-testing.svg</file>
+ <file alias="audio-speaker-right.svg">icons/audio-speaker-right.svg</file>
+ <file alias="audio-speaker-right-testing.svg">icons/audio-speaker-right-testing.svg</file>
+ <file alias="audio-speaker-testing.svg">icons/audio-speaker-testing.svg</file>
+ <file alias="audio-subwoofer.svg">icons/audio-subwoofer.svg</file>
+ <file alias="audio-subwoofer-testing.svg">icons/audio-subwoofer-testing.svg</file>
+ </gresource>
+</gresources>
diff --git a/panels/sound/sounds/click.ogg b/panels/sound/sounds/click.ogg
new file mode 100644
index 0000000..10f4a49
--- /dev/null
+++ b/panels/sound/sounds/click.ogg
Binary files differ
diff --git a/panels/sound/sounds/hum.ogg b/panels/sound/sounds/hum.ogg
new file mode 100644
index 0000000..09a1a7b
--- /dev/null
+++ b/panels/sound/sounds/hum.ogg
Binary files differ
diff --git a/panels/sound/sounds/string.ogg b/panels/sound/sounds/string.ogg
new file mode 100644
index 0000000..7b03130
--- /dev/null
+++ b/panels/sound/sounds/string.ogg
Binary files differ
diff --git a/panels/sound/sounds/swing.ogg b/panels/sound/sounds/swing.ogg
new file mode 100644
index 0000000..4798e61
--- /dev/null
+++ b/panels/sound/sounds/swing.ogg
Binary files differ
diff --git a/panels/thunderbolt/bolt-client.c b/panels/thunderbolt/bolt-client.c
new file mode 100644
index 0000000..1612b65
--- /dev/null
+++ b/panels/thunderbolt/bolt-client.c
@@ -0,0 +1,1054 @@
+/*
+ * Copyright © 2017 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Christian J. Kellner <christian@kellner.me>
+ */
+
+#include "bolt-client.h"
+
+#include "bolt-device.h"
+#include "bolt-error.h"
+#include "bolt-names.h"
+
+#include <gio/gio.h>
+
+static void handle_dbus_device_added (GObject *self,
+ GDBusProxy *bus_proxy,
+ GVariant *params);
+static void handle_dbus_device_removed (GObject *self,
+ GDBusProxy *bus_proxy,
+ GVariant *params);
+
+struct _BoltClient
+{
+ BoltProxy parent;
+};
+
+enum {
+ PROP_0,
+
+ /* D-Bus Props */
+ PROP_VERSION,
+ PROP_PROBING,
+ PROP_SECURITY,
+ PROP_AUTHMODE,
+
+ PROP_LAST
+};
+
+static GParamSpec *props[PROP_LAST] = {NULL, };
+
+enum {
+ SIGNAL_DEVICE_ADDED,
+ SIGNAL_DEVICE_REMOVED,
+ SIGNAL_LAST
+};
+
+static guint signals[SIGNAL_LAST] = {0};
+
+
+G_DEFINE_TYPE (BoltClient,
+ bolt_client,
+ BOLT_TYPE_PROXY);
+
+
+static void
+bolt_client_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ if (bolt_proxy_get_dbus_property (object, pspec, value))
+ return;
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+}
+
+static const BoltProxySignal *
+bolt_client_get_dbus_signals (guint *n)
+{
+ static BoltProxySignal dbus_signals[] = {
+ {"DeviceAdded", handle_dbus_device_added},
+ {"DeviceRemoved", handle_dbus_device_removed},
+ };
+
+ *n = G_N_ELEMENTS (dbus_signals);
+
+ return dbus_signals;
+}
+
+
+static void
+bolt_client_class_init (BoltClientClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ BoltProxyClass *proxy_class = BOLT_PROXY_CLASS (klass);
+
+ gobject_class->get_property = bolt_client_get_property;
+
+ proxy_class->get_dbus_signals = bolt_client_get_dbus_signals;
+
+ props[PROP_VERSION]
+ = g_param_spec_uint ("version",
+ "Version", NULL,
+ 0, G_MAXUINT, 0,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME);
+
+ props[PROP_PROBING]
+ = g_param_spec_boolean ("probing",
+ "Probing", NULL,
+ FALSE,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME);
+
+ props[PROP_SECURITY]
+ = g_param_spec_enum ("security-level",
+ "SecurityLevel", NULL,
+ BOLT_TYPE_SECURITY,
+ BOLT_SECURITY_UNKNOWN,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME);
+
+ props[PROP_AUTHMODE] =
+ g_param_spec_flags ("auth-mode", "AuthMode", NULL,
+ BOLT_TYPE_AUTH_MODE,
+ BOLT_AUTH_ENABLED,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (gobject_class,
+ PROP_LAST,
+ props);
+
+ /* signals */
+ signals[SIGNAL_DEVICE_ADDED] =
+ g_signal_new ("device-added",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE,
+ 1, G_TYPE_STRING);
+
+ signals[SIGNAL_DEVICE_REMOVED] =
+ g_signal_new ("device-removed",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE,
+ 1, G_TYPE_STRING);
+}
+
+
+static void
+bolt_client_init (BoltClient *cli)
+{
+}
+
+/* dbus signals */
+
+static void
+handle_dbus_device_added (GObject *self, GDBusProxy *bus_proxy, GVariant *params)
+{
+ BoltClient *cli = BOLT_CLIENT (self);
+ const char *opath = NULL;
+
+ g_variant_get_child (params, 0, "&o", &opath);
+ g_signal_emit (cli, signals[SIGNAL_DEVICE_ADDED], 0, opath);
+}
+
+static void
+handle_dbus_device_removed (GObject *self, GDBusProxy *bus_proxy, GVariant *params)
+{
+ BoltClient *cli = BOLT_CLIENT (self);
+ const char *opath = NULL;
+
+ g_variant_get_child (params, 0, "&o", &opath);
+ g_signal_emit (cli, signals[SIGNAL_DEVICE_REMOVED], 0, opath);
+}
+
+/* public methods */
+
+BoltClient *
+bolt_client_new (GError **error)
+{
+ BoltClient *cli;
+ GDBusConnection *bus;
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
+ if (bus == NULL)
+ {
+ g_prefix_error (error, "Error connecting to D-Bus: ");
+ return FALSE;
+ }
+
+ cli = g_initable_new (BOLT_TYPE_CLIENT,
+ NULL, error,
+ "g-flags", G_DBUS_PROXY_FLAGS_NONE,
+ "g-connection", bus,
+ "g-name", BOLT_DBUS_NAME,
+ "g-object-path", BOLT_DBUS_PATH,
+ "g-interface-name", BOLT_DBUS_INTERFACE,
+ NULL);
+
+ g_object_unref (bus);
+
+ return cli;
+}
+
+static void
+got_the_client (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GError *error = NULL;
+ GTask *task = user_data;
+ GObject *obj;
+
+ obj = g_async_initable_new_finish (G_ASYNC_INITABLE (source), res, &error);
+
+ if (obj == NULL)
+ {
+ /* error ownership gets transferred to the task */
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ g_task_return_pointer (task, obj, g_object_unref);
+ g_object_unref (task);
+}
+
+static void
+got_the_bus (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GError *error = NULL;
+ GTask *task = user_data;
+ GCancellable *cancellable;
+ GDBusConnection *bus;
+
+ bus = g_bus_get_finish (res, &error);
+ if (bus == NULL)
+ {
+ g_prefix_error (&error, "could not connect to D-Bus: ");
+ /* error ownership gets transferred to the task */
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ cancellable = g_task_get_cancellable (task);
+ g_async_initable_new_async (BOLT_TYPE_CLIENT,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ got_the_client, task,
+ "g-flags", G_DBUS_PROXY_FLAGS_NONE,
+ "g-connection", bus,
+ "g-name", BOLT_DBUS_NAME,
+ "g-object-path", BOLT_DBUS_PATH,
+ "g-interface-name", BOLT_DBUS_INTERFACE,
+ NULL);
+ g_object_unref (bus);
+}
+
+void
+bolt_client_new_async (GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+
+ task = g_task_new (NULL, cancellable, callback, user_data);
+ g_bus_get (G_BUS_TYPE_SYSTEM, cancellable, got_the_bus, task);
+}
+
+BoltClient *
+bolt_client_new_finish (GAsyncResult *res,
+ GError **error)
+{
+ g_return_val_if_fail (G_IS_TASK (res), NULL);
+
+ return g_task_propagate_pointer (G_TASK (res), error);
+}
+
+GPtrArray *
+bolt_client_list_devices (BoltClient *client,
+ GCancellable *cancel,
+ GError **error)
+{
+ g_autoptr(GVariant) val = NULL;
+ g_autoptr(GPtrArray) devices = NULL;
+ g_autoptr(GVariantIter) iter = NULL;
+ GDBusConnection *bus = NULL;
+ const char *d;
+
+ g_return_val_if_fail (BOLT_IS_CLIENT (client), NULL);
+
+ val = g_dbus_proxy_call_sync (G_DBUS_PROXY (client),
+ "ListDevices",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancel,
+ error);
+ if (val == NULL)
+ return NULL;
+
+ bus = g_dbus_proxy_get_connection (G_DBUS_PROXY (client));
+
+ devices = g_ptr_array_new_with_free_func (g_object_unref);
+
+ g_variant_get (val, "(ao)", &iter);
+ while (g_variant_iter_loop (iter, "&o", &d, NULL))
+ {
+ BoltDevice *dev;
+
+ dev = bolt_device_new_for_object_path (bus, d, cancel, error);
+ if (dev == NULL)
+ return NULL;
+
+ g_ptr_array_add (devices, dev);
+ }
+
+ return g_steal_pointer (&devices);
+}
+
+BoltDevice *
+bolt_client_get_device (BoltClient *client,
+ const char *uid,
+ GCancellable *cancel,
+ GError **error)
+{
+ g_autoptr(GVariant) val = NULL;
+ g_autoptr(GError) err = NULL;
+ BoltDevice *dev = NULL;
+ GDBusConnection *bus = NULL;
+ const char *opath = NULL;
+
+ g_return_val_if_fail (BOLT_IS_CLIENT (client), NULL);
+
+ val = g_dbus_proxy_call_sync (G_DBUS_PROXY (client),
+ "DeviceByUid",
+ g_variant_new ("(s)", uid),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancel,
+ &err);
+
+ if (val == NULL)
+ {
+ bolt_error_propagate_stripped (error, &err);
+ return NULL;
+ }
+
+ bus = g_dbus_proxy_get_connection (G_DBUS_PROXY (client));
+ g_variant_get (val, "(&o)", &opath);
+
+ if (opath == NULL)
+ return NULL;
+
+ dev = bolt_device_new_for_object_path (bus, opath, cancel, error);
+ return dev;
+}
+
+BoltDevice *
+bolt_client_enroll_device (BoltClient *client,
+ const char *uid,
+ BoltPolicy policy,
+ BoltAuthCtrl flags,
+ GError **error)
+{
+ g_autoptr(GVariant) val = NULL;
+ g_autoptr(GError) err = NULL;
+ g_autofree char *fstr = NULL;
+ BoltDevice *dev = NULL;
+ GDBusConnection *bus = NULL;
+ GVariant *params = NULL;
+ const char *opath = NULL;
+ const char *pstr;
+
+ g_return_val_if_fail (BOLT_IS_CLIENT (client), NULL);
+
+ pstr = bolt_enum_to_string (BOLT_TYPE_POLICY, policy, error);
+ if (pstr == NULL)
+ return NULL;
+
+ fstr = bolt_flags_to_string (BOLT_TYPE_AUTH_CTRL, flags, error);
+ if (fstr == NULL)
+ return NULL;
+
+ params = g_variant_new ("(sss)", uid, pstr, fstr);
+ val = g_dbus_proxy_call_sync (G_DBUS_PROXY (client),
+ "EnrollDevice",
+ params,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &err);
+
+ if (val == NULL)
+ {
+ bolt_error_propagate_stripped (error, &err);
+ return NULL;
+ }
+
+ bus = g_dbus_proxy_get_connection (G_DBUS_PROXY (client));
+ g_variant_get (val, "(&o)", &opath);
+
+ if (opath == NULL)
+ return NULL;
+
+ dev = bolt_device_new_for_object_path (bus, opath, NULL, error);
+ return dev;
+}
+
+void
+bolt_client_enroll_device_async (BoltClient *client,
+ const char *uid,
+ BoltPolicy policy,
+ BoltAuthCtrl flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autofree char *fstr = NULL;
+ GError *err = NULL;
+ GVariant *params;
+ const char *pstr;
+
+ g_return_if_fail (BOLT_IS_CLIENT (client));
+ g_return_if_fail (uid != NULL);
+
+ pstr = bolt_enum_to_string (BOLT_TYPE_POLICY, policy, &err);
+ if (pstr == NULL)
+ {
+ g_task_report_error (client, callback, user_data, NULL, err);
+ return;
+ }
+
+ fstr = bolt_flags_to_string (BOLT_TYPE_AUTH_CTRL, flags, &err);
+ if (fstr == NULL)
+ {
+ g_task_report_error (client, callback, user_data, NULL, err);
+ return;
+ }
+
+ params = g_variant_new ("(sss)", uid, pstr, fstr);
+ g_dbus_proxy_call (G_DBUS_PROXY (client),
+ "EnrollDevice",
+ params,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+gboolean
+bolt_client_enroll_device_finish (BoltClient *client,
+ GAsyncResult *res,
+ char **path,
+ GError **error)
+{
+ g_autoptr(GError) err = NULL;
+ g_autoptr(GVariant) val = NULL;
+
+ g_return_val_if_fail (BOLT_IS_CLIENT (client), FALSE);
+
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (client), res, &err);
+ if (val == NULL)
+ {
+ bolt_error_propagate_stripped (error, &err);
+ return FALSE;
+ }
+
+ if (path != NULL)
+ g_variant_get (val, "(o)", path);
+
+ return TRUE;
+}
+
+typedef struct OpData
+{
+ const char *iface; /* Manager or Device */
+ const char *method; /* Enroll or Authorize */
+ char *path; /* object path */
+ GVariant *params; /* parameters */
+
+} OpData;
+
+static OpData *
+op_data_new_enroll (const char *uid,
+ const char *policy,
+ const char *flags)
+{
+ GVariant *params;
+ OpData *op;
+
+ params = g_variant_new ("(sss)", uid, policy, flags);
+
+ op = g_slice_new (OpData);
+ op->iface = BOLT_DBUS_INTERFACE;
+ op->method = "EnrollDevice";
+ op->params = g_variant_ref_sink (params);
+ op->path = g_strdup (BOLT_DBUS_PATH);
+
+ return op;
+}
+
+
+static OpData *
+op_data_new_authorize (const char *uid,
+ const char *flags)
+{
+ OpData *op = NULL;
+ GVariant *params;
+ char *path;
+
+ path = bolt_gen_object_path (BOLT_DBUS_PATH_DEVICES, uid);
+ params = g_variant_new ("(s)", flags);
+
+ op = g_slice_new (OpData);
+
+ op->iface = BOLT_DBUS_DEVICE_INTERFACE;
+ op->method = "Authorize";
+ op->params = g_variant_ref_sink (params);
+ op->path = path; /* takes ownership */
+
+ return op;
+}
+
+static void
+op_data_free (OpData *op)
+{
+ g_clear_pointer (&op->params, g_variant_unref);
+ g_clear_pointer (&op->path, g_free);
+ g_slice_free (OpData, op);
+}
+
+static void
+op_queue_free (GQueue *queue)
+{
+ g_queue_free_full (queue, (GDestroyNotify) op_data_free);
+}
+
+static void allop_one_done (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data);
+
+static gboolean
+allop_continue (BoltClient *client, GTask *task, GQueue *ops)
+{
+ GDBusConnection *bus;
+ GCancellable *cancel;
+ OpData *op;
+
+ cancel = g_task_get_cancellable (task);
+ bus = g_dbus_proxy_get_connection (G_DBUS_PROXY (client));
+
+ op = g_queue_pop_head (ops);
+
+ if (op == NULL)
+ return TRUE;
+
+ g_dbus_connection_call (bus,
+ BOLT_DBUS_NAME,
+ op->path,
+ op->iface,
+ op->method,
+ op->params,
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancel,
+ allop_one_done,
+ task);
+
+ op_data_free (op);
+
+ return FALSE;
+}
+
+static void
+allop_one_done (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GVariant) val = NULL;
+ BoltClient *client;
+ GDBusConnection *bus;
+ gboolean done;
+ GError *err = NULL;
+ GQueue *ops;
+ GTask *task;
+
+ task = G_TASK (user_data);
+
+ ops = g_task_get_task_data (task);
+ client = g_task_get_source_object (task);
+ bus = g_dbus_proxy_get_connection (G_DBUS_PROXY (client));
+
+ val = g_dbus_connection_call_finish (bus, res, &err);
+
+ if (val == NULL)
+ {
+ g_task_return_error (task, err); /* takes ownership */
+ g_object_unref (task);
+ /* we are done (albeit with an error) */
+ return;
+ }
+
+ done = allop_continue (client, task, ops);
+
+ if (done)
+ {
+ /* we are done */
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+ }
+}
+
+void
+bolt_client_enroll_all_async (BoltClient *client,
+ GPtrArray *uuids,
+ BoltPolicy policy,
+ BoltAuthCtrl flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autofree char *fstr = NULL;
+ GError *err = NULL;
+ const char *pstr;
+ GQueue *ops;
+ GTask *task;
+
+ g_return_if_fail (BOLT_IS_CLIENT (client));
+ g_return_if_fail (uuids != NULL && uuids->len > 0);
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (callback != NULL);
+
+ pstr = bolt_enum_to_string (BOLT_TYPE_POLICY, policy, &err);
+ if (pstr == NULL)
+ {
+ g_task_report_error (client, callback, user_data, NULL, err);
+ return;
+ }
+
+ fstr = bolt_flags_to_string (BOLT_TYPE_AUTH_CTRL, flags, &err);
+ if (fstr == NULL)
+ {
+ g_task_report_error (client, callback, user_data, NULL, err);
+ return;
+ }
+
+ task = g_task_new (client, cancellable, callback, user_data);
+ g_task_set_return_on_cancel (task, TRUE);
+
+ ops = g_queue_new ();
+ g_task_set_task_data (task, ops, (GDestroyNotify) op_queue_free);
+
+ for (guint i = 0; i < uuids->len; i++)
+ {
+ const char *uid = g_ptr_array_index (uuids, i);
+ OpData *op;
+
+ op = op_data_new_enroll (uid, pstr, fstr);
+
+ g_queue_push_tail (ops, op);
+ }
+
+ allop_continue (client, task, ops);
+}
+
+gboolean
+bolt_client_enroll_all_finish (BoltClient *client,
+ GAsyncResult *res,
+ GError **error)
+{
+ g_autoptr(GError) err = NULL;
+ gboolean ok;
+
+ g_return_val_if_fail (BOLT_IS_CLIENT (client), FALSE);
+ g_return_val_if_fail (g_task_is_valid (res, client), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ ok = g_task_propagate_boolean (G_TASK (res), &err);
+
+ if (!ok)
+ bolt_error_propagate_stripped (error, &err);
+
+ return ok;
+}
+
+void
+bolt_client_authorize_all_async (BoltClient *client,
+ GPtrArray *uuids,
+ BoltAuthCtrl flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autofree char *fstr = NULL;
+ GError *err = NULL;
+ GQueue *ops;
+ GTask *task;
+
+ g_return_if_fail (BOLT_IS_CLIENT (client));
+ g_return_if_fail (uuids != NULL && uuids->len > 0);
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (callback != NULL);
+
+ fstr = bolt_flags_to_string (BOLT_TYPE_AUTH_CTRL, flags, &err);
+ if (fstr == NULL)
+ {
+ g_task_report_error (client, callback, user_data, NULL, err);
+ return;
+ }
+
+ task = g_task_new (client, cancellable, callback, user_data);
+ g_task_set_return_on_cancel (task, TRUE);
+
+ ops = g_queue_new ();
+ g_task_set_task_data (task, ops, (GDestroyNotify) op_queue_free);
+
+ for (guint i = 0; i < uuids->len; i++)
+ {
+ const char *uid = g_ptr_array_index (uuids, i);
+ OpData *op;
+
+ op = op_data_new_authorize (uid, fstr);
+
+ g_queue_push_tail (ops, op);
+ }
+
+ allop_continue (client, task, ops);
+}
+
+gboolean
+bolt_client_authorize_all_finish (BoltClient *client,
+ GAsyncResult *res,
+ GError **error)
+{
+ g_autoptr(GError) err = NULL;
+ gboolean ok;
+
+ g_return_val_if_fail (BOLT_IS_CLIENT (client), FALSE);
+ g_return_val_if_fail (g_task_is_valid (res, client), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ ok = g_task_propagate_boolean (G_TASK (res), &err);
+
+ if (!ok)
+ bolt_error_propagate_stripped (error, &err);
+
+ return ok;
+}
+
+void
+bolt_client_connect_all_async (BoltClient *client,
+ GPtrArray *devices,
+ BoltPolicy policy,
+ BoltAuthCtrl flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autofree char *fstr = NULL;
+ GError *err = NULL;
+ const char *pstr;
+ GQueue *ops;
+ GTask *task;
+
+ g_return_if_fail (BOLT_IS_CLIENT (client));
+ g_return_if_fail (devices != NULL && devices->len > 0);
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (callback != NULL);
+
+ pstr = bolt_enum_to_string (BOLT_TYPE_POLICY, policy, &err);
+ if (pstr == NULL)
+ {
+ g_task_report_error (client, callback, user_data, NULL, err);
+ return;
+ }
+
+ fstr = bolt_flags_to_string (BOLT_TYPE_AUTH_CTRL, flags, &err);
+ if (fstr == NULL)
+ {
+ g_task_report_error (client, callback, user_data, NULL, err);
+ return;
+ }
+
+ task = g_task_new (client, cancellable, callback, user_data);
+ g_task_set_return_on_cancel (task, TRUE);
+
+ ops = g_queue_new ();
+ g_task_set_task_data (task, ops, (GDestroyNotify) op_queue_free);
+
+ for (guint i = 0; i < devices->len; i++)
+ {
+ BoltDevice *dev = g_ptr_array_index (devices, i);
+ const char *uid = bolt_device_get_uid (dev);
+ OpData *op;
+
+ if (bolt_device_is_stored (dev))
+ op = op_data_new_authorize (uid, fstr);
+ else
+ op = op_data_new_enroll (uid, pstr, fstr);
+
+ g_queue_push_tail (ops, op);
+ }
+
+ allop_continue (client, task, ops);
+}
+
+gboolean
+bolt_client_connect_all_finish (BoltClient *client,
+ GAsyncResult *res,
+ GError **error)
+{
+ g_autoptr(GError) err = NULL;
+ gboolean ok;
+
+ g_return_val_if_fail (BOLT_IS_CLIENT (client), FALSE);
+ g_return_val_if_fail (g_task_is_valid (res, client), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ ok = g_task_propagate_boolean (G_TASK (res), &err);
+
+ if (!ok)
+ bolt_error_propagate_stripped (error, &err);
+
+ return ok;
+}
+
+gboolean
+bolt_client_forget_device (BoltClient *client,
+ const char *uid,
+ GError **error)
+{
+ g_autoptr(GVariant) val = NULL;
+ g_autoptr(GError) err = NULL;
+
+ g_return_val_if_fail (BOLT_IS_CLIENT (client), FALSE);
+
+ val = g_dbus_proxy_call_sync (G_DBUS_PROXY (client),
+ "ForgetDevice",
+ g_variant_new ("(s)", uid),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &err);
+
+ if (val == NULL)
+ {
+ bolt_error_propagate_stripped (error, &err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void
+bolt_client_forget_device_async (BoltClient *client,
+ const char *uid,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_fail (BOLT_IS_CLIENT (client));
+
+ g_dbus_proxy_call (G_DBUS_PROXY (client),
+ "ForgetDevice",
+ g_variant_new ("(s)", uid),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+gboolean
+bolt_client_forget_device_finish (BoltClient *client,
+ GAsyncResult *res,
+ GError **error)
+{
+ g_autoptr(GVariant) val = NULL;
+ g_autoptr(GError) err = NULL;
+
+ g_return_val_if_fail (BOLT_IS_CLIENT (client), FALSE);
+
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (client), res, &err);
+ if (val == NULL)
+ {
+ bolt_error_propagate_stripped (error, &err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* getter */
+guint
+bolt_client_get_version (BoltClient *client)
+{
+ const char *key;
+ guint val = 0;
+ gboolean ok;
+
+ g_return_val_if_fail (BOLT_IS_CLIENT (client), val);
+
+ key = g_param_spec_get_name (props[PROP_VERSION]);
+ ok = bolt_proxy_get_property_uint32 (BOLT_PROXY (client), key, &val);
+
+ if (!ok)
+ g_warning ("failed to get property '%s'", key);
+
+ return val;
+}
+
+gboolean
+bolt_client_is_probing (BoltClient *client)
+{
+ const char *key;
+ gboolean val = FALSE;
+ gboolean ok;
+
+ g_return_val_if_fail (BOLT_IS_CLIENT (client), val);
+
+ key = g_param_spec_get_name (props[PROP_PROBING]);
+ ok = bolt_proxy_get_property_bool (BOLT_PROXY (client), key, &val);
+
+ if (!ok)
+ g_warning ("failed to get enum property '%s'", key);
+
+ return val;
+}
+
+BoltSecurity
+bolt_client_get_security (BoltClient *client)
+{
+ const char *key;
+ gboolean ok;
+ gint val = BOLT_SECURITY_UNKNOWN;
+
+ g_return_val_if_fail (BOLT_IS_CLIENT (client), val);
+
+ key = g_param_spec_get_name (props[PROP_SECURITY]);
+ ok = bolt_proxy_get_property_enum (BOLT_PROXY (client), key, &val);
+
+ if (!ok)
+ g_warning ("failed to get enum property '%s'", key);
+
+ return val;
+}
+
+BoltAuthMode
+bolt_client_get_authmode (BoltClient *client)
+{
+ const char *key;
+ gboolean ok;
+ guint val = BOLT_AUTH_DISABLED;
+
+ g_return_val_if_fail (BOLT_IS_CLIENT (client), val);
+
+ key = g_param_spec_get_name (props[PROP_AUTHMODE]);
+ ok = bolt_proxy_get_property_flags (BOLT_PROXY (client), key, &val);
+
+ if (!ok)
+ g_warning ("failed to get enum property '%s'", key);
+
+ return val;
+}
+
+void
+bolt_client_set_authmode_async (BoltClient *client,
+ BoltAuthMode mode,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autofree char *str = NULL;
+ GError *err = NULL;
+ GParamSpec *pspec;
+ GParamSpecFlags *flags_pspec;
+ GFlagsClass *flags_class;
+
+ pspec = props[PROP_AUTHMODE];
+ flags_pspec = G_PARAM_SPEC_FLAGS (pspec);
+ flags_class = flags_pspec->flags_class;
+ str = bolt_flags_class_to_string (flags_class, mode, &err);
+
+ if (str == NULL)
+ {
+ g_task_report_error (client, callback, user_data, NULL, err);
+ return;
+ }
+
+ bolt_proxy_set_property_async (BOLT_PROXY (client),
+ g_param_spec_get_nick (pspec),
+ g_variant_new ("s", str),
+ cancellable,
+ callback,
+ user_data);
+}
+
+gboolean
+bolt_client_set_authmode_finish (BoltClient *client,
+ GAsyncResult *res,
+ GError **error)
+{
+ return bolt_proxy_set_property_finish (res, error);
+}
+
+/* utility functions */
+static gint
+device_sort_by_syspath (gconstpointer ap,
+ gconstpointer bp,
+ gpointer data)
+{
+ BoltDevice *a = BOLT_DEVICE (*((BoltDevice **) ap));
+ BoltDevice *b = BOLT_DEVICE (*((BoltDevice **) bp));
+ gint sort_order = GPOINTER_TO_INT (data);
+ const char *pa;
+ const char *pb;
+
+ pa = bolt_device_get_syspath (a);
+ pb = bolt_device_get_syspath (b);
+
+ return sort_order * g_strcmp0 (pa, pb);
+}
+
+void
+bolt_devices_sort_by_syspath (GPtrArray *devices,
+ gboolean reverse)
+{
+ gpointer sort_order = GINT_TO_POINTER (reverse ? -1 : 1);
+
+ if (devices == NULL)
+ return;
+
+ g_ptr_array_sort_with_data (devices,
+ device_sort_by_syspath,
+ sort_order);
+}
diff --git a/panels/thunderbolt/bolt-client.h b/panels/thunderbolt/bolt-client.h
new file mode 100644
index 0000000..571d5bd
--- /dev/null
+++ b/panels/thunderbolt/bolt-client.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright © 2017 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Christian J. Kellner <christian@kellner.me>
+ */
+
+#pragma once
+
+#include "bolt-enums.h"
+#include "bolt-device.h"
+#include "bolt-proxy.h"
+
+G_BEGIN_DECLS
+
+#define BOLT_TYPE_CLIENT bolt_client_get_type ()
+G_DECLARE_FINAL_TYPE (BoltClient, bolt_client, BOLT, CLIENT, BoltProxy);
+
+BoltClient * bolt_client_new (GError **error);
+
+void bolt_client_new_async (GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+BoltClient * bolt_client_new_finish (GAsyncResult *res,
+ GError **error);
+
+GPtrArray * bolt_client_list_devices (BoltClient *client,
+ GCancellable *cancellable,
+ GError **error);
+
+BoltDevice * bolt_client_get_device (BoltClient *client,
+ const char *uid,
+ GCancellable *cancellable,
+ GError **error);
+
+BoltDevice * bolt_client_enroll_device (BoltClient *client,
+ const char *uid,
+ BoltPolicy policy,
+ BoltAuthCtrl flags,
+ GError **error);
+
+void bolt_client_enroll_device_async (BoltClient *client,
+ const char *uid,
+ BoltPolicy policy,
+ BoltAuthCtrl flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean bolt_client_enroll_device_finish (BoltClient *client,
+ GAsyncResult *res,
+ char **path,
+ GError **error);
+
+void bolt_client_enroll_all_async (BoltClient *client,
+ GPtrArray *uuids,
+ BoltPolicy policy,
+ BoltAuthCtrl flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean bolt_client_enroll_all_finish (BoltClient *client,
+ GAsyncResult *res,
+ GError **error);
+
+void bolt_client_authorize_all_async (BoltClient *client,
+ GPtrArray *uuids,
+ BoltAuthCtrl flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean bolt_client_authorize_all_finish (BoltClient *client,
+ GAsyncResult *res,
+ GError **error);
+
+void bolt_client_connect_all_async (BoltClient *client,
+ GPtrArray *devices,
+ BoltPolicy policy,
+ BoltAuthCtrl flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean bolt_client_connect_all_finish (BoltClient *client,
+ GAsyncResult *res,
+ GError **error);
+
+
+gboolean bolt_client_forget_device (BoltClient *client,
+ const char *uid,
+ GError **error);
+
+void bolt_client_forget_device_async (BoltClient *client,
+ const char *uid,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean bolt_client_forget_device_finish (BoltClient *client,
+ GAsyncResult *res,
+ GError **error);
+
+/* getter */
+guint bolt_client_get_version (BoltClient *client);
+
+gboolean bolt_client_is_probing (BoltClient *client);
+
+BoltSecurity bolt_client_get_security (BoltClient *client);
+
+BoltAuthMode bolt_client_get_authmode (BoltClient *client);
+
+/* setter */
+
+void bolt_client_set_authmode_async (BoltClient *client,
+ BoltAuthMode mode,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean bolt_client_set_authmode_finish (BoltClient *client,
+ GAsyncResult *res,
+ GError **error);
+
+/* utility functions */
+void bolt_devices_sort_by_syspath (GPtrArray *devices,
+ gboolean reverse);
+
+G_END_DECLS
diff --git a/panels/thunderbolt/bolt-device.c b/panels/thunderbolt/bolt-device.c
new file mode 100644
index 0000000..b316950
--- /dev/null
+++ b/panels/thunderbolt/bolt-device.c
@@ -0,0 +1,604 @@
+/*
+ * Copyright © 2017 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Christian J. Kellner <christian@kellner.me>
+ */
+
+#include "config.h"
+
+#include "bolt-device.h"
+
+#include "bolt-enums.h"
+#include "bolt-error.h"
+#include "bolt-names.h"
+
+#include <gio/gio.h>
+
+struct _BoltDevice
+{
+ BoltProxy parent;
+};
+
+enum {
+ PROP_0,
+
+ /* D-Bus Props */
+ PROP_UID,
+ PROP_NAME,
+ PROP_VENDOR,
+ PROP_TYPE,
+ PROP_STATUS,
+ PROP_AUTHFLAGS,
+ PROP_PARENT,
+ PROP_SYSPATH,
+ PROP_CONNTIME,
+ PROP_AUTHTIME,
+
+ PROP_STORED,
+ PROP_POLICY,
+ PROP_KEY,
+ PROP_STORETIME,
+ PROP_LABEL,
+
+ PROP_LAST
+};
+
+static GParamSpec *props[PROP_LAST] = {NULL, };
+
+G_DEFINE_TYPE (BoltDevice,
+ bolt_device,
+ BOLT_TYPE_PROXY);
+
+static void
+bolt_device_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ if (bolt_proxy_get_dbus_property (object, pspec, value))
+ return;
+}
+
+
+
+static void
+bolt_device_class_init (BoltDeviceClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->get_property = bolt_device_get_property;
+
+ props[PROP_UID] =
+ g_param_spec_string ("uid",
+ "Uid", NULL,
+ "unknown",
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NICK);
+
+ props[PROP_NAME] =
+ g_param_spec_string ("name",
+ "Name", NULL,
+ "unknown",
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NICK);
+
+ props[PROP_VENDOR] =
+ g_param_spec_string ("vendor",
+ "Vendor", NULL,
+ "unknown",
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NICK);
+
+ props[PROP_TYPE] =
+ g_param_spec_enum ("type",
+ "Type", NULL,
+ BOLT_TYPE_DEVICE_TYPE,
+ BOLT_DEVICE_PERIPHERAL,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NICK);
+
+ props[PROP_STATUS] =
+ g_param_spec_enum ("status",
+ "Status", NULL,
+ BOLT_TYPE_STATUS,
+ BOLT_STATUS_DISCONNECTED,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NICK);
+
+ props[PROP_AUTHFLAGS] =
+ g_param_spec_flags ("authflags",
+ "AuthFlags", NULL,
+ BOLT_TYPE_AUTH_FLAGS,
+ BOLT_AUTH_NONE,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS);
+
+ props[PROP_PARENT] =
+ g_param_spec_string ("parent",
+ "Parent", NULL,
+ "unknown",
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NICK);
+
+ props[PROP_SYSPATH] =
+ g_param_spec_string ("syspath",
+ "SysfsPath", NULL,
+ "unknown",
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NICK);
+
+ props[PROP_CONNTIME] =
+ g_param_spec_uint64 ("conntime",
+ "ConnectTime", NULL,
+ 0, G_MAXUINT64, 0,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS);
+
+ props[PROP_AUTHTIME] =
+ g_param_spec_uint64 ("authtime",
+ "AuthorizeTime", NULL,
+ 0, G_MAXUINT64, 0,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS);
+
+ props[PROP_STORED] =
+ g_param_spec_boolean ("stored",
+ "Stored", NULL,
+ FALSE,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NICK);
+
+ props[PROP_POLICY] =
+ g_param_spec_enum ("policy",
+ "Policy", NULL,
+ BOLT_TYPE_POLICY,
+ BOLT_POLICY_DEFAULT,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NICK);
+
+ props[PROP_KEY] =
+ g_param_spec_enum ("key",
+ "Key", NULL,
+ BOLT_TYPE_KEY_STATE,
+ BOLT_KEY_MISSING,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NICK);
+
+ props[PROP_STORETIME] =
+ g_param_spec_uint64 ("storetime",
+ "StoreTime", NULL,
+ 0, G_MAXUINT64, 0,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS);
+
+ props[PROP_LABEL] =
+ g_param_spec_string ("label",
+ "Label", NULL,
+ NULL,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (gobject_class,
+ PROP_LAST,
+ props);
+
+}
+
+static void
+bolt_device_init (BoltDevice *mgr)
+{
+}
+
+/* public methods */
+
+BoltDevice *
+bolt_device_new_for_object_path (GDBusConnection *bus,
+ const char *path,
+ GCancellable *cancel,
+ GError **error)
+{
+ BoltDevice *dev;
+
+ dev = g_initable_new (BOLT_TYPE_DEVICE,
+ cancel, error,
+ "g-flags", G_DBUS_PROXY_FLAGS_NONE,
+ "g-connection", bus,
+ "g-name", BOLT_DBUS_NAME,
+ "g-object-path", path,
+ "g-interface-name", BOLT_DBUS_DEVICE_INTERFACE,
+ NULL);
+
+ return dev;
+}
+
+gboolean
+bolt_device_authorize (BoltDevice *dev,
+ BoltAuthCtrl flags,
+ GCancellable *cancel,
+ GError **error)
+{
+ g_autoptr(GError) err = NULL;
+ g_autofree char *fstr = NULL;
+
+ g_return_val_if_fail (BOLT_IS_DEVICE (dev), FALSE);
+
+ fstr = bolt_flags_to_string (BOLT_TYPE_AUTH_CTRL, flags, error);
+ if (fstr == NULL)
+ return FALSE;
+
+ g_dbus_proxy_call_sync (G_DBUS_PROXY (dev),
+ "Authorize",
+ g_variant_new ("(s)", fstr),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancel,
+ &err);
+
+ if (err != NULL)
+ return bolt_error_propagate_stripped (error, &err);
+
+ return TRUE;
+}
+
+void
+bolt_device_authorize_async (BoltDevice *dev,
+ BoltAuthCtrl flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GError *err = NULL;
+ g_autofree char *fstr = NULL;
+
+ g_return_if_fail (BOLT_IS_DEVICE (dev));
+
+ fstr = bolt_flags_to_string (BOLT_TYPE_AUTH_CTRL, flags, &err);
+ if (fstr == NULL)
+ {
+ g_task_report_error (dev, callback, user_data, NULL, err);
+ return;
+ }
+
+ g_dbus_proxy_call (G_DBUS_PROXY (dev),
+ "Authorize",
+ g_variant_new ("(s)", fstr),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+gboolean
+bolt_device_authorize_finish (BoltDevice *dev,
+ GAsyncResult *res,
+ GError **error)
+{
+ g_autoptr(GError) err = NULL;
+ g_autoptr(GVariant) val = NULL;
+
+ g_return_val_if_fail (BOLT_IS_DEVICE (dev), FALSE);
+
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (dev), res, &err);
+ if (val == NULL)
+ {
+ bolt_error_propagate_stripped (error, &err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+const char *
+bolt_device_get_uid (BoltDevice *dev)
+{
+ const char *key;
+ const char *str;
+
+ g_return_val_if_fail (BOLT_IS_DEVICE (dev), NULL);
+
+ key = g_param_spec_get_name (props[PROP_UID]);
+ str = bolt_proxy_get_property_string (BOLT_PROXY (dev), key);
+
+ return str;
+}
+
+const char *
+bolt_device_get_name (BoltDevice *dev)
+{
+ const char *key;
+ const char *str;
+
+ g_return_val_if_fail (BOLT_IS_DEVICE (dev), NULL);
+
+ key = g_param_spec_get_name (props[PROP_NAME]);
+ str = bolt_proxy_get_property_string (BOLT_PROXY (dev), key);
+
+ return str;
+}
+
+const char *
+bolt_device_get_vendor (BoltDevice *dev)
+{
+ const char *key;
+ const char *str;
+
+ g_return_val_if_fail (BOLT_IS_DEVICE (dev), NULL);
+
+ key = g_param_spec_get_name (props[PROP_VENDOR]);
+ str = bolt_proxy_get_property_string (BOLT_PROXY (dev), key);
+
+ return str;
+}
+
+BoltDeviceType
+bolt_device_get_device_type (BoltDevice *dev)
+{
+ const char *key;
+ gboolean ok;
+ gint val = BOLT_DEVICE_PERIPHERAL;
+
+ g_return_val_if_fail (BOLT_IS_DEVICE (dev), val);
+
+ key = g_param_spec_get_name (props[PROP_TYPE]);
+ ok = bolt_proxy_get_property_enum (BOLT_PROXY (dev), key, &val);
+
+ if (!ok)
+ g_warning ("failed to get enum property '%s'", key);
+
+ return val;
+}
+
+BoltStatus
+bolt_device_get_status (BoltDevice *dev)
+{
+ const char *key;
+ gboolean ok;
+ gint val = BOLT_STATUS_UNKNOWN;
+
+ g_return_val_if_fail (BOLT_IS_DEVICE (dev), val);
+
+ key = g_param_spec_get_name (props[PROP_STATUS]);
+ ok = bolt_proxy_get_property_enum (BOLT_PROXY (dev), key, &val);
+
+ if (!ok)
+ g_warning ("failed to get enum property '%s'", key);
+
+ return val;
+}
+
+BoltAuthFlags
+bolt_device_get_authflags (BoltDevice *dev)
+{
+ const char *key;
+ gboolean ok;
+ guint val = BOLT_AUTH_NONE;
+
+ g_return_val_if_fail (BOLT_IS_DEVICE (dev), val);
+
+ key = g_param_spec_get_name (props[PROP_AUTHFLAGS]);
+ ok = bolt_proxy_get_property_flags (BOLT_PROXY (dev), key, &val);
+
+ if (!ok)
+ g_warning ("failed to get enum property '%s'", key);
+
+ return val;
+}
+
+const char *
+bolt_device_get_parent (BoltDevice *dev)
+{
+ const char *key;
+ const char *str;
+
+ g_return_val_if_fail (BOLT_IS_DEVICE (dev), NULL);
+
+ key = g_param_spec_get_name (props[PROP_PARENT]);
+ str = bolt_proxy_get_property_string (BOLT_PROXY (dev), key);
+
+ return str;
+}
+
+const char *
+bolt_device_get_syspath (BoltDevice *dev)
+{
+ const char *key;
+ const char *str;
+
+ g_return_val_if_fail (BOLT_IS_DEVICE (dev), NULL);
+
+ key = g_param_spec_get_name (props[PROP_SYSPATH]);
+ str = bolt_proxy_get_property_string (BOLT_PROXY (dev), key);
+
+ return str;
+}
+
+guint64
+bolt_device_get_conntime (BoltDevice *dev)
+{
+ const char *key;
+ guint64 val = 0;
+ gboolean ok;
+
+ g_return_val_if_fail (BOLT_IS_DEVICE (dev), val);
+
+ key = g_param_spec_get_name (props[PROP_CONNTIME]);
+ ok = bolt_proxy_get_property_uint64 (BOLT_PROXY (dev), key, &val);
+
+ if (!ok)
+ g_warning ("failed to get enum property '%s'", key);
+
+ return val;
+}
+
+guint64
+bolt_device_get_authtime (BoltDevice *dev)
+{
+ const char *key;
+ guint64 val = 0;
+ gboolean ok;
+
+ g_return_val_if_fail (BOLT_IS_DEVICE (dev), val);
+
+ key = g_param_spec_get_name (props[PROP_AUTHTIME]);
+ ok = bolt_proxy_get_property_uint64 (BOLT_PROXY (dev), key, &val);
+
+ if (!ok)
+ g_warning ("failed to get enum property '%s'", key);
+
+ return val;
+}
+
+gboolean
+bolt_device_is_stored (BoltDevice *dev)
+{
+ const char *key;
+ gboolean val = FALSE;
+ gboolean ok;
+
+ g_return_val_if_fail (BOLT_IS_DEVICE (dev), val);
+
+ key = g_param_spec_get_name (props[PROP_STORED]);
+ ok = bolt_proxy_get_property_bool (BOLT_PROXY (dev), key, &val);
+
+ if (!ok)
+ g_warning ("failed to get enum property '%s'", key);
+
+ return val;
+}
+
+BoltPolicy
+bolt_device_get_policy (BoltDevice *dev)
+{
+ const char *key;
+ gboolean ok;
+ gint val = BOLT_POLICY_DEFAULT;
+
+ g_return_val_if_fail (BOLT_IS_DEVICE (dev), val);
+
+ key = g_param_spec_get_name (props[PROP_POLICY]);
+ ok = bolt_proxy_get_property_enum (BOLT_PROXY (dev), key, &val);
+
+ if (!ok)
+ g_warning ("failed to get enum property '%s'", key);
+
+ return val;
+}
+
+BoltKeyState
+bolt_device_get_keystate (BoltDevice *dev)
+{
+ const char *key;
+ gboolean ok;
+ gint val = BOLT_KEY_MISSING;
+
+ g_return_val_if_fail (BOLT_IS_DEVICE (dev), val);
+
+ key = g_param_spec_get_name (props[PROP_KEY]);
+ ok = bolt_proxy_get_property_enum (BOLT_PROXY (dev), key, &val);
+
+ if (!ok)
+ g_warning ("failed to get enum property '%s'", key);
+
+ return val;
+}
+
+guint64
+bolt_device_get_storetime (BoltDevice *dev)
+{
+ const char *key;
+ guint64 val = 0;
+ gboolean ok;
+
+ g_return_val_if_fail (BOLT_IS_DEVICE (dev), val);
+
+ key = g_param_spec_get_name (props[PROP_STORETIME]);
+ ok = bolt_proxy_get_property_uint64 (BOLT_PROXY (dev), key, &val);
+
+ if (!ok)
+ g_warning ("failed to get enum property '%s'", key);
+
+ return val;
+}
+
+const char *
+bolt_device_get_label (BoltDevice *dev)
+{
+ const char *key;
+ const char *str;
+
+ g_return_val_if_fail (BOLT_IS_DEVICE (dev), NULL);
+
+ key = g_param_spec_get_name (props[PROP_LABEL]);
+ str = bolt_proxy_get_property_string (BOLT_PROXY (dev), key);
+
+ return str;
+}
+
+char *
+bolt_device_get_display_name (BoltDevice *dev)
+{
+ const char *label;
+ const char *name;
+ const char *vendor;
+
+ label = bolt_device_get_label (dev);
+ if (label != NULL)
+ return g_strdup (label);
+
+ name = bolt_device_get_name (dev);
+ vendor = bolt_device_get_vendor (dev);
+
+ return g_strdup_printf ("%s %s", vendor, name);
+}
+
+guint64
+bolt_device_get_timestamp (BoltDevice *dev)
+{
+ BoltStatus status;
+ guint64 timestamp = 0;
+
+ status = bolt_device_get_status (dev);
+
+ switch (status)
+ {
+ case BOLT_STATUS_AUTHORIZING:
+ case BOLT_STATUS_AUTH_ERROR:
+ case BOLT_STATUS_CONNECTING:
+ case BOLT_STATUS_CONNECTED:
+ timestamp = bolt_device_get_conntime (dev);
+ break;
+
+ case BOLT_STATUS_DISCONNECTED:
+ /* implicit: device is stored */
+ timestamp = bolt_device_get_storetime (dev);
+ break;
+
+ case BOLT_STATUS_AUTHORIZED:
+ case BOLT_STATUS_AUTHORIZED_DPONLY:
+ case BOLT_STATUS_AUTHORIZED_NEWKEY:
+ case BOLT_STATUS_AUTHORIZED_SECURE:
+ timestamp = bolt_device_get_authtime (dev);
+ break;
+
+ case BOLT_STATUS_UNKNOWN:
+ timestamp = 0;
+ break;
+ }
+
+ return timestamp;
+}
diff --git a/panels/thunderbolt/bolt-device.h b/panels/thunderbolt/bolt-device.h
new file mode 100644
index 0000000..ffd09f9
--- /dev/null
+++ b/panels/thunderbolt/bolt-device.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright © 2017 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Christian J. Kellner <christian@kellner.me>
+ */
+
+#pragma once
+
+#include "bolt-enums.h"
+#include "bolt-proxy.h"
+
+G_BEGIN_DECLS
+
+#define BOLT_TYPE_DEVICE bolt_device_get_type ()
+G_DECLARE_FINAL_TYPE (BoltDevice, bolt_device, BOLT, DEVICE, BoltProxy);
+
+BoltDevice * bolt_device_new_for_object_path (GDBusConnection *bus,
+ const char *path,
+ GCancellable *cancellable,
+ GError **error);
+
+gboolean bolt_device_authorize (BoltDevice *dev,
+ BoltAuthCtrl flags,
+ GCancellable *cancellable,
+ GError **error);
+
+void bolt_device_authorize_async (BoltDevice *dev,
+ BoltAuthCtrl flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean bolt_device_authorize_finish (BoltDevice *dev,
+ GAsyncResult *res,
+ GError **error);
+
+/* getter */
+const char * bolt_device_get_uid (BoltDevice *dev);
+
+const char * bolt_device_get_name (BoltDevice *dev);
+
+const char * bolt_device_get_vendor (BoltDevice *dev);
+
+BoltDeviceType bolt_device_get_device_type (BoltDevice *dev);
+
+BoltStatus bolt_device_get_status (BoltDevice *dev);
+
+BoltAuthFlags bolt_device_get_authflags (BoltDevice *dev);
+
+const char * bolt_device_get_parent (BoltDevice *dev);
+
+const char * bolt_device_get_syspath (BoltDevice *dev);
+
+guint64 bolt_device_get_conntime (BoltDevice *dev);
+
+guint64 bolt_device_get_authtime (BoltDevice *dev);
+
+gboolean bolt_device_is_stored (BoltDevice *dev);
+
+BoltPolicy bolt_device_get_policy (BoltDevice *dev);
+
+BoltKeyState bolt_device_get_keystate (BoltDevice *dev);
+
+guint64 bolt_device_get_storetime (BoltDevice *dev);
+
+const char * bolt_device_get_label (BoltDevice *dev);
+
+/* derived getter */
+char * bolt_device_get_display_name (BoltDevice *dev);
+
+guint64 bolt_device_get_timestamp (BoltDevice *dev);
+
+G_END_DECLS
diff --git a/panels/thunderbolt/bolt-enums.c b/panels/thunderbolt/bolt-enums.c
new file mode 100644
index 0000000..bb34ba7
--- /dev/null
+++ b/panels/thunderbolt/bolt-enums.c
@@ -0,0 +1,397 @@
+/*
+ * Copyright © 2017 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Christian J. Kellner <christian@kellner.me>
+ */
+
+#include "config.h"
+
+#include "bolt-enums.h"
+#include "bolt-error.h"
+
+#include <gio/gio.h>
+
+#if !GLIB_CHECK_VERSION(2, 57, 0)
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (GEnumClass, g_type_class_unref);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (GFlagsClass, g_type_class_unref);
+#endif
+
+gboolean
+bolt_enum_class_validate (GEnumClass *enum_class,
+ gint value,
+ GError **error)
+{
+ const char *name;
+ gboolean oob;
+
+ if (enum_class == NULL)
+ {
+ name = g_type_name_from_class ((GTypeClass *) enum_class);
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+ "could not determine enum class for '%s'",
+ name);
+
+ return FALSE;
+ }
+
+ oob = value < enum_class->minimum || value > enum_class->maximum;
+
+ if (oob)
+ {
+ name = g_type_name_from_class ((GTypeClass *) enum_class);
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+ "enum value '%d' is out of bounds for '%s'",
+ value, name);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+bolt_enum_validate (GType enum_type,
+ gint value,
+ GError **error)
+{
+ g_autoptr(GEnumClass) klass = g_type_class_ref (enum_type);
+ return bolt_enum_class_validate (klass, value, error);
+}
+
+const char *
+bolt_enum_to_string (GType enum_type,
+ gint value,
+ GError **error)
+{
+ g_autoptr(GEnumClass) klass = NULL;
+ GEnumValue *ev;
+
+ klass = g_type_class_ref (enum_type);
+
+ if (!bolt_enum_class_validate (klass, value, error))
+ return NULL;
+
+ ev = g_enum_get_value (klass, value);
+ return ev->value_nick;
+}
+
+gint
+bolt_enum_from_string (GType enum_type,
+ const char *string,
+ GError **error)
+{
+ g_autoptr(GEnumClass) klass = NULL;
+ const char *name;
+ GEnumValue *ev;
+
+ klass = g_type_class_ref (enum_type);
+
+ if (klass == NULL)
+ {
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+ "could not determine enum class");
+ return -1;
+ }
+
+ if (string == NULL)
+ {
+ name = g_type_name_from_class ((GTypeClass *) klass);
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+ "empty string passed for enum class for '%s'",
+ name);
+ return -1;
+ }
+
+ ev = g_enum_get_value_by_nick (klass, string);
+
+ if (ev == NULL)
+ {
+ name = g_type_name (enum_type);
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+ "invalid string '%s' for enum '%s'", string, name);
+ return -1;
+ }
+
+ return ev->value;
+}
+
+char *
+bolt_flags_class_to_string (GFlagsClass *flags_class,
+ guint value,
+ GError **error)
+{
+ g_autoptr(GString) str = NULL;
+ const char *name;
+ GFlagsValue *fv;
+
+ if (flags_class == NULL)
+ {
+ name = g_type_name_from_class ((GTypeClass *) flags_class);
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+ "could not determine flags class for '%s'",
+ name);
+
+ return FALSE;
+ }
+
+ fv = g_flags_get_first_value (flags_class, value);
+ if (fv == NULL)
+ {
+ if (value == 0)
+ return g_strdup ("");
+
+ name = g_type_name_from_class ((GTypeClass *) flags_class);
+
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+ "invalid value '%u' for flags '%s'", value, name);
+ return NULL;
+ }
+
+ value &= ~fv->value;
+ str = g_string_new (fv->value_nick);
+
+ while (value != 0 &&
+ (fv = g_flags_get_first_value (flags_class, value)) != NULL)
+ {
+ g_string_append (str, " | ");
+ g_string_append (str, fv->value_nick);
+
+ value &= ~fv->value;
+ }
+
+ if (value != 0)
+ {
+ name = g_type_name_from_class ((GTypeClass *) flags_class);
+
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+ "unhandled value '%u' for flags '%s'", value, name);
+ return NULL;
+ }
+
+ return g_string_free (g_steal_pointer (&str), FALSE);
+}
+
+gboolean
+bolt_flags_class_from_string (GFlagsClass *flags_class,
+ const char *string,
+ guint *flags_out,
+ GError **error)
+{
+ g_auto(GStrv) vals = NULL;
+ const char *name;
+ guint flags = 0;
+
+ if (flags_class == NULL)
+ {
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+ "could not determine flags class");
+
+ return FALSE;
+ }
+
+ if (string == NULL)
+ {
+ name = g_type_name_from_class ((GTypeClass *) flags_class);
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+ "empty string passed for flags class for '%s'",
+ name);
+ return FALSE;
+ }
+
+ vals = g_strsplit (string, "|", -1);
+
+ for (guint i = 0; vals[i]; i++)
+ {
+ GFlagsValue *fv;
+ char *nick;
+
+ nick = g_strstrip (vals[i]);
+ fv = g_flags_get_value_by_nick (flags_class, nick);
+
+ if (fv == NULL)
+ {
+ name = g_type_name_from_class ((GTypeClass *) flags_class);
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+ "invalid flag '%s' for flags '%s'", string, name);
+
+ return FALSE;
+ }
+
+ flags |= fv->value;
+ }
+
+ if (flags_out != NULL)
+ *flags_out = flags;
+
+ return TRUE;
+}
+
+char *
+bolt_flags_to_string (GType flags_type,
+ guint value,
+ GError **error)
+{
+ g_autoptr(GFlagsClass) klass = NULL;
+
+ klass = g_type_class_ref (flags_type);
+ return bolt_flags_class_to_string (klass, value, error);
+}
+
+gboolean
+bolt_flags_from_string (GType flags_type,
+ const char *string,
+ guint *flags_out,
+ GError **error)
+{
+ g_autoptr(GFlagsClass) klass = NULL;
+
+ klass = g_type_class_ref (flags_type);
+ return bolt_flags_class_from_string (klass, string, flags_out, error);
+}
+
+gboolean
+bolt_flags_update (guint from,
+ guint *to,
+ guint mask)
+{
+ guint val;
+ gboolean chg;
+
+ g_return_val_if_fail (to != NULL, FALSE);
+
+ val = *to & ~mask; /* clear all bits in mask */
+ val = val | (from & mask); /* set all bits in from and mask */
+ chg = *to != val;
+ *to = val;
+
+ return chg;
+}
+
+const char *
+bolt_status_to_string (BoltStatus status)
+{
+ return bolt_enum_to_string (BOLT_TYPE_STATUS, status, NULL);
+}
+
+gboolean
+bolt_status_is_authorized (BoltStatus status)
+{
+ return status == BOLT_STATUS_AUTHORIZED ||
+ status == BOLT_STATUS_AUTHORIZED_SECURE ||
+ status == BOLT_STATUS_AUTHORIZED_NEWKEY;
+}
+
+gboolean
+bolt_status_is_pending (BoltStatus status)
+{
+ return status == BOLT_STATUS_AUTH_ERROR ||
+ status == BOLT_STATUS_CONNECTED;
+}
+
+gboolean
+bolt_status_validate (BoltStatus status)
+{
+ return bolt_enum_validate (BOLT_TYPE_STATUS, status, NULL);
+}
+
+gboolean
+bolt_status_is_connected (BoltStatus status)
+{
+ return status > BOLT_STATUS_DISCONNECTED;
+}
+
+BoltSecurity
+bolt_security_from_string (const char *str)
+{
+ return bolt_enum_from_string (BOLT_TYPE_SECURITY, str, NULL);
+}
+
+const char *
+bolt_security_to_string (BoltSecurity security)
+{
+ return bolt_enum_to_string (BOLT_TYPE_SECURITY, security, NULL);
+}
+
+gboolean
+bolt_security_validate (BoltSecurity security)
+{
+ return bolt_enum_validate (BOLT_TYPE_SECURITY, security, NULL);
+}
+
+gboolean
+bolt_security_allows_pcie (BoltSecurity security)
+{
+ gboolean pcie = FALSE;
+
+ switch (security)
+ {
+ case BOLT_SECURITY_NONE:
+ case BOLT_SECURITY_USER:
+ case BOLT_SECURITY_SECURE:
+ pcie = TRUE;
+ break;
+
+ case BOLT_SECURITY_DPONLY:
+ case BOLT_SECURITY_USBONLY:
+ case BOLT_SECURITY_UNKNOWN:
+ pcie = FALSE;
+ break;
+ }
+
+ return pcie;
+}
+
+BoltPolicy
+bolt_policy_from_string (const char *str)
+{
+ return bolt_enum_from_string (BOLT_TYPE_POLICY, str, NULL);
+}
+
+const char *
+bolt_policy_to_string (BoltPolicy policy)
+{
+ return bolt_enum_to_string (BOLT_TYPE_POLICY, policy, NULL);
+}
+
+gboolean
+bolt_policy_validate (BoltPolicy policy)
+{
+ return bolt_enum_validate (BOLT_TYPE_POLICY, policy, NULL);
+}
+
+BoltDeviceType
+bolt_device_type_from_string (const char *str)
+{
+ return bolt_enum_from_string (BOLT_TYPE_DEVICE_TYPE, str, NULL);
+}
+
+const char *
+bolt_device_type_to_string (BoltDeviceType type)
+{
+ return bolt_enum_to_string (BOLT_TYPE_DEVICE_TYPE, type, NULL);
+}
+
+gboolean
+bolt_device_type_validate (BoltDeviceType type)
+{
+ return bolt_enum_validate (BOLT_TYPE_DEVICE_TYPE, type, NULL);
+}
+
+gboolean
+bolt_device_type_is_host (BoltDeviceType type)
+{
+ return type == BOLT_DEVICE_HOST;
+}
diff --git a/panels/thunderbolt/bolt-enums.h b/panels/thunderbolt/bolt-enums.h
new file mode 100644
index 0000000..6e2953f
--- /dev/null
+++ b/panels/thunderbolt/bolt-enums.h
@@ -0,0 +1,249 @@
+/*
+ * Copyright © 2017 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Christian J. Kellner <christian@kellner.me>
+ */
+
+#pragma once
+
+#include "bolt-names.h"
+#include "bolt-enum-types.h"
+
+
+gboolean bolt_enum_validate (GType enum_type,
+ gint value,
+ GError **error);
+
+gboolean bolt_enum_class_validate (GEnumClass *enum_class,
+ gint value,
+ GError **error);
+
+const char * bolt_enum_to_string (GType enum_type,
+ gint value,
+ GError **error);
+
+gint bolt_enum_from_string (GType enum_type,
+ const char *string,
+ GError **error);
+
+
+char * bolt_flags_class_to_string (GFlagsClass *flags_class,
+ guint value,
+ GError **error);
+
+gboolean bolt_flags_class_from_string (GFlagsClass *flags_class,
+ const char *string,
+ guint *flags_out,
+ GError **error);
+
+char * bolt_flags_to_string (GType flags_type,
+ guint value,
+ GError **error);
+
+gboolean bolt_flags_from_string (GType flags_type,
+ const char *string,
+ guint *flags_out,
+ GError **error);
+
+gboolean bolt_flags_update (guint from,
+ guint *to,
+ guint mask);
+
+#define bolt_flag_isset(flags_, flag_) (!!(flags_ & flag_))
+#define bolt_flag_isclear(flags_, flag_) (!(flags_ & flag_))
+
+/**
+ * BoltStatus:
+ * @BOLT_STATUS_UNKNOWN: Device is in an unknown state (should normally not happen).
+ * @BOLT_STATUS_DISCONNECTED: Device is not connected.
+ * @BOLT_STATUS_CONNECTING: Device is currently being connected.
+ * @BOLT_STATUS_CONNECTED: Device is connected, but not authorized.
+ * @BOLT_STATUS_AUTHORIZING: Device is currently authorizing.
+ * @BOLT_STATUS_AUTH_ERROR: Failed to authorize a device via a key.
+ * @BOLT_STATUS_AUTHORIZED: Device connected and authorized.
+ * @BOLT_STATUS_AUTHORIZED_SECURE: Device connected and securely authorized via a key (deprecated).
+ * @BOLT_STATUS_AUTHORIZED_NEWKEY: Device connected and authorized via a new key (deprecated).
+ * @BOLT_STATUS_AUTHORIZED_DPONLY: Device authorized but with thunderbolt disabled (deprecated).
+ *
+ * The current status of the device.
+ */
+typedef enum {
+
+ BOLT_STATUS_UNKNOWN = -1,
+ BOLT_STATUS_DISCONNECTED = 0,
+ BOLT_STATUS_CONNECTING,
+ BOLT_STATUS_CONNECTED,
+ BOLT_STATUS_AUTHORIZING,
+ BOLT_STATUS_AUTH_ERROR,
+ BOLT_STATUS_AUTHORIZED,
+
+ /* deprecated, do not use */
+ BOLT_STATUS_AUTHORIZED_SECURE,
+ BOLT_STATUS_AUTHORIZED_NEWKEY,
+ BOLT_STATUS_AUTHORIZED_DPONLY
+
+} BoltStatus;
+
+const char * bolt_status_to_string (BoltStatus status);
+gboolean bolt_status_is_authorized (BoltStatus status);
+gboolean bolt_status_is_connected (BoltStatus status);
+gboolean bolt_status_is_pending (BoltStatus status);
+gboolean bolt_status_validate (BoltStatus status);
+
+/**
+ * BoltAuthFlags:
+ * @BOLT_AUTH_NONE: No specific authorization.
+ * @BOLT_AUTH_NOPCIE: PCIe tunnels are *not* authorized.
+ * @BOLT_AUTH_SECURE: Device is securely authorized.
+ * @BOLT_AUTH_NOKEY: Device does *not* support key verification.
+ * @BOLT_AUTH_BOOT: Device was already authorized during pre-boot.
+ *
+ * More specific information about device authorization.
+ */
+typedef enum { /*< flags >*/
+
+ BOLT_AUTH_NONE = 0,
+ BOLT_AUTH_NOPCIE = 1 << 0,
+ BOLT_AUTH_SECURE = 1 << 1,
+ BOLT_AUTH_NOKEY = 1 << 2,
+ BOLT_AUTH_BOOT = 1 << 3,
+
+} BoltAuthFlags;
+
+/**
+ * BoltKeyState:
+ * @BOLT_KEY_UNKNOWN: unknown key state
+ * @BOLT_KEY_MISSING: no key
+ * @BOLT_KEY_HAVE: key exists
+ * @BOLT_KEY_NEW: key is new
+ *
+ * The state of the key.
+ */
+
+typedef enum {
+
+ BOLT_KEY_UNKNOWN = -1,
+ BOLT_KEY_MISSING = 0,
+ BOLT_KEY_HAVE = 1,
+ BOLT_KEY_NEW = 2
+
+} BoltKeyState;
+
+/**
+ * BoltSecurity:
+ * @BOLT_SECURITY_UNKNOWN : Unknown security.
+ * @BOLT_SECURITY_NONE : No security, all devices are automatically connected.
+ * @BOLT_SECURITY_DPONLY : Display Port only devices only.
+ * @BOLT_SECURITY_USER : User needs to authorize devices.
+ * @BOLT_SECURITY_SECURE : User needs to authorize devices. Authorization can
+ * be done via key exchange to verify the device identity.
+ * @BOLT_SECURITY_USBONLY : Only create a PCIe tunnel to the USB controller in a
+ * connected thunderbolt dock, allowing no downstream PCIe tunnels.
+ *
+ * The security level of the thunderbolt domain.
+ */
+typedef enum {
+
+ BOLT_SECURITY_UNKNOWN = -1,
+ BOLT_SECURITY_NONE = 0,
+ BOLT_SECURITY_DPONLY = 1,
+ BOLT_SECURITY_USER = '1',
+ BOLT_SECURITY_SECURE = '2',
+ BOLT_SECURITY_USBONLY = 4,
+
+} BoltSecurity;
+
+
+BoltSecurity bolt_security_from_string (const char *str);
+const char * bolt_security_to_string (BoltSecurity security);
+gboolean bolt_security_validate (BoltSecurity security);
+gboolean bolt_security_allows_pcie (BoltSecurity security);
+
+/**
+ * BoltPolicy:
+ * @BOLT_POLICY_UNKNOWN: Unknown policy.
+ * @BOLT_POLICY_DEFAULT: Default policy.
+ * @BOLT_POLICY_MANUAL: Manual authorization of the device.
+ * @BOLT_POLICY_AUTO: Connect the device automatically,
+ * with the best possible security level supported
+ * by the domain controller.
+ *
+ * What do to for connected devices.
+ */
+typedef enum {
+
+ BOLT_POLICY_UNKNOWN = -1,
+ BOLT_POLICY_DEFAULT = 0,
+ BOLT_POLICY_MANUAL = 1,
+ BOLT_POLICY_AUTO = 2,
+
+} BoltPolicy;
+
+
+BoltPolicy bolt_policy_from_string (const char *str);
+const char * bolt_policy_to_string (BoltPolicy policy);
+gboolean bolt_policy_validate (BoltPolicy policy);
+
+/**
+ * BoltAuthCtrl:
+ * @BOLT_AUTHCTRL_NONE: No authorization flags.
+ *
+ * Control authorization.
+ */
+typedef enum { /*< flags >*/
+
+ BOLT_AUTHCTRL_NONE = 0
+
+} BoltAuthCtrl;
+
+/**
+ * BoltDeviceType:
+ * @BOLT_DEVICE_UNKNOWN_TYPE: Unknown device type
+ * @BOLT_DEVICE_HOST: The device representing the host
+ * @BOLT_DEVICE_PERIPHERAL: A generic thunderbolt peripheral
+ *
+ * The type of the device.
+ */
+typedef enum {
+
+ BOLT_DEVICE_UNKNOWN_TYPE = -1,
+ BOLT_DEVICE_HOST = 0,
+ BOLT_DEVICE_PERIPHERAL
+
+} BoltDeviceType;
+
+BoltDeviceType bolt_device_type_from_string (const char *str);
+const char * bolt_device_type_to_string (BoltDeviceType type);
+gboolean bolt_device_type_validate (BoltDeviceType type);
+gboolean bolt_device_type_is_host (BoltDeviceType type);
+
+/**
+ * BoltAuthMode:
+ * @BOLT_AUTH_DISABLED: Authorization is disabled
+ * @BOLT_AUTH_ENABLED: Authorization is enabled.
+ *
+ * Control authorization.
+ */
+typedef enum { /*< flags >*/
+
+ BOLT_AUTH_DISABLED = 0,
+ BOLT_AUTH_ENABLED = 1
+
+} BoltAuthMode;
+
+#define bolt_auth_mode_is_enabled(auth) ((auth & BOLT_AUTH_ENABLED) != 0)
+#define bolt_auth_mode_is_disabled(auth) (!bolt_auth_mode_is_enabled (auth))
diff --git a/panels/thunderbolt/bolt-error.c b/panels/thunderbolt/bolt-error.c
new file mode 100644
index 0000000..37d844e
--- /dev/null
+++ b/panels/thunderbolt/bolt-error.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright © 2017 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Christian J. Kellner <christian@kellner.me>
+ */
+
+#include "config.h"
+
+#include "bolt-error.h"
+
+#include "bolt-names.h"
+
+#include <gio/gio.h>
+
+/**
+ * SECTION:bolt-error
+ * @Title: Error codes
+ *
+ */
+
+static const GDBusErrorEntry bolt_error_entries[] = {
+ {BOLT_ERROR_FAILED, BOLT_DBUS_NAME ".Error.Failed"},
+ {BOLT_ERROR_UDEV, BOLT_DBUS_NAME ".Error.UDev"},
+};
+
+
+GQuark
+bolt_error_quark (void)
+{
+ static volatile gsize quark_volatile = 0;
+
+ g_dbus_error_register_error_domain ("bolt-error-quark",
+ &quark_volatile,
+ bolt_error_entries,
+ G_N_ELEMENTS (bolt_error_entries));
+ return (GQuark) quark_volatile;
+}
+
+gboolean
+bolt_err_notfound (const GError *error)
+{
+ return g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) ||
+ g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT) ||
+ g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND) ||
+ g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND);
+}
+
+gboolean
+bolt_err_exists (const GError *error)
+{
+ return g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS) ||
+ g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_EXIST);
+}
+
+gboolean
+bolt_err_inval (const GError *error)
+{
+ return g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
+}
+
+gboolean
+bolt_err_cancelled (const GError *error)
+{
+ return g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
+}
+
+gboolean
+bolt_error_propagate_stripped (GError **dest,
+ GError **source)
+{
+ GError *src;
+
+ g_return_val_if_fail (source != NULL, FALSE);
+
+ src = *source;
+
+ if (src == NULL)
+ return TRUE;
+
+ if (g_dbus_error_is_remote_error (src))
+ g_dbus_error_strip_remote_error (src);
+
+ g_propagate_error (dest, g_steal_pointer (source));
+ return FALSE;
+}
diff --git a/panels/thunderbolt/bolt-error.h b/panels/thunderbolt/bolt-error.h
new file mode 100644
index 0000000..7d3823d
--- /dev/null
+++ b/panels/thunderbolt/bolt-error.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright © 2017 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Christian J. Kellner <christian@kellner.me>
+ */
+
+#pragma once
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+/**
+ * BoltError:
+ * @BOLT_ERROR_FAILED: Generic error code
+ * @BOLT_ERROR_UDEV: UDev error
+ *
+ * Error codes used inside Bolt.
+ */
+typedef enum {
+ BOLT_ERROR_FAILED = 0,
+ BOLT_ERROR_UDEV,
+ BOLT_ERROR_NOKEY,
+ BOLT_ERROR_BADKEY,
+ BOLT_ERROR_CFG,
+} BoltError;
+
+
+GQuark bolt_error_quark (void);
+#define BOLT_ERROR (bolt_error_quark ())
+
+/* helper function to check for certain error types */
+gboolean bolt_err_notfound (const GError *error);
+gboolean bolt_err_exists (const GError *error);
+gboolean bolt_err_inval (const GError *error);
+gboolean bolt_err_cancelled (const GError *error);
+
+gboolean bolt_error_propagate_stripped (GError **dest,
+ GError **source);
+
+G_END_DECLS
diff --git a/panels/thunderbolt/bolt-names.c b/panels/thunderbolt/bolt-names.c
new file mode 100644
index 0000000..7426b2f
--- /dev/null
+++ b/panels/thunderbolt/bolt-names.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright © 2019 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Christian J. Kellner <christian@kellner.me>
+ */
+
+#include "config.h"
+
+#include "bolt-names.h"
+
+/* Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_" */
+#define DBUS_OPATH_VALID_CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"
+
+char *
+bolt_gen_object_path (const char *base,
+ const char *oid)
+{
+ g_autofree char *id = NULL;
+
+ if (oid)
+ {
+ id = g_strdup (oid);
+ g_strcanon (id, DBUS_OPATH_VALID_CHARS, '_');
+ }
+
+ if (base && id)
+ return g_build_path ("/", "/", base, id, NULL);
+ else if (base)
+ return g_build_path ("/", "/", base, NULL);
+ else if (id)
+ return g_build_path ("/", "/", id, NULL);
+
+ return g_strdup ("/");
+}
diff --git a/panels/thunderbolt/bolt-names.h b/panels/thunderbolt/bolt-names.h
new file mode 100644
index 0000000..460eed5
--- /dev/null
+++ b/panels/thunderbolt/bolt-names.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright © 2018 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Christian J. Kellner <christian@kellner.me>
+ */
+
+#pragma once
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+/* D-Bus API revision (here for the lack of a better place) */
+#define BOLT_DBUS_API_VERSION 1U
+
+/* logging */
+
+#define BOLT_LOG_DOMAIN_UID "BOLT_DOMAIN_UID"
+#define BOLT_LOG_DOMAIN_NAME "BOLT_DOMAIN_NAME"
+
+#define BOLT_LOG_DEVICE_UID "BOLT_DEVICE_UID"
+#define BOLT_LOG_DEVICE_NAME "BOLT_DEVICE_NAME"
+#define BOLT_LOG_DEVICE_STATE "BOLT_DEVICE_STATE"
+
+#define BOLT_LOG_ERROR_DOMAIN "ERROR_DOMAIN"
+#define BOLT_LOG_ERROR_CODE "ERROR_CODE"
+#define BOLT_LOG_ERROR_MESSAGE "ERROR_MESSAGE"
+
+#define BOLT_LOG_TOPIC "BOLT_TOPIC"
+#define BOLT_LOG_VERSION "BOLT_VERSION"
+#define BOLT_LOG_CONTEXT "BOLT_LOG_CONTEXT"
+#define BOLT_LOG_BUG_MARK "BOLT_LOG_BUG"
+
+/* logging - message ids */
+#define BOLT_LOG_MSG_IDLEN 33
+#define BOLT_LOG_MSG_ID_STARTUP "dd11929c788e48bdbb6276fb5f26b08a"
+
+
+/* dbus */
+
+#define BOLT_DBUS_NAME "org.freedesktop.bolt"
+#define BOLT_DBUS_PATH "/org/freedesktop/bolt"
+#define BOLT_DBUS_PATH_DOMAINS BOLT_DBUS_PATH "/domains"
+#define BOLT_DBUS_PATH_DEVICES BOLT_DBUS_PATH "/devices"
+#define BOLT_DBUS_INTERFACE "org.freedesktop.bolt1.Manager"
+
+#define BOLT_DBUS_DEVICE_INTERFACE "org.freedesktop.bolt1.Device"
+#define BOLT_DBUS_DOMAIN_INTERFACE "org.freedesktop.bolt1.Domain"
+#define BOLT_DBUS_POWER_INTERFACE "org.freedesktop.bolt1.Power"
+
+/* other well known names */
+#define INTEL_WMI_THUNDERBOLT_GUID "86CCFD48-205E-4A77-9C48-2021CBEDE341"
+
+/* helper functions */
+
+char * bolt_gen_object_path (const char *path_base,
+ const char *object_id);
+
+G_END_DECLS
diff --git a/panels/thunderbolt/bolt-proxy.c b/panels/thunderbolt/bolt-proxy.c
new file mode 100644
index 0000000..e044c87
--- /dev/null
+++ b/panels/thunderbolt/bolt-proxy.c
@@ -0,0 +1,514 @@
+/*
+ * Copyright © 2017 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Christian J. Kellner <christian@kellner.me>
+ */
+
+#include "bolt-proxy.h"
+
+#include "bolt-enums.h"
+#include "bolt-error.h"
+#include "bolt-names.h"
+#include "bolt-str.h"
+
+static void bolt_proxy_handle_props_changed (GDBusProxy *proxy,
+ GVariant *changed_properties,
+ GStrv invalidated_properties,
+ gpointer user_data);
+
+static void bolt_proxy_handle_dbus_signal (GDBusProxy *proxy,
+ const gchar *sender_name,
+ const gchar *signal_name,
+ GVariant *params,
+ gpointer user_data);
+
+G_DEFINE_TYPE (BoltProxy, bolt_proxy, G_TYPE_DBUS_PROXY);
+
+
+static void
+bolt_proxy_constructed (GObject *object)
+{
+ G_OBJECT_CLASS (bolt_proxy_parent_class)->constructed (object);
+
+ g_signal_connect (object, "g-properties-changed",
+ G_CALLBACK (bolt_proxy_handle_props_changed), object);
+
+ g_signal_connect (object, "g-signal",
+ G_CALLBACK (bolt_proxy_handle_dbus_signal), object);
+}
+
+static const BoltProxySignal *
+bolt_proxy_get_dbus_signals (guint *n)
+{
+ *n = 0;
+ return NULL;
+}
+
+static void
+bolt_proxy_class_init (BoltProxyClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->constructed = bolt_proxy_constructed;
+
+ klass->get_dbus_signals = bolt_proxy_get_dbus_signals;
+
+}
+
+static void
+bolt_proxy_init (BoltProxy *object)
+{
+}
+
+static void
+bolt_proxy_handle_props_changed (GDBusProxy *proxy,
+ GVariant *changed_properties,
+ GStrv invalidated_properties,
+ gpointer user_data)
+{
+ g_autoptr(GVariantIter) iter = NULL;
+ gboolean handled;
+ GParamSpec **pp;
+ const char *key;
+ guint n;
+
+ pp = g_object_class_list_properties (G_OBJECT_GET_CLASS (proxy), &n);
+
+ g_variant_get (changed_properties, "a{sv}", &iter);
+ while (g_variant_iter_next (iter, "{&sv}", &key, NULL))
+ {
+ handled = FALSE;
+ for (guint i = 0; !handled && i < n; i++)
+ {
+ GParamSpec *pspec = pp[i];
+ const char *nick;
+ const char *name;
+
+ nick = g_param_spec_get_nick (pspec);
+ name = g_param_spec_get_name (pspec);
+
+ handled = bolt_streq (nick, key);
+
+ if (handled)
+ g_object_notify (G_OBJECT (user_data), name);
+ }
+ }
+
+ g_free (pp);
+}
+
+static void
+bolt_proxy_handle_dbus_signal (GDBusProxy *proxy,
+ const gchar *sender_name,
+ const gchar *signal_name,
+ GVariant *params,
+ gpointer user_data)
+{
+ const BoltProxySignal *ps;
+ guint n;
+
+ if (signal_name == NULL)
+ return;
+
+ ps = BOLT_PROXY_GET_CLASS (proxy)->get_dbus_signals (&n);
+
+ for (guint i = 0; i < n; i++)
+ {
+ const BoltProxySignal *sig = &ps[i];
+
+ if (g_str_equal (sig->theirs, signal_name))
+ {
+ sig->handle (G_OBJECT (proxy), proxy, params);
+ break;
+ }
+ }
+
+}
+
+/* public methods */
+
+gboolean
+bolt_proxy_get_dbus_property (GObject *proxy,
+ GParamSpec *spec,
+ GValue *value)
+{
+ g_autoptr(GVariant) val = NULL;
+ const GVariantType *vt;
+ gboolean handled = FALSE;
+ const char *nick;
+
+ nick = g_param_spec_get_nick (spec);
+ val = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), nick);
+
+ if (val == NULL)
+ return FALSE;
+
+ vt = g_variant_get_type (val);
+
+ if (g_variant_type_equal (vt, G_VARIANT_TYPE_STRING) &&
+ G_IS_PARAM_SPEC_ENUM (spec))
+ {
+ GParamSpecEnum *enum_spec = G_PARAM_SPEC_ENUM (spec);
+ GEnumValue *ev;
+ const char *str;
+
+ str = g_variant_get_string (val, NULL);
+ ev = g_enum_get_value_by_nick (enum_spec->enum_class, str);
+
+ handled = ev != NULL;
+
+ if (handled)
+ g_value_set_enum (value, ev->value);
+ else
+ g_value_set_enum (value, enum_spec->default_value);
+ }
+ else if (g_variant_type_equal (vt, G_VARIANT_TYPE_STRING) &&
+ G_IS_PARAM_SPEC_FLAGS (spec))
+ {
+ GParamSpecFlags *flags_spec = G_PARAM_SPEC_FLAGS (spec);
+ GFlagsClass *flags_class = flags_spec->flags_class;
+ const char *str;
+ guint v;
+
+ str = g_variant_get_string (val, NULL);
+ handled = bolt_flags_class_from_string (flags_class, str, &v, NULL);
+
+ if (handled)
+ g_value_set_flags (value, v);
+ else
+ g_value_set_flags (value, flags_spec->default_value);
+ }
+ else
+ {
+ g_dbus_gvariant_to_gvalue (val, value);
+ }
+
+ return handled;
+}
+
+gboolean
+bolt_proxy_has_name_owner (BoltProxy *proxy)
+{
+ const char *name_owner;
+
+ g_return_val_if_fail (proxy != NULL, FALSE);
+ g_return_val_if_fail (BOLT_IS_PROXY (proxy), FALSE);
+
+ name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (proxy));
+
+ return name_owner != NULL;
+}
+
+static GParamSpec *
+find_property (BoltProxy *proxy,
+ const char *name,
+ GError **error)
+{
+ GParamSpec *res = NULL;
+ GParamSpec **pp;
+ guint n;
+
+ pp = g_object_class_list_properties (G_OBJECT_GET_CLASS (proxy), &n);
+
+ for (guint i = 0; i < n; i++)
+ {
+ GParamSpec *pspec = pp[i];
+
+ if (bolt_streq (pspec->name, name))
+ {
+ res = pspec;
+ break;
+ }
+ }
+
+ if (pp == NULL)
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_PROPERTY,
+ "could not find property '%s'", name);
+
+ g_free (pp);
+ return res;
+}
+
+static GVariant *
+bolt_proxy_get_cached_property (BoltProxy *proxy,
+ const char *name)
+{
+ const char *bus_name = NULL;
+ GParamSpec *pspec;
+ GVariant *var;
+
+ g_return_val_if_fail (BOLT_IS_PROXY (proxy), NULL);
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (proxy), name);
+
+ if (pspec == NULL)
+ return NULL;
+
+ bus_name = g_param_spec_get_nick (pspec);
+ var = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), bus_name);
+
+ return var;
+}
+
+gboolean
+bolt_proxy_get_property_bool (BoltProxy *proxy,
+ const char *name,
+ gboolean *value)
+{
+ g_autoptr(GVariant) var = NULL;
+
+ var = bolt_proxy_get_cached_property (proxy, name);
+
+ if (var == NULL)
+ return FALSE;
+ else if (value)
+ *value = g_variant_get_boolean (var);
+
+ return TRUE;
+}
+
+gboolean
+bolt_proxy_get_property_enum (BoltProxy *proxy,
+ const char *name,
+ gint *value)
+{
+ g_autoptr(GVariant) var = NULL;
+ const char *str = NULL;
+ const char *bus_name = NULL;
+ GParamSpec *pspec;
+ GEnumValue *ev;
+
+ g_return_val_if_fail (BOLT_IS_PROXY (proxy), FALSE);
+
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (proxy), name);
+
+ if (pspec == NULL)
+ return FALSE;
+
+ bus_name = g_param_spec_get_nick (pspec);
+ var = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), bus_name);
+ if (var == NULL)
+ return FALSE;
+
+ str = g_variant_get_string (var, NULL);
+
+ if (str == NULL)
+ return FALSE;
+
+ ev = g_enum_get_value_by_nick (G_PARAM_SPEC_ENUM (pspec)->enum_class, str);
+
+ if (ev == NULL)
+ return FALSE;
+
+ if (value)
+ *value = ev->value;
+
+ return TRUE;
+}
+
+gboolean
+bolt_proxy_get_property_flags (BoltProxy *proxy,
+ const char *name,
+ guint *value)
+{
+ g_autoptr(GVariant) var = NULL;
+ const char *str = NULL;
+ const char *bus_name = NULL;
+ GFlagsClass *flags_class;
+ GParamSpec *pspec;
+ guint v;
+ gboolean ok;
+
+ g_return_val_if_fail (BOLT_IS_PROXY (proxy), FALSE);
+
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (proxy), name);
+
+ if (pspec == NULL || !G_IS_PARAM_SPEC_FLAGS (pspec))
+ return FALSE;
+
+ bus_name = g_param_spec_get_nick (pspec);
+ var = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), bus_name);
+ if (var == NULL)
+ return FALSE;
+
+ str = g_variant_get_string (var, NULL);
+
+ if (str == NULL)
+ return FALSE;
+
+ flags_class = G_PARAM_SPEC_FLAGS (pspec)->flags_class;
+ ok = bolt_flags_class_from_string (flags_class, str, &v, NULL);
+
+ if (ok && value)
+ *value = v;
+
+ return ok;
+}
+
+gboolean
+bolt_proxy_get_property_uint32 (BoltProxy *proxy,
+ const char *name,
+ guint *value)
+{
+ g_autoptr(GVariant) var = NULL;
+
+ var = bolt_proxy_get_cached_property (proxy, name);
+
+ if (var == NULL)
+ return FALSE;
+ else if (value)
+ *value = g_variant_get_uint32 (var);
+
+ return TRUE;
+}
+
+gboolean
+bolt_proxy_get_property_int64 (BoltProxy *proxy,
+ const char *name,
+ gint64 *value)
+{
+ g_autoptr(GVariant) var = NULL;
+
+ var = bolt_proxy_get_cached_property (proxy, name);
+
+ if (var == NULL)
+ return FALSE;
+ else if (value)
+ *value = g_variant_get_int64 (var);
+
+ return TRUE;
+}
+
+gboolean
+bolt_proxy_get_property_uint64 (BoltProxy *proxy,
+ const char *name,
+ guint64 *value)
+{
+ g_autoptr(GVariant) var = NULL;
+
+ var = bolt_proxy_get_cached_property (proxy, name);
+
+ if (var == NULL)
+ return FALSE;
+ else if (value)
+ *value = g_variant_get_uint64 (var);
+
+ return TRUE;
+}
+
+const char *
+bolt_proxy_get_property_string (BoltProxy *proxy,
+ const char *name)
+{
+ g_autoptr(GVariant) var = NULL;
+ const char *val = NULL;
+
+ var = bolt_proxy_get_cached_property (proxy, name);
+
+ if (var != NULL)
+ val = g_variant_get_string (var, NULL);
+
+ if (val && *val == '\0')
+ val = NULL;
+
+ return val;
+}
+
+gboolean
+bolt_proxy_set_property (BoltProxy *proxy,
+ const char *name,
+ GVariant *value,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GParamSpec *pp;
+ const char *iface;
+ gboolean ok = FALSE;
+ GVariant *res;
+
+ pp = find_property (proxy, name, NULL);
+ if (pp != NULL)
+ name = g_param_spec_get_nick (pp);
+
+ iface = g_dbus_proxy_get_interface_name (G_DBUS_PROXY (proxy));
+
+ res = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "org.freedesktop.DBus.Properties.Set",
+ g_variant_new ("(ssv)",
+ iface,
+ name,
+ value),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+
+ if (res)
+ {
+ g_variant_unref (res);
+ ok = TRUE;
+ }
+
+ return ok;
+}
+
+void
+bolt_proxy_set_property_async (BoltProxy *proxy,
+ const char *name,
+ GVariant *value,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GParamSpec *pp;
+ const char *iface;
+
+ pp = find_property (proxy, name, NULL);
+
+ if (pp != NULL)
+ name = g_param_spec_get_nick (pp);
+
+ iface = g_dbus_proxy_get_interface_name (G_DBUS_PROXY (proxy));
+
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "org.freedesktop.DBus.Properties.Set",
+ g_variant_new ("(ssv)",
+ iface,
+ name,
+ value),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+gboolean
+bolt_proxy_set_property_finish (GAsyncResult *res,
+ GError **error)
+{
+ BoltProxy *proxy;
+ GVariant *val = NULL;
+
+ proxy = (BoltProxy *) g_async_result_get_source_object (res);
+ val = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+
+ if (val == NULL)
+ return FALSE;
+
+ g_variant_unref (val);
+ return TRUE;
+}
diff --git a/panels/thunderbolt/bolt-proxy.h b/panels/thunderbolt/bolt-proxy.h
new file mode 100644
index 0000000..c05eb8c
--- /dev/null
+++ b/panels/thunderbolt/bolt-proxy.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright © 2017 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Christian J. Kellner <christian@kellner.me>
+ */
+
+#pragma once
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+typedef struct BoltProxySignal
+{
+
+ const char *theirs;
+ void (*handle)(GObject *self,
+ GDBusProxy *bus_proxy,
+ GVariant *params);
+
+} BoltProxySignal;
+
+#define BOLT_TYPE_PROXY (bolt_proxy_get_type ())
+G_DECLARE_DERIVABLE_TYPE (BoltProxy, bolt_proxy, BOLT, PROXY, GDBusProxy)
+
+struct _BoltProxyClass
+{
+ GDBusProxyClass parent;
+
+ /* virtuals */
+ const BoltProxySignal * (*get_dbus_signals) (guint *n);
+};
+
+gboolean bolt_proxy_get_dbus_property (GObject *proxy,
+ GParamSpec *spec,
+ GValue *value);
+
+gboolean bolt_proxy_has_name_owner (BoltProxy *proxy);
+
+gboolean bolt_proxy_get_property_bool (BoltProxy *proxy,
+ const char *name,
+ gboolean *value);
+
+gboolean bolt_proxy_get_property_enum (BoltProxy *proxy,
+ const char *name,
+ gint *value);
+
+gboolean bolt_proxy_get_property_flags (BoltProxy *proxy,
+ const char *name,
+ guint *value);
+
+gboolean bolt_proxy_get_property_uint32 (BoltProxy *proxy,
+ const char *name,
+ guint *value);
+
+gboolean bolt_proxy_get_property_int64 (BoltProxy *proxy,
+ const char *name,
+ gint64 *value);
+
+gboolean bolt_proxy_get_property_uint64 (BoltProxy *proxy,
+ const char *name,
+ guint64 *value);
+
+const char * bolt_proxy_get_property_string (BoltProxy *proxy,
+ const char *name);
+
+gboolean bolt_proxy_set_property (BoltProxy *proxy,
+ const char *name,
+ GVariant *value,
+ GCancellable *cancellable,
+ GError **error);
+
+void bolt_proxy_set_property_async (BoltProxy *proxy,
+ const char *name,
+ GVariant *value,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean bolt_proxy_set_property_finish (GAsyncResult *res,
+ GError **error);
+
+G_END_DECLS
diff --git a/panels/thunderbolt/bolt-str.c b/panels/thunderbolt/bolt-str.c
new file mode 100644
index 0000000..fe0580d
--- /dev/null
+++ b/panels/thunderbolt/bolt-str.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright © 2017 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Christian J. Kellner <christian@kellner.me>
+ */
+
+#include "config.h"
+
+#include "bolt-str.h"
+
+#include <string.h>
+
+typedef void (* zero_fn_t) (void *s,
+ size_t n);
+void
+bolt_erase_n (void *data, gsize n)
+{
+#if !HAVE_FN_EXPLICIT_BZERO
+ #warning no explicit bzero, using fallback
+ static volatile zero_fn_t explicit_bzero = bzero;
+#endif
+
+ explicit_bzero (data, n);
+}
+
+void
+bolt_str_erase (char *str)
+{
+ if (str == NULL)
+ return;
+
+ bolt_erase_n (str, strlen (str));
+}
+
+void
+bolt_str_erase_clear (char **str)
+{
+ g_return_if_fail (str != NULL);
+ if (*str == NULL)
+ return;
+
+ bolt_str_erase (*str);
+ g_free (*str);
+ *str = NULL;
+}
+
+GStrv
+bolt_strv_from_ptr_array (GPtrArray **array)
+{
+ GPtrArray *a;
+
+ if (array == NULL || *array == NULL)
+ return NULL;
+
+ a = *array;
+
+ if (a->len == 0 || a->pdata[a->len - 1] != NULL)
+ g_ptr_array_add (a, NULL);
+
+ *array = NULL;
+ return (GStrv) g_ptr_array_free (a, FALSE);
+}
+
+char *
+bolt_strdup_validate (const char *string)
+{
+ g_autofree char *str = NULL;
+ gboolean ok;
+ gsize l;
+
+ if (string == NULL)
+ return NULL;
+
+ str = g_strdup (string);
+ str = g_strstrip (str);
+
+ l = strlen (str);
+ if (l == 0)
+ return NULL;
+
+ ok = g_utf8_validate (str, l, NULL);
+
+ if (!ok)
+ return NULL;
+
+ return g_steal_pointer (&str);
+}
+
+char *
+bolt_strstrip (char *string)
+{
+ char *str;
+
+ if (string == NULL)
+ return NULL;
+
+ str = g_strstrip (string);
+
+ if (strlen (str) == 0)
+ g_clear_pointer (&str, g_free);
+
+ return str;
+}
diff --git a/panels/thunderbolt/bolt-str.h b/panels/thunderbolt/bolt-str.h
new file mode 100644
index 0000000..ecf95a7
--- /dev/null
+++ b/panels/thunderbolt/bolt-str.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright © 2017 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Christian J. Kellner <christian@kellner.me>
+ */
+
+#pragma once
+
+#include <glib.h>
+#include <string.h>
+
+G_BEGIN_DECLS
+
+void bolt_erase_n (void *data,
+ gsize n);
+void bolt_str_erase (char *str);
+void bolt_str_erase_clear (char **str);
+
+#define bolt_streq(s1, s2) (g_strcmp0 (s1, s2) == 0)
+
+GStrv bolt_strv_from_ptr_array (GPtrArray **array);
+
+#define bolt_yesno(val) val ? "yes" : "no"
+
+char *bolt_strdup_validate (const char *string);
+
+char *bolt_strstrip (char *string);
+
+G_END_DECLS
diff --git a/panels/thunderbolt/bolt-time.c b/panels/thunderbolt/bolt-time.c
new file mode 100644
index 0000000..606aed6
--- /dev/null
+++ b/panels/thunderbolt/bolt-time.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2018 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Christian J. Kellner <christian@kellner.me>
+ */
+
+#include "config.h"
+
+#include "bolt-time.h"
+
+char *
+bolt_epoch_format (guint64 seconds, const char *format)
+{
+ g_autoptr(GDateTime) dt = NULL;
+
+ dt = g_date_time_new_from_unix_utc ((gint64) seconds);
+
+ if (dt == NULL)
+ return NULL;
+
+ return g_date_time_format (dt, format);
+}
+
+guint64
+bolt_now_in_seconds (void)
+{
+ gint64 now = g_get_real_time ();
+
+ return (guint64) now / G_USEC_PER_SEC;
+}
diff --git a/panels/thunderbolt/bolt-time.h b/panels/thunderbolt/bolt-time.h
new file mode 100644
index 0000000..fc3ed97
--- /dev/null
+++ b/panels/thunderbolt/bolt-time.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2018 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Christian J. Kellner <christian@kellner.me>
+ */
+
+#pragma once
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+char * bolt_epoch_format (guint64 seconds,
+ const char *format);
+
+guint64 bolt_now_in_seconds (void);
+
+G_END_DECLS
diff --git a/panels/thunderbolt/cc-bolt-device-dialog.c b/panels/thunderbolt/cc-bolt-device-dialog.c
new file mode 100644
index 0000000..bfe52b7
--- /dev/null
+++ b/panels/thunderbolt/cc-bolt-device-dialog.c
@@ -0,0 +1,515 @@
+/* Copyright (C) 2018 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Christian J. Kellner <ckellner@redhat.com>
+ *
+ */
+
+#include <config.h>
+
+#include <glib/gi18n.h>
+
+#include "bolt-device.h"
+#include "bolt-error.h"
+#include "bolt-time.h"
+
+#include "cc-thunderbolt-resources.h"
+
+#include "cc-bolt-device-dialog.h"
+#include "cc-bolt-device-entry.h"
+
+struct _CcBoltDeviceDialog
+{
+ GtkDialog parent;
+
+ BoltClient *client;
+ BoltDevice *device;
+ GCancellable *cancel;
+
+ /* main ui */
+ GtkHeaderBar *header_bar;
+
+ /* notifications */
+ GtkLabel *notify_label;
+ GtkRevealer *notify_revealer;
+
+ /* device details */
+ GtkLabel *name_label;
+ GtkLabel *status_label;
+ GtkLabel *uuid_label;
+
+ GtkLabel *time_title;
+ GtkLabel *time_label;
+
+ /* parents */
+ GtkExpander *parents_expander;
+ GtkLabel *parents_label;
+ GtkListBox *parents_devices;
+
+ /* actions */
+ GtkWidget *button_box;
+ GtkSpinner *spinner;
+ GtkButton *connect_button;
+ GtkButton *forget_button;
+};
+
+static void on_notify_button_clicked_cb (GtkButton *button,
+ CcBoltDeviceDialog *panel);
+
+static void on_forget_button_clicked_cb (CcBoltDeviceDialog *dialog);
+static void on_connect_button_clicked_cb (CcBoltDeviceDialog *dialog);
+
+G_DEFINE_TYPE (CcBoltDeviceDialog, cc_bolt_device_dialog, GTK_TYPE_DIALOG);
+
+#define RESOURCE_UI "/org/gnome/control-center/thunderbolt/cc-bolt-device-dialog.ui"
+
+static const char *
+status_to_string_for_ui (BoltDevice *dev)
+{
+ BoltStatus status;
+ BoltAuthFlags aflags;
+ gboolean nopcie;
+
+ status = bolt_device_get_status (dev);
+ aflags = bolt_device_get_authflags(dev);
+ nopcie = bolt_flag_isset (aflags, BOLT_AUTH_NOPCIE);
+
+ switch (status)
+ {
+ case BOLT_STATUS_DISCONNECTED:
+ return C_("Thunderbolt Device Status", "Disconnected");
+
+ case BOLT_STATUS_CONNECTING:
+ return C_("Thunderbolt Device Status", "Connecting");
+
+ case BOLT_STATUS_CONNECTED:
+ return C_("Thunderbolt Device Status", "Connected");
+
+ case BOLT_STATUS_AUTH_ERROR:
+ return C_("Thunderbolt Device Status", "Authorization Error");
+
+ case BOLT_STATUS_AUTHORIZING:
+ return C_("Thunderbolt Device Status", "Authorizing");
+
+ case BOLT_STATUS_AUTHORIZED:
+ case BOLT_STATUS_AUTHORIZED_NEWKEY:
+ case BOLT_STATUS_AUTHORIZED_SECURE:
+ case BOLT_STATUS_AUTHORIZED_DPONLY:
+ if (nopcie)
+ return C_("Thunderbolt Device Status", "Reduced Functionality");
+ else
+ return C_("Thunderbolt Device Status", "Connected & Authorized");
+
+ case BOLT_STATUS_UNKNOWN:
+ break; /* use default return value, i.e. Unknown */
+ }
+
+ return C_("Thunderbolt Device Status", "Unknown");
+}
+
+static void
+dialog_update_from_device (CcBoltDeviceDialog *dialog)
+{
+ g_autofree char *generated = NULL;
+ g_autofree char *timestr = NULL;
+ const char *label;
+ const char *uuid;
+ const char *status_brief;
+ BoltStatus status;
+ gboolean stored;
+ BoltDevice *dev;
+ guint timestamp;
+
+ if (gtk_widget_in_destruction (GTK_WIDGET (dialog)))
+ return;
+
+ dev = dialog->device;
+
+ uuid = bolt_device_get_uid (dev);
+ label = bolt_device_get_label (dev);
+
+ stored = bolt_device_is_stored (dev);
+ status = bolt_device_get_status (dev);
+
+ if (label == NULL)
+ {
+ const char *name = bolt_device_get_name (dev);
+ const char *vendor = bolt_device_get_vendor (dev);
+
+ generated = g_strdup_printf ("%s %s", name, vendor);
+ label = generated;
+ }
+
+ gtk_label_set_label (dialog->name_label, label);
+ gtk_window_set_title (GTK_WINDOW (dialog), label);
+
+ status_brief = status_to_string_for_ui (dev);
+ gtk_label_set_label (dialog->status_label, status_brief);
+ gtk_widget_set_visible (GTK_WIDGET (dialog->forget_button), stored);
+
+ /* while we are having an ongoing operation we are setting the buttons
+ * to be in-sensitive. In that case, if the button was visible
+ * before it will be hidden when the operation is finished by the
+ * dialog_operation_done() function */
+ if (gtk_widget_is_sensitive (GTK_WIDGET (dialog->connect_button)))
+ gtk_widget_set_visible (GTK_WIDGET (dialog->connect_button),
+ status == BOLT_STATUS_CONNECTED);
+
+ gtk_label_set_label (dialog->uuid_label, uuid);
+
+ if (bolt_status_is_authorized (status))
+ {
+ /* Translators: The time point the device was authorized. */
+ gtk_label_set_label (dialog->time_title, _("Authorized at:"));
+ timestamp = bolt_device_get_authtime (dev);
+ }
+ else if (bolt_status_is_connected (status))
+ {
+ /* Translators: The time point the device was connected. */
+ gtk_label_set_label (dialog->time_title, _("Connected at:"));
+ timestamp = bolt_device_get_conntime (dev);
+ }
+ else
+ {
+ /* Translators: The time point the device was enrolled,
+ * i.e. authorized and stored in the device database. */
+ gtk_label_set_label (dialog->time_title, _("Enrolled at:"));
+ timestamp = bolt_device_get_storetime (dev);
+ }
+
+ timestr = bolt_epoch_format (timestamp, "%c");
+ gtk_label_set_label (dialog->time_label, timestr);
+
+}
+
+static void
+on_device_notify_cb (GObject *gobject,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ CcBoltDeviceDialog *dialog = CC_BOLT_DEVICE_DIALOG (user_data);
+
+ dialog_update_from_device (dialog);
+}
+
+static void
+dialog_operation_start (CcBoltDeviceDialog *dialog)
+{
+ gtk_widget_set_sensitive (GTK_WIDGET (dialog->connect_button), FALSE);
+ gtk_widget_set_sensitive (GTK_WIDGET (dialog->forget_button), FALSE);
+ gtk_spinner_start (dialog->spinner);
+}
+
+static void
+dialog_operation_done (CcBoltDeviceDialog *dialog,
+ GtkWidget *sender,
+ GError *error)
+{
+ GtkWidget *cb = GTK_WIDGET (dialog->connect_button);
+ GtkWidget *fb = GTK_WIDGET (dialog->forget_button);
+
+ /* don' do anything if we are being destroyed */
+ if (gtk_widget_in_destruction (GTK_WIDGET (dialog)))
+ return;
+
+ /* also don't do anything if the op was canceled */
+ if (error != NULL && bolt_err_cancelled (error))
+ return;
+
+ gtk_spinner_stop (dialog->spinner);
+
+ if (error != NULL)
+ {
+ gtk_label_set_label (dialog->notify_label, error->message);
+ gtk_revealer_set_reveal_child (dialog->notify_revealer, TRUE);
+
+ /* set the *other* button to sensitive */
+ gtk_widget_set_sensitive (cb, cb != sender);
+ gtk_widget_set_sensitive (fb, fb != sender);
+ }
+ else
+ {
+ gtk_widget_set_visible (sender, FALSE);
+ gtk_widget_set_sensitive (cb, TRUE);
+ gtk_widget_set_sensitive (fb, TRUE);
+ }
+}
+
+static void
+on_connect_all_done (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) err = NULL;
+ CcBoltDeviceDialog *dialog = CC_BOLT_DEVICE_DIALOG (user_data);
+ gboolean ok;
+
+ ok = bolt_client_connect_all_finish (dialog->client, res, &err);
+
+ if (!ok)
+ g_prefix_error (&err, _("Failed to authorize device: "));
+
+ dialog_operation_done (dialog, GTK_WIDGET (dialog->connect_button), err);
+}
+
+static void
+on_connect_button_clicked_cb (CcBoltDeviceDialog *dialog)
+{
+ g_autoptr(GPtrArray) devices = NULL;
+ BoltDevice *device = dialog->device;
+ GtkWidget *child;
+
+ g_return_if_fail (device != NULL);
+
+ dialog_operation_start (dialog);
+
+ devices = g_ptr_array_new ();
+
+ /* Iter from the last child to the first one */
+ for (child = gtk_widget_get_last_child (GTK_WIDGET (dialog->parents_devices));
+ child;
+ child = gtk_widget_get_prev_sibling (child))
+ {
+ CcBoltDeviceEntry *entry;
+ BoltDevice *dev;
+ BoltStatus status;
+
+ entry = CC_BOLT_DEVICE_ENTRY (child);
+ dev = cc_bolt_device_entry_get_device (entry);
+ status = bolt_device_get_status (dev);
+
+ /* skip any devices down in the chain that are already authorized
+ * NB: it is not possible to have gaps of non-authorized devices
+ * in the chain, i.e. once we encounter a non-authorized device,
+ * all following device (down the chain, towards the target) will
+ * also be not authorized. */
+ if (!bolt_status_is_pending (status))
+ continue;
+
+ /* device is now either !stored || pending */
+ g_ptr_array_add (devices, dev);
+ }
+
+ /* finally the actual device of the dialog */
+ g_ptr_array_add (devices, device);
+
+ bolt_client_connect_all_async (dialog->client,
+ devices,
+ BOLT_POLICY_DEFAULT,
+ BOLT_AUTHCTRL_NONE,
+ dialog->cancel,
+ on_connect_all_done,
+ dialog);
+}
+
+static void
+on_forget_device_done (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) err = NULL;
+ CcBoltDeviceDialog *dialog = CC_BOLT_DEVICE_DIALOG (user_data);
+ gboolean ok;
+
+ ok = bolt_client_forget_device_finish (dialog->client, res, &err);
+
+ if (!ok)
+ g_prefix_error (&err, _("Failed to forget device: "));
+
+ dialog_operation_done (dialog, GTK_WIDGET (dialog->forget_button), err);
+}
+
+static void
+on_forget_button_clicked_cb (CcBoltDeviceDialog *dialog)
+{
+ const char *uid = NULL;
+
+ g_return_if_fail (dialog->device != NULL);
+
+ uid = bolt_device_get_uid (dialog->device);
+ dialog_operation_start (dialog);
+
+ bolt_client_forget_device_async (dialog->client,
+ uid,
+ dialog->cancel,
+ on_forget_device_done,
+ dialog);
+}
+
+static void
+on_notify_button_clicked_cb (GtkButton *button,
+ CcBoltDeviceDialog *dialog)
+{
+ gtk_revealer_set_reveal_child (dialog->notify_revealer, FALSE);
+}
+
+
+static void
+cc_bolt_device_dialog_finalize (GObject *object)
+{
+ CcBoltDeviceDialog *dialog = CC_BOLT_DEVICE_DIALOG (object);
+
+ g_clear_object (&dialog->device);
+ g_cancellable_cancel (dialog->cancel);
+ g_clear_object (&dialog->cancel);
+ g_clear_object (&dialog->client);
+
+ G_OBJECT_CLASS (cc_bolt_device_dialog_parent_class)->finalize (object);
+}
+
+static void
+cc_bolt_device_dialog_class_init (CcBoltDeviceDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = cc_bolt_device_dialog_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, RESOURCE_UI);
+ gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, header_bar);
+
+ gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, notify_label);
+ gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, notify_revealer);
+
+ gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, name_label);
+ gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, status_label);
+
+ gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, uuid_label);
+ gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, time_title);
+ gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, time_label);
+
+ gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, parents_expander);
+ gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, parents_label);
+ gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, parents_devices);
+
+ gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, button_box);
+ gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, spinner);
+ gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, connect_button);
+ gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceDialog, forget_button);
+
+ gtk_widget_class_bind_template_callback (widget_class, on_notify_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_connect_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_forget_button_clicked_cb);
+}
+
+static void
+cc_bolt_device_dialog_init (CcBoltDeviceDialog *dialog)
+{
+ g_resources_register (cc_thunderbolt_get_resource ());
+ gtk_widget_init_template (GTK_WIDGET (dialog));
+}
+
+/* public functions */
+CcBoltDeviceDialog *
+cc_bolt_device_dialog_new (void)
+{
+ CcBoltDeviceDialog *dialog;
+
+ dialog = g_object_new (CC_TYPE_BOLT_DEVICE_DIALOG,
+ "use-header-bar", TRUE,
+ NULL);
+ return dialog;
+}
+
+void
+cc_bolt_device_dialog_set_client (CcBoltDeviceDialog *dialog,
+ BoltClient *client)
+{
+ g_clear_object (&dialog->client);
+ dialog->client = g_object_ref (client);
+}
+
+void
+cc_bolt_device_dialog_set_device (CcBoltDeviceDialog *dialog,
+ BoltDevice *device,
+ GPtrArray *parents)
+{
+ g_autofree char *msg = NULL;
+ guint i;
+
+ if (device == dialog->device)
+ return;
+
+ if (dialog->device)
+ {
+ GtkWidget *child;
+
+ g_cancellable_cancel (dialog->cancel);
+ g_clear_object (&dialog->cancel);
+ dialog->cancel = g_cancellable_new ();
+
+ g_signal_handlers_disconnect_by_func (dialog->device,
+ G_CALLBACK (on_device_notify_cb),
+ dialog);
+ g_clear_object (&dialog->device);
+
+ while ((child = gtk_widget_get_first_child (GTK_WIDGET (dialog->parents_devices))) != NULL)
+ gtk_list_box_remove (dialog->parents_devices, child);
+
+ gtk_widget_hide (GTK_WIDGET (dialog->parents_expander));
+ }
+
+ if (device == NULL)
+ return;
+
+ dialog->device = g_object_ref (device);
+ g_signal_connect_object (dialog->device,
+ "notify",
+ G_CALLBACK (on_device_notify_cb),
+ dialog,
+ 0);
+
+ /* reset the sensitivity of the buttons, because
+ * dialog_update_from_device, because it can't know */
+ gtk_widget_set_sensitive (GTK_WIDGET (dialog->connect_button), TRUE);
+ gtk_widget_set_sensitive (GTK_WIDGET (dialog->forget_button), TRUE);
+
+ dialog_update_from_device (dialog);
+
+ /* no parents, we are done here */
+ if (!parents || parents->len == 0)
+ return;
+
+ msg = g_strdup_printf (ngettext ("Depends on %u other device",
+ "Depends on %u other devices",
+ parents->len), parents->len);
+
+ gtk_label_set_label (dialog->parents_label, msg);
+ gtk_widget_show (GTK_WIDGET (dialog->parents_expander));
+
+ for (i = 0; i < parents->len; i++)
+ {
+ CcBoltDeviceEntry *entry;
+ BoltDevice *parent;
+
+ parent = g_ptr_array_index (parents, i);
+
+ entry = cc_bolt_device_entry_new (parent, TRUE);
+ gtk_list_box_append (dialog->parents_devices, GTK_WIDGET (entry));
+ }
+}
+
+BoltDevice *
+cc_bolt_device_dialog_peek_device (CcBoltDeviceDialog *dialog)
+{
+ return dialog->device;
+}
+
+gboolean
+cc_bolt_device_dialog_device_equal (CcBoltDeviceDialog *dialog,
+ BoltDevice *device)
+{
+ return dialog->device != NULL && device == dialog->device;
+}
diff --git a/panels/thunderbolt/cc-bolt-device-dialog.h b/panels/thunderbolt/cc-bolt-device-dialog.h
new file mode 100644
index 0000000..abdb46f
--- /dev/null
+++ b/panels/thunderbolt/cc-bolt-device-dialog.h
@@ -0,0 +1,47 @@
+/* Copyright (C) 2018 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Christian J. Kellner <ckellner@redhat.com>
+ *
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "bolt-client.h"
+#include "bolt-device.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_BOLT_DEVICE_DIALOG cc_bolt_device_dialog_get_type ()
+
+G_DECLARE_FINAL_TYPE (CcBoltDeviceDialog, cc_bolt_device_dialog, CC, BOLT_DEVICE_DIALOG, GtkDialog);
+
+CcBoltDeviceDialog * cc_bolt_device_dialog_new (void);
+
+void cc_bolt_device_dialog_set_client (CcBoltDeviceDialog *dialog,
+ BoltClient *client);
+
+void cc_bolt_device_dialog_set_device (CcBoltDeviceDialog *dialog,
+ BoltDevice *device,
+ GPtrArray *parents);
+
+BoltDevice * cc_bolt_device_dialog_peek_device (CcBoltDeviceDialog *dialog);
+
+gboolean cc_bolt_device_dialog_device_equal (CcBoltDeviceDialog *dialog,
+ BoltDevice *device);
+
+G_END_DECLS
diff --git a/panels/thunderbolt/cc-bolt-device-dialog.ui b/panels/thunderbolt/cc-bolt-device-dialog.ui
new file mode 100644
index 0000000..55dff88
--- /dev/null
+++ b/panels/thunderbolt/cc-bolt-device-dialog.ui
@@ -0,0 +1,325 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
+<interface>
+ <requires lib="gtk+" version="3.20"/>
+ <template class="CcBoltDeviceDialog" parent="GtkDialog">
+ <property name="title">Device Identifier</property>
+ <property name="use_header_bar">1</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="hide-on-close">True</property>
+
+ <child internal-child="headerbar">
+ <object class="GtkHeaderBar" id="header_bar">
+ <property name="show_title_buttons">True</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="margin-bottom">24</property>
+ <child>
+ <object class="GtkOverlay">
+ <child type="overlay">
+ <object class="GtkRevealer" id="notify_revealer">
+ <property name="halign">center</property>
+ <property name="valign">start</property>
+ <property name="transition_type">slide-down</property>
+ <child>
+ <object class="GtkFrame">
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="notify_label">
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <accessibility>
+ <property name="label" translatable="yes">Close notification</property>
+ </accessibility>
+ <style>
+ <class name="flat" />
+ </style>
+ <signal name="clicked"
+ handler="on_notify_button_clicked_cb"
+ object="CcBoltDeviceDialog"
+ swapped="no" />
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">window-close-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <style>
+ <class name="app-notification" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+
+ <child>
+ <object class="GtkGrid">
+ <property name="margin-start">72</property>
+ <property name="margin-end">72</property>
+ <property name="margin-top">24</property>
+ <property name="margin-bottom">0</property>
+ <property name="row_spacing">12</property>
+ <property name="column_spacing">24</property>
+ <child>
+ <object class="GtkLabel" id="name_title_label">
+ <property name="halign">end</property>
+ <property name="hexpand">False</property>
+ <property name="vexpand">False</property>
+ <property name="label" translatable="yes">Name:</property>
+ <property name="justify">right</property>
+ <property name="xalign">1</property>
+ <property name="mnemonic_widget">name_label</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="name_label">
+ <property name="hexpand">True</property>
+ <property name="label">Device identifier</property>
+ <property name="use_markup">True</property>
+ <property name="ellipsize">end</property>
+ <property name="xalign">0</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="status_title_label">
+ <property name="halign">end</property>
+ <property name="hexpand">False</property>
+ <property name="vexpand">False</property>
+ <property name="label" translatable="yes">Status:</property>
+ <property name="justify">right</property>
+ <property name="xalign">1</property>
+ <property name="mnemonic_widget">status_label</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="status_label">
+ <property name="valign">center</property>
+ <property name="hexpand">True</property>
+ <property name="label">Status</property>
+ <property name="ellipsize">end</property>
+ <property name="xalign">0</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="uuid_title_label">
+ <property name="halign">end</property>
+ <property name="hexpand">False</property>
+ <property name="vexpand">False</property>
+ <property name="label" translatable="yes">UUID:</property>
+ <property name="justify">right</property>
+ <property name="xalign">1</property>
+ <property name="mnemonic_widget">uuid_label</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="uuid_label">
+ <property name="valign">center</property>
+ <property name="hexpand">True</property>
+ <property name="label">Status</property>
+ <property name="ellipsize">end</property>
+ <property name="xalign">0</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="time_title">
+ <property name="halign">end</property>
+ <property name="hexpand">False</property>
+ <property name="vexpand">False</property>
+ <property name="label">Timestamp:</property>
+ <property name="justify">right</property>
+ <property name="xalign">1</property>
+ <property name="mnemonic_widget">time_label</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="time_label">
+ <property name="valign">center</property>
+ <property name="hexpand">True</property>
+ <property name="label">Status</property>
+ <property name="ellipsize">end</property>
+ <property name="xalign">0</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ <!-- end of grid -->
+ <child>
+ <object class="GtkExpander" id="parents_expander">
+ <property name="visible">False</property>
+ <property name="halign">fill</property>
+ <property name="margin-start">72</property>
+ <property name="margin-end">72</property>
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">0</property>
+ <child type="label">
+ <object class="GtkLabel" id="parents_label">
+ <property name="halign">end</property>
+ <property name="hexpand">False</property>
+ <property name="vexpand">False</property>
+ <property name="label">Depends on other devices:</property>
+ <property name="justify">center</property>
+ <property name="xalign">1</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkListBox" id="parents_devices">
+ <property name="valign">start</property>
+ <property name="vexpand">False</property>
+ <property name="selection-mode">none</property>
+ <style>
+ <class name="boxed-list" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <!-- end of -->
+ <child>
+ <object class="GtkBox" id="button_box">
+ <property name="orientation">horizontal</property>
+ <property name="spacing">12</property>
+ <property name="margin-start">72</property>
+ <property name="margin-end">72</property>
+ <property name="margin-top">36</property>
+ <property name="margin-bottom">0</property>
+ <property name="halign">fill</property>
+ <child>
+ <object class="GtkSpinner" id="spinner">
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="spinning">False</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkButton" id="connect_button">
+ <property name="label" translatable="yes">Authorize and Connect</property>
+ <property name="receives_default">True</property>
+ <property name="halign">fill</property>
+
+ <signal name="clicked"
+ handler="on_connect_button_clicked_cb"
+ object="CcBoltDeviceDialog"
+ swapped="yes" />
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkButton" id="forget_button">
+ <property name="label" translatable="yes">Forget Device</property>
+ <property name="receives_default">False</property>
+ <property name="halign">fill</property>
+ <signal name="clicked"
+ handler="on_forget_button_clicked_cb"
+ object="CcBoltDeviceDialog"
+ swapped="yes" />
+ <style>
+ <class name="destructive-action"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="spinner_box">
+ </object>
+ </child>
+ </object>
+
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+
+ <object class="GtkSizeGroup" id="device_titles_sizegroup">
+ <widgets>
+ <widget name="name_title_label"/>
+ <widget name="status_title_label"/>
+ <widget name="uuid_title_label"/>
+ <widget name="time_title"/>
+ </widgets>
+ </object>
+ <object class="GtkSizeGroup" id="device_labels_sizegroup">
+ <widgets>
+ <widget name="name_label"/>
+ <widget name="status_label"/>
+ <widget name="uuid_label"/>
+ <widget name="time_label"/>
+ </widgets>
+ </object>
+
+ <object class="GtkSizeGroup" id="actions_sizegroup">
+ <widgets>
+ <widget name="forget_button"/>
+ <widget name="connect_button"/>
+ </widgets>
+ </object>
+
+ <object class="GtkSizeGroup" id="spinner_sizegroup">
+ <widgets>
+ <widget name="spinner"/>
+ <widget name="spinner_box"/>
+ </widgets>
+ </object>
+
+</interface>
diff --git a/panels/thunderbolt/cc-bolt-device-entry.c b/panels/thunderbolt/cc-bolt-device-entry.c
new file mode 100644
index 0000000..2bde1ac
--- /dev/null
+++ b/panels/thunderbolt/cc-bolt-device-entry.c
@@ -0,0 +1,223 @@
+/* Copyright (C) 2018 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Christian J. Kellner <ckellner@redhat.com>
+ *
+ */
+
+#include <config.h>
+
+#include "bolt-str.h"
+
+#include "cc-bolt-device-entry.h"
+
+#include "cc-thunderbolt-resources.h"
+
+#include <glib/gi18n.h>
+
+#define RESOURCE_UI "/org/gnome/control-center/thunderbolt/cc-bolt-device-entry.ui"
+
+struct _CcBoltDeviceEntry
+{
+ AdwActionRow parent;
+
+ BoltDevice *device;
+
+ /* main ui */
+ GtkLabel *status_warning;
+ gboolean show_warnings;
+};
+
+static const char * device_status_to_brief_for_ui (BoltDevice *dev);
+
+G_DEFINE_TYPE (CcBoltDeviceEntry, cc_bolt_device_entry, ADW_TYPE_ACTION_ROW);
+
+enum
+{
+ SIGNAL_STATUS_CHANGED,
+ SIGNAL_LAST
+};
+
+static guint signals[SIGNAL_LAST] = { 0, };
+
+static void
+entry_set_name (CcBoltDeviceEntry *entry)
+{
+ g_autofree char *name = NULL;
+ BoltDevice *dev = entry->device;
+
+ g_return_if_fail (dev != NULL);
+
+ name = bolt_device_get_display_name (dev);
+
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (entry), name);
+}
+
+static void
+entry_update_status (CcBoltDeviceEntry *entry)
+{
+ const char *brief;
+ BoltStatus status;
+ gboolean warn;
+
+ status = bolt_device_get_status (entry->device);
+ brief = device_status_to_brief_for_ui (entry->device);
+
+ adw_action_row_set_subtitle (ADW_ACTION_ROW (entry), brief);
+
+ g_signal_emit (entry,
+ signals[SIGNAL_STATUS_CHANGED],
+ 0,
+ status);
+
+ warn = entry->show_warnings && bolt_status_is_pending (status);
+ gtk_widget_set_visible (GTK_WIDGET (entry->status_warning), warn);
+}
+
+static void
+on_device_notify_cb (GObject *gobject,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ CcBoltDeviceEntry *entry = CC_BOLT_DEVICE_ENTRY (user_data);
+ const char *what;
+
+ what = g_param_spec_get_name (pspec);
+
+ if (bolt_streq (what, "status"))
+ entry_update_status (entry);
+ else if (bolt_streq (what, "label") ||
+ bolt_streq (what, "name") ||
+ bolt_streq (what, "vendor"))
+ entry_set_name (entry);
+}
+
+/* device helpers */
+
+static const char *
+device_status_to_brief_for_ui (BoltDevice *dev)
+{
+ BoltStatus status;
+ BoltAuthFlags aflags;
+ gboolean nopcie;
+
+ status = bolt_device_get_status (dev);
+ aflags = bolt_device_get_authflags(dev);
+ nopcie = bolt_flag_isset (aflags, BOLT_AUTH_NOPCIE);
+
+ switch (status)
+ {
+ case BOLT_STATUS_DISCONNECTED:
+ return C_("Thunderbolt Device Status", "Disconnected");
+
+ case BOLT_STATUS_CONNECTING:
+ return C_("Thunderbolt Device Status", "Connecting");
+
+ case BOLT_STATUS_CONNECTED:
+ case BOLT_STATUS_AUTHORIZED_DPONLY:
+ return C_("Thunderbolt Device Status", "Connected");
+
+ case BOLT_STATUS_AUTH_ERROR:
+ return C_("Thunderbolt Device Status", "Error");
+
+ case BOLT_STATUS_AUTHORIZING:
+ return C_("Thunderbolt Device Status", "Authorizing");
+
+ case BOLT_STATUS_AUTHORIZED:
+ case BOLT_STATUS_AUTHORIZED_NEWKEY:
+ case BOLT_STATUS_AUTHORIZED_SECURE:
+ if (nopcie)
+ return C_("Thunderbolt Device Status", "Connected");
+ else
+ return C_("Thunderbolt Device Status", "Authorized");
+
+ case BOLT_STATUS_UNKNOWN:
+ break; /* use function default */
+ }
+
+ return C_("Thunderbolt Device Status", "Unknown");
+}
+
+static void
+cc_bolt_device_entry_finalize (GObject *object)
+{
+ CcBoltDeviceEntry *entry = CC_BOLT_DEVICE_ENTRY (object);
+
+ g_clear_object (&entry->device);
+
+ G_OBJECT_CLASS (cc_bolt_device_entry_parent_class)->finalize (object);
+}
+
+static void
+cc_bolt_device_entry_class_init (CcBoltDeviceEntryClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = cc_bolt_device_entry_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, RESOURCE_UI);
+ gtk_widget_class_bind_template_child (widget_class, CcBoltDeviceEntry, status_warning);
+
+ signals[SIGNAL_STATUS_CHANGED] =
+ g_signal_new ("status-changed",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE,
+ 1, BOLT_TYPE_STATUS);
+}
+
+static void
+cc_bolt_device_entry_init (CcBoltDeviceEntry *entry)
+{
+ g_resources_register (cc_thunderbolt_get_resource ());
+ gtk_widget_init_template (GTK_WIDGET (entry));
+}
+
+/* public function */
+
+CcBoltDeviceEntry *
+cc_bolt_device_entry_new (BoltDevice *device,
+ gboolean show_warnings)
+{
+ CcBoltDeviceEntry *entry;
+
+ entry = g_object_new (CC_TYPE_BOLT_DEVICE_ENTRY, NULL);
+ entry->device = g_object_ref (device);
+ entry->show_warnings = show_warnings;
+
+ entry_set_name (entry);
+ entry_update_status (entry);
+
+ g_signal_connect_object (entry->device,
+ "notify",
+ G_CALLBACK (on_device_notify_cb),
+ entry,
+ 0);
+
+ return entry;
+}
+
+BoltDevice *
+cc_bolt_device_entry_get_device (CcBoltDeviceEntry *entry)
+{
+ g_return_val_if_fail (entry != NULL, NULL);
+ g_return_val_if_fail (CC_IS_BOLT_DEVICE_ENTRY (entry), NULL);
+
+ return entry->device;
+}
diff --git a/panels/thunderbolt/cc-bolt-device-entry.h b/panels/thunderbolt/cc-bolt-device-entry.h
new file mode 100644
index 0000000..e95e3d8
--- /dev/null
+++ b/panels/thunderbolt/cc-bolt-device-entry.h
@@ -0,0 +1,36 @@
+/* Copyright (C) 2018 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Christian J. Kellner <ckellner@redhat.com>
+ *
+ */
+
+#pragma once
+
+#include <adwaita.h>
+#include <gtk/gtk.h>
+#include "bolt-device.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_BOLT_DEVICE_ENTRY cc_bolt_device_entry_get_type ()
+G_DECLARE_FINAL_TYPE (CcBoltDeviceEntry, cc_bolt_device_entry, CC, BOLT_DEVICE_ENTRY, AdwActionRow);
+
+
+CcBoltDeviceEntry * cc_bolt_device_entry_new (BoltDevice *device,
+ gboolean show_warnings);
+BoltDevice * cc_bolt_device_entry_get_device (CcBoltDeviceEntry *entry);
+
+G_END_DECLS
diff --git a/panels/thunderbolt/cc-bolt-device-entry.ui b/panels/thunderbolt/cc-bolt-device-entry.ui
new file mode 100644
index 0000000..2790f92
--- /dev/null
+++ b/panels/thunderbolt/cc-bolt-device-entry.ui
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcBoltDeviceEntry" parent="AdwActionRow">
+ <property name="activatable">True</property>
+ <child type="suffix">
+ <object class="GtkImage" id="status_warning">
+ <property name="visible">False</property>
+ <property name="icon_name">dialog-warning-symbolic</property>
+ <property name="icon_size">1</property>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/thunderbolt/cc-bolt-panel.c b/panels/thunderbolt/cc-bolt-panel.c
new file mode 100644
index 0000000..3fe4186
--- /dev/null
+++ b/panels/thunderbolt/cc-bolt-panel.c
@@ -0,0 +1,960 @@
+/* Copyright © 2018 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Christian J. Kellner <ckellner@redhat.com>
+ *
+ */
+
+#include <config.h>
+
+#include <shell/cc-panel.h>
+
+#include <glib/gi18n.h>
+#include <polkit/polkit.h>
+
+#include "cc-bolt-device-dialog.h"
+#include "cc-bolt-device-entry.h"
+
+#include "bolt-client.h"
+#include "bolt-names.h"
+#include "bolt-str.h"
+
+#include "cc-bolt-panel.h"
+#include "cc-thunderbolt-resources.h"
+
+struct _CcBoltPanel
+{
+ CcPanel parent;
+
+ BoltClient *client;
+
+ /* headerbar menu */
+ GtkBox *headerbar_box;
+ GtkLockButton *lock_button;
+
+ /* main ui */
+ GtkStack *container;
+
+ /* empty state */
+ AdwStatusPage *notb_page;
+
+ /* notifications */
+ GtkLabel *notification_label;
+ GtkRevealer *notification_revealer;
+
+ /* authmode */
+ GtkSwitch *authmode_switch;
+ GtkSpinner *authmode_spinner;
+ GtkStack *direct_access_row;
+
+ /* device list */
+ GHashTable *devices;
+
+ GtkStack *devices_stack;
+ GtkBox *devices_box;
+ GtkBox *pending_box;
+
+ GtkListBox *devices_list;
+ GtkListBox *pending_list;
+
+ /* device details dialog */
+ CcBoltDeviceDialog *device_dialog;
+
+ /* polkit integration */
+ GPermission *permission;
+};
+
+/* initialization */
+static void bolt_client_ready (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data);
+
+/* panel functions */
+static void cc_bolt_panel_set_no_thunderbolt (CcBoltPanel *panel,
+ const char *custom_msg);
+
+static void cc_bolt_panel_name_owner_changed (CcBoltPanel *panel);
+
+static CcBoltDeviceEntry * cc_bolt_panel_add_device (CcBoltPanel *panel,
+ BoltDevice *dev);
+
+static void cc_bolt_panel_del_device_entry (CcBoltPanel *panel,
+ CcBoltDeviceEntry *entry);
+
+static void cc_bolt_panel_authmode_sync (CcBoltPanel *panel);
+
+static void cc_panel_list_box_migrate (CcBoltPanel *panel,
+ GtkListBox *from,
+ GtkListBox *to,
+ CcBoltDeviceEntry *entry);
+
+/* bolt client signals */
+static void on_bolt_name_owner_changed_cb (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data);
+
+static void on_bolt_device_added_cb (BoltClient *cli,
+ const char *path,
+ CcBoltPanel *panel);
+
+static void on_bolt_device_removed_cb (BoltClient *cli,
+ const char *opath,
+ CcBoltPanel *panel);
+
+static void on_bolt_notify_authmode_cb (GObject *gobject,
+ GParamSpec *pspec,
+ gpointer user_data);
+
+/* panel signals */
+static gboolean on_authmode_state_set_cb (CcBoltPanel *panel,
+ gboolean state,
+ GtkSwitch *toggle);
+
+static void on_device_entry_row_activated_cb (CcBoltPanel *panel,
+ GtkListBoxRow *row);
+
+static void on_device_entry_status_changed_cb (CcBoltDeviceEntry *entry,
+ BoltStatus new_status,
+ CcBoltPanel *panel);
+
+static void on_notification_button_clicked_cb (GtkButton *button,
+ CcBoltPanel *panel);
+
+
+/* polkit */
+static void on_permission_ready (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data);
+
+static void on_permission_notify_cb (GPermission *permission,
+ GParamSpec *pspec,
+ CcBoltPanel *panel);
+
+CC_PANEL_REGISTER (CcBoltPanel, cc_bolt_panel);
+
+static void
+bolt_client_ready (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) err = NULL;
+ g_autoptr(CcBoltPanel) panel = NULL;
+ BoltClient *client;
+
+ panel = CC_BOLT_PANEL (user_data);
+ client = bolt_client_new_finish (res, &err);
+
+ if (client == NULL)
+ {
+ const char *text;
+
+ /* operation got cancelled because the panel got destroyed */
+ if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED) ||
+ g_error_matches (err, G_IO_ERROR, G_IO_ERROR_FAILED_HANDLED))
+ return;
+
+ g_warning ("Could not create client: %s", err->message);
+ text = _("The Thunderbolt subsystem (boltd) is not installed or "
+ "not set up properly.");
+
+ adw_status_page_set_description (panel->notb_page, text);
+ gtk_stack_set_visible_child_name (panel->container, "no-thunderbolt");
+
+ return;
+ }
+
+ g_signal_connect_object (client,
+ "notify::g-name-owner",
+ G_CALLBACK (on_bolt_name_owner_changed_cb),
+ panel,
+ 0);
+
+ g_signal_connect_object (client,
+ "device-added",
+ G_CALLBACK (on_bolt_device_added_cb),
+ panel,
+ 0);
+
+ g_signal_connect_object (client,
+ "device-removed",
+ G_CALLBACK (on_bolt_device_removed_cb),
+ panel,
+ 0);
+
+ g_signal_connect_object (client,
+ "notify::auth-mode",
+ G_CALLBACK (on_bolt_notify_authmode_cb),
+ panel,
+ 0);
+
+ /* Treat security-level changes, which should rarely happen, as
+ * if the name owner changed, i.e. as if boltd got restarted */
+ g_signal_connect_object (client,
+ "notify::security-level",
+ G_CALLBACK (on_bolt_name_owner_changed_cb),
+ panel,
+ 0);
+
+ panel->client = client;
+
+ cc_bolt_device_dialog_set_client (panel->device_dialog, client);
+
+ cc_bolt_panel_authmode_sync (panel);
+
+ g_object_bind_property (panel->authmode_switch,
+ "active",
+ panel->devices_box,
+ "sensitive",
+ G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
+
+ g_object_bind_property (panel->authmode_switch,
+ "active",
+ panel->pending_box,
+ "sensitive",
+ G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
+
+ gtk_stack_set_visible_child_name (panel->devices_stack, "no-devices");
+ cc_bolt_panel_name_owner_changed (panel);
+}
+
+static gboolean
+devices_table_transfer_entry (GHashTable *from,
+ GHashTable *to,
+ gconstpointer key)
+{
+ gpointer k, v;
+ gboolean found;
+
+ found = g_hash_table_lookup_extended (from, key, &k, &v);
+
+ if (found)
+ {
+ g_hash_table_steal (from, key);
+ g_hash_table_insert (to, k, v);
+ }
+
+ return found;
+}
+
+static void
+devices_table_clear_entries (GHashTable *table,
+ CcBoltPanel *panel)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_hash_table_iter_init (&iter, table);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ CcBoltDeviceEntry *entry = value;
+
+ cc_bolt_panel_del_device_entry (panel, entry);
+ g_hash_table_iter_remove (&iter);
+ }
+}
+
+static void
+devices_table_synchronize (CcBoltPanel *panel)
+{
+ g_autoptr(GHashTable) old = NULL;
+ g_autoptr(GPtrArray) devices = NULL;
+ g_autoptr(GError) err = NULL;
+ guint i;
+
+ devices = bolt_client_list_devices (panel->client, cc_panel_get_cancellable (CC_PANEL (panel)), &err);
+
+ if (!devices)
+ {
+ g_warning ("Could not list devices: %s", err->message);
+ devices = g_ptr_array_new_with_free_func (g_object_unref);
+ }
+
+ old = panel->devices;
+ panel->devices = g_hash_table_new (g_str_hash, g_str_equal);
+
+ for (i = 0; i < devices->len; i++)
+ {
+ BoltDevice *dev = g_ptr_array_index (devices, i);
+ const char *path;
+ gboolean found;
+
+ path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (dev));
+ found = devices_table_transfer_entry (old, panel->devices, path);
+
+ if (found)
+ continue;
+
+ cc_bolt_panel_add_device (panel, dev);
+ }
+
+ devices_table_clear_entries (old, panel);
+ gtk_stack_set_visible_child_name (panel->container, "devices-listing");
+}
+
+static gboolean
+list_box_sync_visible (GtkListBox *listbox)
+{
+ GtkWidget *child;
+ gboolean show;
+
+ child = gtk_widget_get_first_child (GTK_WIDGET (listbox));
+ show = child != NULL;
+
+ gtk_widget_set_visible (GTK_WIDGET (listbox), show);
+
+ return show;
+}
+
+static GtkWidget *
+cc_bolt_panel_box_for_listbox (CcBoltPanel *panel,
+ GtkListBox *lstbox)
+{
+ if ((gpointer) lstbox == panel->devices_list)
+ return GTK_WIDGET (panel->devices_box);
+ else if ((gpointer) lstbox == panel->pending_list)
+ return GTK_WIDGET (panel->pending_box);
+
+ g_return_val_if_reached (NULL);
+}
+
+static CcBoltDeviceEntry *
+cc_bolt_panel_add_device (CcBoltPanel *panel,
+ BoltDevice *dev)
+{
+ CcBoltDeviceEntry *entry;
+ BoltDeviceType type;
+ BoltStatus status;
+ const char *path;
+
+ type = bolt_device_get_device_type (dev);
+
+ if (type != BOLT_DEVICE_PERIPHERAL)
+ return FALSE;
+
+ entry = cc_bolt_device_entry_new (dev, FALSE);
+ path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (dev));
+
+ /* add to the list box */
+ status = bolt_device_get_status (dev);
+
+ if (bolt_status_is_pending (status))
+ {
+ gtk_list_box_append (panel->pending_list, GTK_WIDGET (entry));
+ gtk_widget_show (GTK_WIDGET (panel->pending_list));
+ gtk_widget_show (GTK_WIDGET (panel->pending_box));
+ }
+ else
+ {
+ gtk_list_box_append (panel->devices_list, GTK_WIDGET (entry));
+ gtk_widget_show (GTK_WIDGET (panel->devices_list));
+ gtk_widget_show (GTK_WIDGET (panel->devices_box));
+ }
+
+ g_signal_connect_object (entry,
+ "status-changed",
+ G_CALLBACK (on_device_entry_status_changed_cb),
+ panel,
+ 0);
+
+ gtk_stack_set_visible_child_name (panel->devices_stack, "have-devices");
+ g_hash_table_insert (panel->devices, (gpointer) path, entry);
+
+ return entry;
+}
+
+static void
+cc_bolt_panel_del_device_entry (CcBoltPanel *panel,
+ CcBoltDeviceEntry *entry)
+{
+ BoltDevice *dev;
+ GtkWidget *box;
+ GtkWidget *p;
+ gboolean show;
+
+ dev = cc_bolt_device_entry_get_device (entry);
+ if (cc_bolt_device_dialog_device_equal (panel->device_dialog, dev))
+ {
+ gtk_widget_hide (GTK_WIDGET (panel->device_dialog));
+ cc_bolt_device_dialog_set_device (panel->device_dialog, NULL, NULL);
+ }
+
+ p = gtk_widget_get_parent (GTK_WIDGET (entry));
+ gtk_list_box_remove (GTK_LIST_BOX (p), GTK_WIDGET (entry));
+
+ box = cc_bolt_panel_box_for_listbox (panel, GTK_LIST_BOX (p));
+ show = list_box_sync_visible (GTK_LIST_BOX (p));
+ gtk_widget_set_visible (box, show);
+
+ if (!gtk_widget_is_visible (GTK_WIDGET (panel->pending_list)) &&
+ !gtk_widget_is_visible (GTK_WIDGET (panel->devices_list)))
+ {
+ gtk_stack_set_visible_child_name (panel->devices_stack, "no-devices");
+ }
+}
+
+static void
+cc_bolt_panel_authmode_sync (CcBoltPanel *panel)
+{
+ BoltClient *client = panel->client;
+ BoltAuthMode mode;
+ gboolean enabled;
+
+ mode = bolt_client_get_authmode (client);
+ enabled = (mode & BOLT_AUTH_ENABLED) != 0;
+
+ g_signal_handlers_block_by_func (panel->authmode_switch, on_authmode_state_set_cb, panel);
+
+ gtk_switch_set_state (panel->authmode_switch, enabled);
+
+ g_signal_handlers_unblock_by_func (panel->authmode_switch, on_authmode_state_set_cb, panel);
+
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (panel->direct_access_row),
+ enabled ?
+ _("Allow direct access to devices such as docks and external GPUs.") :
+ _("Only USB and Display Port devices can attach."));
+}
+
+static void
+cc_panel_list_box_migrate (CcBoltPanel *panel,
+ GtkListBox *from,
+ GtkListBox *to,
+ CcBoltDeviceEntry *entry)
+{
+ GtkWidget *from_box;
+ GtkWidget *to_box;
+ gboolean show;
+ GtkWidget *target;
+
+ target = GTK_WIDGET (entry);
+
+ gtk_list_box_remove (from, target);
+ gtk_list_box_append (to, target);
+ gtk_widget_show (GTK_WIDGET (to));
+
+ from_box = cc_bolt_panel_box_for_listbox (panel, from);
+ to_box = cc_bolt_panel_box_for_listbox (panel, to);
+
+ show = list_box_sync_visible (from);
+ gtk_widget_set_visible (from_box, show);
+ gtk_widget_set_visible (to_box, TRUE);
+}
+
+/* bolt client signals */
+static void
+cc_bolt_panel_set_no_thunderbolt (CcBoltPanel *panel,
+ const char *msg)
+{
+ if (!msg)
+ {
+ msg = _("Thunderbolt could not be detected.\n"
+ "Either the system lacks Thunderbolt support, "
+ "it has been disabled in the BIOS or is set to "
+ "an unsupported security level in the BIOS.");
+ }
+
+ adw_status_page_set_description (panel->notb_page, msg);
+ gtk_stack_set_visible_child_name (panel->container, "no-thunderbolt");
+}
+
+static void
+cc_bolt_panel_name_owner_changed (CcBoltPanel *panel)
+{
+ g_autofree char *name_owner = NULL;
+ BoltClient *client = panel->client;
+ BoltSecurity sl;
+ gboolean notb = TRUE;
+ const char *text = NULL;
+
+ name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (panel->client));
+
+ if (name_owner == NULL)
+ {
+ cc_bolt_panel_set_no_thunderbolt (panel, NULL);
+ devices_table_clear_entries (panel->devices, panel);
+ gtk_widget_hide (GTK_WIDGET (panel->headerbar_box));
+ return;
+ }
+
+ gtk_stack_set_visible_child_name (panel->container, "loading");
+
+ sl = bolt_client_get_security (client);
+
+ switch (sl)
+ {
+ case BOLT_SECURITY_NONE:
+ case BOLT_SECURITY_SECURE:
+ case BOLT_SECURITY_USER:
+ /* we fetch the device list and show them here */
+ notb = FALSE;
+ break;
+
+ case BOLT_SECURITY_DPONLY:
+ case BOLT_SECURITY_USBONLY:
+ text = _("Thunderbolt support has been disabled in the BIOS.");
+ break;
+
+ case BOLT_SECURITY_UNKNOWN:
+ text = _("Thunderbolt security level could not be determined.");;
+ break;
+ }
+
+ if (notb)
+ {
+ /* security level is unknown or un-handled */
+ cc_bolt_panel_set_no_thunderbolt (panel, text);
+ return;
+ }
+
+ if (panel->permission)
+ {
+ gtk_widget_show (GTK_WIDGET (panel->headerbar_box));
+ }
+ else
+ {
+ polkit_permission_new ("org.freedesktop.bolt.manage",
+ NULL,
+ cc_panel_get_cancellable (CC_PANEL (panel)),
+ on_permission_ready,
+ g_object_ref (panel));
+ }
+
+ devices_table_synchronize (panel);
+}
+
+/* bolt client signals */
+static void
+on_bolt_name_owner_changed_cb (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ cc_bolt_panel_name_owner_changed (CC_BOLT_PANEL (user_data));
+}
+
+static void
+on_bolt_device_added_cb (BoltClient *cli,
+ const char *path,
+ CcBoltPanel *panel)
+{
+ g_autoptr(GError) err = NULL;
+ GDBusConnection *bus;
+ BoltDevice *dev;
+ gboolean found;
+
+ found = g_hash_table_contains (panel->devices, path);
+
+ if (found)
+ return;
+
+ bus = g_dbus_proxy_get_connection (G_DBUS_PROXY (panel->client));
+ dev = bolt_device_new_for_object_path (bus, path, cc_panel_get_cancellable (CC_PANEL (panel)), &err);
+
+ if (!dev)
+ {
+ g_warning ("Could not create proxy for %s", path);
+ return;
+ }
+
+ cc_bolt_panel_add_device (panel, dev);
+}
+
+static void
+on_bolt_device_removed_cb (BoltClient *cli,
+ const char *path,
+ CcBoltPanel *panel)
+{
+ CcBoltDeviceEntry *entry;
+
+ entry = g_hash_table_lookup (panel->devices, path);
+
+ if (!entry)
+ return;
+
+ cc_bolt_panel_del_device_entry (panel, entry);
+ g_hash_table_remove (panel->devices, path);
+}
+
+static void
+on_bolt_notify_authmode_cb (GObject *gobject,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ cc_bolt_panel_authmode_sync (CC_BOLT_PANEL (user_data));
+}
+
+/* panel signals */
+
+static void
+on_authmode_ready (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+ CcBoltPanel *panel;
+ gboolean ok;
+
+ ok = bolt_client_set_authmode_finish (BOLT_CLIENT (source_object), res, &error);
+ if (!ok)
+ {
+ g_autofree char *text = NULL;
+
+ g_warning ("Could not set authmode: %s", error->message);
+
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
+ panel = CC_BOLT_PANEL (user_data);
+ text = g_strdup_printf (_("Error switching direct mode: %s"), error->message);
+ gtk_label_set_markup (panel->notification_label, text);
+ gtk_revealer_set_reveal_child (panel->notification_revealer, TRUE);
+
+ /* make sure we are reflecting the correct state */
+ cc_bolt_panel_authmode_sync (panel);
+ }
+
+ panel = CC_BOLT_PANEL (user_data);
+ gtk_spinner_stop (panel->authmode_spinner);
+ gtk_widget_set_sensitive (GTK_WIDGET (panel->authmode_switch), TRUE);
+}
+
+static gboolean
+on_authmode_state_set_cb (CcBoltPanel *panel,
+ gboolean enable,
+ GtkSwitch *toggle)
+{
+ BoltClient *client = panel->client;
+ BoltAuthMode mode;
+
+ gtk_widget_set_sensitive (GTK_WIDGET (panel->authmode_switch), FALSE);
+ gtk_spinner_start (panel->authmode_spinner);
+
+ mode = bolt_client_get_authmode (client);
+
+ if (enable)
+ mode = mode | BOLT_AUTH_ENABLED;
+ else
+ mode = mode & ~BOLT_AUTH_ENABLED;
+
+ bolt_client_set_authmode_async (client, mode, NULL, on_authmode_ready, panel);
+
+ return TRUE;
+}
+
+static void
+on_device_entry_row_activated_cb (CcBoltPanel *panel,
+ GtkListBoxRow *row)
+{
+ g_autoptr(GPtrArray) parents = NULL;
+ CcBoltDeviceEntry *entry;
+ BoltDevice *device;
+ BoltDevice *iter;
+ const char *parent;
+
+ if (!CC_IS_BOLT_DEVICE_ENTRY (row))
+ return;
+
+ entry = CC_BOLT_DEVICE_ENTRY (row);
+ device = cc_bolt_device_entry_get_device (entry);
+
+ /* walk up the chain and collect all parents */
+ parents = g_ptr_array_new_with_free_func (g_object_unref);
+ iter = device;
+
+ parent = bolt_device_get_parent (iter);
+ while (parent != NULL)
+ {
+ g_autofree char *path = NULL;
+ CcBoltDeviceEntry *child;
+ BoltDevice *dev;
+
+ path = bolt_gen_object_path (BOLT_DBUS_PATH_DEVICES, parent);
+
+ /* NB: the host device is not a peripheral and thus not
+ * in the hash table; therefore when get a NULL back, we
+ * should have reached the end of the chain */
+ child = g_hash_table_lookup (panel->devices, path);
+ if (!child)
+ break;
+
+ dev = cc_bolt_device_entry_get_device (child);
+ g_ptr_array_add (parents, g_object_ref (dev));
+ iter = dev;
+
+ parent = bolt_device_get_parent (iter);
+ }
+
+ cc_bolt_device_dialog_set_device (panel->device_dialog, device, parents);
+
+ gtk_window_set_default_size (GTK_WINDOW (panel->device_dialog), 1, 1);
+ gtk_widget_show (GTK_WIDGET (panel->device_dialog));
+}
+
+static void
+on_device_entry_status_changed_cb (CcBoltDeviceEntry *entry,
+ BoltStatus new_status,
+ CcBoltPanel *panel)
+{
+ GtkListBox *from = NULL;
+ GtkListBox *to = NULL;
+ GtkWidget *p;
+ gboolean is_pending;
+ gboolean parent_pending;
+
+ /* if we are doing some active work, then lets not change
+ * the list the entry is in; otherwise we might just hop
+ * from one box to the other and back again.
+ */
+ if (new_status == BOLT_STATUS_CONNECTING || new_status == BOLT_STATUS_AUTHORIZING)
+ return;
+
+ is_pending = bolt_status_is_pending (new_status);
+
+ p = gtk_widget_get_parent (GTK_WIDGET (entry));
+ parent_pending = (gpointer) p == panel->pending_list;
+
+ /* */
+ if (is_pending && !parent_pending)
+ {
+ from = panel->devices_list;
+ to = panel->pending_list;
+ }
+ else if (!is_pending && parent_pending)
+ {
+ from = panel->pending_list;
+ to = panel->devices_list;
+ }
+
+ if (from && to)
+ cc_panel_list_box_migrate (panel, from, to, entry);
+}
+
+
+static void
+on_notification_button_clicked_cb (GtkButton *button,
+ CcBoltPanel *panel)
+{
+ gtk_revealer_set_reveal_child (panel->notification_revealer, FALSE);
+}
+
+/* polkit */
+
+static void
+on_permission_ready (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(CcBoltPanel) panel = user_data;
+ g_autoptr(GError) err = NULL;
+ GPermission *permission;
+ gboolean is_allowed;
+ const char *name;
+
+ permission = polkit_permission_new_finish (res, &err);
+ panel->permission = permission;
+
+ if (!panel->permission)
+ {
+ g_warning ("Could not get polkit permissions: %s", err->message);
+ return;
+ }
+
+ g_signal_connect_object (permission,
+ "notify",
+ G_CALLBACK (on_permission_notify_cb),
+ panel,
+ G_CONNECT_AFTER);
+
+ is_allowed = g_permission_get_allowed (permission);
+ gtk_widget_set_sensitive (GTK_WIDGET (panel->authmode_switch), is_allowed);
+ gtk_lock_button_set_permission (panel->lock_button, permission);
+
+ name = gtk_stack_get_visible_child_name (panel->container);
+
+ gtk_widget_set_visible (GTK_WIDGET (panel->headerbar_box),
+ bolt_streq (name, "devices-listing"));
+}
+
+static void
+on_permission_notify_cb (GPermission *permission,
+ GParamSpec *pspec,
+ CcBoltPanel *panel)
+{
+ gboolean is_allowed = g_permission_get_allowed (permission);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (panel->authmode_switch), is_allowed);
+}
+
+static gint
+device_entries_sort_by_recency_cb (GtkListBoxRow *a_row,
+ GtkListBoxRow *b_row,
+ gpointer user_data)
+{
+ CcBoltDeviceEntry *a_entry = CC_BOLT_DEVICE_ENTRY (a_row);
+ CcBoltDeviceEntry *b_entry = CC_BOLT_DEVICE_ENTRY (b_row);
+ BoltDevice *a = cc_bolt_device_entry_get_device (a_entry);
+ BoltDevice *b = cc_bolt_device_entry_get_device (b_entry);
+ BoltStatus status;
+ gint64 a_ts, b_ts;
+ gint64 score;
+
+ a_ts = (gint64) bolt_device_get_timestamp (a);
+ b_ts = (gint64) bolt_device_get_timestamp (b);
+
+ score = b_ts - a_ts;
+
+ if (score != 0)
+ return score;
+
+ status = bolt_device_get_status (a);
+
+ if (bolt_status_is_connected (status))
+ {
+ const char *a_path;
+ const char *b_path;
+
+ a_path = bolt_device_get_syspath (a);
+ b_path = bolt_device_get_syspath (b);
+
+ return g_strcmp0 (a_path, b_path);
+ }
+ else
+ {
+ const char *a_name;
+ const char *b_name;
+
+ a_name = bolt_device_get_name (a);
+ b_name = bolt_device_get_name (b);
+
+ return g_strcmp0 (a_name, b_name);
+ }
+
+ return 0;
+}
+
+static gint
+device_entries_sort_by_syspath_cb (GtkListBoxRow *a_row,
+ GtkListBoxRow *b_row,
+ gpointer user_data)
+{
+ CcBoltDeviceEntry *a_entry = CC_BOLT_DEVICE_ENTRY (a_row);
+ CcBoltDeviceEntry *b_entry = CC_BOLT_DEVICE_ENTRY (b_row);
+ BoltDevice *a = cc_bolt_device_entry_get_device (a_entry);
+ BoltDevice *b = cc_bolt_device_entry_get_device (b_entry);
+
+ const char *a_path;
+ const char *b_path;
+
+ a_path = bolt_device_get_syspath (a);
+ b_path = bolt_device_get_syspath (b);
+
+ return g_strcmp0 (a_path, b_path);
+}
+
+/* GObject overrides */
+
+static void
+cc_bolt_panel_finalize (GObject *object)
+{
+ CcBoltPanel *panel = CC_BOLT_PANEL (object);
+
+ g_clear_object (&panel->client);
+ g_clear_pointer (&panel->devices, g_hash_table_unref);
+ g_clear_object (&panel->permission);
+
+ G_OBJECT_CLASS (cc_bolt_panel_parent_class)->finalize (object);
+}
+
+static void
+cc_bolt_panel_dispose (GObject *object)
+{
+ CcBoltPanel *panel = CC_BOLT_PANEL (object);
+
+ /* Must be destroyed in dispose, not finalize. */
+ cc_bolt_device_dialog_set_device (panel->device_dialog, NULL, NULL);
+ g_clear_pointer ((GtkWindow **) &panel->device_dialog, gtk_window_destroy);
+
+ G_OBJECT_CLASS (cc_bolt_panel_parent_class)->dispose (object);
+}
+
+static void
+cc_bolt_panel_constructed (GObject *object)
+{
+ CcBoltPanel *panel = CC_BOLT_PANEL (object);
+ GtkWindow *parent;
+ CcShell *shell;
+
+ G_OBJECT_CLASS (cc_bolt_panel_parent_class)->constructed (object);
+
+ shell = cc_panel_get_shell (CC_PANEL (panel));
+ parent = GTK_WINDOW (cc_shell_get_toplevel (shell));
+ gtk_window_set_transient_for (GTK_WINDOW (panel->device_dialog), parent);
+}
+
+static void
+cc_bolt_panel_class_init (CcBoltPanelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->constructed = cc_bolt_panel_constructed;
+ object_class->dispose = cc_bolt_panel_dispose;
+ object_class->finalize = cc_bolt_panel_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/thunderbolt/cc-bolt-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, authmode_spinner);
+ gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, authmode_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, container);
+ gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, devices_list);
+ gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, devices_box);
+ gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, devices_stack);
+ gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, direct_access_row);
+ gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, headerbar_box);
+ gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, lock_button);
+ gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, notb_page);
+ gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, notification_label);
+ gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, notification_revealer);
+ gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, pending_box);
+ gtk_widget_class_bind_template_child (widget_class, CcBoltPanel, pending_list);
+
+ gtk_widget_class_bind_template_callback (widget_class, on_notification_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_authmode_state_set_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_device_entry_row_activated_cb);
+}
+
+static void
+cc_bolt_panel_init (CcBoltPanel *panel)
+{
+ g_resources_register (cc_thunderbolt_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (panel));
+
+ gtk_stack_set_visible_child_name (panel->container, "loading");
+
+ gtk_list_box_set_sort_func (panel->devices_list,
+ device_entries_sort_by_recency_cb,
+ panel,
+ NULL);
+
+ gtk_list_box_set_sort_func (panel->pending_list,
+ device_entries_sort_by_syspath_cb,
+ panel,
+ NULL);
+
+ panel->devices = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
+
+ panel->device_dialog = cc_bolt_device_dialog_new ();
+
+ bolt_client_new_async (cc_panel_get_cancellable (CC_PANEL (panel)), bolt_client_ready, g_object_ref (panel));
+}
diff --git a/panels/thunderbolt/cc-bolt-panel.h b/panels/thunderbolt/cc-bolt-panel.h
new file mode 100644
index 0000000..5901044
--- /dev/null
+++ b/panels/thunderbolt/cc-bolt-panel.h
@@ -0,0 +1,30 @@
+/* Copyright © 2018 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Christian J. Kellner <ckellner@redhat.com>
+ *
+ */
+
+#pragma once
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_BOLT_PANEL cc_bolt_panel_get_type ()
+
+G_DECLARE_FINAL_TYPE (CcBoltPanel, cc_bolt_panel, CC, BOLT_PANEL, CcPanel);
+
+G_END_DECLS
diff --git a/panels/thunderbolt/cc-bolt-panel.ui b/panels/thunderbolt/cc-bolt-panel.ui
new file mode 100644
index 0000000..bb8d96e
--- /dev/null
+++ b/panels/thunderbolt/cc-bolt-panel.ui
@@ -0,0 +1,361 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcBoltPanel" parent="CcPanel">
+
+ <!-- Headerbar entries -->
+ <child type="titlebar-end">
+ <object class="GtkBox" id="headerbar_box">
+ <property name="visible">False</property>
+ <property name="spacing">6</property>
+ <property name="halign">end</property>
+ <child>
+ <object class="GtkLockButton" id="lock_button">
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child type="content">
+ <object class="GtkOverlay">
+ <child type="overlay">
+ <object class="GtkRevealer" id="notification_revealer">
+ <property name="halign">center</property>
+ <property name="valign">start</property>
+ <property name="transition_type">slide-down</property>
+ <child>
+ <object class="GtkFrame">
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="notification_label">
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="can_focus">True</property>
+ <property name="icon-name">window-close-symbolic</property>
+ <accessibility>
+ <property name="label" translatable="yes">Close notification</property>
+ </accessibility>
+ <style>
+ <class name="flat" />
+ </style>
+ <signal name="clicked"
+ handler="on_notification_button_clicked_cb"
+ object="CcBoltPanel"
+ swapped="no" />
+ </object>
+ </child>
+ </object>
+ </child>
+ <style>
+ <class name="app-notification" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkStack" id="container">
+ <property name="hhomogeneous">False</property>
+ <property name="vhomogeneous">False</property>
+ <property name="transition_type">crossfade</property>
+
+ <!-- Spinner for when we are creating -->
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">loading</property>
+ <property name="child">
+ <object class="GtkCenterBox">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="orientation">vertical</property>
+ <property name="margin-top">18</property>
+ <property name="margin-bottom">18</property>
+ <property name="margin-start">18</property>
+ <property name="margin-end">18</property>
+ <child type="center">
+ <object class="GtkSpinner" id="loading-spinner">
+ <property name="spinning">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <!-- No tunderbolt -->
+
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">no-thunderbolt</property>
+ <property name="child">
+ <object class="AdwStatusPage" id="notb_page">
+ <property name="title" translatable="yes">No Thunderbolt Support</property>
+ <property name="description" translatable="yes">Could not connect to the thunderbolt subsystem.</property>
+ <property name="icon-name">thunderbolt-symbolic</property>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <!-- Normal operation mode (show list of devices) -->
+
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">devices-listing</property>
+ <property name="child">
+ <object class="GtkScrolledWindow">
+ <property name="hscrollbar-policy">never</property>
+
+ <child>
+ <object class="GtkViewport">
+
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <property name="valign">start</property>
+
+ <!-- Stub box -->
+ <child>
+ <object class="GtkBox">
+ <property name="hexpand">True</property>
+ </object>
+ </child>
+
+ <!-- center/content box -->
+ <child>
+ <object class="GtkBox">
+ <property name="hexpand">True</property>
+ <property name="spacing">32</property>
+ <property name="margin_top">32</property>
+ <property name="margin_bottom">32</property>
+ <property name="margin-start">18</property>
+ <property name="margin-end">18</property>
+ <property name="orientation">vertical</property>
+
+ <!-- Auth Mode -->
+ <child>
+ <object class="GtkBox" id="authmode_box">
+ <property name="orientation">horizontal</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Direct Access</property>
+
+ <child>
+ <object class="AdwActionRow" id="direct_access_row">
+ <property name="title" translatable="yes" >Allow direct access to devices such as docks and external GPUs.</property>
+ <child type="suffix">
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <property name="spacing">6</property>
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+
+ <child>
+ <object class="GtkSpinner" id="authmode_spinner">
+ <property name="spinning">False</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkSwitch" id="authmode_switch">
+ <property name="halign">end</property>
+ <property name="active">True</property>
+ <signal name="state-set"
+ handler="on_authmode_state_set_cb"
+ object="CcBoltPanel"
+ swapped="yes" />
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- Stack: devices/no-devices -->
+ <child>
+ <object class="GtkStack" id="devices_stack">
+ <property name="transition-type">crossfade</property>
+
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">have-devices</property>
+ <property name="child">
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">32</property>
+
+ <!-- Pending Device List -->
+ <child>
+ <object class="GtkBox" id="pending_box">
+ <property name="visible">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+
+ <!-- Pending Device List: Header -->
+ <child>
+ <object class="GtkBox" id="pending_header">
+ <property name="hexpand">True</property>
+ <property name="halign">start</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkImage">
+ <property name="icon_name">dialog-warning-symbolic</property>
+ <property name="icon_size">1</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Pending Devices</property>
+ <property name="xalign">0.0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSpinner" id="pending_spinner">
+ <property name="hexpand">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- Pending List: Devices -->
+ <child>
+ <object class="GtkFrame">
+ <property name="valign">start</property>
+ <property name="vexpand">False</property>
+ <style>
+ <class name="view" />
+ </style>
+ <child>
+ <object class="GtkListBox" id="pending_list">
+ <property name="selection-mode">none</property>
+ <property name="can_focus">True</property>
+ <signal name="row-activated"
+ handler="on_device_entry_row_activated_cb"
+ object="CcBoltPanel"
+ swapped="yes" />
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- Device List -->
+ <child>
+ <object class="AdwPreferencesGroup" id="devices_box">
+ <property name="title" translatable="yes">Devices</property>
+ <property name="visible">False</property>
+
+
+ <!-- Device List: Devices -->
+ <child>
+ <object class="GtkListBox" id="devices_list">
+ <property name="selection-mode">none</property>
+ <signal name="row-activated"
+ handler="on_device_entry_row_activated_cb"
+ object="CcBoltPanel"
+ swapped="yes" />
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkSpinner" id="probing_spinner">
+ <property name="halign">start</property>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <!-- No Devices -->
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">no-devices</property>
+ <property name="child">
+ <object class="GtkBox">
+ <property name="hexpand">True</property>
+ <property name="halign">start</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Devices</property>
+ <property name="xalign">0.0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">No devices attached</property>
+ <property name="xalign">0.0</property>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child> <!-- End of: No Devices -->
+
+ </object>
+ </child> <!-- End of Stack: devices/no-devices -->
+
+ </object>
+ </child> <!-- End of enter/content box -->
+
+
+ <!-- Stub box -->
+ <child>
+ <object class="GtkBox">
+ <property name="hexpand">True</property>
+ </object>
+ </child>
+
+ <!-- End of content -->
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+
+ </property>
+ </object>
+ </child>
+
+ <!-- End of 'container' -->
+ </object>
+ </child>
+
+ <!-- End of overlay -->
+ </object>
+ </child>
+ </template>
+
+</interface>
diff --git a/panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in b/panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in
new file mode 100644
index 0000000..05d33a2
--- /dev/null
+++ b/panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in
@@ -0,0 +1,18 @@
+[Desktop Entry]
+Name=Thunderbolt
+Comment=Manage Thunderbolt devices
+Exec=gnome-control-center thunderbolt
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-thunderbolt-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;X-GNOME-Settings-Panel;HardwareSettings;X-GNOME-PrivacySettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=thunderbolt
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: those are keywords for the thunderbolt control-center panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=Thunderbolt;privacy;
diff --git a/panels/thunderbolt/icons/meson.build b/panels/thunderbolt/icons/meson.build
new file mode 100644
index 0000000..2633534
--- /dev/null
+++ b/panels/thunderbolt/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-thunderbolt-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/thunderbolt/icons/scalable/org.gnome.Settings-thunderbolt-symbolic.svg b/panels/thunderbolt/icons/scalable/org.gnome.Settings-thunderbolt-symbolic.svg
new file mode 100644
index 0000000..53fd173
--- /dev/null
+++ b/panels/thunderbolt/icons/scalable/org.gnome.Settings-thunderbolt-symbolic.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <path d="m 7.804688 6 h 3.695312 l -4.339844 6.242188 l 1.671875 0.171874 l -4.183593 3.578126 l 1.964843 -1.035157 c 0.316407 0.039063 1.007813 0.0625 1.335938 0.0625 c 3.867187 0 7.003906 -3.136719 7.003906 -7.003906 c -0.015625 -2.46875 -1.28125 -5.007813 -4.003906 -6.328125 l 0.160156 -1.6796875 z m -6.851563 2.015625 c 0 2.625 1.441406 4.917969 3.582031 6.113281 l 0.316406 -3.71875 l 1.011719 1.203125 l 1.804688 -3.613281 h -3.714844 l 3.160156 -6.933594 c -3.46875 0.414063 -6.160156 3.367188 -6.160156 6.949219" fill="#2e3434"/>
+</svg>
diff --git a/panels/thunderbolt/meson.build b/panels/thunderbolt/meson.build
new file mode 100644
index 0000000..241114f
--- /dev/null
+++ b/panels/thunderbolt/meson.build
@@ -0,0 +1,70 @@
+panels_list += cappletname
+
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+sources = files(
+ 'bolt-client.c',
+ 'bolt-device.c',
+ 'bolt-enums.c',
+ 'bolt-error.c',
+ 'bolt-names.c',
+ 'bolt-proxy.c',
+ 'bolt-str.c',
+ 'bolt-time.c',
+ 'cc-bolt-panel.c',
+ 'cc-bolt-device-dialog.c',
+ 'cc-bolt-device-entry.c',
+)
+
+enum_headers = [
+ 'bolt-enums.h',
+ 'bolt-error.h'
+]
+
+sources += gnome.mkenums_simple(
+ 'bolt-enum-types',
+ sources: enum_headers)
+
+resource_data = files(
+ 'cc-bolt-device-dialog.ui',
+ 'cc-bolt-device-entry.ui',
+ 'cc-bolt-panel.ui'
+)
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ source_dir: '.',
+ c_name: 'cc_' + cappletname,
+ dependencies: resource_data,
+ export: true
+)
+
+deps = common_deps + [
+ polkit_gobject_dep,
+ m_dep,
+]
+
+panels_libs += static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [top_inc, common_inc],
+ dependencies: deps,
+ c_args: cflags
+)
+
+subdir('icons')
diff --git a/panels/thunderbolt/thunderbolt.gresource.xml b/panels/thunderbolt/thunderbolt.gresource.xml
new file mode 100644
index 0000000..8953d62
--- /dev/null
+++ b/panels/thunderbolt/thunderbolt.gresource.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/thunderbolt">
+ <file preprocess="xml-stripblanks">cc-bolt-device-dialog.ui</file>
+ <file preprocess="xml-stripblanks">cc-bolt-device-entry.ui</file>
+ <file preprocess="xml-stripblanks">cc-bolt-panel.ui</file>
+ </gresource>
+</gresources>
+
diff --git a/panels/thunderbolt/update-from-bolt.sh b/panels/thunderbolt/update-from-bolt.sh
new file mode 100755
index 0000000..8b22f08
--- /dev/null
+++ b/panels/thunderbolt/update-from-bolt.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+
+if [ $# -ne 1 ]; then
+ echo "$0: usage: <BOLT-SOURCE>"
+ exit 1
+fi
+
+boltsrc="$1"
+
+function die() {
+ echo $*
+ exit 1
+}
+
+function copyone() {
+ dst=$1
+ src="$boltsrc/$dst"
+
+ search=(common cli)
+ for base in ${search[*]}
+ do
+ path="$boltsrc/$base/$dst"
+ if [ -f $path ]; then
+ src=$path
+ break;
+ fi
+ done
+
+ if [ ! -f $src ]; then
+ echo -e "$dst \t[ skipped ] $src (ENOENT)"
+ elif cmp -s $src $dst; then
+ echo -e "$dst \t[ unchanged ]"
+ else
+ cp $src $dst || die "$dst [failed] source: $src"
+ echo -e "$dst \t[ updated ] $src"
+ git add $dst
+ fi
+}
+
+names=(client device enums error names proxy str time)
+
+for fn in ${names[*]}
+do
+ header="bolt-$fn.h"
+ source="bolt-$fn.c"
+
+ copyone $header
+ copyone $source
+done
+
diff --git a/panels/universal-access/cc-cursor-blinking-dialog.c b/panels/universal-access/cc-cursor-blinking-dialog.c
new file mode 100644
index 0000000..1cb9e91
--- /dev/null
+++ b/panels/universal-access/cc-cursor-blinking-dialog.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2020 Canonical Ltd.
+ *
+ * This program 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.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This program 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "cc-cursor-blinking-dialog.h"
+
+#define INTERFACE_SETTINGS "org.gnome.desktop.interface"
+#define KEY_CURSOR_BLINKING "cursor-blink"
+#define KEY_CURSOR_BLINKING_TIME "cursor-blink-time"
+
+struct _CcCursorBlinkingDialog
+{
+ GtkDialog parent;
+
+ GtkScale *blink_time_scale;
+ GtkSwitch *enable_switch;
+
+ GSettings *interface_settings;
+};
+
+G_DEFINE_TYPE (CcCursorBlinkingDialog, cc_cursor_blinking_dialog, GTK_TYPE_DIALOG);
+
+static void
+cc_cursor_blinking_dialog_dispose (GObject *object)
+{
+ CcCursorBlinkingDialog *self = CC_CURSOR_BLINKING_DIALOG (object);
+
+ g_clear_object (&self->interface_settings);
+
+ G_OBJECT_CLASS (cc_cursor_blinking_dialog_parent_class)->dispose (object);
+}
+
+static void
+cc_cursor_blinking_dialog_class_init (CcCursorBlinkingDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_cursor_blinking_dialog_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/universal-access/cc-cursor-blinking-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcCursorBlinkingDialog, blink_time_scale);
+ gtk_widget_class_bind_template_child (widget_class, CcCursorBlinkingDialog, enable_switch);
+}
+
+static void
+cc_cursor_blinking_dialog_init (CcCursorBlinkingDialog *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->interface_settings = g_settings_new (INTERFACE_SETTINGS);
+
+ g_settings_bind (self->interface_settings, KEY_CURSOR_BLINKING,
+ self->enable_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind (self->interface_settings, KEY_CURSOR_BLINKING_TIME,
+ gtk_range_get_adjustment (GTK_RANGE (self->blink_time_scale)), "value",
+ G_SETTINGS_BIND_DEFAULT);
+}
+
+CcCursorBlinkingDialog *
+cc_cursor_blinking_dialog_new (void)
+{
+ return g_object_new (cc_cursor_blinking_dialog_get_type (),
+ "use-header-bar", TRUE,
+ NULL);
+}
diff --git a/panels/universal-access/cc-cursor-blinking-dialog.h b/panels/universal-access/cc-cursor-blinking-dialog.h
new file mode 100644
index 0000000..46d5a05
--- /dev/null
+++ b/panels/universal-access/cc-cursor-blinking-dialog.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2020 Canonical Ltd.
+ *
+ * This program 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.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This program 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (CcCursorBlinkingDialog, cc_cursor_blinking_dialog, CC, CURSOR_BLINKING_DIALOG, GtkDialog)
+
+CcCursorBlinkingDialog *cc_cursor_blinking_dialog_new (void);
+
+G_END_DECLS
diff --git a/panels/universal-access/cc-cursor-blinking-dialog.ui b/panels/universal-access/cc-cursor-blinking-dialog.ui
new file mode 100644
index 0000000..e31e612
--- /dev/null
+++ b/panels/universal-access/cc-cursor-blinking-dialog.ui
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcCursorBlinkingDialog" parent="GtkDialog">
+ <property name="title" translatable="yes">Cursor Blinking</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="use_header_bar">1</property>
+ <child internal-child="headerbar">
+ <object class="GtkHeaderBar">
+ <child>
+ <object class="GtkSwitch" id="enable_switch">
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Enable</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="margin_start">12</property>
+ <property name="margin_end">12</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Cursor blinks in text fields.</property>
+ <property name="margin_start">12</property>
+ <property name="margin_end">6</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">12</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkGrid">
+ <property name="valign">start</property>
+ <property name="margin_start">12</property>
+ <property name="margin_end">6</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">12</property>
+ <property name="orientation">vertical</property>
+ <property name="row_spacing">18</property>
+ <property name="column_spacing">24</property>
+ <child>
+ <object class="GtkBox">
+ <property name="valign">start</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Speed</property>
+ <property name="mnemonic_widget">blink_time_scale</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScale" id="blink_time_scale">
+ <property name="hexpand">True</property>
+ <property name="adjustment">blink_time_adjustment</property>
+ <property name="draw_value">False</property>
+ <property name="width-request">400</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ <accessibility>
+ <property name="label" translatable="yes">Cursor blinking speed</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GtkAdjustment" id="blink_time_adjustment">
+ <property name="lower">100</property>
+ <property name="upper">2500</property>
+ <property name="value">1000</property>
+ <property name="step_increment">200</property>
+ <property name="page_increment">200</property>
+ </object>
+</interface>
diff --git a/panels/universal-access/cc-cursor-size-dialog.c b/panels/universal-access/cc-cursor-size-dialog.c
new file mode 100644
index 0000000..cfd8378
--- /dev/null
+++ b/panels/universal-access/cc-cursor-size-dialog.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2020 Canonical Ltd.
+ *
+ * This program 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.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This program 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "cc-cursor-size-dialog.h"
+
+#define INTERFACE_SETTINGS "org.gnome.desktop.interface"
+#define KEY_MOUSE_CURSOR_SIZE "cursor-size"
+
+struct _CcCursorSizeDialog
+{
+ GtkDialog parent;
+
+ GtkGrid *size_grid;
+
+ GSettings *interface_settings;
+};
+
+G_DEFINE_TYPE (CcCursorSizeDialog, cc_cursor_size_dialog, GTK_TYPE_DIALOG);
+
+static void
+cursor_size_toggled (CcCursorSizeDialog *self, GtkWidget *button)
+{
+ guint cursor_size;
+
+ if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
+ return;
+
+ cursor_size = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (button), "cursor-size"));
+ g_settings_set_int (self->interface_settings, KEY_MOUSE_CURSOR_SIZE, cursor_size);
+ g_debug ("Setting cursor size to %d", cursor_size);
+}
+
+static void
+cc_cursor_size_dialog_dispose (GObject *object)
+{
+ CcCursorSizeDialog *self = CC_CURSOR_SIZE_DIALOG (object);
+
+ g_clear_object (&self->interface_settings);
+
+ G_OBJECT_CLASS (cc_cursor_size_dialog_parent_class)->dispose (object);
+}
+
+static void
+cc_cursor_size_dialog_class_init (CcCursorSizeDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_cursor_size_dialog_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/universal-access/cc-cursor-size-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcCursorSizeDialog, size_grid);
+}
+
+static void
+cc_cursor_size_dialog_init (CcCursorSizeDialog *self)
+{
+ guint cursor_sizes[] = { 24, 32, 48, 64, 96 };
+ guint current_cursor_size, i;
+ GtkSizeGroup *size_group;
+ GtkWidget *last_radio_button = NULL;
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->interface_settings = g_settings_new (INTERFACE_SETTINGS);
+
+ current_cursor_size = g_settings_get_int (self->interface_settings,
+ KEY_MOUSE_CURSOR_SIZE);
+ size_group = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);
+
+ for (i = 0; i < G_N_ELEMENTS(cursor_sizes); i++)
+ {
+ GtkWidget *image, *button;
+ g_autofree gchar *cursor_image_name = NULL;
+
+ cursor_image_name = g_strdup_printf ("/org/gnome/control-center/universal-access/left_ptr_%dpx.png", cursor_sizes[i]);
+ image = gtk_image_new_from_resource (cursor_image_name);
+ gtk_image_set_pixel_size (GTK_IMAGE (image), cursor_sizes[i]);
+ gtk_widget_set_halign (image, GTK_ALIGN_CENTER);
+ gtk_widget_set_valign (image, GTK_ALIGN_CENTER);
+
+ button = gtk_toggle_button_new ();
+ gtk_toggle_button_set_group (GTK_TOGGLE_BUTTON (button), GTK_TOGGLE_BUTTON (last_radio_button));
+ last_radio_button = button;
+ g_object_set_data (G_OBJECT (button), "cursor-size", GUINT_TO_POINTER (cursor_sizes[i]));
+
+ gtk_button_set_child (GTK_BUTTON (button), image);
+ gtk_grid_attach (GTK_GRID (self->size_grid), button, i, 0, 1, 1);
+ gtk_size_group_add_widget (size_group, button);
+
+ g_signal_connect_object (button, "toggled",
+ G_CALLBACK (cursor_size_toggled), self, G_CONNECT_SWAPPED);
+
+ if (current_cursor_size == cursor_sizes[i])
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
+ }
+}
+
+CcCursorSizeDialog *
+cc_cursor_size_dialog_new (void)
+{
+ return g_object_new (cc_cursor_size_dialog_get_type (),
+ "use-header-bar", TRUE,
+ NULL);
+}
diff --git a/panels/universal-access/cc-cursor-size-dialog.h b/panels/universal-access/cc-cursor-size-dialog.h
new file mode 100644
index 0000000..29d2b1e
--- /dev/null
+++ b/panels/universal-access/cc-cursor-size-dialog.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2020 Canonical Ltd.
+ *
+ * This program 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.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This program 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (CcCursorSizeDialog, cc_cursor_size_dialog, CC, CURSOR_SIZE_DIALOG, GtkDialog)
+
+CcCursorSizeDialog *cc_cursor_size_dialog_new (void);
+
+G_END_DECLS
diff --git a/panels/universal-access/cc-cursor-size-dialog.ui b/panels/universal-access/cc-cursor-size-dialog.ui
new file mode 100644
index 0000000..37f10a3
--- /dev/null
+++ b/panels/universal-access/cc-cursor-size-dialog.ui
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcCursorSizeDialog" parent="GtkDialog">
+ <property name="title" translatable="yes">Cursor Size</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin_start">12</property>
+ <property name="margin_end">12</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">8</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="margin_start">12</property>
+ <property name="margin_end">6</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">6</property>
+ <property name="label" translatable="yes">Cursor size can be combined with zoom to make it easier to see the cursor.</property>
+ <property name="wrap">True</property>
+ <property name="max_width_chars">45</property>
+ <property name="xalign">0</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkGrid" id="size_grid">
+ <property name="hexpand">True</property>
+ <property name="halign">center</property>
+ <style>
+ <class name="linked"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/universal-access/cc-pointing-dialog.c b/panels/universal-access/cc-pointing-dialog.c
new file mode 100644
index 0000000..145867b
--- /dev/null
+++ b/panels/universal-access/cc-pointing-dialog.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2020 Canonical Ltd.
+ *
+ * This program 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.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This program 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "cc-pointing-dialog.h"
+
+#define MOUSE_SETTINGS "org.gnome.desktop.a11y.mouse"
+#define KEY_SECONDARY_CLICK_ENABLED "secondary-click-enabled"
+#define KEY_SECONDARY_CLICK_TIME "secondary-click-time"
+#define KEY_DWELL_CLICK_ENABLED "dwell-click-enabled"
+#define KEY_DWELL_TIME "dwell-time"
+#define KEY_DWELL_THRESHOLD "dwell-threshold"
+
+#define KEY_DOUBLE_CLICK_DELAY "double-click"
+
+struct _CcPointingDialog
+{
+ GtkDialog parent;
+
+ GtkBox *dwell_delay_box;
+ GtkScale *dwell_delay_scale;
+ GtkBox *dwell_threshold_box;
+ GtkScale *dwell_threshold_scale;
+ GtkSwitch *hover_click_switch;
+ GtkBox *secondary_click_delay_box;
+ GtkScale *secondary_click_delay_scale;
+ GtkSwitch *secondary_click_switch;
+
+ GSettings *mouse_settings;
+};
+
+G_DEFINE_TYPE (CcPointingDialog, cc_pointing_dialog, GTK_TYPE_DIALOG);
+
+static void
+cc_pointing_dialog_dispose (GObject *object)
+{
+ CcPointingDialog *self = CC_POINTING_DIALOG (object);
+
+ g_clear_object (&self->mouse_settings);
+
+ G_OBJECT_CLASS (cc_pointing_dialog_parent_class)->dispose (object);
+}
+
+static void
+cc_pointing_dialog_class_init (CcPointingDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_pointing_dialog_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/universal-access/cc-pointing-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcPointingDialog, dwell_delay_box);
+ gtk_widget_class_bind_template_child (widget_class, CcPointingDialog, dwell_delay_scale);
+ gtk_widget_class_bind_template_child (widget_class, CcPointingDialog, dwell_threshold_box);
+ gtk_widget_class_bind_template_child (widget_class, CcPointingDialog, dwell_threshold_scale);
+ gtk_widget_class_bind_template_child (widget_class, CcPointingDialog, hover_click_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcPointingDialog, secondary_click_delay_box);
+ gtk_widget_class_bind_template_child (widget_class, CcPointingDialog, secondary_click_delay_scale);
+ gtk_widget_class_bind_template_child (widget_class, CcPointingDialog, secondary_click_switch);
+}
+
+static void
+cc_pointing_dialog_init (CcPointingDialog *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->mouse_settings = g_settings_new (MOUSE_SETTINGS);
+
+ /* simulated secondary click */
+ g_settings_bind (self->mouse_settings, KEY_SECONDARY_CLICK_ENABLED,
+ self->secondary_click_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind (self->mouse_settings, KEY_SECONDARY_CLICK_TIME,
+ gtk_range_get_adjustment (GTK_RANGE (self->secondary_click_delay_scale)), "value",
+ G_SETTINGS_BIND_DEFAULT);
+ g_object_bind_property (self->secondary_click_switch, "active",
+ self->secondary_click_delay_box, "sensitive",
+ G_BINDING_SYNC_CREATE);
+
+ /* dwell click */
+ g_settings_bind (self->mouse_settings, KEY_DWELL_CLICK_ENABLED,
+ self->hover_click_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind (self->mouse_settings, KEY_DWELL_TIME,
+ gtk_range_get_adjustment (GTK_RANGE (self->dwell_delay_scale)), "value",
+ G_SETTINGS_BIND_DEFAULT);
+ g_object_bind_property (self->hover_click_switch, "active",
+ self->dwell_delay_box, "sensitive",
+ G_BINDING_SYNC_CREATE);
+
+ g_settings_bind (self->mouse_settings, KEY_DWELL_THRESHOLD,
+ gtk_range_get_adjustment (GTK_RANGE (self->dwell_threshold_scale)), "value",
+ G_SETTINGS_BIND_DEFAULT);
+ g_object_bind_property (self->hover_click_switch, "active",
+ self->dwell_threshold_box, "sensitive",
+ G_BINDING_SYNC_CREATE);
+}
+
+CcPointingDialog *
+cc_pointing_dialog_new (void)
+{
+ return g_object_new (cc_pointing_dialog_get_type (),
+ "use-header-bar", TRUE,
+ NULL);
+}
diff --git a/panels/universal-access/cc-pointing-dialog.h b/panels/universal-access/cc-pointing-dialog.h
new file mode 100644
index 0000000..c2754aa
--- /dev/null
+++ b/panels/universal-access/cc-pointing-dialog.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2020 Canonical Ltd.
+ *
+ * This program 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.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This program 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (CcPointingDialog, cc_pointing_dialog, CC, POINTING_DIALOG, GtkDialog)
+
+CcPointingDialog *cc_pointing_dialog_new (void);
+
+G_END_DECLS
diff --git a/panels/universal-access/cc-pointing-dialog.ui b/panels/universal-access/cc-pointing-dialog.ui
new file mode 100644
index 0000000..e35fade
--- /dev/null
+++ b/panels/universal-access/cc-pointing-dialog.ui
@@ -0,0 +1,306 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcPointingDialog" parent="GtkDialog">
+ <property name="title" translatable="yes">Click Assist</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="use_header_bar">1</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin_start">12</property>
+ <property name="margin_end">12</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="margin_end">6</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">12</property>
+ <property name="row_spacing">18</property>
+ <property name="column_spacing">24</property>
+ <child>
+ <object class="GtkBox">
+ <property name="valign">start</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Simulated Secondary Click</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">secondary_click_switch</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="secondary_click_description">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Trigger a secondary click by holding down the primary button</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="valign">start</property>
+ <property name="margin_start">10</property>
+ <property name="margin_end">10</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox" id="secondary_click_delay_box">
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="secondary_click_delay_label">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">A_cceptance delay:</property>
+ <property name="use_underline">True</property>
+ <property name="justify">center</property>
+ <property name="mnemonic_widget">secondary_click_delay_scale</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes" context="secondary click">Short</property>
+ <attributes>
+ <attribute name="scale" value="0.83"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScale" id="secondary_click_delay_scale">
+ <property name="adjustment">click_delay_adjustment</property>
+ <property name="draw_value">False</property>
+ <property name="hexpand">True</property>
+ <accessibility>
+ <property name="label" translatable="yes">Secondary click delay</property>
+ </accessibility>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes" context="secondary click delay">Long</property>
+ <attributes>
+ <attribute name="scale" value="0.83"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="valign">start</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Hover Click</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">hover_click_switch</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="hover_click_description">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Trigger a click when the pointer hovers</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="valign">start</property>
+ <property name="margin_start">10</property>
+ <property name="margin_end">10</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox" id="dwell_delay_box">
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="dwell_delay_label">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">D_elay:</property>
+ <property name="use_underline">True</property>
+ <property name="justify">center</property>
+ <property name="mnemonic_widget">dwell_delay_scale</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes" context="dwell click delay">Short</property>
+ <property name="justify">center</property>
+ <attributes>
+ <attribute name="scale" value="0.83"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScale" id="dwell_delay_scale">
+ <property name="adjustment">dwell_time_adjustment</property>
+ <property name="draw_value">False</property>
+ <property name="value_pos">right</property>
+ <property name="hexpand">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes" context="dwell click delay">Long</property>
+ <property name="justify">center</property>
+ <attributes>
+ <attribute name="scale" value="0.83"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="dwell_threshold_box">
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="dwell_threshold_label">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Motion _threshold:</property>
+ <property name="use_underline">True</property>
+ <property name="justify">center</property>
+ <property name="mnemonic_widget">dwell_threshold_scale</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes" context="dwell click threshold">Small</property>
+ <property name="justify">center</property>
+ <attributes>
+ <attribute name="scale" value="0.83"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScale" id="dwell_threshold_scale">
+ <property name="adjustment">dwell_threshold_adjustment</property>
+ <property name="digits">0</property>
+ <property name="draw_value">False</property>
+ <property name="hexpand">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes" context="dwell click threshold">Large</property>
+ <property name="justify">center</property>
+ <attributes>
+ <attribute name="scale" value="0.83"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="secondary_click_switch">
+ <property name="halign">end</property>
+ <property name="valign">start</property>
+ <property name="hexpand">True</property>
+ <accessibility>
+ <relation name="described-by">secondary_click_description</relation>
+ </accessibility>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="hover_click_switch">
+ <property name="halign">end</property>
+ <property name="valign">start</property>
+ <property name="hexpand">True</property>
+ <accessibility>
+ <relation name="described-by">hover_click_description</relation>
+ </accessibility>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GtkSizeGroup">
+ <widgets>
+ <widget name="secondary_click_delay_label"/>
+ <widget name="dwell_delay_label"/>
+ <widget name="dwell_threshold_label"/>
+ </widgets>
+ </object>
+ <object class="GtkAdjustment" id="click_delay_adjustment">
+ <property name="lower">0.5</property>
+ <property name="upper">3</property>
+ <property name="value">1.2</property>
+ <property name="step_increment">0.1</property>
+ <property name="page_increment">0.1</property>
+ </object>
+ <object class="GtkAdjustment" id="dwell_threshold_adjustment">
+ <property name="upper">30</property>
+ <property name="value">15</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">1</property>
+ </object>
+ <object class="GtkAdjustment" id="dwell_time_adjustment">
+ <property name="lower">0.2</property>
+ <property name="upper">3</property>
+ <property name="value">1.2</property>
+ <property name="step_increment">0.1</property>
+ <property name="page_increment">0.1</property>
+ </object>
+</interface>
diff --git a/panels/universal-access/cc-repeat-keys-dialog.c b/panels/universal-access/cc-repeat-keys-dialog.c
new file mode 100644
index 0000000..4a65399
--- /dev/null
+++ b/panels/universal-access/cc-repeat-keys-dialog.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2020 Canonical Ltd.
+ *
+ * This program 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.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This program 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "cc-repeat-keys-dialog.h"
+
+#define KEYBOARD_SETTINGS "org.gnome.desktop.peripherals.keyboard"
+#define KEY_REPEAT_KEYS "repeat"
+#define KEY_DELAY "delay"
+#define KEY_REPEAT_INTERVAL "repeat-interval"
+
+struct _CcRepeatKeysDialog
+{
+ GtkDialog parent;
+
+ GtkSwitch *enable_switch;
+ GtkGrid *delay_grid;
+ GtkScale *delay_scale;
+ GtkGrid *speed_grid;
+ GtkScale *speed_scale;
+
+ GSettings *keyboard_settings;
+};
+
+G_DEFINE_TYPE (CcRepeatKeysDialog, cc_repeat_keys_dialog, GTK_TYPE_DIALOG);
+
+static void
+on_repeat_keys_toggled (CcRepeatKeysDialog *self)
+{
+ gboolean on;
+
+ on = g_settings_get_boolean (self->keyboard_settings, KEY_REPEAT_KEYS);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->delay_grid), on);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->speed_grid), on);
+}
+
+static void
+cc_repeat_keys_dialog_dispose (GObject *object)
+{
+ CcRepeatKeysDialog *self = CC_REPEAT_KEYS_DIALOG (object);
+
+ g_clear_object (&self->keyboard_settings);
+
+ G_OBJECT_CLASS (cc_repeat_keys_dialog_parent_class)->dispose (object);
+}
+
+static void
+cc_repeat_keys_dialog_class_init (CcRepeatKeysDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_repeat_keys_dialog_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/universal-access/cc-repeat-keys-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcRepeatKeysDialog, enable_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcRepeatKeysDialog, delay_grid);
+ gtk_widget_class_bind_template_child (widget_class, CcRepeatKeysDialog, delay_scale);
+ gtk_widget_class_bind_template_child (widget_class, CcRepeatKeysDialog, speed_grid);
+ gtk_widget_class_bind_template_child (widget_class, CcRepeatKeysDialog, speed_scale);
+}
+
+static void
+cc_repeat_keys_dialog_init (CcRepeatKeysDialog *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->keyboard_settings = g_settings_new (KEYBOARD_SETTINGS);
+
+ g_signal_connect_object (self->keyboard_settings, "changed",
+ G_CALLBACK (on_repeat_keys_toggled), self, G_CONNECT_SWAPPED);
+ on_repeat_keys_toggled (self);
+
+ g_settings_bind (self->keyboard_settings, KEY_REPEAT_KEYS,
+ self->enable_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind (self->keyboard_settings, KEY_DELAY,
+ gtk_range_get_adjustment (GTK_RANGE (self->delay_scale)), "value",
+ G_SETTINGS_BIND_DEFAULT);
+ g_settings_bind (self->keyboard_settings, KEY_REPEAT_INTERVAL,
+ gtk_range_get_adjustment (GTK_RANGE (self->speed_scale)), "value",
+ G_SETTINGS_BIND_DEFAULT);
+}
+
+CcRepeatKeysDialog *
+cc_repeat_keys_dialog_new (void)
+{
+ return g_object_new (cc_repeat_keys_dialog_get_type (),
+ "use-header-bar", TRUE,
+ NULL);
+}
diff --git a/panels/universal-access/cc-repeat-keys-dialog.h b/panels/universal-access/cc-repeat-keys-dialog.h
new file mode 100644
index 0000000..ebc1a76
--- /dev/null
+++ b/panels/universal-access/cc-repeat-keys-dialog.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2020 Canonical Ltd.
+ *
+ * This program 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.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This program 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (CcRepeatKeysDialog, cc_repeat_keys_dialog, CC, REPEAT_KEYS_DIALOG, GtkDialog)
+
+CcRepeatKeysDialog *cc_repeat_keys_dialog_new (void);
+
+G_END_DECLS
diff --git a/panels/universal-access/cc-repeat-keys-dialog.ui b/panels/universal-access/cc-repeat-keys-dialog.ui
new file mode 100644
index 0000000..78fa550
--- /dev/null
+++ b/panels/universal-access/cc-repeat-keys-dialog.ui
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcRepeatKeysDialog" parent="GtkDialog">
+ <property name="title" translatable="yes">Repeat Keys</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="use_header_bar">1</property>
+ <child internal-child="headerbar">
+ <object class="GtkHeaderBar">
+ <child>
+ <object class="GtkSwitch" id="enable_switch">
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Enable</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="margin_start">12</property>
+ <property name="margin_end">12</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Key presses repeat when key is held down.</property>
+ <property name="margin_start">12</property>
+ <property name="margin_end">6</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">12</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkGrid" id="delay_grid">
+ <property name="valign">start</property>
+ <property name="margin_start">12</property>
+ <property name="margin_end">6</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">12</property>
+ <property name="orientation">vertical</property>
+ <property name="row_spacing">18</property>
+ <property name="column_spacing">24</property>
+ <child>
+ <object class="GtkBox">
+ <property name="valign">start</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="delay_label">
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Delay</property>
+ <property name="mnemonic_widget">delay_scale</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScale" id="delay_scale">
+ <property name="hexpand">True</property>
+ <property name="adjustment">repeat_delay_adjustment</property>
+ <property name="draw_value">False</property>
+ <property name="has_origin">False</property>
+ <property name="width-request">400</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ <accessibility>
+ <property name="label" translatable="yes">Repeat keys delay</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkGrid" id="speed_grid">
+ <property name="valign">start</property>
+ <property name="margin_start">12</property>
+ <property name="margin_end">6</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">12</property>
+ <property name="orientation">vertical</property>
+ <property name="row_spacing">18</property>
+ <property name="column_spacing">24</property>
+ <child>
+ <object class="GtkBox">
+ <property name="valign">start</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="speed_label">
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Speed</property>
+ <property name="mnemonic_widget">speed_scale</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScale" id="speed_scale">
+ <property name="hexpand">True</property>
+ <property name="adjustment">repeat_speed_adjustment</property>
+ <property name="draw_value">False</property>
+ <property name="has_origin">False</property>
+ <property name="inverted">True</property>
+ <property name="width-request">200</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ <accessibility>
+ <property name="label" translatable="yes">Repeat keys speed</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GtkAdjustment" id="repeat_delay_adjustment">
+ <property name="lower">100</property>
+ <property name="upper">2000</property>
+ <property name="value">500</property>
+ <property name="step_increment">10</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="repeat_speed_adjustment">
+ <property name="lower">0.5</property>
+ <property name="upper">110</property>
+ <property name="value">33.3</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">1</property>
+ </object>
+ <object class="GtkSizeGroup">
+ <widgets>
+ <widget name="delay_label"/>
+ <widget name="speed_label"/>
+ </widgets>
+ </object>
+ <object class="GtkSizeGroup">
+ <widgets>
+ <widget name="delay_scale"/>
+ <widget name="speed_scale"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/panels/universal-access/cc-typing-dialog.c b/panels/universal-access/cc-typing-dialog.c
new file mode 100644
index 0000000..35004d4
--- /dev/null
+++ b/panels/universal-access/cc-typing-dialog.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2020 Canonical Ltd.
+ *
+ * This program 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.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This program 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "cc-typing-dialog.h"
+
+#define KEYBOARD_SETTINGS "org.gnome.desktop.a11y.keyboard"
+#define KEY_KEYBOARD_TOGGLE "enable"
+#define KEY_STICKYKEYS_ENABLED "stickykeys-enable"
+#define KEY_STICKYKEYS_TWO_KEY_OFF "stickykeys-two-key-off"
+#define KEY_STICKYKEYS_MODIFIER_BEEP "stickykeys-modifier-beep"
+#define KEY_SLOWKEYS_ENABLED "slowkeys-enable"
+#define KEY_SLOWKEYS_DELAY "slowkeys-delay"
+#define KEY_SLOWKEYS_BEEP_PRESS "slowkeys-beep-press"
+#define KEY_SLOWKEYS_BEEP_ACCEPT "slowkeys-beep-accept"
+#define KEY_SLOWKEYS_BEEP_REJECT "slowkeys-beep-reject"
+#define KEY_BOUNCEKEYS_ENABLED "bouncekeys-enable"
+#define KEY_BOUNCEKEYS_DELAY "bouncekeys-delay"
+#define KEY_BOUNCEKEYS_BEEP_REJECT "bouncekeys-beep-reject"
+
+struct _CcTypingDialog
+{
+ GtkDialog parent;
+
+ GtkCheckButton *bouncekeys_beep_rejected_check;
+ GtkBox *bouncekeys_delay_box;
+ GtkScale *bouncekeys_delay_scale;
+ GtkSwitch *bouncekeys_switch;
+ GtkSwitch *keyboard_toggle_switch;
+ GtkCheckButton *slowkeys_beep_accepted_check;
+ GtkCheckButton *slowkeys_beep_pressed_check;
+ GtkCheckButton *slowkeys_beep_rejected_check;
+ GtkBox *slowkeys_delay_box;
+ GtkScale *slowkeys_delay_scale;
+ GtkSwitch *slowkeys_switch;
+ GtkCheckButton *stickykeys_beep_modifier_check;
+ GtkCheckButton *stickykeys_disable_two_keys_check;
+ GtkSwitch *stickykeys_switch;
+
+ GSettings *keyboard_settings;
+};
+
+G_DEFINE_TYPE (CcTypingDialog, cc_typing_dialog, GTK_TYPE_DIALOG);
+
+static void
+cc_typing_dialog_dispose (GObject *object)
+{
+ CcTypingDialog *self = CC_TYPING_DIALOG (object);
+
+ g_clear_object (&self->keyboard_settings);
+
+ G_OBJECT_CLASS (cc_typing_dialog_parent_class)->dispose (object);
+}
+
+static void
+cc_typing_dialog_class_init (CcTypingDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_typing_dialog_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/universal-access/cc-typing-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcTypingDialog, bouncekeys_beep_rejected_check);
+ gtk_widget_class_bind_template_child (widget_class, CcTypingDialog, bouncekeys_delay_box);
+ gtk_widget_class_bind_template_child (widget_class, CcTypingDialog, bouncekeys_delay_scale);
+ gtk_widget_class_bind_template_child (widget_class, CcTypingDialog, bouncekeys_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcTypingDialog, keyboard_toggle_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcTypingDialog, slowkeys_beep_accepted_check);
+ gtk_widget_class_bind_template_child (widget_class, CcTypingDialog, slowkeys_beep_pressed_check);
+ gtk_widget_class_bind_template_child (widget_class, CcTypingDialog, slowkeys_beep_rejected_check);
+ gtk_widget_class_bind_template_child (widget_class, CcTypingDialog, slowkeys_delay_box);
+ gtk_widget_class_bind_template_child (widget_class, CcTypingDialog, slowkeys_delay_scale);
+ gtk_widget_class_bind_template_child (widget_class, CcTypingDialog, slowkeys_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcTypingDialog, stickykeys_beep_modifier_check);
+ gtk_widget_class_bind_template_child (widget_class, CcTypingDialog, stickykeys_disable_two_keys_check);
+ gtk_widget_class_bind_template_child (widget_class, CcTypingDialog, stickykeys_switch);
+}
+
+static void
+cc_typing_dialog_init (CcTypingDialog *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->keyboard_settings = g_settings_new (KEYBOARD_SETTINGS);
+
+ /* enable shortcuts */
+ g_settings_bind (self->keyboard_settings, KEY_KEYBOARD_TOGGLE,
+ self->keyboard_toggle_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ /* sticky keys */
+ g_settings_bind (self->keyboard_settings, KEY_STICKYKEYS_ENABLED,
+ self->stickykeys_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind (self->keyboard_settings, KEY_STICKYKEYS_TWO_KEY_OFF,
+ self->stickykeys_disable_two_keys_check, "active",
+ G_SETTINGS_BIND_NO_SENSITIVITY);
+ g_object_bind_property (self->stickykeys_switch, "active",
+ self->stickykeys_disable_two_keys_check, "sensitive",
+ G_BINDING_SYNC_CREATE);
+
+ g_settings_bind (self->keyboard_settings, KEY_STICKYKEYS_MODIFIER_BEEP,
+ self->stickykeys_beep_modifier_check, "active",
+ G_SETTINGS_BIND_NO_SENSITIVITY);
+ g_object_bind_property (self->stickykeys_switch, "active",
+ self->stickykeys_beep_modifier_check, "sensitive",
+ G_BINDING_SYNC_CREATE);
+
+ /* slow keys */
+ g_settings_bind (self->keyboard_settings, KEY_SLOWKEYS_ENABLED,
+ self->slowkeys_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind (self->keyboard_settings, KEY_SLOWKEYS_DELAY,
+ gtk_range_get_adjustment (GTK_RANGE (self->slowkeys_delay_scale)), "value",
+ G_SETTINGS_BIND_DEFAULT);
+ g_object_bind_property (self->slowkeys_switch, "active",
+ self->slowkeys_delay_box, "sensitive",
+ G_BINDING_SYNC_CREATE);
+
+ g_settings_bind (self->keyboard_settings, KEY_SLOWKEYS_BEEP_PRESS,
+ self->slowkeys_beep_pressed_check, "active",
+ G_SETTINGS_BIND_DEFAULT);
+ g_object_bind_property (self->slowkeys_switch, "active",
+ self->slowkeys_beep_pressed_check, "sensitive",
+ G_BINDING_SYNC_CREATE);
+
+ g_settings_bind (self->keyboard_settings, KEY_SLOWKEYS_BEEP_ACCEPT,
+ self->slowkeys_beep_accepted_check, "active",
+ G_SETTINGS_BIND_DEFAULT);
+ g_object_bind_property (self->slowkeys_switch, "active",
+ self->slowkeys_beep_accepted_check, "sensitive",
+ G_BINDING_SYNC_CREATE);
+
+ g_settings_bind (self->keyboard_settings, KEY_SLOWKEYS_BEEP_REJECT,
+ self->slowkeys_beep_rejected_check, "active",
+ G_SETTINGS_BIND_DEFAULT);
+ g_object_bind_property (self->slowkeys_switch, "active",
+ self->slowkeys_beep_rejected_check, "sensitive",
+ G_BINDING_SYNC_CREATE);
+
+ /* bounce keys */
+ g_settings_bind (self->keyboard_settings, KEY_BOUNCEKEYS_ENABLED,
+ self->bouncekeys_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind (self->keyboard_settings, KEY_BOUNCEKEYS_DELAY,
+ gtk_range_get_adjustment (GTK_RANGE (self->bouncekeys_delay_scale)), "value",
+ G_SETTINGS_BIND_DEFAULT);
+ g_object_bind_property (self->bouncekeys_switch, "active",
+ self->bouncekeys_delay_box, "sensitive",
+ G_BINDING_SYNC_CREATE);
+
+ g_settings_bind (self->keyboard_settings, KEY_BOUNCEKEYS_BEEP_REJECT,
+ self->bouncekeys_beep_rejected_check, "active",
+ G_SETTINGS_BIND_NO_SENSITIVITY);
+ g_object_bind_property (self->bouncekeys_switch, "active",
+ self->bouncekeys_beep_rejected_check, "sensitive",
+ G_BINDING_SYNC_CREATE);
+}
+
+CcTypingDialog *
+cc_typing_dialog_new (void)
+{
+ return g_object_new (cc_typing_dialog_get_type (),
+ "use-header-bar", TRUE,
+ NULL);
+}
diff --git a/panels/universal-access/cc-typing-dialog.h b/panels/universal-access/cc-typing-dialog.h
new file mode 100644
index 0000000..dfe0498
--- /dev/null
+++ b/panels/universal-access/cc-typing-dialog.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2020 Canonical Ltd.
+ *
+ * This program 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.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This program 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (CcTypingDialog, cc_typing_dialog, CC, TYPING_DIALOG, GtkDialog)
+
+CcTypingDialog *cc_typing_dialog_new (void);
+
+G_END_DECLS
diff --git a/panels/universal-access/cc-typing-dialog.ui b/panels/universal-access/cc-typing-dialog.ui
new file mode 100644
index 0000000..cf1ee25
--- /dev/null
+++ b/panels/universal-access/cc-typing-dialog.ui
@@ -0,0 +1,381 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcTypingDialog" parent="GtkDialog">
+ <property name="title" translatable="yes">Typing Assist</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="use_header_bar">1</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin_start">12</property>
+ <property name="margin_end">12</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="valign">start</property>
+ <property name="margin_start">12</property>
+ <property name="margin_end">6</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">12</property>
+ <property name="orientation">vertical</property>
+ <property name="row_spacing">18</property>
+ <property name="column_spacing">24</property>
+ <child>
+ <object class="GtkBox">
+ <property name="valign">start</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Sticky Keys</property>
+ <property name="mnemonic_widget">stickykeys_switch</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="sticky_keys_description">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Treats a sequence of modifier keys as a key combination</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="valign">start</property>
+ <property name="margin_start">10</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkCheckButton" id="stickykeys_disable_two_keys_check">
+ <property name="label" translatable="yes">_Disable if two keys are pressed together</property>
+ <property name="sensitive">False</property>
+ <property name="valign">start</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="stickykeys_beep_modifier_check">
+ <property name="label" translatable="yes">Beep when a _modifier key is pressed</property>
+ <property name="sensitive">False</property>
+ <property name="valign">start</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="use_underline">True</property>
+ <property name="label" translatable="yes">S_low Keys</property>
+ <property name="mnemonic_widget">slowkeys_switch</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="slow_keys_description">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Puts a delay between when a key is pressed and when it is accepted</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="valign">start</property>
+ <property name="margin_start">10</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox" id="slowkeys_delay_box">
+ <property name="sensitive">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">A_cceptance delay:</property>
+ <property name="use_underline">True</property>
+ <property name="justify">center</property>
+ <property name="mnemonic_widget">slowkeys_delay_scale</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes" context="slow keys delay">Short</property>
+ <attributes>
+ <attribute name="scale" value="0.83"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScale" id="slowkeys_delay_scale">
+ <property name="adjustment">slowkeys_delay_adjustment</property>
+ <property name="draw_value">False</property>
+ <property name="hexpand">True</property>
+ <accessibility>
+ <property name="label" translatable="yes">Slow keys typing delay</property>
+ </accessibility>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes" context="slow keys delay">Long</property>
+ <attributes>
+ <attribute name="scale" value="0.83"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="slowkeys_beep_pressed_check">
+ <property name="label" translatable="yes">Beep when a key is pr_essed</property>
+ <property name="active">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="slowkeys_beep_accepted_check">
+ <property name="label" translatable="yes">Beep when a key is _accepted</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="slowkeys_beep_rejected_check">
+ <property name="label" translatable="yes">Beep when a key is _rejected</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ </layout>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Bounce Keys</property>
+ <property name="mnemonic_widget">bouncekeys_switch</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="bounce_keys_description">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Ignores fast duplicate keypresses</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="valign">start</property>
+ <property name="margin_start">10</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox" id="bouncekeys_delay_box">
+ <property name="sensitive">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">A_cceptance delay:</property>
+ <property name="use_underline">True</property>
+ <property name="justify">center</property>
+ <property name="mnemonic_widget">bouncekeys_delay_scale</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes" context="bounce keys delay">Short</property>
+ <attributes>
+ <attribute name="scale" value="0.83"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScale" id="bouncekeys_delay_scale">
+ <property name="adjustment">bouncekeys_delay_adjustment</property>
+ <property name="draw_value">False</property>
+ <property name="hexpand">True</property>
+ <accessibility>
+ <property name="label" translatable="yes">Bounce keys typing delay</property>
+ </accessibility>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes" context="bounce keys delay">Long</property>
+ <attributes>
+ <attribute name="scale" value="0.83"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="bouncekeys_beep_rejected_check">
+ <property name="label" translatable="yes">Beep when a key is _rejected</property>
+ <property name="sensitive">False</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="stickykeys_switch">
+ <property name="halign">end</property>
+ <property name="valign">start</property>
+ <property name="hexpand">True</property>
+ <accessibility>
+ <relation name="described-by">sticky_keys_description</relation>
+ </accessibility>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="slowkeys_switch">
+ <property name="halign">end</property>
+ <property name="valign">start</property>
+ <property name="hexpand">True</property>
+ <accessibility>
+ <relation name="described-by">slow_keys_description</relation>
+ </accessibility>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="bouncekeys_switch">
+ <property name="halign">end</property>
+ <property name="valign">start</property>
+ <property name="hexpand">True</property>
+ <accessibility>
+ <relation name="described-by">bounce_keys_description</relation>
+ </accessibility>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ <child>
+ <object class="GtkLabel">
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Enable by Keyboard</property>
+ <property name="mnemonic_widget">keyboard_toggle_switch</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="keyboard_toggle_description">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Turn accessibility features on and off using the keyboard</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="keyboard_toggle_switch">
+ <property name="halign">end</property>
+ <property name="valign">start</property>
+ <property name="hexpand">True</property>
+ <accessibility>
+ <relation name="described-by">keyboard_toggle_description</relation>
+ </accessibility>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GtkAdjustment" id="bouncekeys_delay_adjustment">
+ <property name="upper">900</property>
+ <property name="value">0.5</property>
+ <property name="step_increment">10</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="slowkeys_delay_adjustment">
+ <property name="upper">500</property>
+ <property name="value">0.5</property>
+ <property name="step_increment">10</property>
+ <property name="page_increment">10</property>
+ </object>
+</interface>
diff --git a/panels/universal-access/cc-ua-panel.c b/panels/universal-access/cc-ua-panel.c
new file mode 100644
index 0000000..75cf893
--- /dev/null
+++ b/panels/universal-access/cc-ua-panel.c
@@ -0,0 +1,574 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2010 Intel, Inc
+ * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Thomas Wood <thomas.wood@intel.com>
+ * Rodrigo Moya <rodrigo@gnome.org>
+ *
+ */
+
+#include <config.h>
+
+#include <math.h>
+#include <glib/gi18n-lib.h>
+#include <gdesktop-enums.h>
+
+#include "cc-ua-panel.h"
+#include "cc-ua-resources.h"
+#include "cc-cursor-blinking-dialog.h"
+#include "cc-cursor-size-dialog.h"
+#include "cc-pointing-dialog.h"
+#include "cc-repeat-keys-dialog.h"
+#include "cc-typing-dialog.h"
+#include "cc-visual-alerts-dialog.h"
+#include "cc-zoom-options-dialog.h"
+
+#define DPI_FACTOR_LARGE 1.25
+#define DPI_FACTOR_NORMAL 1.0
+#define HIGH_CONTRAST_THEME "HighContrast"
+
+/* shell settings */
+#define A11Y_SETTINGS "org.gnome.desktop.a11y"
+#define KEY_ALWAYS_SHOW_STATUS "always-show-universal-access-status"
+
+/* a11y interface settings */
+#define A11Y_INTERFACE_SETTINGS "org.gnome.desktop.a11y.interface"
+#define KEY_HIGH_CONTRAST "high-contrast"
+
+/* interface settings */
+#define INTERFACE_SETTINGS "org.gnome.desktop.interface"
+#define KEY_TEXT_SCALING_FACTOR "text-scaling-factor"
+#define KEY_GTK_THEME "gtk-theme"
+#define KEY_ICON_THEME "icon-theme"
+#define KEY_CURSOR_BLINKING "cursor-blink"
+#define KEY_CURSOR_BLINKING_TIME "cursor-blink-time"
+#define KEY_MOUSE_CURSOR_SIZE "cursor-size"
+#define KEY_LOCATE_POINTER "locate-pointer"
+#define KEY_ENABLE_ANIMATIONS "enable-animations"
+
+/* application settings */
+#define APPLICATION_SETTINGS "org.gnome.desktop.a11y.applications"
+#define KEY_SCREEN_KEYBOARD_ENABLED "screen-keyboard-enabled"
+#define KEY_SCREEN_MAGNIFIER_ENABLED "screen-magnifier-enabled"
+#define KEY_SCREEN_READER_ENABLED "screen-reader-enabled"
+
+/* wm settings */
+#define WM_SETTINGS "org.gnome.desktop.wm.preferences"
+#define KEY_VISUAL_BELL_ENABLED "visual-bell"
+
+/* keyboard settings */
+#define KEYBOARD_SETTINGS "org.gnome.desktop.a11y.keyboard"
+#define KEY_KEYBOARD_TOGGLE "enable"
+#define KEY_STICKYKEYS_ENABLED "stickykeys-enable"
+#define KEY_STICKYKEYS_TWO_KEY_OFF "stickykeys-two-key-off"
+#define KEY_STICKYKEYS_MODIFIER_BEEP "stickykeys-modifier-beep"
+#define KEY_SLOWKEYS_ENABLED "slowkeys-enable"
+#define KEY_SLOWKEYS_DELAY "slowkeys-delay"
+#define KEY_SLOWKEYS_BEEP_PRESS "slowkeys-beep-press"
+#define KEY_SLOWKEYS_BEEP_ACCEPT "slowkeys-beep-accept"
+#define KEY_SLOWKEYS_BEEP_REJECT "slowkeys-beep-reject"
+#define KEY_BOUNCEKEYS_ENABLED "bouncekeys-enable"
+#define KEY_BOUNCEKEYS_DELAY "bouncekeys-delay"
+#define KEY_BOUNCEKEYS_BEEP_REJECT "bouncekeys-beep-reject"
+#define KEY_MOUSEKEYS_ENABLED "mousekeys-enable"
+#define KEY_TOGGLEKEYS_ENABLED "togglekeys-enable"
+
+/* keyboard desktop settings */
+#define KEYBOARD_DESKTOP_SETTINGS "org.gnome.desktop.peripherals.keyboard"
+#define KEY_REPEAT_KEYS "repeat"
+
+/* mouse settings */
+#define MOUSE_SETTINGS "org.gnome.desktop.a11y.mouse"
+#define KEY_SECONDARY_CLICK_ENABLED "secondary-click-enabled"
+#define KEY_SECONDARY_CLICK_TIME "secondary-click-time"
+#define KEY_DWELL_CLICK_ENABLED "dwell-click-enabled"
+#define KEY_DWELL_TIME "dwell-time"
+#define KEY_DWELL_THRESHOLD "dwell-threshold"
+
+#define MOUSE_PERIPHERAL_SETTINGS "org.gnome.desktop.peripherals.mouse"
+#define KEY_DOUBLE_CLICK_DELAY "double-click"
+
+struct _CcUaPanel
+{
+ CcPanel parent_instance;
+
+ GtkLabel *accessx_label;
+ AdwActionRow *accessx_row;
+ GtkLabel *click_assist_label;
+ AdwActionRow *click_assist_row;
+ GtkLabel *cursor_blinking_label;
+ AdwActionRow *cursor_blinking_row;
+ GtkLabel *cursor_size_label;
+ AdwActionRow *cursor_size_row;
+ GtkScale *double_click_delay_scale;
+ GtkSwitch *enable_animations_switch;
+ GtkSwitch *highcontrast_enable_switch;
+ GtkSwitch *large_text_enable_switch;
+ GtkSwitch *locate_pointer_enable_switch;
+ GtkSwitch *mouse_keys_enable_switch;
+ GtkLabel *repeat_keys_label;
+ AdwActionRow *repeat_keys_row;
+ GtkSwitch *screen_keyboard_enable_switch;
+ GtkSwitch *screen_reader_switch;
+ AdwActionRow *screen_reader_row;
+ GtkSwitch *show_status_switch;
+ GtkSwitch *sound_keys_switch;
+ AdwActionRow *sound_keys_row;
+ GtkLabel *visual_alerts_label;
+ AdwActionRow *visual_alerts_row;
+ GtkLabel *zoom_label;
+ AdwActionRow *zoom_row;
+
+ GSettings *wm_settings;
+ GSettings *a11y_settings;
+ GSettings *a11y_interface_settings;
+ GSettings *interface_settings;
+ GSettings *kb_settings;
+ GSettings *mouse_settings;
+ GSettings *kb_desktop_settings;
+ GSettings *application_settings;
+ GSettings *gds_mouse_settings;
+};
+
+CC_PANEL_REGISTER (CcUaPanel, cc_ua_panel)
+
+static void
+run_dialog (CcUaPanel *self, GtkDialog *dialog)
+{
+ GtkNative *native = gtk_widget_get_native (GTK_WIDGET (self));
+
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (native));
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+static void
+activate_row (CcUaPanel *self, AdwActionRow *row)
+{
+ if (row == self->zoom_row)
+ {
+ run_dialog (self, GTK_DIALOG (cc_zoom_options_dialog_new ()));
+ }
+ else if (row == self->cursor_size_row)
+ {
+ run_dialog (self, GTK_DIALOG (cc_cursor_size_dialog_new ()));
+ }
+ else if (row == self->visual_alerts_row)
+ {
+ run_dialog (self, GTK_DIALOG (cc_visual_alerts_dialog_new ()));
+ }
+ else if (row == self->repeat_keys_row)
+ {
+ run_dialog (self, GTK_DIALOG (cc_repeat_keys_dialog_new ()));
+ }
+ else if (row == self->cursor_blinking_row)
+ {
+ run_dialog (self, GTK_DIALOG (cc_cursor_blinking_dialog_new ()));
+ }
+ else if (row == self->accessx_row)
+ {
+ run_dialog (self, GTK_DIALOG (cc_typing_dialog_new ()));
+ }
+ else if (row == self->click_assist_row)
+ {
+ run_dialog (self, GTK_DIALOG (cc_pointing_dialog_new ()));
+ }
+}
+
+static void
+cc_ua_panel_dispose (GObject *object)
+{
+ CcUaPanel *self = CC_UA_PANEL (object);
+
+ g_clear_object (&self->wm_settings);
+ g_clear_object (&self->a11y_settings);
+ g_clear_object (&self->a11y_interface_settings);
+ g_clear_object (&self->interface_settings);
+ g_clear_object (&self->kb_settings);
+ g_clear_object (&self->mouse_settings);
+ g_clear_object (&self->kb_desktop_settings);
+ g_clear_object (&self->application_settings);
+ g_clear_object (&self->gds_mouse_settings);
+
+ G_OBJECT_CLASS (cc_ua_panel_parent_class)->dispose (object);
+}
+
+static const char *
+cc_ua_panel_get_help_uri (CcPanel *panel)
+{
+ return "help:gnome-help/a11y";
+}
+
+static void
+cc_ua_panel_class_init (CcUaPanelClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+
+ panel_class->get_help_uri = cc_ua_panel_get_help_uri;
+
+ object_class->dispose = cc_ua_panel_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/universal-access/cc-ua-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, accessx_label);
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, accessx_row);
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, click_assist_label);
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, click_assist_row);
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, cursor_blinking_label);
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, cursor_blinking_row);
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, cursor_size_label);
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, cursor_size_row);
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, double_click_delay_scale);
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, enable_animations_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, highcontrast_enable_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, large_text_enable_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, locate_pointer_enable_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, mouse_keys_enable_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, repeat_keys_label);
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, repeat_keys_row);
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, screen_keyboard_enable_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, screen_reader_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, screen_reader_row);
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, show_status_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, sound_keys_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, sound_keys_row);
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, visual_alerts_label);
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, visual_alerts_row);
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, zoom_label);
+ gtk_widget_class_bind_template_child (widget_class, CcUaPanel, zoom_row);
+ gtk_widget_class_bind_template_callback (widget_class, activate_row);
+}
+
+/* seeing section */
+
+static gboolean
+is_large_factor (gdouble factor)
+{
+ return (factor > DPI_FACTOR_NORMAL);
+}
+
+static gboolean
+get_large_text_mapping (GValue *value,
+ GVariant *variant,
+ gpointer user_data)
+{
+ gdouble factor;
+
+ factor = g_variant_get_double (variant);
+ g_value_set_boolean (value, is_large_factor (factor));
+
+ return TRUE;
+}
+
+static GVariant *
+set_large_text_mapping (const GValue *value,
+ const GVariantType *expected_type,
+ gpointer user_data)
+{
+ gboolean large;
+ GSettings *settings = user_data;
+ GVariant *ret = NULL;
+
+ large = g_value_get_boolean (value);
+ if (large)
+ ret = g_variant_new_double (DPI_FACTOR_LARGE);
+ else
+ g_settings_reset (settings, KEY_TEXT_SCALING_FACTOR);
+
+ return ret;
+}
+
+static gboolean
+get_contrast_mapping (GValue *value,
+ GVariant *variant,
+ gpointer user_data)
+{
+ gboolean hc;
+
+ hc = g_variant_get_boolean (variant);
+ g_value_set_boolean (value, hc);
+
+ return TRUE;
+}
+
+static GVariant *
+set_contrast_mapping (const GValue *value,
+ const GVariantType *expected_type,
+ gpointer user_data)
+{
+ gboolean hc;
+ CcUaPanel *self = user_data;
+
+ hc = g_value_get_boolean (value);
+ if (hc)
+ {
+ g_settings_set_string (self->interface_settings, KEY_GTK_THEME, HIGH_CONTRAST_THEME);
+ }
+ else
+ {
+ g_settings_reset (self->interface_settings, KEY_GTK_THEME);
+ g_settings_reset (self->interface_settings, KEY_ICON_THEME);
+ }
+
+ return g_variant_new_boolean (hc);
+}
+
+static gboolean
+on_off_label_mapping_get (GValue *value,
+ GVariant *variant,
+ gpointer user_data)
+{
+ g_value_set_string (value, g_variant_get_boolean (variant) ? _("On") : _("Off"));
+
+ return TRUE;
+}
+
+static gboolean
+cursor_size_label_mapping_get (GValue *value,
+ GVariant *variant,
+ gpointer user_data)
+{
+ char *label;
+ int cursor_size;
+
+ cursor_size = g_variant_get_int32 (variant);
+
+ switch (cursor_size)
+ {
+ case 24:
+ /* translators: the labels will read:
+ * Cursor Size: Default */
+ label = g_strdup (C_("cursor size", "Default"));
+ break;
+ case 32:
+ label = g_strdup (C_("cursor size", "Medium"));
+ break;
+ case 48:
+ label = g_strdup (C_("cursor size", "Large"));
+ break;
+ case 64:
+ label = g_strdup (C_("cursor size", "Larger"));
+ break;
+ case 96:
+ label = g_strdup (C_("cursor size", "Largest"));
+ break;
+ default:
+ label = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE,
+ "%d pixel",
+ "%d pixels",
+ cursor_size),
+ cursor_size);
+ break;
+ }
+
+ g_value_take_string (value, label);
+
+ return TRUE;
+}
+
+static void
+cc_ua_panel_init_status (CcUaPanel *self)
+{
+ g_settings_bind (self->a11y_settings, KEY_ALWAYS_SHOW_STATUS,
+ self->show_status_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+}
+
+static void
+cc_ua_panel_init_seeing (CcUaPanel *self)
+{
+ g_settings_bind_with_mapping (self->a11y_interface_settings, KEY_HIGH_CONTRAST,
+ self->highcontrast_enable_switch,
+ "active", G_SETTINGS_BIND_DEFAULT,
+ get_contrast_mapping,
+ set_contrast_mapping,
+ self,
+ NULL);
+
+ /* enable animation */
+ g_settings_bind (self->interface_settings, KEY_ENABLE_ANIMATIONS,
+ self->enable_animations_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+
+ /* large text */
+
+ g_settings_bind_with_mapping (self->interface_settings, KEY_TEXT_SCALING_FACTOR,
+ self->large_text_enable_switch,
+ "active", G_SETTINGS_BIND_DEFAULT,
+ get_large_text_mapping,
+ set_large_text_mapping,
+ self->interface_settings,
+ NULL);
+
+ /* screen reader */
+
+ g_settings_bind (self->application_settings, "screen-reader-enabled",
+ self->screen_reader_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ /* sound keys */
+
+ g_settings_bind (self->kb_settings, KEY_TOGGLEKEYS_ENABLED,
+ self->sound_keys_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ /* cursor size */
+
+ g_settings_bind_with_mapping (self->interface_settings, KEY_MOUSE_CURSOR_SIZE, // FIXME
+ self->cursor_size_label,
+ "label", G_SETTINGS_BIND_GET,
+ cursor_size_label_mapping_get,
+ NULL, NULL, NULL);
+
+ /* zoom */
+
+ g_settings_bind_with_mapping (self->application_settings, "screen-magnifier-enabled",
+ self->zoom_label,
+ "label", G_SETTINGS_BIND_GET,
+ on_off_label_mapping_get,
+ NULL, NULL, NULL);
+}
+
+/* hearing/sound section */
+
+static void
+cc_ua_panel_init_hearing (CcUaPanel *self)
+{
+ g_settings_bind_with_mapping (self->wm_settings, KEY_VISUAL_BELL_ENABLED,
+ self->visual_alerts_label,
+ "label", G_SETTINGS_BIND_GET,
+ on_off_label_mapping_get,
+ NULL, NULL, NULL);
+}
+
+/* typing/keyboard section */
+static void
+on_repeat_keys_toggled (CcUaPanel *self)
+{
+ gboolean on;
+
+ on = g_settings_get_boolean (self->kb_desktop_settings, KEY_REPEAT_KEYS);
+
+ gtk_label_set_text (self->repeat_keys_label, on ? _("On") : _("Off"));
+}
+
+static void
+on_cursor_blinking_toggled (CcUaPanel *self)
+{
+ gboolean on;
+
+ on = g_settings_get_boolean (self->interface_settings, KEY_CURSOR_BLINKING);
+
+ gtk_label_set_text (self->cursor_blinking_label, on ? _("On") : _("Off"));
+}
+
+static void
+update_accessx_label (CcUaPanel *self)
+{
+ gboolean on;
+
+ on = g_settings_get_boolean (self->kb_settings, KEY_STICKYKEYS_ENABLED) ||
+ g_settings_get_boolean (self->kb_settings, KEY_SLOWKEYS_ENABLED) ||
+ g_settings_get_boolean (self->kb_settings, KEY_BOUNCEKEYS_ENABLED);
+
+ gtk_label_set_text (self->accessx_label, on ? _("On") : _("Off"));
+}
+
+static void
+cc_ua_panel_init_keyboard (CcUaPanel *self)
+{
+ /* on-screen keyboard */
+ g_settings_bind (self->application_settings, KEY_SCREEN_KEYBOARD_ENABLED,
+ self->screen_keyboard_enable_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ /* Repeat keys */
+ g_signal_connect_object (self->kb_desktop_settings, "changed",
+ G_CALLBACK (on_repeat_keys_toggled), self, G_CONNECT_SWAPPED);
+ on_repeat_keys_toggled (self);
+
+ /* Cursor Blinking */
+ g_signal_connect_object (self->interface_settings, "changed",
+ G_CALLBACK (on_cursor_blinking_toggled), self, G_CONNECT_SWAPPED);
+ on_cursor_blinking_toggled (self);
+
+ /* accessx */
+ g_signal_connect_object (self->kb_settings, "changed",
+ G_CALLBACK (update_accessx_label), self, G_CONNECT_SWAPPED);
+ update_accessx_label (self);
+}
+
+/* mouse/pointing & clicking section */
+static void
+update_click_assist_label (CcUaPanel *self)
+{
+ gboolean on;
+
+ on = g_settings_get_boolean (self->mouse_settings, KEY_SECONDARY_CLICK_ENABLED) ||
+ g_settings_get_boolean (self->mouse_settings, KEY_DWELL_CLICK_ENABLED);
+
+ gtk_label_set_text (self->click_assist_label, on ? _("On") : _("Off"));
+}
+
+
+static void
+cc_ua_panel_init_mouse (CcUaPanel *self)
+{
+ g_settings_bind (self->kb_settings, KEY_MOUSEKEYS_ENABLED,
+ self->mouse_keys_enable_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind (self->interface_settings, KEY_LOCATE_POINTER,
+ self->locate_pointer_enable_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_signal_connect_object (self->mouse_settings, "changed",
+ G_CALLBACK (update_click_assist_label), self, G_CONNECT_SWAPPED);
+ update_click_assist_label (self);
+
+ g_settings_bind (self->gds_mouse_settings, "double-click",
+ gtk_range_get_adjustment (GTK_RANGE (self->double_click_delay_scale)), "value",
+ G_SETTINGS_BIND_DEFAULT);
+
+ gtk_scale_add_mark (GTK_SCALE (self->double_click_delay_scale), 400, GTK_POS_BOTTOM, NULL);
+}
+
+static void
+cc_ua_panel_init (CcUaPanel *self)
+{
+ g_resources_register (cc_universal_access_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->interface_settings = g_settings_new (INTERFACE_SETTINGS);
+ self->a11y_interface_settings = g_settings_new (A11Y_INTERFACE_SETTINGS);
+ self->a11y_settings = g_settings_new (A11Y_SETTINGS);
+ self->wm_settings = g_settings_new (WM_SETTINGS);
+ self->kb_settings = g_settings_new (KEYBOARD_SETTINGS);
+ self->kb_desktop_settings = g_settings_new (KEYBOARD_DESKTOP_SETTINGS);
+ self->mouse_settings = g_settings_new (MOUSE_SETTINGS);
+ self->gds_mouse_settings = g_settings_new (MOUSE_PERIPHERAL_SETTINGS);
+ self->application_settings = g_settings_new (APPLICATION_SETTINGS);
+
+ cc_ua_panel_init_status (self);
+ cc_ua_panel_init_seeing (self);
+ cc_ua_panel_init_hearing (self);
+ cc_ua_panel_init_keyboard (self);
+ cc_ua_panel_init_mouse (self);
+}
diff --git a/panels/universal-access/cc-ua-panel.h b/panels/universal-access/cc-ua-panel.h
new file mode 100644
index 0000000..6d925fa
--- /dev/null
+++ b/panels/universal-access/cc-ua-panel.h
@@ -0,0 +1,31 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2010 Intel, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ *
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_UA_PANEL (cc_ua_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcUaPanel, cc_ua_panel, CC, UA_PANEL, CcPanel)
+
+G_END_DECLS
diff --git a/panels/universal-access/cc-ua-panel.ui b/panels/universal-access/cc-ua-panel.ui
new file mode 100644
index 0000000..fb01d98
--- /dev/null
+++ b/panels/universal-access/cc-ua-panel.ui
@@ -0,0 +1,308 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <object class="GtkAdjustment" id="double_click_delay_adjustment">
+ <property name="lower">100</property>
+ <property name="upper">1000</property>
+ <property name="value">400</property>
+ <property name="step_increment">100</property>
+ <property name="page_increment">100</property>
+ </object>
+ <template class="CcUaPanel" parent="CcPanel">
+ <child type="content">
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">_Always Show Accessibility Menu</property>
+ <property name="use-underline">True</property>
+ <property name="activatable-widget">show_status_switch</property>
+ <child type="suffix">
+ <object class="GtkSwitch" id="show_status_switch">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Seeing</property>
+ <child>
+ <object class="AdwActionRow" id="highcontrast_row">
+ <property name="title" translatable="yes">_High Contrast</property>
+ <property name="use-underline">True</property>
+ <property name="activatable-widget">highcontrast_enable_switch</property>
+ <child type="suffix">
+ <object class="GtkSwitch" id="highcontrast_enable_switch">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">_Large Text</property>
+ <property name="use-underline">True</property>
+ <property name="activatable-widget">large_text_enable_switch</property>
+ <child type="suffix">
+ <object class="GtkSwitch" id="large_text_enable_switch">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Enable A_nimations</property>
+ <property name="use-underline">True</property>
+ <property name="activatable-widget">enable_animations_switch</property>
+ <child type="suffix">
+ <object class="GtkSwitch" id="enable_animations_switch">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="screen_reader_row">
+ <property name="title" translatable="yes">Screen _Reader</property>
+ <property name="subtitle" translatable="yes">The screen reader reads displayed text as you move the focus.</property>
+ <property name="use-underline">True</property>
+ <property name="activatable-widget">screen_reader_switch</property>
+ <child type="suffix">
+ <object class="GtkSwitch" id="screen_reader_switch">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="sound_keys_row">
+ <property name="title" translatable="yes">_Sound Keys</property>
+ <property name="subtitle" translatable="yes">Beep when Num Lock or Caps Lock are turned on or off.</property>
+ <property name="use-underline">True</property>
+ <property name="activatable-widget">sound_keys_switch</property>
+ <child type="suffix">
+ <object class="GtkSwitch" id="sound_keys_switch">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="cursor_size_row">
+ <property name="title" translatable="yes">C_ursor Size</property>
+ <property name="use-underline">True</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="activate_row" swapped="yes"/>
+ <child type="suffix">
+ <object class="GtkLabel" id="cursor_size_label">
+ <property name="valign">center</property>
+ <property name="xalign">1</property>
+ </object>
+ </child>
+ <child type="suffix">
+ <object class="GtkImage">
+ <property name="valign">center</property>
+ <property name="icon-name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="zoom_row">
+ <property name="title" translatable="yes">_Zoom</property>
+ <property name="use-underline">True</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="activate_row" swapped="yes"/>
+ <child type="suffix">
+ <object class="GtkLabel" id="zoom_label">
+ <property name="valign">center</property>
+ <property name="xalign">1</property>
+ </object>
+ </child>
+ <child type="suffix">
+ <object class="GtkImage">
+ <property name="valign">center</property>
+ <property name="icon-name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Hearing</property>
+ <child>
+ <object class="AdwActionRow" id="visual_alerts_row">
+ <property name="title" translatable="yes">_Visual Alerts</property>
+ <property name="use-underline">True</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="activate_row" swapped="yes"/>
+ <child type="suffix">
+ <object class="GtkLabel" id="visual_alerts_label">
+ <property name="valign">center</property>
+ <property name="xalign">1</property>
+ </object>
+ </child>
+ <child type="suffix">
+ <object class="GtkImage">
+ <property name="valign">center</property>
+ <property name="icon-name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Typing</property>
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Screen _Keyboard</property>
+ <property name="use-underline">True</property>
+ <property name="activatable-widget">screen_keyboard_enable_switch</property>
+ <child type="suffix">
+ <object class="GtkSwitch" id="screen_keyboard_enable_switch">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="repeat_keys_row">
+ <property name="title" translatable="yes">R_epeat Keys</property>
+ <property name="use-underline">True</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="activate_row" swapped="yes"/>
+ <child type="suffix">
+ <object class="GtkLabel" id="repeat_keys_label">
+ <property name="valign">center</property>
+ <property name="xalign">1</property>
+ </object>
+ </child>
+ <child type="suffix">
+ <object class="GtkImage">
+ <property name="valign">center</property>
+ <property name="icon-name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="cursor_blinking_row">
+ <property name="title" translatable="yes">Cursor _Blinking</property>
+ <property name="use-underline">True</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="activate_row" swapped="yes"/>
+ <child type="suffix">
+ <object class="GtkLabel" id="cursor_blinking_label">
+ <property name="valign">center</property>
+ <property name="xalign">1</property>
+ </object>
+ </child>
+ <child type="suffix">
+ <object class="GtkImage">
+ <property name="valign">center</property>
+ <property name="icon-name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="accessx_row">
+ <property name="title" translatable="yes">_Typing Assist (AccessX)</property>
+ <property name="use-underline">True</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="activate_row" swapped="yes"/>
+ <child type="suffix">
+ <object class="GtkLabel" id="accessx_label">
+ <property name="valign">center</property>
+ <property name="xalign">1</property>
+ </object>
+ </child>
+ <child type="suffix">
+ <object class="GtkImage">
+ <property name="valign">center</property>
+ <property name="icon-name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Pointing &amp;amp; Clicking</property>
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">_Mouse Keys</property>
+ <property name="use-underline">True</property>
+ <property name="activatable-widget">mouse_keys_enable_switch</property>
+ <child type="suffix">
+ <object class="GtkSwitch" id="mouse_keys_enable_switch">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">_Locate Pointer</property>
+ <property name="use-underline">True</property>
+ <property name="activatable-widget">locate_pointer_enable_switch</property>
+ <child type="suffix">
+ <object class="GtkSwitch" id="locate_pointer_enable_switch">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="click_assist_row">
+ <property name="title" translatable="yes">_Click Assist</property>
+ <property name="use-underline">True</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="activate_row" swapped="yes"/>
+ <child type="suffix">
+ <object class="GtkLabel" id="click_assist_label">
+ <property name="valign">center</property>
+ <property name="xalign">1</property>
+ </object>
+ </child>
+ <child type="suffix">
+ <object class="GtkImage">
+ <property name="valign">center</property>
+ <property name="icon-name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="double_click_delay_row">
+ <property name="title" translatable="yes">_Double-Click Delay</property>
+ <property name="use-underline">True</property>
+ <signal name="activated" handler="activate_row" swapped="yes"/>
+ <child>
+ <object class="GtkScale" id="double_click_delay_scale">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="adjustment">double_click_delay_adjustment</property>
+ <property name="draw_value">False</property>
+ <accessibility>
+ <property name="label" translatable="yes">Double-Click Delay</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/universal-access/cc-visual-alerts-dialog.c b/panels/universal-access/cc-visual-alerts-dialog.c
new file mode 100644
index 0000000..398753d
--- /dev/null
+++ b/panels/universal-access/cc-visual-alerts-dialog.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2020 Canonical Ltd.
+ *
+ * This program 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.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This program 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <gdesktop-enums.h>
+
+#include "cc-visual-alerts-dialog.h"
+
+#define WM_SETTINGS "org.gnome.desktop.wm.preferences"
+#define KEY_VISUAL_BELL_ENABLED "visual-bell"
+#define KEY_VISUAL_BELL_TYPE "visual-bell-type"
+
+struct _CcVisualAlertsDialog
+{
+ GtkDialog parent;
+
+ GtkSwitch *enable_switch;
+ GtkCheckButton *screen_radio;
+ GtkButton *test_button;
+ GtkCheckButton *window_radio;
+
+ GSettings *wm_settings;
+};
+
+G_DEFINE_TYPE (CcVisualAlertsDialog, cc_visual_alerts_dialog, GTK_TYPE_DIALOG);
+
+static void
+visual_bell_type_notify_cb (CcVisualAlertsDialog *self)
+{
+ GtkCheckButton *widget;
+ GDesktopVisualBellType type;
+
+ type = g_settings_get_enum (self->wm_settings, KEY_VISUAL_BELL_TYPE);
+
+ if (type == G_DESKTOP_VISUAL_BELL_FRAME_FLASH)
+ widget = self->window_radio;
+ else
+ widget = self->screen_radio;
+
+ gtk_check_button_set_active (widget, TRUE);
+}
+
+static void
+visual_bell_type_toggle_cb (CcVisualAlertsDialog *self)
+{
+ gboolean frame_flash;
+ GDesktopVisualBellType type;
+
+ frame_flash = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->window_radio));
+
+ if (frame_flash)
+ type = G_DESKTOP_VISUAL_BELL_FRAME_FLASH;
+ else
+ type = G_DESKTOP_VISUAL_BELL_FULLSCREEN_FLASH;
+ g_settings_set_enum (self->wm_settings, KEY_VISUAL_BELL_TYPE, type);
+}
+
+static void
+test_flash (CcVisualAlertsDialog *self)
+{
+ GtkNative *native = gtk_widget_get_native (GTK_WIDGET (self));
+ GdkSurface *surface = gtk_native_get_surface (native);
+
+ gdk_surface_beep (surface);
+}
+
+static void
+cc_visual_alerts_dialog_dispose (GObject *object)
+{
+ CcVisualAlertsDialog *self = CC_VISUAL_ALERTS_DIALOG (object);
+
+ g_clear_object (&self->wm_settings);
+
+ G_OBJECT_CLASS (cc_visual_alerts_dialog_parent_class)->dispose (object);
+}
+
+static void
+cc_visual_alerts_dialog_class_init (CcVisualAlertsDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_visual_alerts_dialog_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/universal-access/cc-visual-alerts-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcVisualAlertsDialog, enable_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcVisualAlertsDialog, screen_radio);
+ gtk_widget_class_bind_template_child (widget_class, CcVisualAlertsDialog, test_button);
+ gtk_widget_class_bind_template_child (widget_class, CcVisualAlertsDialog, window_radio);
+}
+
+static void
+cc_visual_alerts_dialog_init (CcVisualAlertsDialog *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->wm_settings = g_settings_new (WM_SETTINGS);
+
+ /* set the initial visual bell values */
+ visual_bell_type_notify_cb (self);
+
+ /* and listen */
+ g_settings_bind (self->wm_settings, KEY_VISUAL_BELL_ENABLED,
+ self->enable_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_object_bind_property (self->enable_switch, "active",
+ self->window_radio, "sensitive",
+ G_BINDING_SYNC_CREATE);
+
+ g_object_bind_property (self->enable_switch, "active",
+ self->screen_radio, "sensitive",
+ G_BINDING_SYNC_CREATE);
+ g_signal_connect_object (self->wm_settings, "changed::" KEY_VISUAL_BELL_TYPE,
+ G_CALLBACK (visual_bell_type_notify_cb), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->window_radio,
+ "toggled", G_CALLBACK (visual_bell_type_toggle_cb), self, G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self->test_button,
+ "clicked", G_CALLBACK (test_flash), self, G_CONNECT_SWAPPED);
+}
+
+CcVisualAlertsDialog *
+cc_visual_alerts_dialog_new (void)
+{
+ return g_object_new (cc_visual_alerts_dialog_get_type (),
+ "use-header-bar", TRUE,
+ NULL);
+}
diff --git a/panels/universal-access/cc-visual-alerts-dialog.h b/panels/universal-access/cc-visual-alerts-dialog.h
new file mode 100644
index 0000000..49add84
--- /dev/null
+++ b/panels/universal-access/cc-visual-alerts-dialog.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2020 Canonical Ltd.
+ *
+ * This program 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.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This program 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (CcVisualAlertsDialog, cc_visual_alerts_dialog, CC, VISUAL_ALERTS_DIALOG, GtkDialog)
+
+CcVisualAlertsDialog *cc_visual_alerts_dialog_new (void);
+
+G_END_DECLS
diff --git a/panels/universal-access/cc-visual-alerts-dialog.ui b/panels/universal-access/cc-visual-alerts-dialog.ui
new file mode 100644
index 0000000..a162190
--- /dev/null
+++ b/panels/universal-access/cc-visual-alerts-dialog.ui
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="CcVisualAlertsDialog" parent="GtkDialog">
+ <property name="title" translatable="yes">Visual Alerts</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="use_header_bar">1</property>
+ <child internal-child="headerbar">
+ <object class="GtkHeaderBar">
+ <property name="show_title_buttons">True</property>
+ <child>
+ <object class="GtkButton" id="test_button">
+ <property name="label" translatable="yes">_Test flash</property>
+ <property name="use_underline">True</property>
+ <property name="valign">center</property>
+ <style>
+ <class name="text-button"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="margin_start">12</property>
+ <property name="margin_end">12</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="margin_start">12</property>
+ <property name="margin_end">6</property>
+ <property name="margin_top">6</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Use a visual indication when an alert sound occurs.</property>
+ <property name="wrap">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkGrid">
+ <property name="margin_start">12</property>
+ <property name="margin_end">6</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="row_spacing">12</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="hexpand">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Visual Alerts</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">enable_switch</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="enable_switch">
+ <property name="halign">end</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="screen_radio">
+ <property name="label" translatable="yes">Flash the entire _screen</property>
+ <property name="group">window_radio</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ <property name="column-span">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="window_radio">
+ <property name="label" translatable="yes">Flash the entire _window</property>
+ <property name="active">True</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ <property name="column-span">2</property>
+ </layout>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/universal-access/cc-zoom-options-dialog.c b/panels/universal-access/cc-zoom-options-dialog.c
new file mode 100644
index 0000000..1f06aa8
--- /dev/null
+++ b/panels/universal-access/cc-zoom-options-dialog.c
@@ -0,0 +1,553 @@
+/*
+ * Copyright 2011 Inclusive Design Research Centre, OCAD University.
+ *
+ * This program 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.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This program 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Joseph Scheuhammer <clown@alum.mit.edu>
+ */
+
+#include "cc-zoom-options-dialog.h"
+#include <gdk/gdk.h>
+#include <glib/gi18n.h>
+#include <string.h>
+
+#define POSITION_MODEL_VALUE_COLUMN 2
+#define FONT_SCALE 1.25
+
+struct _CcZoomOptionsDialog
+{
+ GtkDialog parent;
+
+ GSettings *settings;
+ GSettings *application_settings;
+
+ GtkWidget *screen_position_combobox;
+ GtkWidget *follow_mouse_radio;
+ GtkWidget *screen_part_radio;
+ GtkWidget *centered_radio;
+ GtkWidget *push_radio;
+ GtkWidget *proportional_radio;
+ GtkWidget *extend_beyond_checkbox;
+ GtkWidget *brightness_slider;
+ GtkWidget *contrast_slider;
+ GtkWidget *crosshair_picker_color_button;
+ GtkWidget *magnifier_factor_spin;
+ GtkWidget *seeing_zoom_switch;
+ GtkWidget *crosshair_thickness_scale;
+ GtkWidget *grayscale_slider;
+ GtkWidget *crosshair_clip_checkbox;
+ GtkWidget *crosshair_length_slider;
+ GtkWidget *crosshair_enabled_switcher;
+ GtkWidget *inverse_enabled_switch;
+};
+
+G_DEFINE_TYPE (CcZoomOptionsDialog, cc_zoom_options_dialog, GTK_TYPE_DIALOG);
+
+static gchar *brightness_keys[] = {
+ "brightness-red",
+ "brightness-green",
+ "brightness-blue",
+ NULL
+};
+
+static gchar *contrast_keys[] = {
+ "contrast-red",
+ "contrast-green",
+ "contrast-blue",
+ NULL
+};
+
+static void set_enable_screen_part_ui (CcZoomOptionsDialog *self);
+static void scale_label (GtkWidget *check, PangoAttrList *attrs);
+static void xhairs_length_add_marks (CcZoomOptionsDialog *self, GtkScale *scale);
+static void effects_slider_set_value (GtkRange *slider, GSettings *settings);
+static void brightness_slider_notify_cb (CcZoomOptionsDialog *self, const gchar *key);
+static void contrast_slider_notify_cb (CcZoomOptionsDialog *self, const gchar *key);
+static void effects_slider_changed (CcZoomOptionsDialog *self, GtkRange *slider);
+
+static void
+mouse_tracking_radio_toggled_cb (CcZoomOptionsDialog *self, GtkWidget *widget)
+{
+ if (!gtk_check_button_get_active (GTK_CHECK_BUTTON (widget)))
+ return;
+
+ if (widget == self->centered_radio)
+ g_settings_set_string (self->settings, "mouse-tracking", "centered");
+ else if (widget == self->proportional_radio)
+ g_settings_set_string (self->settings, "mouse-tracking", "proportional");
+ else if (widget == self->push_radio)
+ g_settings_set_string (self->settings, "mouse-tracking", "push");
+}
+
+static void
+mouse_tracking_notify_cb (CcZoomOptionsDialog *self)
+{
+ g_autofree gchar *tracking = NULL;
+
+ tracking = g_settings_get_string (self->settings, "mouse-tracking");
+ if (g_strcmp0 (tracking, "centered") == 0)
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->centered_radio), TRUE);
+ else if (g_strcmp0 (tracking, "proportional") == 0)
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->proportional_radio), TRUE);
+ else
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->push_radio), TRUE);
+}
+
+static void
+init_screen_part_section (CcZoomOptionsDialog *self, PangoAttrList *pango_attrs)
+{
+ gboolean lens_mode;
+
+ /* Scale the labels of the toggles */
+ scale_label (self->follow_mouse_radio, pango_attrs);
+ scale_label (self->screen_part_radio, pango_attrs);
+ scale_label (self->centered_radio, pango_attrs);
+ scale_label (self->push_radio, pango_attrs);
+ scale_label (self->proportional_radio, pango_attrs);
+ scale_label (self->extend_beyond_checkbox, pango_attrs);
+
+ lens_mode = g_settings_get_boolean (self->settings, "lens-mode");
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->follow_mouse_radio), lens_mode);
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->screen_part_radio), !lens_mode);
+
+ set_enable_screen_part_ui (self);
+
+ g_settings_bind (self->settings, "lens-mode",
+ self->follow_mouse_radio, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind (self->settings, "scroll-at-edges",
+ self->extend_beyond_checkbox, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_signal_connect_object (G_OBJECT (self->screen_part_radio), "toggled",
+ G_CALLBACK (set_enable_screen_part_ui), self, G_CONNECT_SWAPPED);
+
+ mouse_tracking_notify_cb (self);
+ g_signal_connect_object (G_OBJECT (self->settings), "changed::mouse-tracking",
+ G_CALLBACK (mouse_tracking_notify_cb), self, G_CONNECT_SWAPPED);
+}
+
+static void
+set_enable_screen_part_ui (CcZoomOptionsDialog *self)
+{
+ gboolean screen_part;
+
+ /* If the "screen part" radio is not checked, then the "follow mouse" radio
+ * is checked (== lens mode). Set mouse tracking back to the default.
+ */
+ screen_part = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->screen_part_radio));
+ if (!screen_part)
+ {
+ g_settings_set_string (self->settings,
+ "mouse-tracking", "proportional");
+ }
+
+ gtk_widget_set_sensitive (self->centered_radio, screen_part);
+ gtk_widget_set_sensitive (self->push_radio, screen_part);
+ gtk_widget_set_sensitive (self->proportional_radio, screen_part);
+ gtk_widget_set_sensitive (self->extend_beyond_checkbox, screen_part);
+}
+
+static void
+scale_label (GtkWidget *check, PangoAttrList *attrs)
+{
+ GtkWidget *label;
+
+ label = gtk_widget_get_first_child (check);
+ label = gtk_widget_get_next_sibling (label);
+ gtk_label_set_attributes (GTK_LABEL (label), attrs);
+}
+
+static void
+screen_position_combo_changed_cb (CcZoomOptionsDialog *self)
+{
+ g_autofree gchar *combo_value = NULL;
+ GtkTreeIter iter;
+
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (self->screen_position_combobox), &iter);
+
+ gtk_tree_model_get (gtk_combo_box_get_model (GTK_COMBO_BOX (self->screen_position_combobox)), &iter,
+ POSITION_MODEL_VALUE_COLUMN, &combo_value,
+ -1);
+
+ if (g_strcmp0 (combo_value, ""))
+ {
+ g_settings_set_string (self->settings, "screen-position", combo_value);
+ }
+}
+
+static void
+screen_position_notify_cb (CcZoomOptionsDialog *self,
+ const gchar *key)
+{
+ g_autofree gchar *position = NULL;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ GtkComboBox *combobox;
+ gboolean valid;
+
+ position = g_settings_get_string (self->settings, key);
+ combobox = GTK_COMBO_BOX (self->screen_position_combobox);
+ model = gtk_combo_box_get_model (combobox);
+
+ /* Find the matching screen position value in the combobox model. If nothing
+ * matches, leave the combobox as is.
+ */
+ valid = gtk_tree_model_get_iter_first (model, &iter);
+ while (valid)
+ {
+ g_autofree gchar *combo_value = NULL;
+
+ gtk_tree_model_get (model, &iter,
+ POSITION_MODEL_VALUE_COLUMN, &combo_value,
+ -1);
+ if (!g_strcmp0 (combo_value, position))
+ {
+ g_signal_handlers_block_by_func (combobox, screen_position_combo_changed_cb, self);
+ gtk_combo_box_set_active_iter (combobox, &iter);
+ g_signal_handlers_unblock_by_func (combobox, screen_position_combo_changed_cb, self);
+ break;
+ }
+
+ valid = gtk_tree_model_iter_next (model, &iter);
+ }
+}
+
+static void
+init_xhairs_color_opacity (GtkColorButton *color_button, GSettings *settings)
+{
+ g_autofree gchar *color_setting = NULL;
+ GdkRGBA rgba;
+
+ color_setting = g_settings_get_string (settings, "cross-hairs-color");
+ gdk_rgba_parse (&rgba, color_setting);
+
+ rgba.alpha = g_settings_get_double (settings, "cross-hairs-opacity");
+ gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (color_button), &rgba);
+}
+
+static void
+xhairs_color_notify_cb (CcZoomOptionsDialog *self)
+{
+ init_xhairs_color_opacity (GTK_COLOR_BUTTON (self->crosshair_picker_color_button), self->settings);
+}
+
+static void
+xhairs_opacity_notify_cb (CcZoomOptionsDialog *self, gchar *key)
+{
+ GdkRGBA rgba;
+ gdouble opacity;
+
+ opacity = g_settings_get_double (self->settings, key);
+ gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (self->crosshair_picker_color_button), &rgba);
+ rgba.alpha = opacity * 65535;
+ gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (self->crosshair_picker_color_button), &rgba);
+}
+
+#define TO_HEX(x) (int) ((gdouble) x * 255.0)
+static void
+xhairs_color_opacity_changed (CcZoomOptionsDialog *self)
+{
+ GdkRGBA rgba;
+ g_autofree gchar *color_string = NULL;
+
+ gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (self->crosshair_picker_color_button), &rgba);
+ color_string = g_strdup_printf ("#%02x%02x%02x",
+ TO_HEX(rgba.red),
+ TO_HEX(rgba.green),
+ TO_HEX(rgba.blue));
+
+ g_settings_set_string (self->settings, "cross-hairs-color", color_string);
+
+ g_settings_set_double (self->settings, "cross-hairs-opacity", rgba.alpha);
+}
+
+static void xhairs_length_add_marks (CcZoomOptionsDialog *self, GtkScale *scale)
+{
+ GtkAdjustment *scale_model;
+ GdkRectangle rect;
+ GdkMonitor *monitor;
+ GdkDisplay *display;
+ GdkSurface *surface;
+ GtkWindow *transient_for;
+ gint length, quarter_length;
+
+ /* Get maximum dimension of the monitor */
+ transient_for = gtk_window_get_transient_for (GTK_WINDOW (self));
+ display = gtk_widget_get_display (GTK_WIDGET (transient_for));
+ surface = gtk_native_get_surface (GTK_NATIVE (transient_for));
+ monitor = gdk_display_get_monitor_at_surface (display, surface);
+ gdk_monitor_get_geometry (monitor, &rect);
+
+ length = MAX (rect.width, rect.height);
+ scale_model = gtk_range_get_adjustment (GTK_RANGE (scale));
+
+ if (length < gtk_adjustment_get_upper (scale_model))
+ gtk_adjustment_set_upper (scale_model, length);
+
+ /* The crosshair is made up of four lines in pairs (top, bottom) and
+ (left, right). Stipulating: "quarter of the screen" means that the
+ length of one hair is 25% of the screen. */
+ quarter_length = length / 4;
+
+ gtk_scale_add_mark (scale, 0, GTK_POS_BOTTOM, C_("Distance", "Short"));
+ gtk_scale_add_mark (scale, quarter_length, GTK_POS_BOTTOM, C_("Distance", "¼ Screen"));
+ gtk_scale_add_mark (scale, quarter_length * 2 , GTK_POS_BOTTOM, C_("Distance", "½ Screen"));
+ gtk_scale_add_mark (scale, quarter_length * 3, GTK_POS_BOTTOM, C_("Distance", "¾ Screen"));
+ gtk_scale_add_mark (scale, length, GTK_POS_BOTTOM, C_("Distance", "Long"));
+}
+
+static void
+init_effects_slider (GtkRange *slider,
+ CcZoomOptionsDialog *self,
+ gchar **keys,
+ GCallback notify_cb)
+{
+ gchar **key;
+
+ g_object_set_data (G_OBJECT (slider), "settings-keys", keys);
+ effects_slider_set_value (slider, self->settings);
+
+ for (key = keys; *key; key++)
+ {
+ g_autofree gchar *signal = g_strdup_printf ("changed::%s", *key);
+ g_signal_connect_object (G_OBJECT (self->settings), signal, notify_cb, self, G_CONNECT_SWAPPED);
+ }
+ g_signal_connect_object (G_OBJECT (slider), "value-changed",
+ G_CALLBACK (effects_slider_changed),
+ self, G_CONNECT_SWAPPED);
+ gtk_scale_add_mark (GTK_SCALE (slider), 0, GTK_POS_BOTTOM, NULL);
+}
+
+static void
+effects_slider_set_value (GtkRange *slider, GSettings *settings)
+{
+ gchar **keys;
+ gdouble red, green, blue;
+ gdouble value;
+
+ keys = g_object_get_data (G_OBJECT (slider), "settings-keys");
+
+ red = g_settings_get_double (settings, keys[0]);
+ green = g_settings_get_double (settings, keys[1]);
+ blue = g_settings_get_double (settings, keys[2]);
+
+ if (red == green && green == blue)
+ value = red;
+ else
+ /* use NTSC conversion weights for reasonable average */
+ value = 0.299 * red + 0.587 * green + 0.114 * blue;
+
+ gtk_range_set_value (slider, value);
+}
+
+static void
+brightness_slider_notify_cb (CcZoomOptionsDialog *self,
+ const gchar *key)
+{
+ GtkRange *slider = GTK_RANGE (self->brightness_slider);
+
+ g_signal_handlers_block_by_func (slider, effects_slider_changed, self);
+ effects_slider_set_value (slider, self->settings);
+ g_signal_handlers_unblock_by_func (slider, effects_slider_changed, self);
+}
+
+static void
+contrast_slider_notify_cb (CcZoomOptionsDialog *self,
+ const gchar *key)
+{
+ GtkRange *slider = GTK_RANGE (self->contrast_slider);
+
+ g_signal_handlers_block_by_func (slider, effects_slider_changed, self);
+ effects_slider_set_value (slider, self->settings);
+ g_signal_handlers_unblock_by_func (slider, effects_slider_changed, self);
+}
+
+static void
+effects_slider_changed (CcZoomOptionsDialog *self, GtkRange *slider)
+{
+ gchar **keys, **key;
+ gdouble value;
+
+ keys = g_object_get_data (G_OBJECT (slider), "settings-keys");
+ value = gtk_range_get_value (slider);
+
+ for (key = keys; *key; key++)
+ {
+ g_settings_set_double (self->settings, *key, value);
+ }
+}
+
+static void
+cc_zoom_options_dialog_constructed (GObject *object)
+{
+ PangoAttribute *attr;
+ PangoAttrList *pango_attrs;
+ CcZoomOptionsDialog *self;
+
+ self = CC_ZOOM_OPTIONS_DIALOG (object);
+
+ G_OBJECT_CLASS (cc_zoom_options_dialog_parent_class)->constructed (object);
+
+ pango_attrs = pango_attr_list_new ();
+ attr = pango_attr_scale_new (FONT_SCALE);
+ pango_attr_list_insert (pango_attrs, attr);
+
+ /* Zoom switch */
+ g_settings_bind (self->application_settings, "screen-magnifier-enabled",
+ self->seeing_zoom_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ /* Magnification factor */
+ g_settings_bind (self->settings, "mag-factor",
+ gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (self->magnifier_factor_spin)),
+ "value", G_SETTINGS_BIND_DEFAULT);
+
+ /* Screen position combo */
+ screen_position_notify_cb (self, "screen-position");
+ g_signal_connect_object (self->settings, "changed::screen-position",
+ G_CALLBACK (screen_position_notify_cb), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->screen_position_combobox, "changed",
+ G_CALLBACK (screen_position_combo_changed_cb), self, G_CONNECT_SWAPPED);
+
+ /* Screen part section */
+ init_screen_part_section (self, pango_attrs);
+
+ /* Cross hairs: show/hide ... */
+ g_settings_bind (self->settings, "show-cross-hairs",
+ self->crosshair_enabled_switcher, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ /* ... Cross hairs: color and opacity */
+ init_xhairs_color_opacity (GTK_COLOR_BUTTON (self->crosshair_picker_color_button), self->settings);
+ g_signal_connect_object (self->settings, "changed::cross-hairs-color",
+ G_CALLBACK (xhairs_color_notify_cb), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->settings, "changed::cross-hairs-opacity",
+ G_CALLBACK (xhairs_opacity_notify_cb), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->crosshair_picker_color_button, "color-set",
+ G_CALLBACK (xhairs_color_opacity_changed),
+ self, G_CONNECT_SWAPPED);
+
+ /* ... Cross hairs: thickness ... */
+ g_settings_bind (self->settings, "cross-hairs-thickness",
+ gtk_range_get_adjustment (GTK_RANGE (self->crosshair_thickness_scale)), "value",
+ G_SETTINGS_BIND_DEFAULT);
+
+ /* ... Cross hairs: clip ... */
+ scale_label (self->crosshair_clip_checkbox, pango_attrs);
+ g_settings_bind (self->settings, "cross-hairs-clip",
+ self->crosshair_clip_checkbox, "active",
+ G_SETTINGS_BIND_INVERT_BOOLEAN);
+
+ /* ... Cross hairs: length ... */
+ g_settings_bind (self->settings, "cross-hairs-length",
+ gtk_range_get_adjustment (GTK_RANGE (self->crosshair_length_slider)), "value",
+ G_SETTINGS_BIND_DEFAULT);
+
+ /* ... Color effects ... */
+ g_settings_bind (self->settings, "invert-lightness", self->inverse_enabled_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ init_effects_slider (GTK_RANGE (self->brightness_slider),
+ self,
+ brightness_keys,
+ G_CALLBACK (brightness_slider_notify_cb));
+
+ init_effects_slider (GTK_RANGE (self->contrast_slider),
+ self,
+ contrast_keys,
+ G_CALLBACK (contrast_slider_notify_cb));
+
+ g_settings_bind (self->settings, "color-saturation",
+ gtk_range_get_adjustment (GTK_RANGE (self->grayscale_slider)), "value",
+ G_SETTINGS_BIND_DEFAULT);
+ gtk_scale_add_mark (GTK_SCALE(self->grayscale_slider), 1.0, GTK_POS_BOTTOM, NULL);
+
+ pango_attr_list_unref (pango_attrs);
+}
+
+static void
+cc_zoom_options_dialog_realize (GtkWidget *widget)
+{
+ CcZoomOptionsDialog *self = CC_ZOOM_OPTIONS_DIALOG (widget);
+
+ GTK_WIDGET_CLASS (cc_zoom_options_dialog_parent_class)->realize (widget);
+
+ xhairs_length_add_marks (self, GTK_SCALE (self->crosshair_length_slider));
+}
+
+static void
+cc_zoom_options_dialog_finalize (GObject *object)
+{
+ CcZoomOptionsDialog *self = CC_ZOOM_OPTIONS_DIALOG (object);
+
+ g_clear_object (&self->settings);
+ g_clear_object (&self->application_settings);
+
+ G_OBJECT_CLASS (cc_zoom_options_dialog_parent_class)->finalize (object);
+}
+
+static void
+cc_zoom_options_dialog_class_init (CcZoomOptionsDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = cc_zoom_options_dialog_finalize;
+ object_class->constructed = cc_zoom_options_dialog_constructed;
+
+ widget_class->realize = cc_zoom_options_dialog_realize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/universal-access/cc-zoom-options-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcZoomOptionsDialog, brightness_slider);
+ gtk_widget_class_bind_template_child (widget_class, CcZoomOptionsDialog, centered_radio);
+ gtk_widget_class_bind_template_child (widget_class, CcZoomOptionsDialog, contrast_slider);
+ gtk_widget_class_bind_template_child (widget_class, CcZoomOptionsDialog, crosshair_clip_checkbox);
+ gtk_widget_class_bind_template_child (widget_class, CcZoomOptionsDialog, crosshair_enabled_switcher);
+ gtk_widget_class_bind_template_child (widget_class, CcZoomOptionsDialog, crosshair_length_slider);
+ gtk_widget_class_bind_template_child (widget_class, CcZoomOptionsDialog, crosshair_picker_color_button);
+ gtk_widget_class_bind_template_child (widget_class, CcZoomOptionsDialog, crosshair_thickness_scale);
+ gtk_widget_class_bind_template_child (widget_class, CcZoomOptionsDialog, extend_beyond_checkbox);
+ gtk_widget_class_bind_template_child (widget_class, CcZoomOptionsDialog, follow_mouse_radio);
+ gtk_widget_class_bind_template_child (widget_class, CcZoomOptionsDialog, grayscale_slider);
+ gtk_widget_class_bind_template_child (widget_class, CcZoomOptionsDialog, inverse_enabled_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcZoomOptionsDialog, magnifier_factor_spin);
+ gtk_widget_class_bind_template_child (widget_class, CcZoomOptionsDialog, proportional_radio);
+ gtk_widget_class_bind_template_child (widget_class, CcZoomOptionsDialog, push_radio);
+ gtk_widget_class_bind_template_child (widget_class, CcZoomOptionsDialog, screen_part_radio);
+ gtk_widget_class_bind_template_child (widget_class, CcZoomOptionsDialog, screen_position_combobox);
+ gtk_widget_class_bind_template_child (widget_class, CcZoomOptionsDialog, seeing_zoom_switch);
+
+ gtk_widget_class_bind_template_callback (widget_class, mouse_tracking_radio_toggled_cb);
+}
+
+static void
+cc_zoom_options_dialog_init (CcZoomOptionsDialog *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->settings = g_settings_new ("org.gnome.desktop.a11y.magnifier");
+ self->application_settings = g_settings_new ("org.gnome.desktop.a11y.applications");
+}
+
+CcZoomOptionsDialog *
+cc_zoom_options_dialog_new (void)
+{
+ return g_object_new (cc_zoom_options_dialog_get_type (),
+ "use-header-bar", TRUE,
+ NULL);
+}
diff --git a/panels/universal-access/cc-zoom-options-dialog.h b/panels/universal-access/cc-zoom-options-dialog.h
new file mode 100644
index 0000000..de15aa8
--- /dev/null
+++ b/panels/universal-access/cc-zoom-options-dialog.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2011 Inclusive Design Research Centre, OCAD University.
+ *
+ * This program 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.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This program 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Joseph Scheuhammer <clown@alum.mit.edu>
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (CcZoomOptionsDialog, cc_zoom_options_dialog, CC, ZOOM_OPTIONS_DIALOG, GtkDialog)
+
+CcZoomOptionsDialog *cc_zoom_options_dialog_new (void);
+
+G_END_DECLS
diff --git a/panels/universal-access/cc-zoom-options-dialog.ui b/panels/universal-access/cc-zoom-options-dialog.ui
new file mode 100644
index 0000000..e212b85
--- /dev/null
+++ b/panels/universal-access/cc-zoom-options-dialog.ui
@@ -0,0 +1,686 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkAdjustment" id="brightness_adjustment">
+ <property name="lower">-0.75</property>
+ <property name="upper">0.75</property>
+ <property name="step_increment">0.10000000000000001</property>
+ <property name="page_increment">0.10000000000000001</property>
+ </object>
+ <object class="GtkAdjustment" id="contrast_adjustment">
+ <property name="lower">-0.75</property>
+ <property name="upper">0.75</property>
+ <property name="step_increment">0.10000000000000001</property>
+ <property name="page_increment">0.10000000000000001</property>
+ </object>
+ <object class="GtkAdjustment" id="grayscale_adjustment">
+ <property name="upper">1</property>
+ <property name="value">1</property>
+ <property name="step_increment">0.10000000000000001</property>
+ <property name="page_increment">0.20000000000000001</property>
+ </object>
+ <object class="GtkAdjustment" id="magnifier_factor_adjustment">
+ <property name="lower">1</property>
+ <property name="upper">20</property>
+ <property name="value">2</property>
+ <property name="step_increment">0.25</property>
+ <property name="page_increment">1</property>
+ </object>
+ <object class="GtkListStore" id="screen_position_model">
+ <columns>
+ <!-- column-name positions -->
+ <column type="gchararray"/>
+ <!-- column-name text_scale -->
+ <column type="gfloat"/>
+ <!-- column-name setting_value -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Full Screen</col>
+ <col id="1">1.25</col>
+ <col id="2">full-screen</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Top Half</col>
+ <col id="1">1.25</col>
+ <col id="2">top-half</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Bottom Half</col>
+ <col id="1">1.25</col>
+ <col id="2">bottom-half</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Left Half</col>
+ <col id="1">1.25</col>
+ <col id="2">left-half</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Right Half</col>
+ <col id="1">1.25</col>
+ <col id="2">right-half</col>
+ </row>
+ </data>
+ </object>
+ <template class="CcZoomOptionsDialog" parent="GtkDialog">
+ <property name="modal">True</property>
+ <property name="title" translatable="yes">Zoom Options</property>
+ <property name="resizable">False</property>
+ <property name="hide-on-close">True</property>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">3</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin_start">6</property>
+ <property name="margin_end">6</property>
+ <property name="margin_top">6</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">_Zoom</property>
+ <property name="hexpand">True</property>
+ <property name="xalign">0</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">seeing_zoom_switch</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ <attribute name="scale" value="1.25"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="seeing_zoom_switch" />
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkNotebook">
+ <property name="margin_start">6</property>
+ <property name="margin_end">6</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">6</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin_start">18</property>
+ <property name="margin_end">18</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="spacing">12</property>
+ <property name="orientation">vertical</property>
+
+ <!-- Magnification -->
+ <child>
+ <object class="GtkBox">
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Magnification:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">magnifier_factor_spin</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ <attribute name="scale" value="1.25"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="magnifier_factor_spin">
+ <property name="halign">start</property>
+ <property name="adjustment">magnifier_factor_adjustment</property>
+ <property name="digits">2</property>
+ <property name="hexpand">True</property>
+ <property name="margin-start">21</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Magnifier Position:</property>
+ <property name="xalign">0.0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ <attribute name="scale" value="1.25"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">6</property>
+ <property name="margin-start">24</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkGrid">
+ <child>
+ <object class="GtkCheckButton" id="follow_mouse_radio">
+ <property name="label" translatable="yes">_Follow mouse cursor</property>
+ <property name="active">True</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="screen_part_radio">
+ <property name="label" translatable="yes">_Screen part:</property>
+ <property name="group">follow_mouse_radio</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="screen_position_combobox">
+ <property name="model">screen_position_model</property>
+ <property name="active">0</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ <child>
+ <object class="GtkCellRendererText"/>
+ <attributes>
+ <attribute name="scale">1</attribute>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-start">18</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkCheckButton" id="extend_beyond_checkbox">
+ <property name="label" translatable="yes">Magnifier _extends outside of screen</property>
+ <property name="use_underline">True</property>
+ <property name="margin-start">2</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="centered_radio">
+ <property name="label" translatable="yes">_Keep magnifier cursor centered</property>
+ <property name="active">True</property>
+ <property name="use_underline">True</property>
+ <signal name="toggled" handler="mouse_tracking_radio_toggled_cb" object="CcZoomOptionsDialog" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="push_radio">
+ <property name="label" translatable="yes">Magnifier cursor _pushes contents around</property>
+ <property name="group">centered_radio</property>
+ <property name="use_underline">True</property>
+ <signal name="toggled" handler="mouse_tracking_radio_toggled_cb" object="CcZoomOptionsDialog" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="proportional_radio">
+ <property name="label" translatable="yes">Magnifier cursor moves with _contents</property>
+ <property name="group">centered_radio</property>
+ <property name="use_underline">True</property>
+ <signal name="toggled" handler="mouse_tracking_radio_toggled_cb" object="CcZoomOptionsDialog" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Magnifier</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="margin_start">18</property>
+ <property name="margin_end">24</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="spacing">12</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">_Crosshairs:</property>
+ <property name="use_markup">True</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">crosshair_enabled_switcher</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ <attribute name="scale" value="1.25"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="crosshair_enabled_switcher">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="crosshair_clip_checkbox">
+ <property name="label" translatable="yes">_Overlaps mouse cursor</property>
+ <property name="halign">start</property>
+ <property name="margin_start">100</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">8</property>
+ <property name="margin-start">16</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="column_spacing">12</property>
+ <property name="row_spacing">16</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Thickness:</property>
+ <property name="justify">center</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">crosshair_thickness_scale</property>
+ <property name="width_chars">12</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ <attributes>
+ <attribute name="scale" value="1.25"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">3</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes" context="universal access, thickness">Thin</property>
+ <property name="justify">center</property>
+ <attributes>
+ <attribute name="scale" value="1.25"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScale" id="crosshair_thickness_scale">
+ <property name="adjustment">crosshair_thickness_adjustment</property>
+ <property name="hexpand">True</property>
+ <property name="draw_value">False</property>
+ <property name="value_pos">right</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes" context="universal access, thickness">Thick</property>
+ <property name="justify">center</property>
+ <property name="margin-start">8</property>
+ <attributes>
+ <attribute name="scale" value="1.25"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Length:</property>
+ <property name="justify">center</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">crosshair_length_slider</property>
+ <property name="width_chars">12</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ <attributes>
+ <attribute name="scale" value="1.25"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">3</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ <child>
+ <object class="GtkScale" id="crosshair_length_slider">
+ <property name="adjustment">crosshair_length_adjustment</property>
+ <property name="hexpand">True</property>
+ <property name="draw_value">False</property>
+ <property name="value_pos">right</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes" comments="The color of the accessibility crosshair">Co_lor:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">crosshair_picker_color_button</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ <attributes>
+ <attribute name="scale" value="1.25"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="crosshair_picker_color_button">
+ <property name="valign">start</property>
+ <property name="halign">start</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Crosshairs</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="margin_start">18</property>
+ <property name="margin_end">24</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="spacing">12</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Color Effects:</property>
+ <property name="xalign">0</property>
+ <property name="use_markup">True</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ <attribute name="scale" value="1.25"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">8</property>
+ <property name="margin-start">16</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="row_spacing">16</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_White on black:</property>
+ <property name="justify">right</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">inverse_enabled_switch</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ <attributes>
+ <attribute name="scale" value="1.25"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Brightness:</property>
+ <property name="justify">right</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">brightness_slider</property>
+ <property name="width_chars">12</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ <attributes>
+ <attribute name="scale" value="1.25"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Contrast:</property>
+ <property name="justify">right</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">contrast_slider</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ <attributes>
+ <attribute name="scale" value="1.25"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes" context="universal access, contrast" comments="The contrast scale goes from Color to None (grayscale)">Co_lor</property>
+ <property name="justify">right</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">grayscale_slider</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ </layout>
+ <attributes>
+ <attribute name="scale" value="1.25"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">3</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ </layout>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes" context="universal access, color">None</property>
+ <property name="justify">center</property>
+ <attributes>
+ <attribute name="scale" value="1.25"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScale" id="grayscale_slider">
+ <property name="adjustment">grayscale_adjustment</property>
+ <property name="hexpand">True</property>
+ <property name="draw_value">False</property>
+ <property name="value_pos">right</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes" context="universal access, color">Full</property>
+ <property name="justify">center</property>
+ <property name="margin-start">8</property>
+ <attributes>
+ <attribute name="scale" value="1.25"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">12</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ <child>
+ <object class="GtkSwitch" id="inverse_enabled_switch" />
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">3</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes" context="universal access, brightness">Low</property>
+ <property name="justify">center</property>
+ <attributes>
+ <attribute name="scale" value="1.25"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScale" id="brightness_slider">
+ <property name="adjustment">brightness_adjustment</property>
+ <property name="hexpand">True</property>
+ <property name="draw_value">False</property>
+ <property name="value_pos">left</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes" context="universal access, brightness">High</property>
+ <property name="justify">center</property>
+ <property name="margin-start">8</property>
+ <attributes>
+ <attribute name="scale" value="1.25"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">3</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes" context="universal access, contrast">Low</property>
+ <property name="justify">center</property>
+ <attributes>
+ <attribute name="scale" value="1.25"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScale" id="contrast_slider">
+ <property name="adjustment">contrast_adjustment</property>
+ <property name="hexpand">True</property>
+ <property name="draw_value">False</property>
+ <property name="value_pos">left</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes" context="universal access, contrast">High</property>
+ <property name="justify">center</property>
+ <property name="margin-start">8</property>
+ <attributes>
+ <attribute name="scale" value="1.25"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Color Effects</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GtkAdjustment" id="crosshair_thickness_adjustment">
+ <property name="lower">1</property>
+ <property name="upper">100</property>
+ <property name="value">8</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="crosshair_length_adjustment">
+ <property name="lower">20</property>
+ <property name="upper">4096</property>
+ <property name="value">4096</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">100</property>
+ </object>
+</interface>
diff --git a/panels/universal-access/gnome-universal-access-panel.desktop.in.in b/panels/universal-access/gnome-universal-access-panel.desktop.in.in
new file mode 100644
index 0000000..ef770fe
--- /dev/null
+++ b/panels/universal-access/gnome-universal-access-panel.desktop.in.in
@@ -0,0 +1,18 @@
+[Desktop Entry]
+Name=Accessibility
+Comment=Make it easier to see, hear, type, point and click
+Exec=gnome-control-center universal-access
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-accessibility
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;X-GNOME-Settings-Panel;X-GNOME-DetailsSettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=Universal Access
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: Search terms to find the Accessibility panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=Keyboard;Mouse;a11y;Accessibility;Universal Access;Contrast;Cursor;Sound;Zoom;Screen;Reader;big;high;large;text;font;size;AccessX;Sticky;Keys;Slow;Bounce;Mouse;Double;click;Delay;Speed;Assist;Repeat;Blink;visual;hearing;audio;typing;animations;
diff --git a/panels/universal-access/icons/meson.build b/panels/universal-access/icons/meson.build
new file mode 100644
index 0000000..68f02a9
--- /dev/null
+++ b/panels/universal-access/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-accessibility-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/universal-access/icons/scalable/org.gnome.Settings-accessibility-symbolic.svg b/panels/universal-access/icons/scalable/org.gnome.Settings-accessibility-symbolic.svg
new file mode 100644
index 0000000..b7efb64
--- /dev/null
+++ b/panels/universal-access/icons/scalable/org.gnome.Settings-accessibility-symbolic.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <g fill="#2e3436">
+ <path d="m 8.015625 0 c 1.105469 0 2 0.894531 2 2 s -0.894531 2 -2 2 c -1.101563 0 -2 -0.894531 -2 -2 s 0.898437 -2 2 -2 z m 0 0"/>
+ <path d="m 2 7 h 3 v 9 h 2 v -4 c 0 -0.550781 0.449219 -1 1 -1 s 1 0.449219 1 1 v 4 h 2 v -9 h 3 v -2 h -12 z m 0 0"/>
+ </g>
+</svg>
diff --git a/panels/universal-access/left_ptr_24px.png b/panels/universal-access/left_ptr_24px.png
new file mode 100644
index 0000000..46f7760
--- /dev/null
+++ b/panels/universal-access/left_ptr_24px.png
Binary files differ
diff --git a/panels/universal-access/left_ptr_32px.png b/panels/universal-access/left_ptr_32px.png
new file mode 100644
index 0000000..5d9ba96
--- /dev/null
+++ b/panels/universal-access/left_ptr_32px.png
Binary files differ
diff --git a/panels/universal-access/left_ptr_48px.png b/panels/universal-access/left_ptr_48px.png
new file mode 100644
index 0000000..51b1dc2
--- /dev/null
+++ b/panels/universal-access/left_ptr_48px.png
Binary files differ
diff --git a/panels/universal-access/left_ptr_64px.png b/panels/universal-access/left_ptr_64px.png
new file mode 100644
index 0000000..4cf77a4
--- /dev/null
+++ b/panels/universal-access/left_ptr_64px.png
Binary files differ
diff --git a/panels/universal-access/left_ptr_96px.png b/panels/universal-access/left_ptr_96px.png
new file mode 100644
index 0000000..5897a7c
--- /dev/null
+++ b/panels/universal-access/left_ptr_96px.png
Binary files differ
diff --git a/panels/universal-access/meson.build b/panels/universal-access/meson.build
new file mode 100644
index 0000000..b86b8c3
--- /dev/null
+++ b/panels/universal-access/meson.build
@@ -0,0 +1,64 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+sources = files(
+ 'cc-cursor-blinking-dialog.c',
+ 'cc-cursor-size-dialog.c',
+ 'cc-pointing-dialog.c',
+ 'cc-repeat-keys-dialog.c',
+ 'cc-typing-dialog.c',
+ 'cc-ua-panel.c',
+ 'cc-visual-alerts-dialog.c',
+ 'cc-zoom-options-dialog.c'
+)
+
+resource_data = files(
+ 'cc-ua-panel.ui',
+ 'left_ptr_24px.png',
+ 'left_ptr_32px.png',
+ 'left_ptr_48px.png',
+ 'left_ptr_64px.png',
+ 'left_ptr_96px.png',
+ 'cc-cursor-blinking-dialog.ui',
+ 'cc-cursor-size-dialog.ui',
+ 'cc-pointing-dialog.ui',
+ 'cc-repeat-keys-dialog.ui',
+ 'cc-typing-dialog.ui',
+ 'cc-visual-alerts-dialog.ui',
+ 'cc-zoom-options-dialog.ui'
+)
+
+sources += gnome.compile_resources(
+ 'cc-ua-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname.underscorify(),
+ dependencies: resource_data,
+ export: true
+)
+
+deps = common_deps + [m_dep]
+
+panels_libs += static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [ top_inc, common_inc ],
+ dependencies: deps,
+ c_args: cflags
+)
+
+subdir('icons')
diff --git a/panels/universal-access/universal-access.gresource.xml b/panels/universal-access/universal-access.gresource.xml
new file mode 100644
index 0000000..713ef3d
--- /dev/null
+++ b/panels/universal-access/universal-access.gresource.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/universal-access">
+ <file preprocess="xml-stripblanks">cc-cursor-blinking-dialog.ui</file>
+ <file preprocess="xml-stripblanks">cc-cursor-size-dialog.ui</file>
+ <file preprocess="xml-stripblanks">cc-pointing-dialog.ui</file>
+ <file preprocess="xml-stripblanks">cc-repeat-keys-dialog.ui</file>
+ <file preprocess="xml-stripblanks">cc-typing-dialog.ui</file>
+ <file preprocess="xml-stripblanks">cc-ua-panel.ui</file>
+ <file preprocess="xml-stripblanks">cc-visual-alerts-dialog.ui</file>
+ <file preprocess="xml-stripblanks">cc-zoom-options-dialog.ui</file>
+ <file>left_ptr_24px.png</file>
+ <file>left_ptr_32px.png</file>
+ <file>left_ptr_48px.png</file>
+ <file>left_ptr_64px.png</file>
+ <file>left_ptr_96px.png</file>
+ </gresource>
+</gresources>
diff --git a/panels/usage/cc-usage-panel.c b/panels/usage/cc-usage-panel.c
new file mode 100644
index 0000000..29230aa
--- /dev/null
+++ b/panels/usage/cc-usage-panel.c
@@ -0,0 +1,362 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2018 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#include "cc-usage-panel.h"
+#include "cc-usage-panel-enums.h"
+#include "cc-usage-resources.h"
+#include "cc-util.h"
+
+#include <gio/gdesktopappinfo.h>
+#include <glib/gi18n.h>
+
+struct _CcUsagePanel
+{
+ CcPanel parent_instance;
+
+ GSettings *privacy_settings;
+
+ GtkSwitch *recently_used_switch;
+ AdwComboRow *retain_history_combo;
+
+ GtkSwitch *purge_trash_switch;
+ GtkSwitch *purge_temp_switch;
+ AdwComboRow *purge_after_combo;
+ GtkButton *purge_temp_button;
+ GtkButton *purge_trash_button;
+};
+
+CC_PANEL_REGISTER (CcUsagePanel, cc_usage_panel)
+
+static char *
+purge_after_name_cb (AdwEnumListItem *item,
+ gpointer user_data)
+{
+ switch (adw_enum_list_item_get_value (item))
+ {
+ case CC_USAGE_PANEL_PURGE_AFTER_1_HOUR:
+ /* Translators: Option for "Automatically Delete Period" in "Trash & Temporary Files" group */
+ return g_strdup (C_("purge_files", "1 hour"));
+ case CC_USAGE_PANEL_PURGE_AFTER_1_DAY:
+ /* Translators: Option for "Automatically Delete Period" in "Trash & Temporary Files" group */
+ return g_strdup (C_("purge_files", "1 day"));
+ case CC_USAGE_PANEL_PURGE_AFTER_2_DAYS:
+ /* Translators: Option for "Automatically Delete Period" in "Trash & Temporary Files" group */
+ return g_strdup (C_("purge_files", "2 days"));
+ case CC_USAGE_PANEL_PURGE_AFTER_3_DAYS:
+ /* Translators: Option for "Automatically Delete Period" in "Trash & Temporary Files" group */
+ return g_strdup (C_("purge_files", "3 days"));
+ case CC_USAGE_PANEL_PURGE_AFTER_4_DAYS:
+ /* Translators: Option for "Automatically Delete Period" in "Trash & Temporary Files" group */
+ return g_strdup (C_("purge_files", "4 days"));
+ case CC_USAGE_PANEL_PURGE_AFTER_5_DAYS:
+ /* Translators: Option for "Automatically Delete Period" in "Trash & Temporary Files" group */
+ return g_strdup (C_("purge_files", "5 days"));
+ case CC_USAGE_PANEL_PURGE_AFTER_6_DAYS:
+ /* Translators: Option for "Automatically Delete Period" in "Trash & Temporary Files" group */
+ return g_strdup (C_("purge_files", "6 days"));
+ case CC_USAGE_PANEL_PURGE_AFTER_7_DAYS:
+ /* Translators: Option for "Automatically Delete Period" in "Trash & Temporary Files" group */
+ return g_strdup (C_("purge_files", "7 days"));
+ case CC_USAGE_PANEL_PURGE_AFTER_14_DAYS:
+ /* Translators: Option for "Automatically Delete Period" in "Trash & Temporary Files" group */
+ return g_strdup (C_("purge_files", "14 days"));
+ case CC_USAGE_PANEL_PURGE_AFTER_30_DAYS:
+ /* Translators: Option for "Automatically Delete Period" in "Trash & Temporary Files" group */
+ return g_strdup (C_("purge_files", "30 days"));
+ default:
+ return NULL;
+ }
+}
+
+static void
+purge_after_combo_changed_cb (AdwComboRow *combo_row,
+ GParamSpec *pspec,
+ CcUsagePanel *self)
+{
+ AdwEnumListItem *item;
+ CcUsagePanelPurgeAfter value;
+
+ item = ADW_ENUM_LIST_ITEM (adw_combo_row_get_selected_item (combo_row));
+ value = adw_enum_list_item_get_value (item);
+
+ g_settings_set (self->privacy_settings, "old-files-age", "u", value);
+}
+
+static void
+set_purge_after_value_for_combo (AdwComboRow *combo_row,
+ CcUsagePanel *self)
+{
+ AdwEnumListModel *model;
+ guint value;
+
+ model = ADW_ENUM_LIST_MODEL (adw_combo_row_get_model (combo_row));
+
+ g_settings_get (self->privacy_settings, "old-files-age", "u", &value);
+ adw_combo_row_set_selected (combo_row,
+ adw_enum_list_model_find_position (model, value));
+}
+
+static GtkDialog *
+run_warning (CcUsagePanel *self,
+ const gchar *prompt,
+ const gchar *text,
+ const gchar *button_title)
+{
+ GtkWindow *parent;
+ GtkWidget *dialog;
+ GtkWidget *button;
+ CcShell *shell;
+
+ shell = cc_panel_get_shell (CC_PANEL (self));
+ parent = GTK_WINDOW (cc_shell_get_toplevel (shell));
+
+ dialog = gtk_message_dialog_new (parent,
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_NONE,
+ NULL);
+ g_object_set (dialog,
+ "text", prompt,
+ "secondary-text", text,
+ NULL);
+ gtk_dialog_add_button (GTK_DIALOG (dialog), _("_Cancel"), GTK_RESPONSE_CANCEL);
+ gtk_dialog_add_button (GTK_DIALOG (dialog), button_title, GTK_RESPONSE_OK);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), FALSE);
+
+ button = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+ gtk_style_context_add_class (gtk_widget_get_style_context (button), "destructive-action");
+
+ gtk_window_present (GTK_WINDOW (dialog));
+
+ return GTK_DIALOG (dialog);
+}
+
+static void
+on_empty_trash_warning_response_cb (GtkDialog *dialog,
+ gint response,
+ CcUsagePanel *self)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+
+ if (response != GTK_RESPONSE_OK)
+ goto out;
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+ g_dbus_connection_call (bus,
+ "org.gnome.SettingsDaemon.Housekeeping",
+ "/org/gnome/SettingsDaemon/Housekeeping",
+ "org.gnome.SettingsDaemon.Housekeeping",
+ "EmptyTrash",
+ NULL, NULL, 0, -1, NULL, NULL, NULL);
+
+out:
+ gtk_window_destroy (GTK_WINDOW (dialog));
+}
+
+static void
+empty_trash (CcUsagePanel *self)
+{
+ GtkDialog *dialog;
+
+ dialog = run_warning (self,
+ _("Empty all items from Trash?"),
+ _("All items in the Trash will be permanently deleted."),
+ _("_Empty Trash"));
+
+ g_signal_connect_object (dialog,
+ "response",
+ G_CALLBACK (on_empty_trash_warning_response_cb),
+ self,
+ 0);
+}
+
+static void
+on_purge_temp_warning_response_cb (GtkDialog *dialog,
+ gint response,
+ CcUsagePanel *self)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+
+ if (response != GTK_RESPONSE_OK)
+ goto out;
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+ g_dbus_connection_call (bus,
+ "org.gnome.SettingsDaemon.Housekeeping",
+ "/org/gnome/SettingsDaemon/Housekeeping",
+ "org.gnome.SettingsDaemon.Housekeeping",
+ "RemoveTempFiles",
+ NULL, NULL, 0, -1, NULL, NULL, NULL);
+
+out:
+ gtk_window_destroy (GTK_WINDOW (dialog));
+}
+static void
+purge_temp (CcUsagePanel *self)
+{
+ GtkDialog *dialog;
+
+ dialog = run_warning (self,
+ _("Delete all the temporary files?"),
+ _("All the temporary files will be permanently deleted."),
+ _("_Purge Temporary Files"));
+
+ g_signal_connect_object (dialog,
+ "response",
+ G_CALLBACK (on_purge_temp_warning_response_cb),
+ self,
+ 0);
+}
+
+static void
+cc_usage_panel_finalize (GObject *object)
+{
+ CcUsagePanel *self = CC_USAGE_PANEL (object);
+
+ g_clear_object (&self->privacy_settings);
+
+ G_OBJECT_CLASS (cc_usage_panel_parent_class)->finalize (object);
+}
+
+static char *
+retain_history_name_cb (AdwEnumListItem *item,
+ gpointer user_data)
+{
+ switch (adw_enum_list_item_get_value (item))
+ {
+ case CC_USAGE_PANEL_RETAIN_HISTORY_1_DAY:
+ /* Translators: Option for "File History Duration" in "File History" group */
+ return g_strdup (C_("retain_history", "1 day"));
+ case CC_USAGE_PANEL_RETAIN_HISTORY_7_DAYS:
+ /* Translators: Option for "File History Duration" in "File History" group */
+ return g_strdup (C_("retain_history", "7 days"));
+ case CC_USAGE_PANEL_RETAIN_HISTORY_30_DAYS:
+ /* Translators: Option for "File History Duration" in "File History" group */
+ return g_strdup (C_("retain_history", "30 days"));
+ case CC_USAGE_PANEL_RETAIN_HISTORY_FOREVER:
+ /* Translators: Option for "File History Duration" in "File History" group */
+ return g_strdup (C_("retain_history", "Forever"));
+ default:
+ return NULL;
+ }
+}
+
+static void
+retain_history_combo_changed_cb (AdwComboRow *combo_row,
+ GParamSpec *pspec,
+ CcUsagePanel *self)
+{
+ AdwEnumListItem *item;
+ CcUsagePanelRetainHistory value;
+
+ item = ADW_ENUM_LIST_ITEM (adw_combo_row_get_selected_item (combo_row));
+ value = adw_enum_list_item_get_value (item);
+
+ g_settings_set (self->privacy_settings, "recent-files-max-age", "i", value);
+}
+
+static void
+set_retain_history_value_for_combo (AdwComboRow *combo_row,
+ CcUsagePanel *self)
+{
+ AdwEnumListModel *model;
+ gint value;
+
+ model = ADW_ENUM_LIST_MODEL (adw_combo_row_get_model (combo_row));
+
+ g_settings_get (self->privacy_settings, "recent-files-max-age", "i", &value);
+ adw_combo_row_set_selected (combo_row,
+ adw_enum_list_model_find_position (model, value));
+}
+
+static void
+cc_usage_panel_init (CcUsagePanel *self)
+{
+ g_resources_register (cc_usage_get_resource ());
+
+ g_type_ensure (CC_TYPE_USAGE_PANEL_PURGE_AFTER);
+ g_type_ensure (CC_TYPE_USAGE_PANEL_RETAIN_HISTORY);
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->privacy_settings = g_settings_new ("org.gnome.desktop.privacy");
+
+ g_settings_bind (self->privacy_settings,
+ "remember-recent-files",
+ self->recently_used_switch,
+ "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ set_retain_history_value_for_combo (self->retain_history_combo, self);
+
+ g_settings_bind (self->privacy_settings,
+ "remember-recent-files",
+ self->retain_history_combo,
+ "sensitive",
+ G_SETTINGS_BIND_GET);
+
+ g_settings_bind (self->privacy_settings, "remove-old-trash-files",
+ self->purge_trash_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind (self->privacy_settings, "remove-old-temp-files",
+ self->purge_temp_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ set_purge_after_value_for_combo (self->purge_after_combo, self);
+
+ g_signal_connect_object (self->purge_trash_button, "clicked", G_CALLBACK (empty_trash), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->purge_temp_button, "clicked", G_CALLBACK (purge_temp), self, G_CONNECT_SWAPPED);
+}
+
+static void
+clear_recent (CcUsagePanel *self)
+{
+ GtkRecentManager *m;
+
+ m = gtk_recent_manager_get_default ();
+ gtk_recent_manager_purge_items (m, NULL);
+}
+
+static void
+cc_usage_panel_class_init (CcUsagePanelClass *klass)
+{
+ GObjectClass *oclass = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ oclass->finalize = cc_usage_panel_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/usage/cc-usage-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcUsagePanel, purge_after_combo);
+ gtk_widget_class_bind_template_child (widget_class, CcUsagePanel, purge_temp_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcUsagePanel, purge_trash_button);
+ gtk_widget_class_bind_template_child (widget_class, CcUsagePanel, purge_trash_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcUsagePanel, purge_temp_button);
+ gtk_widget_class_bind_template_child (widget_class, CcUsagePanel, recently_used_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcUsagePanel, retain_history_combo);
+
+ gtk_widget_class_bind_template_callback (widget_class, clear_recent);
+ gtk_widget_class_bind_template_callback (widget_class, retain_history_name_cb);
+ gtk_widget_class_bind_template_callback (widget_class, retain_history_combo_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, purge_after_name_cb);
+ gtk_widget_class_bind_template_callback (widget_class, purge_after_combo_changed_cb);
+}
diff --git a/panels/usage/cc-usage-panel.h b/panels/usage/cc-usage-panel.h
new file mode 100644
index 0000000..62a9a9e
--- /dev/null
+++ b/panels/usage/cc-usage-panel.h
@@ -0,0 +1,50 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2018 Red Hat, Inc
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_USAGE_PANEL (cc_usage_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcUsagePanel, cc_usage_panel, CC, USAGE_PANEL, CcPanel)
+
+typedef enum {
+ CC_USAGE_PANEL_PURGE_AFTER_1_HOUR = 0,
+ CC_USAGE_PANEL_PURGE_AFTER_1_DAY = 1,
+ CC_USAGE_PANEL_PURGE_AFTER_2_DAYS = 2,
+ CC_USAGE_PANEL_PURGE_AFTER_3_DAYS = 3,
+ CC_USAGE_PANEL_PURGE_AFTER_4_DAYS = 4,
+ CC_USAGE_PANEL_PURGE_AFTER_5_DAYS = 5,
+ CC_USAGE_PANEL_PURGE_AFTER_6_DAYS = 6,
+ CC_USAGE_PANEL_PURGE_AFTER_7_DAYS = 7,
+ CC_USAGE_PANEL_PURGE_AFTER_14_DAYS = 14,
+ CC_USAGE_PANEL_PURGE_AFTER_30_DAYS = 30,
+} CcUsagePanelPurgeAfter;
+
+typedef enum {
+ CC_USAGE_PANEL_RETAIN_HISTORY_1_DAY = 1,
+ CC_USAGE_PANEL_RETAIN_HISTORY_7_DAYS = 7,
+ CC_USAGE_PANEL_RETAIN_HISTORY_30_DAYS = 30,
+ CC_USAGE_PANEL_RETAIN_HISTORY_FOREVER = -1,
+} CcUsagePanelRetainHistory;
+
+G_END_DECLS
diff --git a/panels/usage/cc-usage-panel.ui b/panels/usage/cc-usage-panel.ui
new file mode 100644
index 0000000..7a5c27f
--- /dev/null
+++ b/panels/usage/cc-usage-panel.ui
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcUsagePanel" parent="CcPanel">
+ <child type="content">
+ <object class="AdwPreferencesPage">
+ <!-- File History -->
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">File History</property>
+ <property name="description" translatable="yes">File history keeps a record of files that you have used. This information is shared between applications, and makes it easier to find files that you might want to use.</property>
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">File H_istory</property>
+ <property name="activatable-widget">recently_used_switch</property>
+ <property name="use-underline">true</property>
+ <child>
+ <object class="GtkSwitch" id="recently_used_switch">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwComboRow" id="retain_history_combo">
+ <property name="title" translatable="yes">File _History Duration</property>
+ <property name="use-underline">true</property>
+ <signal name="notify::selected-item" handler="retain_history_combo_changed_cb"/>
+ <property name="model">
+ <object class="AdwEnumListModel">
+ <property name="enum-type">CcUsagePanelRetainHistory</property>
+ </object>
+ </property>
+ <property name="expression">
+ <closure type="gchararray" function="retain_history_name_cb"/>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="hexpand">true</property>
+ <property name="halign">end</property>
+ <property name="homogeneous">true</property>
+ <property name="spacing">12</property>
+ <property name="margin-top">12</property>
+ <child>
+ <object class="GtkButton" id="clear_recent_button">
+ <property name="valign">center</property>
+ <property name="label" translatable="yes">_Clear History…</property>
+ <property name="use_underline">1</property>
+ <signal name="clicked" handler="clear_recent" swapped="yes"/>
+ <style>
+ <class name="destructive-action"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <!-- Trash & Temporary Files -->
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Trash &amp;amp; Temporary Files</property>
+ <property name="description" translatable="yes">Trash and temporary files can sometimes include personal or sensitive information. Automatically deleting them can help to protect privacy.</property>
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Automatically Delete _Trash Content</property>
+ <property name="activatable-widget">purge_trash_switch</property>
+ <property name="use-underline">true</property>
+ <child>
+ <object class="GtkSwitch" id="purge_trash_switch">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Automatically Delete Temporary _Files</property>
+ <property name="activatable-widget">purge_temp_switch</property>
+ <property name="use-underline">true</property>
+ <child>
+ <object class="GtkSwitch" id="purge_temp_switch">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwComboRow" id="purge_after_combo">
+ <property name="title" translatable="yes">Automatically Delete _Period</property>
+ <property name="use-underline">true</property>
+ <signal name="notify::selected-item" handler="purge_after_combo_changed_cb"/>
+ <property name="model">
+ <object class="AdwEnumListModel">
+ <property name="enum-type">CcUsagePanelPurgeAfter</property>
+ </object>
+ </property>
+ <property name="expression">
+ <closure type="gchararray" function="purge_after_name_cb"/>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="hexpand">true</property>
+ <property name="halign">end</property>
+ <property name="homogeneous">true</property>
+ <property name="margin-top">12</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkButton" id="purge_trash_button">
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <property name="label" translatable="yes">_Empty Trash…</property>
+ <property name="use-underline">true</property>
+ <style>
+ <class name="destructive-action"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="purge_temp_button">
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <property name="label" translatable="yes">_Delete Temporary Files…</property>
+ <property name="use-underline">true</property>
+ <style>
+ <class name="destructive-action"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/usage/gnome-usage-panel.desktop.in.in b/panels/usage/gnome-usage-panel.desktop.in.in
new file mode 100644
index 0000000..8a62303
--- /dev/null
+++ b/panels/usage/gnome-usage-panel.desktop.in.in
@@ -0,0 +1,19 @@
+[Desktop Entry]
+Name=File History & Trash
+Comment=Don't leave traces
+Exec=gnome-control-center usage
+# FIXME
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-file-history-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-PrivacySettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=privacy
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: Search terms to find the Usage panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=usage;recent;history;files;temporary;tmp;private;privacy;trash;purge;retain;
diff --git a/panels/usage/icons/meson.build b/panels/usage/icons/meson.build
new file mode 100644
index 0000000..79f20c5
--- /dev/null
+++ b/panels/usage/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-file-history-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/usage/icons/scalable/org.gnome.Settings-file-history-symbolic.svg b/panels/usage/icons/scalable/org.gnome.Settings-file-history-symbolic.svg
new file mode 100644
index 0000000..eb459b9
--- /dev/null
+++ b/panels/usage/icons/scalable/org.gnome.Settings-file-history-symbolic.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <path d="m 4 0 c -1.644531 0 -3 1.355469 -3 3 v 9 c 0 1.644531 1.355469 3 3 3 h 8 c 1.644531 0 3 -1.355469 3 -3 v -9 c 0 -1.644531 -1.355469 -3 -3 -3 z m 0 2 h 8 c 0.570312 0 1 0.429688 1 1 v 4 h -10 v -4 c 0 -0.570312 0.429688 -1 1 -1 z m 2.464844 1.429688 c -0.019532 0 -0.039063 0.003906 -0.058594 0.007812 c -0.019531 0 -0.042969 0 -0.0625 0 c -0.214844 0.070312 -0.355469 0.273438 -0.34375 0.5 v 0.0625 c 0 0.546875 0.453125 1 1 1 h 2 c 0.546875 0 1 -0.453125 1 -1 v -0.0625 c 0.011719 -0.675781 -1.011719 -0.675781 -1 0 v 0.0625 h -2 v -0.0625 c 0.003906 -0.296875 -0.246094 -0.527344 -0.535156 -0.507812 z m -3.464844 4.570312 h 10 v 4 c 0 0.570312 -0.429688 1 -1 1 h -8 c -0.570312 0 -1 -0.429688 -1 -1 z m 3.464844 1.429688 c -0.019532 0 -0.039063 0.003906 -0.058594 0.007812 c -0.019531 0 -0.042969 0 -0.0625 0 c -0.214844 0.070312 -0.355469 0.273438 -0.34375 0.5 v 0.0625 c 0 0.546875 0.453125 1 1 1 h 2 c 0.546875 0 1 -0.453125 1 -1 v -0.0625 c 0.011719 -0.675781 -1.011719 -0.675781 -1 0 v 0.0625 h -2 v -0.0625 c 0.003906 -0.296875 -0.246094 -0.527344 -0.535156 -0.507812 z m 0 0" fill="#222222" fill-rule="evenodd"/>
+</svg>
diff --git a/panels/usage/meson.build b/panels/usage/meson.build
new file mode 100644
index 0000000..8365b83
--- /dev/null
+++ b/panels/usage/meson.build
@@ -0,0 +1,45 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+sources = files('cc-usage-panel.c')
+
+resource_data = files('cc-usage-panel.ui')
+
+sources += gnome.mkenums_simple(
+ 'cc-usage-panel-enums',
+ sources: ['cc-usage-panel.h'],
+)
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname,
+ dependencies: resource_data,
+ export: true
+)
+
+cflags += '-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir)
+
+panels_libs += static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [top_inc, common_inc],
+ dependencies: common_deps,
+ c_args: cflags
+)
+subdir('icons')
diff --git a/panels/usage/usage.gresource.xml b/panels/usage/usage.gresource.xml
new file mode 100644
index 0000000..3f55dbf
--- /dev/null
+++ b/panels/usage/usage.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/usage">
+ <file preprocess="xml-stripblanks">cc-usage-panel.ui</file>
+ </gresource>
+</gresources>
diff --git a/panels/user-accounts/cc-add-user-dialog.c b/panels/user-accounts/cc-add-user-dialog.c
new file mode 100644
index 0000000..e462015
--- /dev/null
+++ b/panels/user-accounts/cc-add-user-dialog.c
@@ -0,0 +1,1717 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2009-2010 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#include "config.h"
+
+#include <adwaita.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <act/act.h>
+
+#include "cc-add-user-dialog.h"
+#include "cc-realm-manager.h"
+#include "user-utils.h"
+#include "pw-utils.h"
+
+#define PASSWORD_CHECK_TIMEOUT 600
+#define DOMAIN_DEFAULT_HINT _("Should match the web address of your login provider.")
+
+typedef enum {
+ MODE_LOCAL,
+ MODE_ENTERPRISE,
+ MODE_OFFLINE
+} AccountMode;
+
+static void mode_change (CcAddUserDialog *self,
+ AccountMode mode);
+
+static void dialog_validate (CcAddUserDialog *self);
+
+static void on_join_login (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data);
+
+static void on_realm_joined (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data);
+
+static void add_button_clicked_cb (CcAddUserDialog *self);
+
+struct _CcAddUserDialog {
+ GtkDialog parent_instance;
+
+ GtkButton *add_button;
+ AdwActionRow *enterprise_button;
+ GtkComboBox *enterprise_domain_combo;
+ GtkEntry *enterprise_domain_entry;
+ GtkLabel *enterprise_domain_hint;
+ AdwActionRow *enterprise_domain_row;
+ GtkImage *enterprise_domain_status_icon;
+ AdwPreferencesGroup *enterprise_group;
+ AdwPreferencesPage *enterprise_page;
+ AdwPreferencesGroup *enterprise_login_group;
+ GtkEntry *enterprise_login_entry;
+ GtkImage *enterprise_login_status_icon;
+ GtkPasswordEntry *enterprise_password_entry;
+ GtkImage *enterprise_password_status_icon;
+ GtkListStore *enterprise_realm_model;
+ GtkSwitch *local_account_type_switch;
+ GtkEntry *local_name_entry;
+ GtkImage *local_name_status_icon;
+ AdwPreferencesPage *local_page;
+ AdwActionRow *local_password_row;
+ GtkImage *local_password_status_icon;
+ GtkLevelBar *local_strength_indicator;
+ GtkComboBoxText *local_username_combo;
+ GtkListStore *local_username_model;
+ GtkPasswordEntry *local_password_entry;
+ GtkLabel *local_password_hint;
+ GtkCheckButton *local_password_radio;
+ GtkEntry *local_username_entry;
+ AdwActionRow *local_username_row;
+ GtkImage *local_username_status_icon;
+ GtkPasswordEntry *local_verify_entry;
+ AdwActionRow *local_verify_password_row;
+ GtkImage *local_verify_status_icon;
+ AdwPreferencesPage *offline_page;
+ AdwPreferencesGroup *password_group;
+ GtkSpinner *spinner;
+ GtkStack *stack;
+
+ GCancellable *cancellable;
+ GPermission *permission;
+ AccountMode mode;
+ ActUser *user;
+
+ gboolean has_custom_username;
+ gint local_name_timeout_id;
+ gint local_username_timeout_id;
+ ActUserPasswordMode local_password_mode;
+ gint local_password_timeout_id;
+ gboolean local_valid_username;
+
+ guint realmd_watch;
+ CcRealmManager *realm_manager;
+ CcRealmObject *selected_realm;
+ gboolean enterprise_check_credentials;
+ gint enterprise_domain_timeout_id;
+ gboolean enterprise_domain_chosen;
+
+ /* Join credential dialog */
+ GtkDialog *join_dialog;
+ GtkLabel *join_domain;
+ GtkEntry *join_name;
+ GtkEntry *join_password;
+ gboolean join_prompted;
+};
+
+G_DEFINE_TYPE (CcAddUserDialog, cc_add_user_dialog, GTK_TYPE_DIALOG);
+
+static void
+show_error_dialog (CcAddUserDialog *self,
+ const gchar *message,
+ GError *error)
+{
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new (GTK_WINDOW (self),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_USE_HEADER_BAR,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ "%s", message);
+
+ if (error != NULL) {
+ g_dbus_error_strip_remote_error (error);
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s", error->message);
+ }
+
+ g_signal_connect (dialog, "response", G_CALLBACK (gtk_window_destroy), NULL);
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+static void
+begin_action (CcAddUserDialog *self)
+{
+ g_debug ("Beginning action, disabling dialog controls");
+
+ if (self->enterprise_check_credentials) {
+ gtk_widget_set_sensitive (GTK_WIDGET (self->stack), FALSE);
+ }
+ gtk_widget_set_sensitive (GTK_WIDGET (self->enterprise_button), FALSE);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->add_button), FALSE);
+
+ gtk_widget_show (GTK_WIDGET (self->spinner));
+ gtk_spinner_start (self->spinner);
+}
+
+static void
+finish_action (CcAddUserDialog *self)
+{
+ g_debug ("Completed domain action");
+
+ if (self->enterprise_check_credentials) {
+ gtk_widget_set_sensitive (GTK_WIDGET (self->stack), TRUE);
+ }
+ gtk_widget_set_sensitive (GTK_WIDGET (self->enterprise_button), TRUE);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->add_button), TRUE);
+
+ gtk_widget_hide (GTK_WIDGET (self->spinner));
+ gtk_spinner_stop (self->spinner);
+}
+
+static void
+user_loaded_cb (CcAddUserDialog *self,
+ GParamSpec *pspec,
+ ActUser *user)
+{
+ const gchar *password;
+
+ finish_action (self);
+
+ /* Set a password for the user */
+ password = gtk_editable_get_text (GTK_EDITABLE (self->local_password_entry));
+ act_user_set_password_mode (user, self->local_password_mode);
+ if (self->local_password_mode == ACT_USER_PASSWORD_MODE_REGULAR)
+ act_user_set_password (user, password, "");
+
+ self->user = g_object_ref (user);
+ gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_CLOSE);
+}
+
+static void
+create_user_done (ActUserManager *manager,
+ GAsyncResult *res,
+ CcAddUserDialog *self)
+{
+ ActUser *user;
+ g_autoptr(GError) error = NULL;
+
+ /* Note that user is returned without an extra reference */
+
+ user = act_user_manager_create_user_finish (manager, res, &error);
+
+ if (user == NULL) {
+ finish_action (self);
+ g_debug ("Failed to create user: %s", error->message);
+ if (!g_error_matches (error, ACT_USER_MANAGER_ERROR, ACT_USER_MANAGER_ERROR_PERMISSION_DENIED))
+ show_error_dialog (self, _("Failed to add account"), error);
+ gtk_widget_grab_focus (GTK_WIDGET (self->local_name_entry));
+ } else {
+ g_debug ("Created user: %s", act_user_get_user_name (user));
+
+ /* Check if the returned object is fully loaded before returning it */
+ if (act_user_is_loaded (user))
+ user_loaded_cb (self, NULL, user);
+ else
+ g_signal_connect_object (user, "notify::is-loaded", G_CALLBACK (user_loaded_cb), self, G_CONNECT_SWAPPED);
+ }
+}
+
+static void
+local_create_user (CcAddUserDialog *self)
+{
+ ActUserManager *manager;
+ const gchar *username;
+ const gchar *name;
+ gint account_type;
+
+ begin_action (self);
+
+ name = gtk_editable_get_text (GTK_EDITABLE (self->local_name_entry));
+ username = gtk_combo_box_text_get_active_text (self->local_username_combo);
+ account_type = gtk_switch_get_active (self->local_account_type_switch) ? ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR : ACT_USER_ACCOUNT_TYPE_STANDARD;
+
+ g_debug ("Creating local user: %s", username);
+
+ manager = act_user_manager_get_default ();
+ act_user_manager_create_user_async (manager,
+ username,
+ name,
+ account_type,
+ self->cancellable,
+ (GAsyncReadyCallback)create_user_done,
+ self);
+}
+
+static gint
+update_password_strength (CcAddUserDialog *self)
+{
+ const gchar *password;
+ const gchar *username;
+ const gchar *hint;
+ const gchar *verify;
+ gint strength_level;
+
+ password = gtk_editable_get_text (GTK_EDITABLE (self->local_password_entry));
+ username = gtk_combo_box_text_get_active_text (self->local_username_combo);
+
+ pw_strength (password, NULL, username, &hint, &strength_level);
+
+ gtk_level_bar_set_value (self->local_strength_indicator, strength_level);
+ gtk_label_set_label (self->local_password_hint, hint);
+
+ if (strength_level > 1) {
+ gtk_image_set_from_icon_name (self->local_password_status_icon, "emblem-ok-symbolic");
+ } else if (strlen (password) == 0) {
+ gtk_image_set_from_icon_name (self->local_password_status_icon, "dialog-warning-symbolic");
+ } else {
+ gtk_image_set_from_icon_name (self->local_password_status_icon, "dialog-warning-symbolic");
+ }
+
+ verify = gtk_editable_get_text (GTK_EDITABLE (self->local_verify_entry));
+ if (strlen (verify) == 0) {
+ gtk_widget_set_sensitive (GTK_WIDGET (self->local_verify_entry), strength_level > 1);
+ }
+
+ return strength_level;
+}
+
+static gboolean
+local_validate (CcAddUserDialog *self)
+{
+ gboolean valid_name;
+ gboolean valid_password;
+ const gchar *name;
+ const gchar *password;
+ const gchar *verify;
+ gint strength;
+
+ if (self->local_valid_username) {
+ gtk_image_set_from_icon_name (self->local_username_status_icon, "emblem-ok-symbolic");
+ }
+
+ name = gtk_editable_get_text (GTK_EDITABLE (self->local_name_entry));
+ valid_name = is_valid_name (name);
+ if (valid_name) {
+ gtk_image_set_from_icon_name (self->local_name_status_icon, "emblem-ok-symbolic");
+ }
+
+ password = gtk_editable_get_text (GTK_EDITABLE (self->local_password_entry));
+ verify = gtk_editable_get_text (GTK_EDITABLE (self->local_verify_entry));
+ if (self->local_password_mode == ACT_USER_PASSWORD_MODE_REGULAR) {
+ strength = update_password_strength (self);
+ valid_password = strength > 1 && strcmp (password, verify) == 0;
+ } else {
+ valid_password = TRUE;
+ }
+
+ return valid_name && self->local_valid_username && valid_password;
+}
+
+static void local_username_is_valid_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(CcAddUserDialog) self = CC_ADD_USER_DIALOG (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *tip = NULL;
+ g_autofree gchar *name = NULL;
+ g_autofree gchar *username = NULL;
+ gboolean valid;
+
+ valid = is_valid_username_finish (result, &tip, &username, &error);
+ if (error != NULL) {
+ g_warning ("Could not check username by usermod: %s", error->message);
+ valid = TRUE;
+ }
+
+ name = gtk_combo_box_text_get_active_text (self->local_username_combo);
+ if (g_strcmp0 (name, username) == 0) {
+ self->local_valid_username = valid;
+ adw_action_row_set_subtitle (ADW_ACTION_ROW (self->local_username_row), tip);
+ dialog_validate (self);
+ }
+}
+
+static gboolean
+local_username_timeout (CcAddUserDialog *self)
+{
+ g_autofree gchar *name = NULL;
+
+ self->local_username_timeout_id = 0;
+
+ name = gtk_combo_box_text_get_active_text (self->local_username_combo);
+ is_valid_username_async (name, NULL, local_username_is_valid_cb, g_object_ref (self));
+
+ return FALSE;
+}
+
+static gboolean
+local_username_combo_focus_out_event_cb (CcAddUserDialog *self)
+{
+ if (self->local_username_timeout_id != 0) {
+ g_source_remove (self->local_username_timeout_id);
+ self->local_username_timeout_id = 0;
+ }
+
+ local_username_timeout (self);
+
+ return FALSE;
+}
+
+static void
+local_username_combo_changed_cb (CcAddUserDialog *self)
+{
+ const gchar *username;
+
+ username = gtk_editable_get_text (GTK_EDITABLE (self->local_username_entry));
+ if (*username == '\0')
+ self->has_custom_username = FALSE;
+ else if (gtk_widget_has_focus (GTK_WIDGET (self->local_username_entry)) ||
+ gtk_combo_box_get_active (GTK_COMBO_BOX (self->local_username_combo)) > 0)
+ self->has_custom_username = TRUE;
+
+ if (self->local_username_timeout_id != 0) {
+ g_source_remove (self->local_username_timeout_id);
+ self->local_username_timeout_id = 0;
+ }
+
+ gtk_image_set_from_icon_name (self->local_username_status_icon, "dialog-warning-symbolic");
+ gtk_widget_set_sensitive (GTK_WIDGET (self->add_button), FALSE);
+
+ self->local_valid_username = FALSE;
+ self->local_username_timeout_id = g_timeout_add (PASSWORD_CHECK_TIMEOUT, (GSourceFunc) local_username_timeout, self);
+}
+
+static gboolean
+local_name_timeout (CcAddUserDialog *self)
+{
+ self->local_name_timeout_id = 0;
+
+ dialog_validate (self);
+
+ return FALSE;
+}
+
+static gboolean
+local_name_entry_focus_out_event_cb (CcAddUserDialog *self)
+{
+ if (self->local_name_timeout_id != 0) {
+ g_source_remove (self->local_name_timeout_id);
+ self->local_name_timeout_id = 0;
+ }
+
+ local_name_timeout (self);
+
+ return FALSE;
+}
+
+static void
+generate_username_choices (const gchar *name,
+ GtkListStore *store)
+{
+ gboolean in_use, same_as_initial;
+ g_autofree gchar *lc_name = NULL;
+ g_autofree gchar *ascii_name = NULL;
+ g_autofree gchar *stripped_name = NULL;
+ g_auto(GStrv) words1 = NULL;
+ char **w1, **w2;
+ char *c;
+ char *unicode_fallback = "?";
+ g_autoptr(GString) first_word = NULL;
+ g_autoptr(GString) last_word = NULL;
+ g_autoptr(GString) item0 = NULL;
+ g_autoptr(GString) item1 = NULL;
+ g_autoptr(GString) item2 = NULL;
+ g_autoptr(GString) item3 = NULL;
+ g_autoptr(GString) item4 = NULL;
+ int len;
+ int nwords1, nwords2, i;
+ g_autoptr(GHashTable) items = NULL;
+ GtkTreeIter iter;
+ gsize max_name_length;
+
+ gtk_list_store_clear (store);
+
+ ascii_name = g_convert_with_fallback (name, -1, "ASCII//TRANSLIT", "UTF-8",
+ unicode_fallback, NULL, NULL, NULL);
+ /* Re-try without TRANSLIT. musl does not implement it */
+ if (ascii_name == NULL)
+ ascii_name = g_convert_with_fallback (name, -1, "ASCII", "UTF-8",
+ unicode_fallback, NULL, NULL, NULL);
+ if (ascii_name == NULL)
+ return;
+
+ lc_name = g_ascii_strdown (ascii_name, -1);
+
+ /* Remove all non ASCII alphanumeric chars from the name,
+ * apart from the few allowed symbols.
+ *
+ * We do remove '.', even though it is usually allowed,
+ * since it often comes in via an abbreviated middle name,
+ * and the dot looks just wrong in the proposals then.
+ */
+ stripped_name = g_strnfill (strlen (lc_name) + 1, '\0');
+ i = 0;
+ for (c = lc_name; *c; c++) {
+ if (!(g_ascii_isdigit (*c) || g_ascii_islower (*c) ||
+ *c == ' ' || *c == '-' || *c == '_' ||
+ /* used to track invalid words, removed below */
+ *c == '?') )
+ continue;
+
+ stripped_name[i] = *c;
+ i++;
+ }
+
+ if (strlen (stripped_name) == 0) {
+ return;
+ }
+
+ /* we split name on spaces, and then on dashes, so that we can treat
+ * words linked with dashes the same way, i.e. both fully shown, or
+ * both abbreviated
+ */
+ words1 = g_strsplit_set (stripped_name, " ", -1);
+ len = g_strv_length (words1);
+
+ /* The default item is a concatenation of all words without ? */
+ item0 = g_string_sized_new (strlen (stripped_name));
+
+ /* Concatenate the whole first word with the first letter of each
+ * word (item1), and the last word with the first letter of each
+ * word (item2). item3 and item4 are symmetrical respectively to
+ * item1 and item2.
+ *
+ * Constant 5 is the max reasonable number of words we may get when
+ * splitting on dashes, since we can't guess it at this point,
+ * and reallocating would be too bad.
+ */
+ item1 = g_string_sized_new (strlen (words1[0]) + len - 1 + 5);
+ item3 = g_string_sized_new (strlen (words1[0]) + len - 1 + 5);
+
+ item2 = g_string_sized_new (strlen (words1[len - 1]) + len - 1 + 5);
+ item4 = g_string_sized_new (strlen (words1[len - 1]) + len - 1 + 5);
+
+ /* again, guess at the max size of names */
+ first_word = g_string_sized_new (20);
+ last_word = g_string_sized_new (20);
+
+ nwords1 = 0;
+ nwords2 = 0;
+ for (w1 = words1; *w1; w1++) {
+ g_auto(GStrv) words2 = NULL;
+
+ if (strlen (*w1) == 0)
+ continue;
+
+ /* skip words with string '?', most likely resulting
+ * from failed transliteration to ASCII
+ */
+ if (strstr (*w1, unicode_fallback) != NULL)
+ continue;
+
+ nwords1++; /* count real words, excluding empty string */
+
+ item0 = g_string_append (item0, *w1);
+
+ words2 = g_strsplit_set (*w1, "-", -1);
+ /* reset last word if a new non-empty word has been found */
+ if (strlen (*words2) > 0)
+ last_word = g_string_set_size (last_word, 0);
+
+ for (w2 = words2; *w2; w2++) {
+ if (strlen (*w2) == 0)
+ continue;
+
+ nwords2++;
+
+ /* part of the first "toplevel" real word */
+ if (nwords1 == 1) {
+ item1 = g_string_append (item1, *w2);
+ first_word = g_string_append (first_word, *w2);
+ }
+ else {
+ item1 = g_string_append_unichar (item1,
+ g_utf8_get_char (*w2));
+ item3 = g_string_append_unichar (item3,
+ g_utf8_get_char (*w2));
+ }
+
+ /* not part of the last "toplevel" word */
+ if (w1 != words1 + len - 1) {
+ item2 = g_string_append_unichar (item2,
+ g_utf8_get_char (*w2));
+ item4 = g_string_append_unichar (item4,
+ g_utf8_get_char (*w2));
+ }
+
+ /* always save current word so that we have it if last one reveals empty */
+ last_word = g_string_append (last_word, *w2);
+ }
+ }
+ item2 = g_string_append (item2, last_word->str);
+ item3 = g_string_append (item3, first_word->str);
+ item4 = g_string_prepend (item4, last_word->str);
+
+ max_name_length = get_username_max_length ();
+
+ g_string_truncate (first_word, max_name_length);
+ g_string_truncate (last_word, max_name_length);
+
+ g_string_truncate (item0, max_name_length);
+ g_string_truncate (item1, max_name_length);
+ g_string_truncate (item2, max_name_length);
+ g_string_truncate (item3, max_name_length);
+ g_string_truncate (item4, max_name_length);
+
+ items = g_hash_table_new (g_str_hash, g_str_equal);
+
+ in_use = is_username_used (item0->str);
+ if (!in_use && !g_ascii_isdigit (item0->str[0])) {
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0, item0->str, -1);
+ g_hash_table_insert (items, item0->str, item0->str);
+ }
+
+ in_use = is_username_used (item1->str);
+ same_as_initial = (g_strcmp0 (item0->str, item1->str) == 0);
+ if (!same_as_initial && nwords2 > 0 && !in_use && !g_ascii_isdigit (item1->str[0])) {
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0, item1->str, -1);
+ g_hash_table_insert (items, item1->str, item1->str);
+ }
+
+ /* if there's only one word, would be the same as item1 */
+ if (nwords2 > 1) {
+ /* add other items */
+ in_use = is_username_used (item2->str);
+ if (!in_use && !g_ascii_isdigit (item2->str[0]) &&
+ !g_hash_table_lookup (items, item2->str)) {
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0, item2->str, -1);
+ g_hash_table_insert (items, item2->str, item2->str);
+ }
+
+ in_use = is_username_used (item3->str);
+ if (!in_use && !g_ascii_isdigit (item3->str[0]) &&
+ !g_hash_table_lookup (items, item3->str)) {
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0, item3->str, -1);
+ g_hash_table_insert (items, item3->str, item3->str);
+ }
+
+ in_use = is_username_used (item4->str);
+ if (!in_use && !g_ascii_isdigit (item4->str[0]) &&
+ !g_hash_table_lookup (items, item4->str)) {
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0, item4->str, -1);
+ g_hash_table_insert (items, item4->str, item4->str);
+ }
+
+ /* add the last word */
+ in_use = is_username_used (last_word->str);
+ if (!in_use && !g_ascii_isdigit (last_word->str[0]) &&
+ !g_hash_table_lookup (items, last_word->str)) {
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0, last_word->str, -1);
+ g_hash_table_insert (items, last_word->str, last_word->str);
+ }
+
+ /* ...and the first one */
+ in_use = is_username_used (first_word->str);
+ if (!in_use && !g_ascii_isdigit (first_word->str[0]) &&
+ !g_hash_table_lookup (items, first_word->str)) {
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0, first_word->str, -1);
+ g_hash_table_insert (items, first_word->str, first_word->str);
+ }
+ }
+}
+
+static void
+local_name_entry_changed_cb (CcAddUserDialog *self)
+{
+ const char *name;
+
+ gtk_list_store_clear (self->local_username_model);
+
+ name = gtk_editable_get_text (GTK_EDITABLE (self->local_name_entry));
+ if ((name == NULL || strlen (name) == 0) && !self->has_custom_username) {
+ gtk_editable_set_text (GTK_EDITABLE (self->local_username_entry), "");
+ } else if (name != NULL && strlen (name) != 0) {
+ generate_username_choices (name, self->local_username_model);
+ if (!self->has_custom_username)
+ gtk_combo_box_set_active (GTK_COMBO_BOX (self->local_username_combo), 0);
+ }
+
+ if (self->local_name_timeout_id != 0) {
+ g_source_remove (self->local_name_timeout_id);
+ self->local_name_timeout_id = 0;
+ }
+
+ gtk_image_set_from_icon_name (self->local_name_status_icon, "dialog-warning-symbolic");
+ gtk_widget_set_sensitive (GTK_WIDGET (self->add_button), FALSE);
+
+ self->local_name_timeout_id = g_timeout_add (PASSWORD_CHECK_TIMEOUT, (GSourceFunc) local_name_timeout, self);
+}
+
+static void
+update_password_match (CcAddUserDialog *self)
+{
+ const gchar *password;
+ const gchar *verify;
+ const gchar *message = "";
+
+ password = gtk_editable_get_text (GTK_EDITABLE (self->local_password_entry));
+ verify = gtk_editable_get_text (GTK_EDITABLE (self->local_verify_entry));
+ if (strlen (verify) != 0) {
+ if (strcmp (password, verify) != 0) {
+ message = _("The passwords do not match.");
+ } else {
+ gtk_image_set_from_icon_name (self->local_verify_status_icon, "emblem-ok-symbolic");
+ }
+ }
+ adw_action_row_set_subtitle (ADW_ACTION_ROW (self->local_verify_password_row), message);
+}
+
+static void
+generate_password (CcAddUserDialog *self)
+{
+ g_autofree gchar *pwd = NULL;
+
+ pwd = pw_generate ();
+ if (pwd == NULL)
+ return;
+
+ gtk_editable_set_text (GTK_EDITABLE (self->local_password_entry), pwd);
+ gtk_editable_set_text (GTK_EDITABLE (self->local_verify_entry), pwd);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->local_verify_entry), TRUE);
+}
+
+static gboolean
+local_password_timeout (CcAddUserDialog *self)
+{
+ self->local_password_timeout_id = 0;
+
+ dialog_validate (self);
+ update_password_match (self);
+
+ return FALSE;
+}
+
+static gboolean
+password_focus_out_event_cb (CcAddUserDialog *self)
+{
+ if (self->local_password_timeout_id != 0) {
+ g_source_remove (self->local_password_timeout_id);
+ self->local_password_timeout_id = 0;
+ }
+
+ local_password_timeout (self);
+
+ return FALSE;
+}
+
+static gboolean
+local_password_entry_key_press_event_cb (GtkEventControllerKey *controller,
+ guint keyval,
+ guint keycode,
+ GdkModifierType state,
+ CcAddUserDialog *self)
+{
+ if (keyval == GDK_KEY_Tab)
+ local_password_timeout (self);
+
+ return FALSE;
+}
+
+static void
+recheck_password_match (CcAddUserDialog *self)
+{
+ if (self->local_password_timeout_id != 0) {
+ g_source_remove (self->local_password_timeout_id);
+ self->local_password_timeout_id = 0;
+ }
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->add_button), FALSE);
+
+ self->local_password_timeout_id = g_timeout_add (PASSWORD_CHECK_TIMEOUT, (GSourceFunc) local_password_timeout, self);
+}
+
+static void
+local_password_entry_changed_cb (CcAddUserDialog *self)
+{
+ gtk_image_set_from_icon_name (self->local_password_status_icon, "dialog-warning-symbolic");
+ gtk_image_set_from_icon_name (self->local_verify_status_icon, "dialog-warning-symbolic");
+ recheck_password_match (self);
+}
+
+static void
+local_verify_entry_changed_cb (CcAddUserDialog *self)
+{
+ gtk_image_set_from_icon_name (self->local_verify_status_icon, "dialog-warning-symbolic");
+ recheck_password_match (self);
+}
+
+static void
+local_password_radio_changed_cb (CcAddUserDialog *self)
+{
+ gboolean active;
+
+ active = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->local_password_radio));
+ self->local_password_mode = active ? ACT_USER_PASSWORD_MODE_REGULAR : ACT_USER_PASSWORD_MODE_SET_AT_LOGIN;
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->password_group), active);
+
+ dialog_validate (self);
+}
+
+static gboolean
+enterprise_validate (CcAddUserDialog *self)
+{
+ const gchar *name;
+ gboolean valid_name;
+ gboolean valid_domain;
+ GtkTreeIter iter;
+
+ name = gtk_editable_get_text (GTK_EDITABLE (self->enterprise_login_entry));
+ valid_name = is_valid_name (name);
+
+ if (gtk_combo_box_get_active_iter (self->enterprise_domain_combo, &iter)) {
+ gtk_tree_model_get (GTK_TREE_MODEL (self->enterprise_realm_model),
+ &iter, 0, &name, -1);
+ } else {
+ name = gtk_editable_get_text (GTK_EDITABLE (self->enterprise_domain_entry));
+ }
+
+ valid_domain = is_valid_name (name) && self->selected_realm != NULL;
+ return valid_name && valid_domain;
+}
+
+static void
+enterprise_add_realm (CcAddUserDialog *self,
+ CcRealmObject *realm)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ g_autoptr(CcRealmCommon) common = NULL;
+ const gchar *realm_name;
+ gboolean match;
+ gboolean ret;
+
+ common = cc_realm_object_get_common (realm);
+ g_return_if_fail (common != NULL);
+
+ realm_name = cc_realm_common_get_name (common);
+
+ /*
+ * Don't add a second realm if we already have one with this name.
+ * Sometimes realmd returns to realms for the same name, if it has
+ * different ways to use that realm. The first one that realmd
+ * returns is the one it prefers.
+ */
+
+ model = GTK_TREE_MODEL (self->enterprise_realm_model);
+ ret = gtk_tree_model_get_iter_first (model, &iter);
+ while (ret) {
+ g_autofree gchar *name = NULL;
+
+ gtk_tree_model_get (model, &iter, 0, &name, -1);
+ match = (g_strcmp0 (name, realm_name) == 0);
+ if (match) {
+ g_debug ("ignoring duplicate realm: %s", realm_name);
+ return;
+ }
+ ret = gtk_tree_model_iter_next (model, &iter);
+ }
+
+ gtk_list_store_append (self->enterprise_realm_model, &iter);
+ gtk_list_store_set (self->enterprise_realm_model, &iter,
+ 0, realm_name,
+ 1, realm,
+ -1);
+
+ /* Prefill domain entry by the existing one */
+ if (!self->enterprise_domain_chosen && cc_realm_is_configured (realm)) {
+ gtk_editable_set_text (GTK_EDITABLE (self->enterprise_domain_entry), realm_name);
+ }
+
+ g_debug ("added realm to drop down: %s %s", realm_name,
+ g_dbus_object_get_object_path (G_DBUS_OBJECT (realm)));
+}
+
+static void
+on_manager_realm_added (CcAddUserDialog *self,
+ CcRealmObject *realm)
+{
+ enterprise_add_realm (self, realm);
+}
+
+
+static void
+on_register_user (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(CcAddUserDialog) self = CC_ADD_USER_DIALOG (user_data);
+ g_autoptr(GError) error = NULL;
+ ActUser *user;
+
+ if (g_cancellable_is_cancelled (self->cancellable)) {
+ return;
+ }
+
+ user = act_user_manager_cache_user_finish (ACT_USER_MANAGER (source), result, &error);
+
+ /* This is where we're finally done */
+ if (user != NULL) {
+ g_debug ("Successfully cached remote user: %s", act_user_get_user_name (user));
+ finish_action (self);
+ self->user = g_object_ref (user);
+ gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_CLOSE);
+ } else {
+ show_error_dialog (self, _("Failed to register account"), error);
+ g_message ("Couldn't cache user account: %s", error->message);
+ finish_action (self);
+ }
+}
+
+static void
+on_permit_user_login (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(CcAddUserDialog) self = CC_ADD_USER_DIALOG (user_data);
+ CcRealmCommon *common;
+ ActUserManager *manager;
+ g_autoptr(GError) error = NULL;
+
+ if (g_cancellable_is_cancelled (self->cancellable)) {
+ return;
+ }
+
+ common = CC_REALM_COMMON (source);
+ if (cc_realm_common_call_change_login_policy_finish (common, result, &error)) {
+ g_autofree gchar *login = NULL;
+
+ /*
+ * Now tell the account service about this user. The account service
+ * should also lookup information about this via the realm and make
+ * sure all that is functional.
+ */
+ manager = act_user_manager_get_default ();
+ login = cc_realm_calculate_login (common, gtk_editable_get_text (GTK_EDITABLE (self->enterprise_login_entry)));
+ g_return_if_fail (login != NULL);
+
+ g_debug ("Caching remote user: %s", login);
+
+ act_user_manager_cache_user_async (manager, login, self->cancellable,
+ on_register_user, g_object_ref (self));
+
+ } else {
+ show_error_dialog (self, _("Failed to register account"), error);
+ g_message ("Couldn't permit logins on account: %s", error->message);
+ finish_action (self);
+ }
+}
+
+static void
+enterprise_permit_user_login (CcAddUserDialog *self)
+{
+ g_autoptr(CcRealmCommon) common = NULL;
+ g_autofree gchar *login = NULL;
+ const gchar *add[2];
+ const gchar *remove[1];
+ GVariant *options;
+
+ common = cc_realm_object_get_common (self->selected_realm);
+ if (common == NULL) {
+ g_debug ("Failed to register account: failed to get d-bus interface");
+ show_error_dialog (self, _("Failed to register account"), NULL);
+ finish_action (self);
+ return;
+ }
+
+ login = cc_realm_calculate_login (common, gtk_editable_get_text (GTK_EDITABLE (self->enterprise_login_entry)));
+ g_return_if_fail (login != NULL);
+
+ add[0] = login;
+ add[1] = NULL;
+ remove[0] = NULL;
+
+ g_debug ("Permitting login for: %s", login);
+ options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0);
+
+ cc_realm_common_call_change_login_policy (common, "",
+ add, remove, options,
+ self->cancellable,
+ on_permit_user_login,
+ g_object_ref (self));
+}
+
+static void
+on_join_response (CcAddUserDialog *self,
+ gint response,
+ GtkDialog *dialog)
+{
+ gtk_widget_hide (GTK_WIDGET (dialog));
+ if (response != GTK_RESPONSE_OK) {
+ finish_action (self);
+ return;
+ }
+
+ g_debug ("Logging in as admin user: %s", gtk_editable_get_text (GTK_EDITABLE (self->join_name)));
+
+ /* Prompted for some admin credentials, try to use them to log in */
+ cc_realm_login (self->selected_realm,
+ gtk_editable_get_text (GTK_EDITABLE (self->join_name)),
+ gtk_editable_get_text (GTK_EDITABLE (self->join_password)),
+ self->cancellable,
+ on_join_login,
+ g_object_ref (self));
+}
+
+static void
+join_show_prompt (CcAddUserDialog *self,
+ GError *error)
+{
+ g_autoptr(CcRealmKerberosMembership) membership = NULL;
+ g_autoptr(CcRealmKerberos) kerberos = NULL;
+ const gchar *name;
+
+ gtk_editable_set_text (GTK_EDITABLE (self->join_password), "");
+ gtk_widget_grab_focus (GTK_WIDGET (self->join_password));
+
+ kerberos = cc_realm_object_get_kerberos (self->selected_realm);
+ membership = cc_realm_object_get_kerberos_membership (self->selected_realm);
+
+ gtk_label_set_text (self->join_domain,
+ cc_realm_kerberos_get_domain_name (kerberos));
+
+ //clear_entry_validation_error (self->join_name);
+ //clear_entry_validation_error (self->join_password);
+
+ if (!self->join_prompted) {
+ name = cc_realm_kerberos_membership_get_suggested_administrator (membership);
+ if (name && !g_str_equal (name, "")) {
+ g_debug ("Suggesting admin user: %s", name);
+ gtk_editable_set_text (GTK_EDITABLE (self->join_name), name);
+ } else {
+ gtk_widget_grab_focus (GTK_WIDGET (self->join_name));
+ }
+
+ } else if (g_error_matches (error, CC_REALM_ERROR, CC_REALM_ERROR_BAD_PASSWORD)) {
+ g_debug ("Bad admin password: %s", error->message);
+ //set_entry_validation_error (self->join_password, error->message);
+
+ } else {
+ g_debug ("Admin login failure: %s", error->message);
+ g_dbus_error_strip_remote_error (error);
+ //set_entry_validation_error (self->join_name, error->message);
+ }
+
+ g_debug ("Showing admin password dialog");
+ gtk_window_set_transient_for (GTK_WINDOW (self->join_dialog), GTK_WINDOW (self));
+ gtk_window_set_modal (GTK_WINDOW (self->join_dialog), TRUE);
+ gtk_window_present (GTK_WINDOW (self->join_dialog));
+
+ self->join_prompted = TRUE;
+
+ /* And now we wait for on_join_response() */
+}
+
+static void
+on_join_login (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(CcAddUserDialog) self = CC_ADD_USER_DIALOG (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GBytes) creds = NULL;
+
+ if (g_cancellable_is_cancelled (self->cancellable)) {
+ return;
+ }
+
+ creds = cc_realm_login_finish (result, &error);
+
+ /* Logged in as admin successfully, use creds to join domain */
+ if (creds != NULL) {
+ if (!cc_realm_join_as_admin (self->selected_realm,
+ gtk_editable_get_text (GTK_EDITABLE (self->join_name)),
+ gtk_editable_get_text (GTK_EDITABLE (self->join_password)),
+ creds, self->cancellable, on_realm_joined,
+ g_object_ref (self))) {
+ show_error_dialog (self, _("No supported way to authenticate with this domain"), NULL);
+ g_message ("Authenticating as admin is not supported by the realm");
+ finish_action (self);
+ }
+
+ /* Couldn't login as admin, show prompt again */
+ } else {
+ join_show_prompt (self, error);
+ g_message ("Couldn't log in as admin to join domain: %s", error->message);
+ }
+}
+
+static void
+join_init (CcAddUserDialog *self)
+{
+ g_autoptr(GtkBuilder) builder = NULL;
+ g_autoptr(GError) error = NULL;
+
+ builder = gtk_builder_new ();
+
+ if (!gtk_builder_add_from_resource (builder,
+ "/org/gnome/control-center/user-accounts/join-dialog.ui",
+ &error)) {
+ g_error ("%s", error->message);
+ return;
+ }
+
+ self->join_dialog = GTK_DIALOG (gtk_builder_get_object (builder, "join-dialog"));
+ self->join_domain = GTK_LABEL (gtk_builder_get_object (builder, "join-domain"));
+ self->join_name = GTK_ENTRY (gtk_builder_get_object (builder, "join-name"));
+ self->join_password = GTK_ENTRY (gtk_builder_get_object (builder, "join-password"));
+
+ g_signal_connect_object (self->join_dialog, "response",
+ G_CALLBACK (on_join_response), self, G_CONNECT_SWAPPED);
+}
+
+static void
+on_realm_joined (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(CcAddUserDialog) self = CC_ADD_USER_DIALOG (user_data);
+ g_autoptr(GError) error = NULL;
+
+ if (g_cancellable_is_cancelled (self->cancellable)) {
+ return;
+ }
+
+ cc_realm_join_finish (self->selected_realm,
+ result, &error);
+
+ /* Yay, joined the domain, register the user locally */
+ if (error == NULL) {
+ g_debug ("Joining realm completed successfully");
+ enterprise_permit_user_login (self);
+
+ /* Credential failure while joining domain, prompt for admin creds */
+ } else if (g_error_matches (error, CC_REALM_ERROR, CC_REALM_ERROR_BAD_LOGIN) ||
+ g_error_matches (error, CC_REALM_ERROR, CC_REALM_ERROR_BAD_PASSWORD)) {
+ g_debug ("Joining realm failed due to credentials");
+ join_show_prompt (self, error);
+
+ /* Other failure */
+ } else {
+ show_error_dialog (self, _("Failed to join domain"), error);
+ g_message ("Failed to join the domain: %s", error->message);
+ finish_action (self);
+ }
+}
+
+static void
+on_realm_login (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(CcAddUserDialog) self = CC_ADD_USER_DIALOG (user_data);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GBytes) creds = NULL;
+ const gchar *message;
+
+ if (g_cancellable_is_cancelled (self->cancellable)) {
+ return;
+ }
+
+ creds = cc_realm_login_finish (result, &error);
+
+ /*
+ * User login is valid, but cannot authenticate right now (eg: user needs
+ * to change password at next login etc.)
+ */
+ if (g_error_matches (error, CC_REALM_ERROR, CC_REALM_ERROR_CANNOT_AUTH)) {
+ g_clear_error (&error);
+ creds = NULL;
+ }
+
+ if (error == NULL) {
+
+ /* Already joined to the domain, just register this user */
+ if (cc_realm_is_configured (self->selected_realm)) {
+ g_debug ("Already joined to this realm");
+ enterprise_permit_user_login (self);
+
+ /* Join the domain, try using the user's creds */
+ } else if (creds == NULL ||
+ !cc_realm_join_as_user (self->selected_realm,
+ gtk_editable_get_text (GTK_EDITABLE (self->enterprise_login_entry)),
+ gtk_editable_get_text (GTK_EDITABLE (self->enterprise_password_entry)),
+ creds, self->cancellable,
+ on_realm_joined,
+ g_object_ref (self))) {
+
+ /* If we can't do user auth, try to authenticate as admin */
+ g_debug ("Cannot join with user credentials");
+ join_show_prompt (self, NULL);
+ }
+
+ /* A problem with the user's login name or password */
+ } else if (g_error_matches (error, CC_REALM_ERROR, CC_REALM_ERROR_BAD_LOGIN)) {
+ g_debug ("Problem with the user's login: %s", error->message);
+ message = _("That login name didn’t work.\nPlease try again.");
+ adw_preferences_group_set_description (self->enterprise_login_group, message);
+ finish_action (self);
+ gtk_widget_grab_focus (GTK_WIDGET (self->enterprise_login_entry));
+
+ } else if (g_error_matches (error, CC_REALM_ERROR, CC_REALM_ERROR_BAD_PASSWORD)) {
+ g_debug ("Problem with the user's password: %s", error->message);
+ message = _("That login password didn’t work.\nPlease try again.");
+ adw_preferences_group_set_description (self->enterprise_login_group, message);
+ finish_action (self);
+ gtk_widget_grab_focus (GTK_WIDGET (self->enterprise_password_entry));
+
+ /* Other login failure */
+ } else {
+ g_dbus_error_strip_remote_error (error);
+ show_error_dialog (self, _("Failed to log into domain"), error);
+ g_message ("Couldn't log in as user: %s", error->message);
+ finish_action (self);
+ }
+}
+
+static void
+enterprise_check_login (CcAddUserDialog *self)
+{
+ g_assert (self->selected_realm);
+
+ cc_realm_login (self->selected_realm,
+ gtk_editable_get_text (GTK_EDITABLE (self->enterprise_login_entry)),
+ gtk_editable_get_text (GTK_EDITABLE (self->enterprise_password_entry)),
+ self->cancellable,
+ on_realm_login,
+ g_object_ref (self));
+}
+
+static void
+on_realm_discover_input (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(CcAddUserDialog) self = CC_ADD_USER_DIALOG (user_data);
+ g_autoptr(GError) error = NULL;
+ GList *realms;
+
+ if (g_cancellable_is_cancelled (self->cancellable)) {
+ return;
+ }
+
+ realms = cc_realm_manager_discover_finish (self->realm_manager,
+ result, &error);
+
+ /* Found a realm, log user into domain */
+ if (error == NULL) {
+ g_assert (realms != NULL);
+ self->selected_realm = g_object_ref (realms->data);
+
+ if (self->enterprise_check_credentials) {
+ enterprise_check_login (self);
+ }
+ gtk_image_set_from_icon_name (self->enterprise_domain_status_icon, "emblem-ok-symbolic");
+ gtk_label_set_text (self->enterprise_domain_hint, DOMAIN_DEFAULT_HINT);
+ g_list_free_full (realms, g_object_unref);
+
+ /* The domain is likely invalid*/
+ } else {
+ g_autofree gchar *message = NULL;
+
+ g_message ("Couldn't discover domain: %s", error->message);
+ g_dbus_error_strip_remote_error (error);
+
+ if (g_error_matches (error, CC_REALM_ERROR, CC_REALM_ERROR_GENERIC)) {
+ message = g_strdup (_("Unable to find the domain. Maybe you misspelled it?"));
+ } else {
+ message = g_strdup_printf ("%s.", error->message);
+ }
+ gtk_label_set_text (self->enterprise_domain_hint, message);
+
+ if (self->enterprise_check_credentials) {
+ finish_action (self);
+ self->enterprise_check_credentials = FALSE;
+ }
+ }
+
+ if (!self->enterprise_check_credentials) {
+ finish_action (self);
+ dialog_validate (self);
+ }
+}
+
+static void
+enterprise_check_domain (CcAddUserDialog *self)
+{
+ const gchar *domain;
+
+ domain = gtk_editable_get_text (GTK_EDITABLE (self->enterprise_domain_entry));
+ if (strlen (domain) == 0) {
+ gtk_label_set_text (self->enterprise_domain_hint, DOMAIN_DEFAULT_HINT);
+ return;
+ }
+
+ begin_action (self);
+
+ self->join_prompted = FALSE;
+ cc_realm_manager_discover (self->realm_manager,
+ domain,
+ self->cancellable,
+ on_realm_discover_input,
+ g_object_ref (self));
+}
+
+static void
+enterprise_add_user (CcAddUserDialog *self)
+{
+ self->join_prompted = FALSE;
+ self->enterprise_check_credentials = TRUE;
+ begin_action (self);
+ enterprise_check_login (self);
+
+}
+
+static void
+clear_realm_manager (CcAddUserDialog *self)
+{
+ if (self->realm_manager) {
+ g_signal_handlers_disconnect_by_func (self->realm_manager,
+ on_manager_realm_added,
+ self);
+ g_clear_object (&self->realm_manager);
+ }
+}
+
+static void
+on_realm_manager_created (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(CcAddUserDialog) self = CC_ADD_USER_DIALOG (user_data);
+ g_autoptr(GError) error = NULL;
+ GList *realms, *l;
+
+ clear_realm_manager (self);
+
+ self->realm_manager = cc_realm_manager_new_finish (result, &error);
+ if (error != NULL) {
+ g_warning ("Couldn't contact realmd service: %s", error->message);
+ return;
+ }
+
+ if (g_cancellable_is_cancelled (self->cancellable)) {
+ return;
+ }
+
+ /* Lookup all the realm objects */
+ realms = cc_realm_manager_get_realms (self->realm_manager);
+ for (l = realms; l != NULL; l = g_list_next (l))
+ enterprise_add_realm (self, l->data);
+ g_list_free (realms);
+ g_signal_connect_object (self->realm_manager, "realm-added",
+ G_CALLBACK (on_manager_realm_added), self, G_CONNECT_SWAPPED);
+
+ /* When no realms try to discover a sensible default, triggers realm-added signal */
+ cc_realm_manager_discover (self->realm_manager, "", self->cancellable,
+ NULL, NULL);
+
+ /* Show the 'Enterprise Login' stuff, and update mode */
+ gtk_widget_show (GTK_WIDGET (self->enterprise_group));
+ mode_change (self, self->mode);
+}
+
+static void
+on_realmd_appeared (GDBusConnection *connection,
+ const gchar *name,
+ const gchar *name_owner,
+ gpointer user_data)
+{
+ CcAddUserDialog *self = CC_ADD_USER_DIALOG (user_data);
+ cc_realm_manager_new (self->cancellable, on_realm_manager_created,
+ g_object_ref (self));
+}
+
+static void
+on_realmd_disappeared (GDBusConnection *unused1,
+ const gchar *unused2,
+ gpointer user_data)
+{
+ CcAddUserDialog *self = CC_ADD_USER_DIALOG (user_data);
+
+ clear_realm_manager (self);
+ gtk_list_store_clear (self->enterprise_realm_model);
+ gtk_widget_hide (GTK_WIDGET (self->enterprise_group));
+ mode_change (self, MODE_LOCAL);
+}
+
+static void
+on_network_changed (GNetworkMonitor *monitor,
+ gboolean available,
+ gpointer user_data)
+{
+ CcAddUserDialog *self = CC_ADD_USER_DIALOG (user_data);
+
+ if (self->mode != MODE_LOCAL)
+ mode_change (self, MODE_ENTERPRISE);
+}
+
+static gboolean
+enterprise_domain_timeout (CcAddUserDialog *self)
+{
+ GtkTreeIter iter;
+
+ self->enterprise_domain_timeout_id = 0;
+
+ if (gtk_combo_box_get_active_iter (self->enterprise_domain_combo, &iter)) {
+ gtk_tree_model_get (GTK_TREE_MODEL (self->enterprise_realm_model), &iter, 1, &self->selected_realm, -1);
+ gtk_image_set_from_icon_name (self->enterprise_domain_status_icon, "emblem-ok-symbolic");
+ gtk_label_set_text (self->enterprise_domain_hint, DOMAIN_DEFAULT_HINT);
+ }
+ else {
+ enterprise_check_domain (self);
+ }
+
+ return FALSE;
+}
+
+static void
+enterprise_domain_combo_changed_cb (CcAddUserDialog *self)
+{
+ if (self->enterprise_domain_timeout_id != 0) {
+ g_source_remove (self->enterprise_domain_timeout_id);
+ self->enterprise_domain_timeout_id = 0;
+ }
+
+ g_clear_object (&self->selected_realm);
+ gtk_image_set_from_icon_name (self->enterprise_domain_status_icon, "dialog-warning-symbolic");
+ self->enterprise_domain_timeout_id = g_timeout_add (PASSWORD_CHECK_TIMEOUT, (GSourceFunc) enterprise_domain_timeout, self);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->add_button), FALSE);
+
+ self->enterprise_domain_chosen = TRUE;
+ dialog_validate (self);
+}
+
+static gboolean
+enterprise_domain_combo_focus_out_event_cb (CcAddUserDialog *self)
+{
+ if (self->enterprise_domain_timeout_id != 0) {
+ g_source_remove (self->enterprise_domain_timeout_id);
+ self->enterprise_domain_timeout_id = 0;
+ }
+
+ if (self->selected_realm == NULL) {
+ enterprise_check_domain (self);
+ }
+
+ return FALSE;
+}
+
+static void
+enterprise_login_entry_changed_cb (CcAddUserDialog *self)
+{
+ dialog_validate (self);
+ gtk_image_set_from_icon_name (self->enterprise_login_status_icon, "dialog-warning-symbolic");
+ gtk_image_set_from_icon_name (self->enterprise_password_status_icon, "dialog-warning-symbolic");
+}
+
+static void
+enterprise_password_entry_changed_cb (CcAddUserDialog *self)
+{
+ dialog_validate (self);
+ gtk_image_set_from_icon_name (self->enterprise_password_status_icon, "dialog-warning-symbolic");
+}
+
+static void
+dialog_validate (CcAddUserDialog *self)
+{
+ gboolean valid = FALSE;
+
+ switch (self->mode) {
+ case MODE_LOCAL:
+ valid = local_validate (self);
+ break;
+ case MODE_ENTERPRISE:
+ valid = enterprise_validate (self);
+ break;
+ default:
+ valid = FALSE;
+ break;
+ }
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->add_button), valid);
+}
+
+static void
+mode_change (CcAddUserDialog *self,
+ AccountMode mode)
+{
+ gboolean available;
+ GNetworkMonitor *monitor;
+
+ if (mode != MODE_LOCAL) {
+ monitor = g_network_monitor_get_default ();
+ available = g_network_monitor_get_network_available (monitor);
+ mode = available ? MODE_ENTERPRISE : MODE_OFFLINE;
+ }
+
+ switch (mode) {
+ default:
+ case MODE_LOCAL:
+ gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->local_page));
+ gtk_widget_grab_focus (GTK_WIDGET (self->local_name_entry));
+ break;
+ case MODE_ENTERPRISE:
+ gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->enterprise_page));
+ gtk_widget_grab_focus (GTK_WIDGET (self->enterprise_domain_entry));
+ break;
+ case MODE_OFFLINE:
+ gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->offline_page));
+ break;
+ }
+
+ self->mode = mode;
+ dialog_validate (self);
+}
+
+static void
+enterprise_button_toggled_cb (CcAddUserDialog *self)
+{
+ mode_change (self, MODE_ENTERPRISE);
+}
+
+static void
+cc_add_user_dialog_init (CcAddUserDialog *self)
+{
+ GNetworkMonitor *monitor;
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->cancellable = g_cancellable_new ();
+
+ self->local_password_mode = ACT_USER_PASSWORD_MODE_SET_AT_LOGIN;
+ dialog_validate (self);
+ update_password_strength (self);
+ local_username_timeout (self);
+
+ enterprise_check_domain (self);
+
+ self->realmd_watch = g_bus_watch_name (G_BUS_TYPE_SYSTEM, "org.freedesktop.realmd",
+ G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
+ on_realmd_appeared, on_realmd_disappeared,
+ self, NULL);
+
+ monitor = g_network_monitor_get_default ();
+ g_signal_connect_object (monitor, "network-changed", G_CALLBACK (on_network_changed), self, 0);
+
+ join_init (self);
+
+ mode_change (self, MODE_LOCAL);
+}
+
+static void
+on_permission_acquired (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(CcAddUserDialog) self = CC_ADD_USER_DIALOG (user_data);
+ g_autoptr(GError) error = NULL;
+
+ /* Paired with begin_action in cc_add_user_dialog_response () */
+ finish_action (self);
+
+ if (g_permission_acquire_finish (self->permission, res, &error)) {
+ g_return_if_fail (g_permission_get_allowed (self->permission));
+ add_button_clicked_cb (self);
+ } else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ g_warning ("Failed to acquire permission: %s", error->message);
+ }
+}
+
+static void
+add_button_clicked_cb (CcAddUserDialog *self)
+{
+ /* We don't (or no longer) have necessary permissions */
+ if (self->permission && !g_permission_get_allowed (self->permission)) {
+ begin_action (self);
+ g_permission_acquire_async (self->permission, self->cancellable,
+ on_permission_acquired, g_object_ref (self));
+ return;
+ }
+
+ switch (self->mode) {
+ case MODE_LOCAL:
+ local_create_user (self);
+ break;
+ case MODE_ENTERPRISE:
+ enterprise_add_user (self);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
+cc_add_user_dialog_dispose (GObject *obj)
+{
+ CcAddUserDialog *self = CC_ADD_USER_DIALOG (obj);
+
+ if (self->cancellable)
+ g_cancellable_cancel (self->cancellable);
+
+ g_clear_object (&self->user);
+
+ if (self->realmd_watch)
+ g_bus_unwatch_name (self->realmd_watch);
+ self->realmd_watch = 0;
+
+ if (self->realm_manager) {
+ g_signal_handlers_disconnect_by_func (self->realm_manager,
+ on_manager_realm_added,
+ self);
+ g_clear_object (&self->realm_manager);
+ }
+
+ if (self->local_password_timeout_id != 0) {
+ g_source_remove (self->local_password_timeout_id);
+ self->local_password_timeout_id = 0;
+ }
+
+ if (self->local_name_timeout_id != 0) {
+ g_source_remove (self->local_name_timeout_id);
+ self->local_name_timeout_id = 0;
+ }
+
+ if (self->local_username_timeout_id != 0) {
+ g_source_remove (self->local_username_timeout_id);
+ self->local_username_timeout_id = 0;
+ }
+
+ if (self->enterprise_domain_timeout_id != 0) {
+ g_source_remove (self->enterprise_domain_timeout_id);
+ self->enterprise_domain_timeout_id = 0;
+ }
+
+ if (self->join_dialog != NULL) {
+ gtk_window_destroy (GTK_WINDOW (self->join_dialog));
+ }
+
+ G_OBJECT_CLASS (cc_add_user_dialog_parent_class)->dispose (obj);
+}
+
+static void
+cc_add_user_dialog_finalize (GObject *obj)
+{
+ CcAddUserDialog *self = CC_ADD_USER_DIALOG (obj);
+
+ g_clear_object (&self->cancellable);
+ g_clear_object (&self->permission);
+
+ G_OBJECT_CLASS (cc_add_user_dialog_parent_class)->finalize (obj);
+}
+
+static void
+cc_add_user_dialog_class_init (CcAddUserDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_add_user_dialog_dispose;
+ object_class->finalize = cc_add_user_dialog_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/user-accounts/cc-add-user-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, add_button);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, enterprise_button);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, enterprise_domain_combo);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, enterprise_domain_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, enterprise_domain_hint);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, enterprise_domain_row);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, enterprise_domain_status_icon);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, enterprise_group);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, enterprise_page);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, enterprise_login_group);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, enterprise_login_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, enterprise_login_status_icon);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, enterprise_password_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, enterprise_password_status_icon);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, enterprise_realm_model);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, local_account_type_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, local_page);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, local_password_hint);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, local_password_row);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, local_password_status_icon);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, local_name_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, local_name_status_icon);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, local_username_combo);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, local_username_model);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, local_password_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, local_password_radio);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, local_username_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, local_username_row);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, local_username_status_icon);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, local_strength_indicator);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, local_verify_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, local_verify_password_row);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, local_verify_status_icon);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, offline_page);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, password_group);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, spinner);
+ gtk_widget_class_bind_template_child (widget_class, CcAddUserDialog, stack);
+
+ gtk_widget_class_bind_template_callback (widget_class, add_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, dialog_validate);
+ gtk_widget_class_bind_template_callback (widget_class, enterprise_button_toggled_cb);
+ gtk_widget_class_bind_template_callback (widget_class, enterprise_domain_combo_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, enterprise_domain_combo_focus_out_event_cb);
+ gtk_widget_class_bind_template_callback (widget_class, enterprise_login_entry_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, enterprise_password_entry_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, generate_password);
+ gtk_widget_class_bind_template_callback (widget_class, local_name_entry_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, local_name_entry_focus_out_event_cb);
+ gtk_widget_class_bind_template_callback (widget_class, local_password_entry_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, local_password_entry_key_press_event_cb);
+ gtk_widget_class_bind_template_callback (widget_class, local_password_radio_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, local_username_combo_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, local_username_combo_focus_out_event_cb);
+ gtk_widget_class_bind_template_callback (widget_class, local_verify_entry_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, password_focus_out_event_cb);
+}
+
+CcAddUserDialog *
+cc_add_user_dialog_new (GPermission *permission)
+{
+ CcAddUserDialog *self;
+
+ self = g_object_new (CC_TYPE_ADD_USER_DIALOG, "use-header-bar", 1, NULL);
+
+ if (permission != NULL)
+ self->permission = g_object_ref (permission);
+
+ return self;
+}
+
+ActUser *
+cc_add_user_dialog_get_user (CcAddUserDialog *self)
+{
+ g_return_val_if_fail (CC_IS_ADD_USER_DIALOG (self), NULL);
+ return self->user;
+}
diff --git a/panels/user-accounts/cc-add-user-dialog.h b/panels/user-accounts/cc-add-user-dialog.h
new file mode 100644
index 0000000..c666d4d
--- /dev/null
+++ b/panels/user-accounts/cc-add-user-dialog.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2009-2010 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#pragma once
+
+#include <act/act.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_ADD_USER_DIALOG (cc_add_user_dialog_get_type ())
+G_DECLARE_FINAL_TYPE (CcAddUserDialog, cc_add_user_dialog, CC, ADD_USER_DIALOG, GtkDialog)
+
+CcAddUserDialog *cc_add_user_dialog_new (GPermission *permission);
+ActUser *cc_add_user_dialog_get_user (CcAddUserDialog *dialog);
+
+G_END_DECLS
diff --git a/panels/user-accounts/cc-add-user-dialog.ui b/panels/user-accounts/cc-add-user-dialog.ui
new file mode 100644
index 0000000..afdc65f
--- /dev/null
+++ b/panels/user-accounts/cc-add-user-dialog.ui
@@ -0,0 +1,411 @@
+<?xml version="1.0"?>
+<interface>
+ <!-- interface-requires gtk+ 3.8 -->
+ <!-- interface-naming-policy toplevel-contextual -->
+ <object class="GtkListStore" id="local_username_model">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <template class="CcAddUserDialog" parent="GtkDialog">
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="hide-on-close">True</property>
+ <property name="title" translatable="yes">Add User</property>
+ <property name="icon_name">system-users</property>
+ <property name="default-width">500</property>
+ <property name="use_header_bar">1</property>
+ <child type="titlebar">
+ <object class="AdwHeaderBar">
+ <property name="show-end-title-buttons">False</property>
+ <property name="show-start-title-buttons">False</property>
+ <child type="start">
+ <object class="GtkButton" id="cancel_button">
+ <property name="label" translatable="yes">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="visible">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ <property name="valign">center</property>
+ <signal name="clicked" handler="gtk_window_destroy" object="CcAddUserDialog"/>
+ <style>
+ <class name="text-button"/>
+ </style>
+ </object>
+ </child>
+ <child type="end">
+ <object class="GtkButton" id="add_button">
+ <property name="label" translatable="yes">_Add</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ <property name="valign">center</property>
+ <signal name="clicked" handler="add_button_clicked_cb" object="CcAddUserDialog" swapped="yes"/>
+ <style>
+ <class name="text-button"/>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ </child>
+ <child type="end">
+ <object class="GtkSpinner" id="spinner">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStack" id="stack">
+ <child>
+ <object class="AdwPreferencesPage" id="local_page">
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="AdwActionRow" id="local_name_row">
+ <property name="activatable-widget">local_name_entry</property>
+ <property name="title" translatable="yes">Name</property>
+ <child>
+ <object class="GtkEntry" id="local_name_entry">
+ <property name="valign">center</property>
+ <property name="max-length">255</property>
+ <property name="activates_default">True</property>
+ <property name="hexpand">True</property>
+ <signal name="changed" handler="local_name_entry_changed_cb" object="CcAddUserDialog" swapped="yes"/>
+ <signal name="activate" handler="dialog_validate" object="CcAddUserDialog" swapped="yes"/>
+ <child>
+ <object class="GtkEventControllerFocus">
+ <signal name="leave" handler="local_name_entry_focus_out_event_cb" object="CcAddUserDialog" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="suffix">
+ <object class="GtkImage" id="local_name_status_icon">
+ <property name="icon-name">dialog-warning-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="local_username_row">
+ <property name="activatable-widget">local_username_combo</property>
+ <property name="title" translatable="yes">Username</property>
+ <property name="subtitle-lines">2</property>
+ <child>
+ <object class="GtkComboBoxText" id="local_username_combo">
+ <property name="valign">center</property>
+ <property name="has_entry">True</property>
+ <property name="entry_text_column">0</property>
+ <property name="model">local_username_model</property>
+ <signal name="changed" handler="local_username_combo_changed_cb" object="CcAddUserDialog" swapped="yes"/>
+ <child>
+ <object class="GtkEventControllerFocus">
+ <signal name="leave" handler="local_username_combo_focus_out_event_cb" object="CcAddUserDialog" swapped="yes"/>
+ </object>
+ </child>
+ <child internal-child="entry">
+ <object class="GtkEntry" id="local_username_entry">
+ <property name="activates_default">True</property>
+ <property name="hexpand">True</property>
+ <signal name="activate" handler="dialog_validate" object="CcAddUserDialog" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="suffix">
+ <object class="GtkImage" id="local_username_status_icon">
+ <property name="icon-name">dialog-warning-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="AdwActionRow">
+ <property name="activatable-widget">local_account_type_switch</property>
+ <property name="title" translatable="yes">Administrator</property>
+ <property name="subtitle" translatable="yes">Administrators can add and remove other users, and can change settings for all users. Parental controls cannot be applied to administrators.</property>
+ <property name="subtitle-lines">3</property>
+ <child type="suffix">
+ <object class="GtkSwitch" id="local_account_type_switch">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Password</property>
+ <child>
+ <object class="AdwActionRow">
+ <property name="activatable-widget">local_password_login_radio</property>
+ <property name="title" translatable="yes">User sets password on first login</property>
+ <child type="prefix">
+ <object class="GtkCheckButton" id="local_password_login_radio">
+ <property name="valign">center</property>
+ <property name="active">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow">
+ <property name="activatable-widget">local_password_radio</property>
+ <property name="title" translatable="yes">Set password now</property>
+ <child type="prefix">
+ <object class="GtkCheckButton" id="local_password_radio">
+ <property name="valign">center</property>
+ <property name="use_underline">True</property>
+ <property name="group">local_password_login_radio</property>
+ <signal name="toggled" handler="local_password_radio_changed_cb" object="CcAddUserDialog" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup" id="password_group">
+ <property name="sensitive">False</property>
+ <child>
+ <object class="AdwActionRow" id="local_password_row">
+ <property name="activatable-widget">local_password_entry</property>
+ <property name="title" translatable="yes">Password</property>
+ <property name="subtitle-lines">2</property>
+ <child>
+ <object class="GtkPasswordEntry" id="local_password_entry">
+ <property name="hexpand">True</property>
+ <property name="has_tooltip">True</property>
+ <property name="valign">center</property>
+ <property name="show-peek-icon">True</property>
+ <signal name="notify::text" handler="local_password_entry_changed_cb" object="CcAddUserDialog" swapped="yes"/>
+ <signal name="activate" handler="dialog_validate" object="CcAddUserDialog" swapped="yes"/>
+ <child>
+ <object class="GtkEventControllerKey">
+ <signal name="key-pressed" handler="local_password_entry_key_press_event_cb" object="CcAddUserDialog" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEventControllerFocus">
+ <signal name="leave" handler="password_focus_out_event_cb" object="CcAddUserDialog" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="suffix">
+ <object class="GtkButton">
+ <property name="visible">False</property>
+ <property name="icon-name">system-run-symbolic</property>
+ <property name="valign">center</property>
+ <signal name="clicked" handler="generate_password" object="CcAddUserDialog" swapped="yes"/>
+ <style>
+ <class name="flat"/>
+ </style>
+ </object>
+ </child>
+ <child type="suffix">
+ <object class="GtkImage" id="local_password_status_icon">
+ <property name="icon-name">dialog-warning-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="local_verify_password_row">
+ <property name="activatable-widget">local_verify_entry</property>
+ <property name="title" translatable="yes">Confirm</property>
+ <child>
+ <object class="GtkPasswordEntry" id="local_verify_entry">
+ <property name="hexpand">True</property>
+ <property name="valign">center</property>
+ <property name="sensitive">False</property>
+ <property name="show-peek-icon">True</property>
+ <signal name="notify::text" handler="local_verify_entry_changed_cb" object="CcAddUserDialog" swapped="yes"/>
+ <signal name="activate" handler="dialog_validate" object="CcAddUserDialog" swapped="yes"/>
+ <child>
+ <object class="GtkEventControllerFocus">
+ <signal name="leave" handler="password_focus_out_event_cb" object="CcAddUserDialog" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="suffix">
+ <object class="GtkImage" id="local_verify_status_icon">
+ <property name="icon-name">dialog-warning-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLevelBar" id="local_strength_indicator">
+ <property name="mode">continuous</property>
+ <property name="max-value">5</property>
+ <property name="margin-top">12</property>
+ <offsets>
+ <offset name="strength-weak" value="1"/>
+ <offset name="strength-low" value="2"/>
+ <offset name="strength-medium" value="3"/>
+ <offset name="strength-good" value="4"/>
+ <offset name="strength-high" value="5"/>
+ </offsets>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="local_password_hint">
+ <property name="halign">start</property>
+ <property name="wrap">True</property>
+ <property name="margin-top">12</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup" id="enterprise_group">
+ <property name="visible">False</property>
+ <child>
+ <object class="AdwActionRow" id="enterprise_button">
+ <property name="title" translatable="yes">Enterprise Login</property>
+ <property name="subtitle" translatable="yes">User accounts which are managed by a company or organization.</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="enterprise_button_toggled_cb" object="CcAddUserDialog" swapped="yes"/>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesPage" id="enterprise_page">
+ <property name="visible">True</property>
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="AdwActionRow" id="enterprise_domain_row">
+ <property name="title" translatable="yes">Domain</property>
+ <property name="activatable_widget">enterprise_domain_combo</property>
+ <child>
+ <object class="GtkComboBox" id="enterprise_domain_combo">
+ <property name="valign">center</property>
+ <property name="has_entry">True</property>
+ <property name="entry_text_column">0</property>
+ <property name="model">enterprise_realm_model</property>
+ <signal name="changed" handler="enterprise_domain_combo_changed_cb" object="CcAddUserDialog" swapped="yes"/>
+ <child internal-child="entry">
+ <object class="GtkEntry" id="enterprise_domain_entry">
+ </object>
+ </child>
+ <child>
+ <object class="GtkEventControllerFocus">
+ <signal name="leave" handler="enterprise_domain_combo_focus_out_event_cb" object="CcAddUserDialog" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="suffix">
+ <object class="GtkImage" id="enterprise_domain_status_icon">
+ <property name="icon-name">dialog-warning-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="enterprise_domain_hint">
+ <property name="halign">start</property>
+ <property name="margin-top">12</property>
+ <property name="wrap">True</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup" id="enterprise_login_group">
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Username</property>
+ <property name="activatable_widget">enterprise_login_entry</property>
+ <child>
+ <object class="GtkEntry" id="enterprise_login_entry">
+ <property name="valign">center</property>
+ <property name="invisible_char">●</property>
+ <property name="activates_default">True</property>
+ <property name="invisible_char_set">True</property>
+ <property name="input_purpose">password</property>
+ <signal name="changed" handler="enterprise_login_entry_changed_cb" object="CcAddUserDialog" swapped="yes"/>
+ </object>
+ </child>
+ <child type="suffix">
+ <object class="GtkImage" id="enterprise_login_status_icon">
+ <property name="icon-name">dialog-warning-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Password</property>
+ <property name="activatable_widget">enterprise_password_entry</property>
+ <child>
+ <object class="GtkPasswordEntry" id="enterprise_password_entry">
+ <property name="valign">center</property>
+ <property name="activates_default">True</property>
+ <signal name="changed" handler="enterprise_password_entry_changed_cb" object="CcAddUserDialog" swapped="yes"/>
+ </object>
+ </child>
+ <child type="suffix">
+ <object class="GtkImage" id="enterprise_password_status_icon">
+ <property name="icon-name">dialog-warning-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesPage" id="offline_page">
+ <child>
+ <object class="AdwStatusPage">
+ <property name="title" translatable="yes">You are Offline</property>
+ <property name="description" translatable="yes">Enterprise login allows an existing centrally managed user account to be used on this device. You can also use this account to access company resources on the internet.</property>
+ <property name="icon-name">network-offline-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GtkSizeGroup">
+ <widgets>
+ <widget name="cancel_button"/>
+ <widget name="add_button"/>
+ </widgets>
+ </object>
+ <object class="GtkListStore" id="enterprise_realm_model">
+ <columns>
+ <!-- column-name title -->
+ <column type="gchararray"/>
+ <!-- column-name realm -->
+ <column type="GObject"/>
+ </columns>
+ </object>
+</interface>
diff --git a/panels/user-accounts/cc-avatar-chooser.c b/panels/user-accounts/cc-avatar-chooser.c
new file mode 100644
index 0000000..218d73f
--- /dev/null
+++ b/panels/user-accounts/cc-avatar-chooser.c
@@ -0,0 +1,452 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2009-2010 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+
+#include <adwaita.h>
+#include <gio/gunixoutputstream.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <gtk/gtk.h>
+#include <act/act.h>
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnome-desktop/gnome-desktop-thumbnail.h>
+
+#include "cc-avatar-chooser.h"
+#include "cc-crop-area.h"
+#include "user-utils.h"
+
+#define ROW_SPAN 5
+#define AVATAR_CHOOSER_PIXEL_SIZE 80
+#define PIXEL_SIZE 512
+
+struct _CcAvatarChooser {
+ GtkPopover parent;
+
+ GtkWidget *transient_for;
+
+ GtkWidget *crop_area;
+ GtkWidget *user_flowbox;
+ GtkWidget *flowbox;
+
+ GnomeDesktopThumbnailFactory *thumb_factory;
+ GListStore *faces;
+
+ ActUser *user;
+};
+
+G_DEFINE_TYPE (CcAvatarChooser, cc_avatar_chooser, GTK_TYPE_POPOVER)
+
+static void
+crop_dialog_response (CcAvatarChooser *self,
+ gint response_id,
+ GtkWidget *dialog)
+{
+ g_autoptr(GdkPixbuf) pb = NULL;
+ g_autoptr(GdkPixbuf) pb2 = NULL;
+
+ if (response_id != GTK_RESPONSE_ACCEPT) {
+ self->crop_area = NULL;
+ gtk_window_destroy (GTK_WINDOW (dialog));
+ return;
+ }
+
+ pb = cc_crop_area_create_pixbuf (CC_CROP_AREA (self->crop_area));
+ pb2 = gdk_pixbuf_scale_simple (pb, PIXEL_SIZE, PIXEL_SIZE, GDK_INTERP_BILINEAR);
+
+ set_user_icon_data (self->user, pb2);
+
+ self->crop_area = NULL;
+ gtk_window_destroy (GTK_WINDOW (dialog));
+
+ gtk_popover_popdown (GTK_POPOVER (self));
+}
+
+static void
+cc_avatar_chooser_crop (CcAvatarChooser *self,
+ GdkPixbuf *pixbuf)
+{
+ GtkWidget *dialog;
+ GtkWindow *toplevel;
+
+ toplevel = (GtkWindow *)gtk_widget_get_native (GTK_WIDGET (self->transient_for));
+ dialog = gtk_dialog_new_with_buttons ("",
+ toplevel,
+ GTK_DIALOG_USE_HEADER_BAR,
+ _("_Cancel"),
+ GTK_RESPONSE_CANCEL,
+ _("Select"),
+ GTK_RESPONSE_ACCEPT,
+ NULL);
+ gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), "system-users");
+
+ g_signal_connect_object (G_OBJECT (dialog), "response",
+ G_CALLBACK (crop_dialog_response), self, G_CONNECT_SWAPPED);
+
+ /* Content */
+ self->crop_area = cc_crop_area_new ();
+ gtk_widget_show (self->crop_area);
+ cc_crop_area_set_min_size (CC_CROP_AREA (self->crop_area), 48, 48);
+ cc_crop_area_set_paintable (CC_CROP_AREA (self->crop_area),
+ GDK_PAINTABLE (gdk_texture_new_for_pixbuf (pixbuf)));
+ gtk_box_prepend (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
+ self->crop_area);
+ gtk_widget_set_hexpand (self->crop_area, TRUE);
+ gtk_widget_set_vexpand (self->crop_area, TRUE);
+
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 400, 300);
+
+ gtk_widget_show (dialog);
+}
+
+static void
+file_chooser_response (CcAvatarChooser *self,
+ gint response,
+ GtkDialog *chooser)
+{
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GdkPixbuf) pixbuf = NULL;
+ g_autoptr(GdkPixbuf) pixbuf2 = NULL;
+ g_autoptr(GFile) file = NULL;
+ g_autoptr(GFileInputStream) stream = NULL;
+
+ if (response != GTK_RESPONSE_ACCEPT) {
+ gtk_window_destroy (GTK_WINDOW (chooser));
+ return;
+ }
+
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (chooser));
+ stream = g_file_read (file, NULL, &error);
+ pixbuf = gdk_pixbuf_new_from_stream (G_INPUT_STREAM (stream),
+ NULL, &error);
+ if (pixbuf == NULL) {
+ g_warning ("Failed to load %s: %s", g_file_get_uri (file), error->message);
+ }
+
+ pixbuf2 = gdk_pixbuf_apply_embedded_orientation (pixbuf);
+
+ gtk_window_destroy (GTK_WINDOW (chooser));
+
+ cc_avatar_chooser_crop (self, pixbuf2);
+}
+
+static void
+cc_avatar_chooser_select_file (CcAvatarChooser *self)
+{
+ g_autoptr(GFile) folder = NULL;
+ GtkWidget *chooser;
+ GtkFileFilter *filter;
+ GtkWindow *toplevel;
+
+ toplevel = (GtkWindow*) gtk_widget_get_native (GTK_WIDGET (self->transient_for));
+ chooser = gtk_file_chooser_dialog_new (_("Browse for more pictures"),
+ toplevel,
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Open"), GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ gtk_window_set_modal (GTK_WINDOW (chooser), TRUE);
+
+ folder = g_file_new_for_path (g_get_user_special_dir (G_USER_DIRECTORY_PICTURES));
+ if (folder)
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (chooser),
+ folder,
+ NULL);
+
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_add_pixbuf_formats (filter);
+ gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (chooser), filter);
+
+ g_signal_connect_object (chooser, "response",
+ G_CALLBACK (file_chooser_response), self, G_CONNECT_SWAPPED);
+
+ gtk_popover_popdown (GTK_POPOVER (self));
+ gtk_window_present (GTK_WINDOW (chooser));
+}
+
+static void
+face_widget_activated (CcAvatarChooser *self,
+ GtkFlowBoxChild *child)
+{
+ const gchar *filename;
+ GtkWidget *image;
+
+ image = gtk_flow_box_child_get_child (child);
+ filename = g_object_get_data (G_OBJECT (image), "filename");
+
+ act_user_set_icon_file (self->user, filename);
+
+ gtk_popover_popdown (GTK_POPOVER (self));
+}
+
+static GtkWidget *
+create_face_widget (gpointer item,
+ gpointer user_data)
+{
+ g_autofree gchar *image_path = NULL;
+ g_autoptr(GdkPixbuf) source_pixbuf = NULL;
+ g_autoptr(GdkPixbuf) pixbuf = NULL;
+ GtkWidget *image;
+
+ image_path = g_file_get_path (G_FILE (item));
+
+ source_pixbuf = gdk_pixbuf_new_from_file_at_size (image_path,
+ AVATAR_CHOOSER_PIXEL_SIZE,
+ AVATAR_CHOOSER_PIXEL_SIZE,
+ NULL);
+ if (source_pixbuf == NULL) {
+ image = gtk_image_new_from_icon_name ("image-missing");
+ gtk_image_set_pixel_size (GTK_IMAGE (image), AVATAR_CHOOSER_PIXEL_SIZE);
+ gtk_widget_show (image);
+
+ g_object_set_data_full (G_OBJECT (image),
+ "filename", g_steal_pointer (&image_path), g_free);
+
+ return image;
+ }
+
+ pixbuf = round_image (source_pixbuf);
+ image = gtk_image_new_from_pixbuf (pixbuf);
+ gtk_image_set_pixel_size (GTK_IMAGE (image), AVATAR_CHOOSER_PIXEL_SIZE);
+ gtk_widget_show (image);
+
+ g_object_set_data_full (G_OBJECT (image),
+ "filename", g_steal_pointer (&image_path), g_free);
+
+ return image;
+}
+
+static GStrv
+get_settings_facesdirs (void)
+{
+ g_autoptr(GSettings) settings = g_settings_new ("org.gnome.desktop.interface");
+ g_auto(GStrv) settings_dirs = g_settings_get_strv (settings, "avatar-directories");
+ GPtrArray *facesdirs = g_ptr_array_new ();
+
+ if (settings_dirs != NULL) {
+ int i;
+ for (i = 0; settings_dirs[i] != NULL; i++) {
+ char *path = settings_dirs[i];
+ if (g_strcmp0 (path, "") != 0)
+ g_ptr_array_add (facesdirs, g_strdup (path));
+ }
+ }
+ g_ptr_array_add (facesdirs, NULL);
+
+ return (GStrv) g_ptr_array_steal (facesdirs, NULL);
+}
+
+static GStrv
+get_system_facesdirs (void)
+{
+ const char * const * data_dirs;
+ GPtrArray *facesdirs;
+ int i;
+
+ facesdirs = g_ptr_array_new ();
+
+ data_dirs = g_get_system_data_dirs ();
+ for (i = 0; data_dirs[i] != NULL; i++) {
+ char *path = g_build_filename (data_dirs[i], "pixmaps", "faces", NULL);
+ g_ptr_array_add (facesdirs, path);
+ }
+ g_ptr_array_add (facesdirs, NULL);
+ return (GStrv) g_ptr_array_steal (facesdirs, NULL);
+}
+
+static gboolean
+add_faces_from_dirs (GListStore *faces, GStrv facesdirs, gboolean add_all)
+{
+ GFile *file;
+ GFileType type;
+ const gchar *target;
+ guint i;
+ gboolean added_faces = FALSE;
+
+ for (i = 0; facesdirs[i] != NULL; i++) {
+ g_autoptr(GFile) dir = NULL;
+ g_autoptr(GFileEnumerator) enumerator = NULL;
+
+ dir = g_file_new_for_path (facesdirs[i]);
+
+ enumerator = g_file_enumerate_children (dir,
+ G_FILE_ATTRIBUTE_STANDARD_NAME ","
+ G_FILE_ATTRIBUTE_STANDARD_TYPE ","
+ G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK ","
+ G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET,
+ G_FILE_QUERY_INFO_NONE,
+ NULL, NULL);
+ if (enumerator == NULL) {
+ continue;
+ }
+
+ while (TRUE) {
+ g_autoptr(GFileInfo) info = g_file_enumerator_next_file (enumerator, NULL, NULL);
+ if (info == NULL) {
+ break;
+ }
+
+ type = g_file_info_get_file_type (info);
+ if (type != G_FILE_TYPE_REGULAR &&
+ type != G_FILE_TYPE_SYMBOLIC_LINK) {
+ continue;
+ }
+
+ target = g_file_info_get_symlink_target (info);
+ if (target != NULL && g_str_has_prefix (target , "legacy/")) {
+ continue;
+ }
+
+ file = g_file_get_child (dir, g_file_info_get_name (info));
+ g_list_store_append (faces, file);
+
+ added_faces = TRUE;
+ }
+
+ g_file_enumerator_close (enumerator, NULL, NULL);
+
+ if (added_faces && !add_all)
+ break;
+ }
+ return added_faces;
+}
+
+
+static void
+setup_photo_popup (CcAvatarChooser *self)
+{
+ g_auto(GStrv) settings_facesdirs = NULL;
+
+ self->faces = g_list_store_new (G_TYPE_FILE);
+ gtk_flow_box_bind_model (GTK_FLOW_BOX (self->flowbox),
+ G_LIST_MODEL (self->faces),
+ create_face_widget,
+ self,
+ NULL);
+
+ g_signal_connect_object (self->flowbox, "child-activated",
+ G_CALLBACK (face_widget_activated), self, G_CONNECT_SWAPPED);
+
+ settings_facesdirs = get_settings_facesdirs ();
+
+ if (!add_faces_from_dirs (self->faces, settings_facesdirs, TRUE)) {
+ g_auto(GStrv) system_facesdirs = get_system_facesdirs ();
+ add_faces_from_dirs (self->faces, system_facesdirs, FALSE);
+ }
+}
+
+CcAvatarChooser *
+cc_avatar_chooser_new (GtkWidget *transient_for)
+{
+ CcAvatarChooser *self;
+
+ self = g_object_new (CC_TYPE_AVATAR_CHOOSER,
+ NULL);
+ self->transient_for = transient_for;
+ self->thumb_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL);
+
+ setup_photo_popup (self);
+
+ return self;
+}
+
+static void
+cc_avatar_chooser_dispose (GObject *object)
+{
+ CcAvatarChooser *self = CC_AVATAR_CHOOSER (object);
+
+ g_clear_object (&self->thumb_factory);
+ g_clear_object (&self->user);
+
+ G_OBJECT_CLASS (cc_avatar_chooser_parent_class)->dispose (object);
+}
+
+static void
+cc_avatar_chooser_init (CcAvatarChooser *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+cc_avatar_chooser_class_init (CcAvatarChooserClass *klass)
+{
+ GtkWidgetClass *wclass = GTK_WIDGET_CLASS (klass);
+ GObjectClass *oclass = G_OBJECT_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (wclass, "/org/gnome/control-center/user-accounts/cc-avatar-chooser.ui");
+
+ gtk_widget_class_bind_template_child (wclass, CcAvatarChooser, user_flowbox);
+ gtk_widget_class_bind_template_child (wclass, CcAvatarChooser, flowbox);
+
+ gtk_widget_class_bind_template_callback (wclass, cc_avatar_chooser_select_file);
+
+ oclass->dispose = cc_avatar_chooser_dispose;
+}
+
+static void
+user_flowbox_activated (CcAvatarChooser *self)
+{
+ set_default_avatar (self->user);
+
+ gtk_popover_popdown (GTK_POPOVER (self));
+}
+
+void
+cc_avatar_chooser_set_user (CcAvatarChooser *self,
+ ActUser *user)
+{
+ g_autoptr(GdkPixbuf) pixbuf = NULL;
+ const gchar *name;
+ GtkWidget *avatar;
+
+ g_return_if_fail (self != NULL);
+
+ if (self->user) {
+ GtkWidget *child;
+
+ child = gtk_widget_get_first_child (GTK_WIDGET (self->user_flowbox));
+ while (child) {
+ GtkWidget *next = gtk_widget_get_next_sibling (child);
+
+ if (GTK_FLOW_BOX_CHILD (child))
+ gtk_flow_box_remove (GTK_FLOW_BOX (self->user_flowbox), child);
+
+ child = next;
+ }
+
+ g_clear_object (&self->user);
+ }
+ self->user = g_object_ref (user);
+
+ name = act_user_get_real_name (user);
+ if (name == NULL)
+ name = act_user_get_user_name (user);
+ avatar = adw_avatar_new (AVATAR_CHOOSER_PIXEL_SIZE, name, TRUE);
+ gtk_flow_box_append (GTK_FLOW_BOX (self->user_flowbox), avatar);
+
+ g_signal_connect_object (self->user_flowbox, "child-activated", G_CALLBACK (user_flowbox_activated), self, G_CONNECT_SWAPPED);
+}
+
diff --git a/panels/user-accounts/cc-avatar-chooser.h b/panels/user-accounts/cc-avatar-chooser.h
new file mode 100644
index 0000000..879e482
--- /dev/null
+++ b/panels/user-accounts/cc-avatar-chooser.h
@@ -0,0 +1,39 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2009-2010 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <act/act.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_AVATAR_CHOOSER (cc_avatar_chooser_get_type())
+
+G_DECLARE_FINAL_TYPE (CcAvatarChooser, cc_avatar_chooser, CC, AVATAR_CHOOSER, GtkPopover)
+
+typedef struct _CcAvatarChooser CcAvatarChooser;
+
+CcAvatarChooser *cc_avatar_chooser_new (GtkWidget *transient_for);
+void cc_avatar_chooser_free (CcAvatarChooser *dialog);
+void cc_avatar_chooser_set_user (CcAvatarChooser *dialog,
+ ActUser *user);
+
+G_END_DECLS
diff --git a/panels/user-accounts/cc-avatar-chooser.ui b/panels/user-accounts/cc-avatar-chooser.ui
new file mode 100644
index 0000000..fe1696f
--- /dev/null
+++ b/panels/user-accounts/cc-avatar-chooser.ui
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<interface>
+ <!-- interface-requires gtk+ 3.8 -->
+ <template class="CcAvatarChooser" parent="GtkPopover">
+ <property name="visible">False</property>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">GTK_ORIENTATION_VERTICAL</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkFlowBox" id="user_flowbox">
+ <property name="selection-mode">none</property>
+ <property name="homogeneous">True</property>
+ <property name="max-children-per-line">5</property>
+ <property name="column-spacing">10</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkFlowBox" id="flowbox">
+ <property name="selection-mode">none</property>
+ <property name="homogeneous">True</property>
+ <property name="max-children-per-line">5</property>
+ <property name="column-spacing">10</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="halign">GTK_ALIGN_CENTER</property>
+ <property name="spacing">20</property>
+ <child>
+ <object class="GtkButton">
+ <property name="label" translatable="yes">Select a File…</property>
+ <signal name="clicked" handler="cc_avatar_chooser_select_file" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/user-accounts/cc-crop-area.c b/panels/user-accounts/cc-crop-area.c
new file mode 100644
index 0000000..a644b60
--- /dev/null
+++ b/panels/user-accounts/cc-crop-area.c
@@ -0,0 +1,717 @@
+/*
+ * Copyright 2021 Red Hat, Inc,
+ *
+ * Authors:
+ * - Matthias Clasen <mclasen@redhat.com>
+ * - Niels De Graef <nielsdg@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <gsk/gl/gskglrenderer.h>
+
+#include "cc-crop-area.h"
+
+/**
+ * CcCropArea:
+ *
+ * A widget that shows a [iface@Gdk.Paintable] and allows the user specify a
+ * cropping rectangle to effectively crop to that given area.
+ */
+
+/* Location of the cursor relative to the cropping rectangle/circle */
+typedef enum {
+ OUTSIDE,
+ INSIDE,
+ TOP,
+ TOP_LEFT,
+ TOP_RIGHT,
+ BOTTOM,
+ BOTTOM_LEFT,
+ BOTTOM_RIGHT,
+ LEFT,
+ RIGHT
+} Location;
+
+struct _CcCropArea {
+ GtkWidget parent_instance;
+
+ GdkPaintable *paintable;
+
+ double scale; /* scale factor to go from paintable size to widget size */
+
+ const char *current_cursor;
+ Location active_region;
+ double drag_offx;
+ double drag_offy;
+
+ /* In source coordinates. See get_scaled_crop() for widget coordinates */
+ GdkRectangle crop;
+
+ /* In widget coordinates */
+ GdkRectangle image;
+ int min_crop_width;
+ int min_crop_height;
+};
+
+G_DEFINE_TYPE (CcCropArea, cc_crop_area, GTK_TYPE_WIDGET);
+
+static void
+update_image_and_crop (CcCropArea *area)
+{
+ GtkAllocation allocation;
+ int width, height;
+ int dest_width, dest_height;
+ double scale;
+
+ if (area->paintable == NULL)
+ return;
+
+ gtk_widget_get_allocation (GTK_WIDGET (area), &allocation);
+
+ /* Get the size of the paintable */
+ width = gdk_paintable_get_intrinsic_width (area->paintable);
+ height = gdk_paintable_get_intrinsic_height (area->paintable);
+
+ /* Find out the scale to convert to widget width/height */
+ scale = allocation.height / (double) height;
+ if (scale * width > allocation.width)
+ scale = allocation.width / (double) width;
+
+ dest_width = width * scale;
+ dest_height = height * scale;
+
+ if (area->scale == 0.0) {
+ double scale_to_80, scale_to_image, crop_scale;
+
+ /* Start with a crop area of 80% of the area, unless it's larger than min_size */
+ scale_to_80 = MIN ((double) dest_width * 0.8, (double) dest_height * 0.8);
+ scale_to_image = MIN ((double) area->min_crop_width, (double) area->min_crop_height);
+ crop_scale = MAX (scale_to_80, scale_to_image);
+
+ /* Divide by `scale` to get back to paintable coordinates */
+ area->crop.width = crop_scale / scale;
+ area->crop.height = crop_scale / scale;
+ area->crop.x = (width - area->crop.width) / 2;
+ area->crop.y = (height - area->crop.height) / 2;
+ }
+
+ area->scale = scale;
+ area->image.x = (allocation.width - dest_width) / 2;
+ area->image.y = (allocation.height - dest_height) / 2;
+ area->image.width = dest_width;
+ area->image.height = dest_height;
+}
+
+/* Returns area->crop in widget coordinates (vs paintable coordsinates) */
+static void
+get_scaled_crop (CcCropArea *area,
+ GdkRectangle *crop)
+{
+ crop->x = area->image.x + area->crop.x * area->scale;
+ crop->y = area->image.y + area->crop.y * area->scale;
+ crop->width = area->crop.width * area->scale;
+ crop->height = area->crop.height * area->scale;
+}
+
+typedef enum {
+ BELOW,
+ LOWER,
+ BETWEEN,
+ UPPER,
+ ABOVE
+} Range;
+
+static Range
+find_range (int x,
+ int min,
+ int max)
+{
+ int tolerance = 12;
+
+ if (x < min - tolerance)
+ return BELOW;
+ if (x <= min + tolerance)
+ return LOWER;
+ if (x < max - tolerance)
+ return BETWEEN;
+ if (x <= max + tolerance)
+ return UPPER;
+ return ABOVE;
+}
+
+/* Finds the location of (@x, @y) relative to the crop @rect */
+static Location
+find_location (GdkRectangle *rect,
+ int x,
+ int y)
+{
+ Range x_range, y_range;
+ Location location[5][5] = {
+ { OUTSIDE, OUTSIDE, OUTSIDE, OUTSIDE, OUTSIDE },
+ { OUTSIDE, TOP_LEFT, TOP, TOP_RIGHT, OUTSIDE },
+ { OUTSIDE, LEFT, INSIDE, RIGHT, OUTSIDE },
+ { OUTSIDE, BOTTOM_LEFT, BOTTOM, BOTTOM_RIGHT, OUTSIDE },
+ { OUTSIDE, OUTSIDE, OUTSIDE, OUTSIDE, OUTSIDE }
+ };
+
+ x_range = find_range (x, rect->x, rect->x + rect->width);
+ y_range = find_range (y, rect->y, rect->y + rect->height);
+
+ return location[y_range][x_range];
+}
+
+static void
+update_cursor (CcCropArea *area,
+ int x,
+ int y)
+{
+ const char *cursor_type;
+ GdkRectangle crop;
+ int region;
+
+ region = area->active_region;
+ if (region == OUTSIDE) {
+ get_scaled_crop (area, &crop);
+ region = find_location (&crop, x, y);
+ }
+
+ switch (region) {
+ case OUTSIDE:
+ cursor_type = "default";
+ break;
+ case TOP_LEFT:
+ cursor_type = "nw-resize";
+ break;
+ case TOP:
+ cursor_type = "n-resize";
+ break;
+ case TOP_RIGHT:
+ cursor_type = "ne-resize";
+ break;
+ case LEFT:
+ cursor_type = "w-resize";
+ break;
+ case INSIDE:
+ cursor_type = "move";
+ break;
+ case RIGHT:
+ cursor_type = "e-resize";
+ break;
+ case BOTTOM_LEFT:
+ cursor_type = "sw-resize";
+ break;
+ case BOTTOM:
+ cursor_type = "s-resize";
+ break;
+ case BOTTOM_RIGHT:
+ cursor_type = "se-resize";
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ if (cursor_type != area->current_cursor) {
+ GtkNative *native;
+ g_autoptr (GdkCursor) cursor = NULL;
+
+ native = gtk_widget_get_native (GTK_WIDGET (area));
+ if (!native) {
+ g_warning ("Can't adjust cursor: no GtkNative found");
+ return;
+ }
+ cursor = gdk_cursor_new_from_name (cursor_type, NULL);
+ gdk_surface_set_cursor (gtk_native_get_surface (native), cursor);
+ area->current_cursor = cursor_type;
+ }
+}
+
+static int
+eval_radial_line (double center_x, double center_y,
+ double bounds_x, double bounds_y,
+ double user_x)
+{
+ double decision_slope;
+ double decision_intercept;
+
+ decision_slope = (bounds_y - center_y) / (bounds_x - center_x);
+ decision_intercept = -(decision_slope * bounds_x);
+
+ return (int) (decision_slope * user_x + decision_intercept);
+}
+
+static gboolean
+on_motion (GtkEventControllerMotion *controller,
+ double event_x,
+ double event_y,
+ void *user_data)
+{
+ CcCropArea *area = CC_CROP_AREA (user_data);
+
+ if (area->paintable == NULL)
+ return FALSE;
+
+ update_cursor (area, event_x, event_y);
+
+ return FALSE;
+}
+
+static void
+on_leave (GtkEventControllerMotion *controller,
+ void *user_data)
+{
+ CcCropArea *area = CC_CROP_AREA (user_data);
+
+ if (area->paintable == NULL)
+ return;
+
+ /* Restore 'default' cursor */
+ update_cursor (area, 0, 0);
+}
+
+static void
+on_drag_begin (GtkGestureDrag *gesture,
+ double start_x,
+ double start_y,
+ void *user_data)
+{
+ CcCropArea *area = CC_CROP_AREA (user_data);
+ GdkRectangle crop;
+
+ if (area->paintable == NULL)
+ return;
+
+ update_cursor (area, start_x, start_y);
+
+ get_scaled_crop (area, &crop);
+
+ area->active_region = find_location (&crop, start_x, start_y);
+
+ area->drag_offx = 0.0;
+ area->drag_offy = 0.0;
+}
+
+static void
+on_drag_update (GtkGestureDrag *gesture,
+ double offset_x,
+ double offset_y,
+ void *user_data)
+{
+ CcCropArea *area = CC_CROP_AREA (user_data);
+ double start_x, start_y;
+ int x, y, delta_x, delta_y;
+ int width, height;
+ int adj_width, adj_height;
+ int pb_width, pb_height;
+ int left, right, top, bottom;
+ double new_width, new_height;
+ double center_x, center_y;
+ int min_width, min_height;
+
+ pb_width = gdk_paintable_get_intrinsic_width (area->paintable);
+ pb_height = gdk_paintable_get_intrinsic_height (area->paintable);
+
+ gtk_gesture_drag_get_start_point (gesture, &start_x, &start_y);
+
+ /* Get the x, y, dx, dy in paintable coords */
+ x = (start_x + offset_x - area->image.x) / area->scale;
+ y = (start_y + offset_y - area->image.y) / area->scale;
+ delta_x = (offset_x - area->drag_offx) / area->scale;
+ delta_y = (offset_y - area->drag_offy) / area->scale;
+
+ /* Helper variables */
+ left = area->crop.x;
+ right = area->crop.x + area->crop.width - 1;
+ top = area->crop.y;
+ bottom = area->crop.y + area->crop.height - 1;
+
+ center_x = (left + right) / 2.0;
+ center_y = (top + bottom) / 2.0;
+
+ /* What we have to do depends on where the user started dragging */
+ switch (area->active_region) {
+ case INSIDE:
+ width = right - left + 1;
+ height = bottom - top + 1;
+
+ left = MAX (left + delta_x, 0);
+ right = MIN (right + delta_x, pb_width);
+ top = MAX (top + delta_y, 0);
+ bottom = MIN (bottom + delta_y, pb_height);
+
+ adj_width = right - left + 1;
+ adj_height = bottom - top + 1;
+ if (adj_width != width) {
+ if (delta_x < 0)
+ right = left + width - 1;
+ else
+ left = right - width + 1;
+ }
+ if (adj_height != height) {
+ if (delta_y < 0)
+ bottom = top + height - 1;
+ else
+ top = bottom - height + 1;
+ }
+
+ break;
+
+ case TOP_LEFT:
+ if (y < eval_radial_line (center_x, center_y, left, top, x)) {
+ top = y;
+ new_width = bottom - top;
+ left = right - new_width;
+ } else {
+ left = x;
+ new_height = right - left;
+ top = bottom - new_height;
+ }
+ break;
+
+ case TOP:
+ top = y;
+ new_width = bottom - top;
+ right = left + new_width;
+ break;
+
+ case TOP_RIGHT:
+ if (y < eval_radial_line (center_x, center_y, right, top, x)) {
+ top = y;
+ new_width = bottom - top;
+ right = left + new_width;
+ } else {
+ right = x;
+ new_height = right - left;
+ top = bottom - new_height;
+ }
+ break;
+
+ case LEFT:
+ left = x;
+ new_height = right - left;
+ bottom = top + new_height;
+ break;
+
+ case BOTTOM_LEFT:
+ if (y < eval_radial_line (center_x, center_y, left, bottom, x)) {
+ left = x;
+ new_height = right - left;
+ bottom = top + new_height;
+ } else {
+ bottom = y;
+ new_width = bottom - top;
+ left = right - new_width;
+ }
+ break;
+
+ case RIGHT:
+ right = x;
+ new_height = right - left;
+ bottom = top + new_height;
+ break;
+
+ case BOTTOM_RIGHT:
+ if (y < eval_radial_line (center_x, center_y, right, bottom, x)) {
+ right = x;
+ new_height = right - left;
+ bottom = top + new_height;
+ } else {
+ bottom = y;
+ new_width = bottom - top;
+ right = left + new_width;
+ }
+ break;
+
+ case BOTTOM:
+ bottom = y;
+ new_width = bottom - top;
+ right= left + new_width;
+ break;
+
+ default:
+ return;
+ }
+
+ min_width = area->min_crop_width / area->scale;
+ min_height = area->min_crop_height / area->scale;
+
+ width = right - left + 1;
+ height = bottom - top + 1;
+ if (left < 0 || top < 0 ||
+ right > pb_width || bottom > pb_height ||
+ width < min_width || height < min_height) {
+ left = area->crop.x;
+ right = area->crop.x + area->crop.width - 1;
+ top = area->crop.y;
+ bottom = area->crop.y + area->crop.height - 1;
+ }
+
+ area->crop.x = left;
+ area->crop.y = top;
+ area->crop.width = right - left + 1;
+ area->crop.height = bottom - top + 1;
+
+ area->drag_offx = offset_x;
+ area->drag_offy = offset_y;
+
+ gtk_widget_queue_draw (GTK_WIDGET (area));
+}
+
+static void
+on_drag_end (GtkGestureDrag *gesture,
+ double offset_x,
+ double offset_y,
+ void *user_data)
+{
+ CcCropArea *area = CC_CROP_AREA (user_data);
+
+ area->active_region = OUTSIDE;
+ area->drag_offx = 0.0;
+ area->drag_offy = 0.0;
+}
+
+static void
+on_drag_cancel (GtkGesture *gesture,
+ GdkEventSequence *sequence,
+ void *user_data)
+{
+ CcCropArea *area = CC_CROP_AREA (user_data);
+
+ area->active_region = OUTSIDE;
+ area->drag_offx = 0;
+ area->drag_offy = 0;
+}
+
+static void
+cc_crop_area_snapshot (GtkWidget *widget,
+ GtkSnapshot *snapshot)
+{
+ CcCropArea *area = CC_CROP_AREA (widget);
+ cairo_t *cr;
+ GdkRectangle crop;
+
+ if (area->paintable == NULL)
+ return;
+
+ update_image_and_crop (area);
+
+
+ gtk_snapshot_save (snapshot);
+
+ /* First draw the picture */
+ gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (area->image.x, area->image.y));
+
+ gdk_paintable_snapshot (area->paintable, snapshot, area->image.width, area->image.height);
+
+ /* Draw the cropping UI on top with cairo */
+ cr = gtk_snapshot_append_cairo (snapshot, &GRAPHENE_RECT_INIT (0, 0, area->image.width, area->image.height));
+
+ get_scaled_crop (area, &crop);
+ crop.x -= area->image.x;
+ crop.y -= area->image.y;
+
+ /* Draw the circle */
+ cairo_save (cr);
+ cairo_arc (cr, crop.x + crop.width / 2, crop.y + crop.width / 2, crop.width / 2, 0, 2 * G_PI);
+ cairo_rectangle (cr, 0, 0, area->image.width, area->image.height);
+ cairo_set_source_rgba (cr, 0, 0, 0, 0.4);
+ cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_fill (cr);
+ cairo_restore (cr);
+
+ /* draw the four corners */
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_set_line_width (cr, 4.0);
+
+ /* top left corner */
+ cairo_move_to (cr, crop.x + 15, crop.y);
+ cairo_line_to (cr, crop.x, crop.y);
+ cairo_line_to (cr, crop.x, crop.y + 15);
+ /* top right corner */
+ cairo_move_to (cr, crop.x + crop.width - 15, crop.y);
+ cairo_line_to (cr, crop.x + crop.width, crop.y);
+ cairo_line_to (cr, crop.x + crop.width, crop.y + 15);
+ /* bottom right corner */
+ cairo_move_to (cr, crop.x + crop.width - 15, crop.y + crop.height);
+ cairo_line_to (cr, crop.x + crop.width, crop.y + crop.height);
+ cairo_line_to (cr, crop.x + crop.width, crop.y + crop.height - 15);
+ /* bottom left corner */
+ cairo_move_to (cr, crop.x + 15, crop.y + crop.height);
+ cairo_line_to (cr, crop.x, crop.y + crop.height);
+ cairo_line_to (cr, crop.x, crop.y + crop.height - 15);
+
+ cairo_stroke (cr);
+
+ gtk_snapshot_restore (snapshot);
+}
+
+static void
+cc_crop_area_finalize (GObject *object)
+{
+ CcCropArea *area = CC_CROP_AREA (object);
+
+ g_clear_object (&area->paintable);
+}
+
+static void
+cc_crop_area_class_init (CcCropAreaClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = cc_crop_area_finalize;
+
+ widget_class->snapshot = cc_crop_area_snapshot;
+}
+
+static void
+cc_crop_area_init (CcCropArea *area)
+{
+ GtkGesture *gesture;
+ GtkEventController *controller;
+
+ /* Add handlers for dragging */
+ gesture = gtk_gesture_drag_new ();
+ g_signal_connect (gesture, "drag-begin", G_CALLBACK (on_drag_begin), area);
+ g_signal_connect (gesture, "drag-update", G_CALLBACK (on_drag_update),
+ area);
+ g_signal_connect (gesture, "drag-end", G_CALLBACK (on_drag_end), area);
+ g_signal_connect (gesture, "cancel", G_CALLBACK (on_drag_cancel), area);
+ gtk_widget_add_controller (GTK_WIDGET (area), GTK_EVENT_CONTROLLER (gesture));
+
+ /* Add handlers for motion events */
+ controller = gtk_event_controller_motion_new ();
+ g_signal_connect (controller, "motion", G_CALLBACK (on_motion), area);
+ g_signal_connect (controller, "leave", G_CALLBACK (on_leave), area);
+ gtk_widget_add_controller (GTK_WIDGET (area), GTK_EVENT_CONTROLLER (controller));
+
+ area->scale = 0.0;
+ area->image.x = 0;
+ area->image.y = 0;
+ area->image.width = 0;
+ area->image.height = 0;
+ area->active_region = OUTSIDE;
+ area->min_crop_width = 48;
+ area->min_crop_height = 48;
+
+ gtk_widget_set_size_request (GTK_WIDGET (area), 48, 48);
+}
+
+GtkWidget *
+cc_crop_area_new (void)
+{
+ return g_object_new (CC_TYPE_CROP_AREA, NULL);
+}
+
+/**
+ * cc_crop_area_create_pixbuf:
+ * @area: A crop area
+ *
+ * Renders the area's paintable, with the cropping applied by the user, into a
+ * GdkPixbuf.
+ *
+ * Returns: (transfer full): The cropped picture
+ */
+GdkPixbuf *
+cc_crop_area_create_pixbuf (CcCropArea *area)
+{
+ g_autoptr (GtkSnapshot) snapshot = NULL;
+ g_autoptr (GskRenderNode) node = NULL;
+ g_autoptr (GskRenderer) renderer = NULL;
+ g_autoptr (GdkTexture) texture = NULL;
+ g_autoptr (GError) error = NULL;
+ graphene_rect_t viewport;
+
+ g_return_val_if_fail (CC_IS_CROP_AREA (area), NULL);
+
+ snapshot = gtk_snapshot_new ();
+ gdk_paintable_snapshot (area->paintable, snapshot,
+ gdk_paintable_get_intrinsic_width (area->paintable),
+ gdk_paintable_get_intrinsic_height (area->paintable));
+ node = gtk_snapshot_free_to_node (g_steal_pointer (&snapshot));
+
+ renderer = gsk_gl_renderer_new ();
+ if (!gsk_renderer_realize (renderer, NULL, &error)) {
+ g_warning ("Couldn't realize GL renderer: %s", error->message);
+ return NULL;
+ }
+ viewport = GRAPHENE_RECT_INIT (area->crop.x, area->crop.y,
+ area->crop.width, area->crop.height);
+ texture = gsk_renderer_render_texture (renderer, node, &viewport);
+ gsk_renderer_unrealize (renderer);
+
+ return gdk_pixbuf_get_from_texture (texture);
+}
+
+/**
+ * cc_crop_area_get_paintable:
+ * @area: A crop area
+ *
+ * Returns the area's paintable, unmodified.
+ *
+ * Returns: (transfer none) (nullable): The paintable which the user can crop
+ */
+GdkPaintable *
+cc_crop_area_get_paintable (CcCropArea *area)
+{
+ g_return_val_if_fail (CC_IS_CROP_AREA (area), NULL);
+
+ return area->paintable;
+}
+
+void
+cc_crop_area_set_paintable (CcCropArea *area,
+ GdkPaintable *paintable)
+{
+ g_return_if_fail (CC_IS_CROP_AREA (area));
+ g_return_if_fail (GDK_IS_PAINTABLE (paintable));
+
+ g_set_object (&area->paintable, paintable);
+
+ area->scale = 0.0;
+ area->image.x = 0;
+ area->image.y = 0;
+ area->image.width = 0;
+ area->image.height = 0;
+
+ gtk_widget_queue_draw (GTK_WIDGET (area));
+}
+
+/**
+ * cc_crop_area_set_min_size:
+ * @area: A crop widget
+ * @width: The minimal width
+ * @height: The minimal height
+ *
+ * Sets the minimal size of the crop rectangle (in paintable coordinates)
+ */
+void
+cc_crop_area_set_min_size (CcCropArea *area,
+ int width,
+ int height)
+{
+ g_return_if_fail (CC_IS_CROP_AREA (area));
+
+ area->min_crop_width = width;
+ area->min_crop_height = height;
+
+ gtk_widget_set_size_request (GTK_WIDGET (area),
+ area->min_crop_width,
+ area->min_crop_height);
+}
diff --git a/panels/user-accounts/cc-crop-area.h b/panels/user-accounts/cc-crop-area.h
new file mode 100644
index 0000000..da80024
--- /dev/null
+++ b/panels/user-accounts/cc-crop-area.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2009 Bastien Nocera <hadess@hadess.net>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _CC_CROP_AREA_H_
+#define _CC_CROP_AREA_H_
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_CROP_AREA (cc_crop_area_get_type ())
+G_DECLARE_FINAL_TYPE (CcCropArea, cc_crop_area, CC, CROP_AREA, GtkWidget)
+
+GtkWidget * cc_crop_area_new (void);
+GdkPaintable * cc_crop_area_get_paintable (CcCropArea *area);
+void cc_crop_area_set_paintable (CcCropArea *area,
+ GdkPaintable *paintable);
+void cc_crop_area_set_min_size (CcCropArea *area,
+ int width,
+ int height);
+GdkPixbuf * cc_crop_area_create_pixbuf (CcCropArea *area);
+
+G_END_DECLS
+
+#endif /* _CC_CROP_AREA_H_ */
diff --git a/panels/user-accounts/cc-fingerprint-dialog.c b/panels/user-accounts/cc-fingerprint-dialog.c
new file mode 100644
index 0000000..b8ebba6
--- /dev/null
+++ b/panels/user-accounts/cc-fingerprint-dialog.c
@@ -0,0 +1,1527 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2020 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ * Authors: Marco Trevisan <marco.trevisan@canonical.com>
+ */
+
+#include <glib/gi18n.h>
+#include <cairo/cairo.h>
+
+#include "cc-fingerprint-dialog.h"
+
+#include "cc-fingerprint-manager.h"
+#include "cc-fprintd-generated.h"
+#include "cc-list-row.h"
+
+#include "config.h"
+
+#define CC_FPRINTD_NAME "net.reactivated.Fprint"
+
+/* Translate fprintd strings */
+#define TR(s) dgettext ("fprintd", s)
+#include "fingerprint-strings.h"
+
+typedef enum {
+ DIALOG_STATE_NONE = 0,
+ DIALOG_STATE_DEVICES_LISTING = (1 << 0),
+ DIALOG_STATE_DEVICE_CLAIMING = (1 << 1),
+ DIALOG_STATE_DEVICE_CLAIMED = (1 << 2),
+ DIALOG_STATE_DEVICE_PRINTS_LISTING = (1 << 3),
+ DIALOG_STATE_DEVICE_RELEASING = (1 << 4),
+ DIALOG_STATE_DEVICE_ENROLL_STARTING = (1 << 5),
+ DIALOG_STATE_DEVICE_ENROLLING = (1 << 6),
+ DIALOG_STATE_DEVICE_ENROLL_STOPPING = (1 << 7),
+ DIALOG_STATE_DEVICE_DELETING = (1 << 8),
+
+ DIALOG_STATE_IDLE = DIALOG_STATE_DEVICE_CLAIMED | DIALOG_STATE_DEVICE_ENROLLING,
+} DialogState;
+
+struct _CcFingerprintDialog
+{
+ GtkWindow parent_instance;
+
+ GtkButton *back_button;
+ GtkButton *cancel_button;
+ GtkButton *delete_prints_button;
+ GtkButton *done_button;
+ GtkBox *add_print_popover_box;
+ GtkEntry *enroll_print_entry;
+ GtkFlowBox *prints_gallery;
+ GtkHeaderBar *titlebar;
+ GtkImage *enroll_result_image;
+ GtkLabel *enroll_message;
+ GtkLabel *enroll_result_message;
+ GtkLabel *infobar_error;
+ GtkLabel *title;
+ GtkListBox *devices_list;
+ GtkPopover *add_print_popover;
+ GtkSpinner *spinner;
+ GtkStack *stack;
+ GtkWidget *add_print_icon;
+ GtkWidget *delete_confirmation_infobar;
+ GtkWidget *device_selector;
+ GtkWidget *enroll_print_bin;
+ GtkWidget *enroll_result_icon;
+ GtkWidget *enrollment_view;
+ GtkWidget *error_infobar;
+ GtkWidget *no_devices_found;
+ GtkWidget *prints_manager;
+
+ CcFingerprintManager *manager;
+ DialogState dialog_state;
+ CcFprintdDevice *device;
+ gulong device_signal_id;
+ gulong device_name_owner_id;
+ GCancellable *cancellable;
+ GStrv enrolled_fingers;
+ guint enroll_stages_passed;
+ guint enroll_stage_passed_id;
+ gdouble enroll_progress;
+};
+
+/* TODO - fprintd and API changes required:
+ - Identify the finger when the enroll dialog is visible
+ + Only if device supports identification
+ · And only in such case support enrolling more than one finger
+ - Delete a single fingerprint | and remove the "Delete all" button
+ - Highlight the finger when the sensor is touched during enrollment
+ - Add customized labels to fingerprints
+ - Devices hotplug (object manager)
+ */
+
+G_DEFINE_TYPE (CcFingerprintDialog, cc_fingerprint_dialog, GTK_TYPE_WINDOW)
+
+enum {
+ PROP_0,
+ PROP_MANAGER,
+ N_PROPS
+};
+
+#define N_VALID_FINGERS G_N_ELEMENTS (FINGER_IDS) - 1
+/* The order of the fingers here will affect the UI order */
+const char * FINGER_IDS[] = {
+ "right-index-finger",
+ "left-index-finger",
+ "right-thumb",
+ "right-middle-finger",
+ "right-ring-finger",
+ "right-little-finger",
+ "left-thumb",
+ "left-middle-finger",
+ "left-ring-finger",
+ "left-little-finger",
+ "any",
+};
+
+typedef enum {
+ ENROLL_STATE_NORMAL,
+ ENROLL_STATE_RETRY,
+ ENROLL_STATE_SUCCESS,
+ ENROLL_STATE_WARNING,
+ ENROLL_STATE_ERROR,
+ ENROLL_STATE_COMPLETED,
+ N_ENROLL_STATES,
+} EnrollState;
+
+const char * ENROLL_STATE_CLASSES[N_ENROLL_STATES] = {
+ "",
+ "retry",
+ "success",
+ "warning",
+ "error",
+ "completed",
+};
+
+static GParamSpec *properties[N_PROPS];
+
+CcFingerprintDialog *
+cc_fingerprint_dialog_new (CcFingerprintManager *manager)
+{
+ return g_object_new (CC_TYPE_FINGERPRINT_DIALOG,
+ "fingerprint-manager", manager,
+ NULL);
+}
+
+static gboolean
+update_dialog_state (CcFingerprintDialog *self,
+ DialogState state)
+{
+ if (self->dialog_state == state)
+ return FALSE;
+
+ self->dialog_state = state;
+
+ if (self->dialog_state == DIALOG_STATE_NONE ||
+ self->dialog_state == (self->dialog_state & DIALOG_STATE_IDLE))
+ {
+ gtk_spinner_stop (self->spinner);
+ }
+ else
+ {
+ gtk_spinner_start (self->spinner);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+add_dialog_state (CcFingerprintDialog *self,
+ DialogState state)
+{
+ return update_dialog_state (self, (self->dialog_state | state));
+}
+
+static gboolean
+remove_dialog_state (CcFingerprintDialog *self,
+ DialogState state)
+{
+ return update_dialog_state (self, (self->dialog_state & ~state));
+}
+
+typedef struct
+{
+ CcFingerprintDialog *dialog;
+ DialogState state;
+} DialogStateRemover;
+
+static DialogStateRemover *
+auto_state_remover (CcFingerprintDialog *self,
+ DialogState state)
+{
+ DialogStateRemover *state_remover;
+
+ state_remover = g_new0 (DialogStateRemover, 1);
+ state_remover->dialog = g_object_ref (self);
+ state_remover->state = state;
+
+ return state_remover;
+}
+
+static void
+auto_state_remover_cleanup (DialogStateRemover *state_remover)
+{
+ remove_dialog_state (state_remover->dialog, state_remover->state);
+ g_clear_object (&state_remover->dialog);
+ g_free (state_remover);
+}
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (DialogStateRemover, auto_state_remover_cleanup);
+
+static const char *
+dbus_error_to_human (CcFingerprintDialog *self,
+ GError *error)
+{
+ g_autofree char *dbus_error = g_dbus_error_get_remote_error (error);
+
+ if (dbus_error == NULL)
+ { /* Fallback to generic */ }
+ else if (g_str_equal (dbus_error, CC_FPRINTD_NAME ".Error.ClaimDevice"))
+ return _("the device needs to be claimed to perform this action");
+ else if (g_str_equal (dbus_error, CC_FPRINTD_NAME ".Error.AlreadyInUse"))
+ return _("the device is already claimed by another process");
+ else if (g_str_equal (dbus_error, CC_FPRINTD_NAME ".Error.PermissionDenied"))
+ return _("you do not have permission to perform the action");
+ else if (g_str_equal (dbus_error, CC_FPRINTD_NAME ".Error.NoEnrolledPrints"))
+ return _("no prints have been enrolled");
+ else if (g_str_equal (dbus_error, CC_FPRINTD_NAME ".Error.NoActionInProgress"))
+ { /* Fallback to generic */ }
+ else if (g_str_equal (dbus_error, CC_FPRINTD_NAME ".Error.InvalidFingername"))
+ { /* Fallback to generic */ }
+ else if (g_str_equal (dbus_error, CC_FPRINTD_NAME ".Error.Internal"))
+ { /* Fallback to generic */ }
+
+ if (self->dialog_state & DIALOG_STATE_DEVICE_ENROLLING)
+ return _("Failed to communicate with the device during enrollment");
+
+ if (self->dialog_state & DIALOG_STATE_DEVICE_CLAIMED ||
+ self->dialog_state & DIALOG_STATE_DEVICE_CLAIMING)
+ return _("Failed to communicate with the fingerprint reader");
+
+ return _("Failed to communicate with the fingerprint daemon");
+}
+
+static void
+disconnect_device_signals (CcFingerprintDialog *self)
+{
+ if (!self->device)
+ return;
+
+ if (self->device_signal_id)
+ {
+ g_signal_handler_disconnect (self->device, self->device_signal_id);
+ self->device_signal_id = 0;
+ }
+
+ if (self->device_name_owner_id)
+ {
+ g_signal_handler_disconnect (self->device, self->device_name_owner_id);
+ self->device_name_owner_id = 0;
+ }
+}
+
+static void
+cc_fingerprint_dialog_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcFingerprintDialog *self = CC_FINGERPRINT_DIALOG (object);
+
+ switch (prop_id)
+ {
+ case PROP_MANAGER:
+ g_value_set_object (value, self->manager);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_fingerprint_dialog_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcFingerprintDialog *self = CC_FINGERPRINT_DIALOG (object);
+
+ switch (prop_id)
+ {
+ case PROP_MANAGER:
+ g_set_object (&self->manager, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+notify_error (CcFingerprintDialog *self,
+ const char *error_message)
+{
+ if (error_message)
+ gtk_label_set_label (self->infobar_error, error_message);
+
+ gtk_widget_set_visible (self->error_infobar, error_message != NULL);
+}
+
+static GtkWidget *
+fingerprint_icon_new (const char *icon_name,
+ const char *label_text,
+ GType icon_widget_type,
+ gpointer progress_data,
+ GtkWidget **out_icon,
+ GtkWidget **out_label)
+{
+ GtkStyleContext *context;
+ GtkWidget *box;
+ GtkWidget *label;
+ GtkWidget *image;
+ GtkWidget *icon_widget;
+
+ g_return_val_if_fail (g_type_is_a (icon_widget_type, GTK_TYPE_WIDGET), NULL);
+
+ box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
+ gtk_widget_set_name (box, "fingerprint-box");
+ gtk_widget_set_hexpand (box, TRUE);
+
+ image = gtk_image_new_from_icon_name (icon_name);
+
+ if (icon_widget_type == GTK_TYPE_IMAGE)
+ icon_widget = image;
+ else
+ icon_widget = g_object_new (icon_widget_type, NULL);
+
+ if (g_type_is_a (icon_widget_type, GTK_TYPE_MENU_BUTTON))
+ {
+ gtk_menu_button_set_child (GTK_MENU_BUTTON (icon_widget), image);
+ gtk_widget_set_can_focus (icon_widget, FALSE);
+ }
+
+ gtk_widget_set_halign (icon_widget, GTK_ALIGN_CENTER);
+ gtk_widget_set_valign (icon_widget, GTK_ALIGN_CENTER);
+ gtk_widget_set_name (icon_widget, "fingerprint-image");
+
+ gtk_box_append (GTK_BOX (box), icon_widget);
+
+ context = gtk_widget_get_style_context (icon_widget);
+ gtk_style_context_add_class (context, "circular");
+
+ label = gtk_label_new_with_mnemonic (label_text);
+ gtk_box_append (GTK_BOX (box), label);
+
+ context = gtk_widget_get_style_context (box);
+ gtk_style_context_add_class (context, "fingerprint-icon");
+
+ if (out_icon)
+ *out_icon = icon_widget;
+
+ if (out_label)
+ *out_label = label;
+
+ return box;
+}
+
+static GtkWidget *
+fingerprint_menu_button (const char *icon_name,
+ const char *label_text)
+{
+ GtkWidget *flowbox_child;
+ GtkWidget *button;
+ GtkWidget *label;
+ GtkWidget *box;
+
+ box = fingerprint_icon_new (icon_name, label_text, GTK_TYPE_MENU_BUTTON, NULL,
+ &button, &label);
+
+ flowbox_child = gtk_flow_box_child_new ();
+ gtk_widget_set_focus_on_click (flowbox_child, FALSE);
+ gtk_widget_set_name (flowbox_child, "fingerprint-flowbox");
+
+ gtk_flow_box_child_set_child (GTK_FLOW_BOX_CHILD (flowbox_child), box);
+
+ g_object_set_data (G_OBJECT (flowbox_child), "button", button);
+ g_object_set_data (G_OBJECT (flowbox_child), "icon",
+ GTK_IMAGE (gtk_menu_button_get_child (GTK_MENU_BUTTON (button))));
+ g_object_set_data (G_OBJECT (flowbox_child), "label", label);
+ g_object_set_data (G_OBJECT (button), "flowbox-child", flowbox_child);
+
+ return flowbox_child;
+}
+
+static gboolean
+prints_visibility_filter (GtkFlowBoxChild *child,
+ gpointer user_data)
+{
+ CcFingerprintDialog *self = user_data;
+ const char *finger_id;
+
+ if (gtk_stack_get_visible_child (self->stack) != self->prints_manager)
+ return FALSE;
+
+ finger_id = g_object_get_data (G_OBJECT (child), "finger-id");
+
+ if (!finger_id)
+ return TRUE;
+
+ if (!self->enrolled_fingers)
+ return FALSE;
+
+ return g_strv_contains ((const gchar **) self->enrolled_fingers, finger_id);
+}
+
+static GList *
+get_container_children (GtkWidget *container)
+{
+ GtkWidget *child;
+ GList *list = NULL;
+
+ child = gtk_widget_get_first_child (container);
+ while (child) {
+ GtkWidget *next = gtk_widget_get_next_sibling (child);
+
+ list = g_list_append (list, child);
+
+ child = next;
+ }
+
+ return list;
+}
+
+static void
+update_prints_to_add_visibility (CcFingerprintDialog *self)
+{
+ g_autoptr(GList) print_buttons = NULL;
+ GList *l;
+ guint i;
+
+ print_buttons = get_container_children (GTK_WIDGET (self->add_print_popover_box));
+
+ for (i = 0, l = print_buttons; i < N_VALID_FINGERS && l; ++i, l = l->next)
+ {
+ GtkWidget *button = l->data;
+ gboolean enrolled;
+
+ enrolled = self->enrolled_fingers &&
+ g_strv_contains ((const gchar **) self->enrolled_fingers,
+ FINGER_IDS[i]);
+
+ gtk_widget_set_visible (button, !enrolled);
+ }
+}
+
+static void
+update_prints_visibility (CcFingerprintDialog *self)
+{
+ update_prints_to_add_visibility (self);
+
+ gtk_flow_box_invalidate_filter (self->prints_gallery);
+}
+
+static void
+list_enrolled_cb (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_auto(GStrv) enrolled_fingers = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(DialogStateRemover) state_remover = NULL;
+ CcFprintdDevice *fprintd_device = CC_FPRINTD_DEVICE (object);
+ CcFingerprintDialog *self = user_data;
+ guint n_enrolled_fingers = 0;
+
+ cc_fprintd_device_call_list_enrolled_fingers_finish (fprintd_device,
+ &enrolled_fingers,
+ res, &error);
+
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
+ state_remover = auto_state_remover (self, DIALOG_STATE_DEVICE_PRINTS_LISTING);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->add_print_icon), TRUE);
+
+ if (self->dialog_state & DIALOG_STATE_DEVICE_CLAIMED)
+ gtk_widget_set_sensitive (GTK_WIDGET (self->prints_manager), TRUE);
+
+ if (error)
+ {
+ g_autofree char *dbus_error = g_dbus_error_get_remote_error (error);
+
+ if (!dbus_error || !g_str_equal (dbus_error, CC_FPRINTD_NAME ".Error.NoEnrolledPrints"))
+ {
+ g_autofree char *error_message = NULL;
+
+ error_message = g_strdup_printf (_("Failed to list fingerprints: %s"),
+ dbus_error_to_human (self, error));
+ g_warning ("Listing of fingerprints on device %s failed: %s",
+ cc_fprintd_device_get_name (self->device), error->message);
+ notify_error (self, error_message);
+ return;
+ }
+ }
+ else
+ {
+ n_enrolled_fingers = g_strv_length (enrolled_fingers);
+ }
+
+ self->enrolled_fingers = g_steal_pointer (&enrolled_fingers);
+ gtk_flow_box_set_max_children_per_line (self->prints_gallery,
+ MIN (3, n_enrolled_fingers + 1));
+
+ update_prints_visibility (self);
+
+ if (n_enrolled_fingers == N_VALID_FINGERS)
+ gtk_widget_set_sensitive (self->add_print_icon, FALSE);
+
+ if (n_enrolled_fingers > 0)
+ gtk_widget_show (GTK_WIDGET (self->delete_prints_button));
+}
+
+static void
+update_prints_store (CcFingerprintDialog *self)
+{
+ ActUser *user;
+
+ g_assert_true (CC_FPRINTD_IS_DEVICE (self->device));
+
+ if (!add_dialog_state (self, DIALOG_STATE_DEVICE_PRINTS_LISTING))
+ return;
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->add_print_icon), FALSE);
+ gtk_widget_hide (GTK_WIDGET (self->delete_prints_button));
+
+ g_clear_pointer (&self->enrolled_fingers, g_strfreev);
+
+ user = cc_fingerprint_manager_get_user (self->manager);
+ cc_fprintd_device_call_list_enrolled_fingers (self->device,
+ act_user_get_user_name (user),
+ self->cancellable,
+ list_enrolled_cb,
+ self);
+}
+
+static void
+delete_prints_cb (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+ CcFprintdDevice *fprintd_device = CC_FPRINTD_DEVICE (object);
+ CcFingerprintDialog *self = user_data;
+
+ cc_fprintd_device_call_delete_enrolled_fingers2_finish (fprintd_device, res, &error);
+
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
+ if (error)
+ {
+ g_autofree char *error_message = NULL;
+
+ error_message = g_strdup_printf (_("Failed to delete saved fingerprints: %s"),
+ dbus_error_to_human (self, error));
+ g_warning ("Deletion of fingerprints on device %s failed: %s",
+ cc_fprintd_device_get_name (self->device), error->message);
+ notify_error (self, error_message);
+ }
+
+ update_prints_store (self);
+ cc_fingerprint_manager_update_state (self->manager, NULL, NULL);
+}
+
+static void
+delete_enrolled_prints (CcFingerprintDialog *self)
+{
+ g_return_if_fail (self->dialog_state & DIALOG_STATE_DEVICE_CLAIMED);
+
+ if (!add_dialog_state (self, DIALOG_STATE_DEVICE_DELETING))
+ return;
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->prints_manager), FALSE);
+
+ cc_fprintd_device_call_delete_enrolled_fingers2 (self->device,
+ self->cancellable,
+ delete_prints_cb,
+ self);
+}
+
+static const char *
+get_finger_name (const char *finger_id)
+{
+ if (g_str_equal (finger_id, "left-thumb"))
+ return _("Left thumb");
+ if (g_str_equal (finger_id, "left-middle-finger"))
+ return _("Left middle finger");
+ if (g_str_equal (finger_id, "left-index-finger"))
+ return _("_Left index finger");
+ if (g_str_equal (finger_id, "left-ring-finger"))
+ return _("Left ring finger");
+ if (g_str_equal (finger_id, "left-little-finger"))
+ return _("Left little finger");
+ if (g_str_equal (finger_id, "right-thumb"))
+ return _("Right thumb");
+ if (g_str_equal (finger_id, "right-middle-finger"))
+ return _("Right middle finger");
+ if (g_str_equal (finger_id, "right-index-finger"))
+ return _("_Right index finger");
+ if (g_str_equal (finger_id, "right-ring-finger"))
+ return _("Right ring finger");
+ if (g_str_equal (finger_id, "right-little-finger"))
+ return _("Right little finger");
+
+ g_return_val_if_reached (_("Unknown Finger"));
+}
+
+static gboolean
+have_multiple_devices (CcFingerprintDialog *self)
+{
+ g_autoptr(GList) devices_rows = NULL;
+
+ devices_rows = get_container_children (GTK_WIDGET (self->devices_list));
+
+ return devices_rows && devices_rows->next;
+}
+
+static void
+set_enroll_result_message (CcFingerprintDialog *self,
+ EnrollState enroll_state,
+ const char *message)
+{
+ GtkStyleContext *style_context;
+ const char *icon_name;
+ guint i;
+
+ g_return_if_fail (enroll_state >= 0 && enroll_state < N_ENROLL_STATES);
+
+ style_context = gtk_widget_get_style_context (self->enroll_result_icon);
+
+ switch (enroll_state)
+ {
+ case ENROLL_STATE_WARNING:
+ case ENROLL_STATE_ERROR:
+ icon_name = "fingerprint-detection-warning-symbolic";
+ break;
+ case ENROLL_STATE_COMPLETED:
+ icon_name = "fingerprint-detection-complete-symbolic";
+ break;
+ default:
+ icon_name = "fingerprint-detection-symbolic";
+ }
+
+ for (i = 0; i < N_ENROLL_STATES; ++i)
+ gtk_style_context_remove_class (style_context, ENROLL_STATE_CLASSES[i]);
+
+ gtk_style_context_add_class (style_context, ENROLL_STATE_CLASSES[enroll_state]);
+
+ gtk_image_set_from_icon_name (self->enroll_result_image, icon_name);
+ gtk_label_set_label (self->enroll_result_message, message);
+}
+
+static gboolean
+stage_passed_timeout_cb (gpointer user_data)
+{
+ CcFingerprintDialog *self = user_data;
+ const char *current_message;
+
+ current_message = gtk_label_get_label (self->enroll_result_message);
+ set_enroll_result_message (self, ENROLL_STATE_NORMAL, current_message);
+ self->enroll_stage_passed_id = 0;
+
+ return FALSE;
+}
+
+static void
+handle_enroll_signal (CcFingerprintDialog *self,
+ const char *result,
+ gboolean done)
+{
+ gboolean completed;
+
+ g_return_if_fail (self->dialog_state & DIALOG_STATE_DEVICE_ENROLLING);
+
+ g_debug ("Device enroll result message: %s, done: %d", result, done);
+
+ completed = g_str_equal (result, "enroll-completed");
+ g_clear_handle_id (&self->enroll_stage_passed_id, g_source_remove);
+
+ if (g_str_equal (result, "enroll-stage-passed") || completed)
+ {
+ guint enroll_stages;
+
+ enroll_stages = cc_fprintd_device_get_num_enroll_stages (self->device);
+
+ self->enroll_stages_passed++;
+
+ if (enroll_stages > 0)
+ self->enroll_progress =
+ MIN (1.0f, self->enroll_stages_passed / (double) enroll_stages);
+ else
+ g_warning ("The device %s requires an invalid number of enroll stages (%u)",
+ cc_fprintd_device_get_name (self->device), enroll_stages);
+
+ g_debug ("Enroll state passed, %u/%u (%.2f%%)",
+ self->enroll_stages_passed, (guint) enroll_stages,
+ self->enroll_progress);
+
+ if (!completed)
+ {
+ set_enroll_result_message (self, ENROLL_STATE_SUCCESS, NULL);
+
+ self->enroll_stage_passed_id =
+ g_timeout_add (750, stage_passed_timeout_cb, self);
+ }
+ else
+ {
+ if (!G_APPROX_VALUE (self->enroll_progress, 1.0f, FLT_EPSILON))
+ {
+ g_warning ("Device marked enroll as completed, but progress is at %.2f",
+ self->enroll_progress);
+ self->enroll_progress = 1.0f;
+ }
+ }
+ }
+ else if (!done)
+ {
+ const char *scan_type;
+ const char *message;
+ gboolean is_swipe;
+
+ scan_type = cc_fprintd_device_get_scan_type (self->device);
+ is_swipe = g_str_equal (scan_type, "swipe");
+
+ message = enroll_result_str_to_msg (result, is_swipe);
+ set_enroll_result_message (self, ENROLL_STATE_RETRY, message);
+
+ self->enroll_stage_passed_id =
+ g_timeout_add (850, stage_passed_timeout_cb, self);
+ }
+
+ if (done)
+ {
+ if (completed)
+ {
+ /* TRANSLATORS: This is the message shown when the fingerprint
+ * enrollment has been completed successfully */
+ set_enroll_result_message (self, ENROLL_STATE_COMPLETED,
+ C_("Fingerprint enroll state", "Complete"));
+ gtk_widget_set_sensitive (GTK_WIDGET (self->cancel_button), FALSE);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->done_button), TRUE);
+ gtk_widget_grab_focus (GTK_WIDGET (self->done_button));
+ }
+ else
+ {
+ const char *message;
+
+ if (g_str_equal (result, "enroll-disconnected"))
+ {
+ message = _("Fingerprint device disconnected");
+ remove_dialog_state (self, DIALOG_STATE_DEVICE_CLAIMED |
+ DIALOG_STATE_DEVICE_ENROLLING);
+ }
+ else if (g_str_equal (result, "enroll-data-full"))
+ {
+ message = _("Fingerprint device storage is full");
+ }
+ else
+ {
+ message = _("Failed to enroll new fingerprint");
+ }
+
+ set_enroll_result_message (self, ENROLL_STATE_WARNING, message);
+ }
+ }
+}
+
+static void
+enroll_start_cb (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+ g_autoptr(DialogStateRemover) state_remover = NULL;
+ CcFprintdDevice *fprintd_device = CC_FPRINTD_DEVICE (object);
+ CcFingerprintDialog *self = user_data;
+
+ cc_fprintd_device_call_enroll_start_finish (fprintd_device, res, &error);
+
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
+ state_remover = auto_state_remover (self, DIALOG_STATE_DEVICE_ENROLL_STARTING);
+
+ if (error)
+ {
+ g_autofree char *error_message = NULL;
+
+ remove_dialog_state (self, DIALOG_STATE_DEVICE_ENROLLING);
+
+ error_message = g_strdup_printf (_("Failed to start enrollment: %s"),
+ dbus_error_to_human (self, error));
+ g_warning ("Enrollment on device %s failed: %s",
+ cc_fprintd_device_get_name (self->device), error->message);
+ notify_error (self, error_message);
+
+ set_enroll_result_message (self, ENROLL_STATE_ERROR,
+ C_("Fingerprint enroll state",
+ "Failed to enroll new fingerprint"));
+ gtk_widget_set_sensitive (self->enrollment_view, FALSE);
+
+ return;
+ }
+}
+
+static void
+enroll_stop_cb (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+ g_autoptr(DialogStateRemover) state_remover = NULL;
+ CcFprintdDevice *fprintd_device = CC_FPRINTD_DEVICE (object);
+ CcFingerprintDialog *self = user_data;
+
+ cc_fprintd_device_call_enroll_stop_finish (fprintd_device, res, &error);
+
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
+ state_remover = auto_state_remover (self, DIALOG_STATE_DEVICE_ENROLLING |
+ DIALOG_STATE_DEVICE_ENROLL_STOPPING);
+ gtk_widget_set_sensitive (self->enrollment_view, TRUE);
+ gtk_stack_set_visible_child (self->stack, self->prints_manager);
+
+ if (error)
+ {
+ g_autofree char *error_message = NULL;
+
+ error_message = g_strdup_printf (_("Failed to stop enrollment: %s"),
+ dbus_error_to_human (self, error));
+ g_warning ("Stopping enrollment on device %s failed: %s",
+ cc_fprintd_device_get_name (self->device), error->message);
+ notify_error (self, error_message);
+
+ return;
+ }
+
+ cc_fingerprint_manager_update_state (self->manager, NULL, NULL);
+}
+
+static void
+enroll_stop (CcFingerprintDialog *self)
+{
+ g_return_if_fail (self->dialog_state & DIALOG_STATE_DEVICE_ENROLLING);
+
+ if (!add_dialog_state (self, DIALOG_STATE_DEVICE_ENROLL_STOPPING))
+ return;
+
+ gtk_widget_set_sensitive (self->enrollment_view, FALSE);
+ cc_fprintd_device_call_enroll_stop (self->device, self->cancellable,
+ enroll_stop_cb, self);
+}
+
+static char *
+get_enrollment_string (CcFingerprintDialog *self,
+ const char *finger_id)
+{
+ char *ret;
+ const char *scan_type;
+ const char *device_name;
+ gboolean is_swipe;
+
+ device_name = NULL;
+ scan_type = cc_fprintd_device_get_scan_type (self->device);
+ is_swipe = g_str_equal (scan_type, "swipe");
+
+ if (have_multiple_devices (self))
+ device_name = cc_fprintd_device_get_name (self->device);
+
+ ret = finger_str_to_msg (finger_id, device_name, is_swipe);
+
+ if (ret)
+ return ret;
+
+ return g_strdup (_("Repeatedly lift and place your finger on the reader to enroll your fingerprint"));
+}
+
+static void
+enroll_finger (CcFingerprintDialog *self,
+ const char *finger_id)
+{
+ g_auto(GStrv) tmp_finger_name = NULL;
+ g_autofree char *finger_name = NULL;
+ g_autofree char *enroll_message = NULL;
+
+ g_return_if_fail (finger_id);
+
+ if (!add_dialog_state (self, DIALOG_STATE_DEVICE_ENROLLING |
+ DIALOG_STATE_DEVICE_ENROLL_STARTING))
+ return;
+
+ self->enroll_progress = 0;
+ self->enroll_stages_passed = 0;
+
+ g_debug ("Enrolling finger %s", finger_id);
+
+ enroll_message = get_enrollment_string (self, finger_id);
+ tmp_finger_name = g_strsplit (get_finger_name (finger_id), "_", -1);
+ finger_name = g_strjoinv ("", tmp_finger_name);
+
+ set_enroll_result_message (self, ENROLL_STATE_NORMAL, NULL);
+ gtk_stack_set_visible_child (self->stack, self->enrollment_view);
+ gtk_label_set_label (self->enroll_message, enroll_message);
+ gtk_editable_set_text (GTK_EDITABLE (self->enroll_print_entry), finger_name);
+
+ cc_fprintd_device_call_enroll_start (self->device, finger_id, self->cancellable,
+ enroll_start_cb, self);
+}
+
+static void
+populate_enrollment_view (CcFingerprintDialog *self)
+{
+ GtkStyleContext *style_context;
+
+ self->enroll_result_icon =
+ fingerprint_icon_new ("fingerprint-detection-symbolic",
+ NULL,
+ GTK_TYPE_IMAGE,
+ &self->enroll_progress,
+ (GtkWidget **) &self->enroll_result_image,
+ (GtkWidget **) &self->enroll_result_message);
+
+ gtk_box_prepend (GTK_BOX (self->enroll_print_bin), self->enroll_result_icon);
+
+ style_context = gtk_widget_get_style_context (self->enroll_result_icon);
+ gtk_style_context_add_class (style_context, "enroll-status");
+}
+
+static void
+on_print_activated_cb (GtkFlowBox *flowbox,
+ GtkFlowBoxChild *child,
+ CcFingerprintDialog *self)
+{
+ GtkWidget *selected_button;
+
+ selected_button = g_object_get_data (G_OBJECT (child), "button");
+ g_signal_emit_by_name (GTK_MENU_BUTTON (selected_button), "activate");
+}
+
+static void
+on_enroll_cb (CcFingerprintDialog *self,
+ GtkMenuButton *button)
+{
+ const char *finger_id;
+
+ finger_id = g_object_get_data (G_OBJECT (button), "finger-id");
+ enroll_finger (self, finger_id);
+}
+
+static void
+populate_add_print_popover (CcFingerprintDialog *self)
+{
+ guint i;
+
+ for (i = 0; i < N_VALID_FINGERS; ++i)
+ {
+ GtkWidget *finger_item;
+
+ finger_item = gtk_button_new ();
+ gtk_button_set_label (GTK_BUTTON (finger_item), get_finger_name (FINGER_IDS[i]));
+ gtk_button_set_use_underline (GTK_BUTTON (finger_item), TRUE);
+ g_object_set_data (G_OBJECT (finger_item), "finger-id", (gpointer) FINGER_IDS[i]);
+ gtk_box_prepend (GTK_BOX (self->add_print_popover_box), finger_item);
+
+ g_signal_connect_object (finger_item, "clicked", G_CALLBACK (on_enroll_cb),
+ self, G_CONNECT_SWAPPED);
+ }
+}
+
+static void
+populate_prints_gallery (CcFingerprintDialog *self)
+{
+ const char *add_print_label;
+ GtkWidget *button;
+ GtkStyleContext *style_context;
+ guint i;
+
+ g_return_if_fail (!GTK_IS_WIDGET (self->add_print_icon));
+
+ for (i = 0; i < N_VALID_FINGERS; ++i)
+ {
+ GtkWidget *flowbox_child;
+ GtkWidget *popover;
+ GtkWidget *reenroll_button;
+
+ flowbox_child = fingerprint_menu_button ("fingerprint-detection-symbolic",
+ get_finger_name (FINGER_IDS[i]));
+
+ button = g_object_get_data (G_OBJECT (flowbox_child), "button");
+
+ popover = gtk_popover_new ();
+ reenroll_button = gtk_button_new ();
+ gtk_button_set_use_underline (GTK_BUTTON (reenroll_button), TRUE);
+ gtk_button_set_label (GTK_BUTTON (reenroll_button), _("_Re-enroll this finger…"));
+ g_object_set_data (G_OBJECT (reenroll_button), "finger-id",
+ (gpointer) FINGER_IDS[i]);
+ g_signal_connect_object (reenroll_button, "clicked", G_CALLBACK (on_enroll_cb), self, G_CONNECT_SWAPPED);
+ gtk_popover_set_child (GTK_POPOVER (popover), reenroll_button);
+
+ gtk_menu_button_set_popover (GTK_MENU_BUTTON (button),
+ popover);
+ g_object_set_data (G_OBJECT (flowbox_child), "finger-id",
+ (gpointer) FINGER_IDS[i]);
+
+ gtk_flow_box_insert (self->prints_gallery, flowbox_child, i);
+ }
+
+ /* TRANSLATORS: This is the label for the button to enroll a new finger */
+ add_print_label = _("Scan new fingerprint");
+ self->add_print_icon = fingerprint_menu_button ("list-add-symbolic",
+ add_print_label);
+ style_context = gtk_widget_get_style_context (self->add_print_icon);
+ gtk_style_context_add_class (style_context, "fingerprint-print-add");
+
+ populate_add_print_popover (self);
+ button = g_object_get_data (G_OBJECT (self->add_print_icon), "button");
+ gtk_menu_button_set_popover (GTK_MENU_BUTTON (button),
+ GTK_WIDGET (self->add_print_popover));
+
+ gtk_flow_box_insert (self->prints_gallery, self->add_print_icon, -1);
+ gtk_flow_box_set_max_children_per_line (self->prints_gallery, 1);
+
+ gtk_flow_box_set_filter_func (self->prints_gallery, prints_visibility_filter,
+ self, NULL);
+
+ update_prints_visibility (self);
+}
+
+static void
+release_device_cb (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+ CcFprintdDevice *fprintd_device = CC_FPRINTD_DEVICE (object);
+ CcFingerprintDialog *self = user_data;
+
+ cc_fprintd_device_call_release_finish (fprintd_device, res, &error);
+
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
+ if (error)
+ {
+ g_autofree char *error_message = NULL;
+
+ error_message = g_strdup_printf (_("Failed to release fingerprint device %s: %s"),
+ cc_fprintd_device_get_name (fprintd_device),
+ dbus_error_to_human (self, error));
+ g_warning ("Releasing device %s failed: %s",
+ cc_fprintd_device_get_name (self->device), error->message);
+
+ notify_error (self, error_message);
+ return;
+ }
+
+ remove_dialog_state (self, DIALOG_STATE_DEVICE_CLAIMED);
+}
+
+static void
+release_device (CcFingerprintDialog *self)
+{
+ if (!self->device || !(self->dialog_state & DIALOG_STATE_DEVICE_CLAIMED))
+ return;
+
+ disconnect_device_signals (self);
+
+ cc_fprintd_device_call_release (self->device,
+ self->cancellable,
+ release_device_cb,
+ self);
+}
+
+static void
+on_device_signal (CcFingerprintDialog *self,
+ gchar *sender_name,
+ gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ if (g_str_equal (signal_name, "EnrollStatus"))
+ {
+ const char *result;
+ gboolean done;
+
+ if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sb)")))
+ {
+ g_warning ("Unexpected enroll parameters type %s",
+ g_variant_get_type_string (parameters));
+ return;
+ }
+
+ g_variant_get (parameters, "(&sb)", &result, &done);
+ handle_enroll_signal (self, result, done);
+ }
+}
+
+static void claim_device (CcFingerprintDialog *self);
+
+static void
+on_device_owner_changed (CcFprintdDevice *device,
+ GParamSpec *spec,
+ CcFingerprintDialog *self)
+{
+ g_autofree char *name_owner = NULL;
+
+ name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (device));
+
+ if (!name_owner)
+ {
+ if (self->dialog_state & DIALOG_STATE_DEVICE_CLAIMED)
+ {
+ disconnect_device_signals (self);
+
+ if (self->dialog_state & DIALOG_STATE_DEVICE_ENROLLING)
+ {
+ set_enroll_result_message (self, ENROLL_STATE_ERROR,
+ C_("Fingerprint enroll state",
+ "Problem Reading Device"));
+ }
+
+ remove_dialog_state (self, DIALOG_STATE_DEVICE_CLAIMED);
+ claim_device (self);
+ }
+ }
+}
+
+static void
+claim_device_cb (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+ g_autoptr(DialogStateRemover) state_remover = NULL;
+ CcFprintdDevice *fprintd_device = CC_FPRINTD_DEVICE (object);
+ CcFingerprintDialog *self = user_data;
+
+ cc_fprintd_device_call_claim_finish (fprintd_device, res, &error);
+
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
+ state_remover = auto_state_remover (self, DIALOG_STATE_DEVICE_CLAIMING);
+
+ if (error)
+ {
+ g_autofree char *dbus_error = g_dbus_error_get_remote_error (error);
+ g_autofree char *error_message = NULL;
+
+ if (dbus_error && g_str_equal (dbus_error, CC_FPRINTD_NAME ".Error.AlreadyInUse") &&
+ (self->dialog_state & DIALOG_STATE_DEVICE_CLAIMED))
+ return;
+
+ error_message = g_strdup_printf (_("Failed to claim fingerprint device %s: %s"),
+ cc_fprintd_device_get_name (self->device),
+ dbus_error_to_human (self, error));
+ g_warning ("Claiming device %s failed: %s",
+ cc_fprintd_device_get_name (self->device), error->message);
+ notify_error (self, error_message);
+ return;
+ }
+
+ if (!add_dialog_state (self, DIALOG_STATE_DEVICE_CLAIMED))
+ return;
+
+ gtk_widget_set_sensitive (self->prints_manager, TRUE);
+ self->device_signal_id = g_signal_connect_object (self->device, "g-signal",
+ G_CALLBACK (on_device_signal),
+ self, G_CONNECT_SWAPPED);
+ self->device_name_owner_id = g_signal_connect_object (self->device, "notify::g-name-owner",
+ G_CALLBACK (on_device_owner_changed),
+ self, 0);
+}
+
+static void
+claim_device (CcFingerprintDialog *self)
+{
+ ActUser *user;
+
+ g_return_if_fail (!(self->dialog_state & DIALOG_STATE_DEVICE_CLAIMED));
+
+ if (!add_dialog_state (self, DIALOG_STATE_DEVICE_CLAIMING))
+ return;
+
+ user = cc_fingerprint_manager_get_user (self->manager);
+ gtk_widget_set_sensitive (self->prints_manager, FALSE);
+
+ cc_fprintd_device_call_claim (self->device,
+ act_user_get_user_name (user),
+ self->cancellable,
+ claim_device_cb,
+ self);
+}
+
+static void
+on_stack_child_changed (CcFingerprintDialog *self)
+{
+ GtkWidget *visible_child = gtk_stack_get_visible_child (self->stack);
+
+ g_debug ("Fingerprint dialog child changed: %s",
+ gtk_stack_get_visible_child_name (self->stack));
+
+ gtk_widget_hide (GTK_WIDGET (self->back_button));
+ gtk_widget_hide (GTK_WIDGET (self->cancel_button));
+ gtk_widget_hide (GTK_WIDGET (self->done_button));
+
+ adw_header_bar_set_show_start_title_buttons (ADW_HEADER_BAR (self->titlebar), TRUE);
+ adw_header_bar_set_show_end_title_buttons (ADW_HEADER_BAR (self->titlebar), TRUE);
+ gtk_flow_box_invalidate_filter (self->prints_gallery);
+
+ if (visible_child == self->prints_manager)
+ {
+ gtk_widget_set_visible (GTK_WIDGET (self->back_button),
+ have_multiple_devices (self));
+ notify_error (self, NULL);
+ update_prints_store (self);
+
+ if (!(self->dialog_state & DIALOG_STATE_DEVICE_CLAIMED))
+ claim_device (self);
+ }
+ else if (visible_child == self->enrollment_view)
+ {
+ adw_header_bar_set_show_start_title_buttons (ADW_HEADER_BAR (self->titlebar), FALSE);
+ adw_header_bar_set_show_end_title_buttons (ADW_HEADER_BAR (self->titlebar), FALSE);
+
+ gtk_widget_show (GTK_WIDGET (self->cancel_button));
+ gtk_widget_set_sensitive (GTK_WIDGET (self->cancel_button), TRUE);
+
+ gtk_widget_show (GTK_WIDGET (self->done_button));
+ gtk_widget_set_sensitive (GTK_WIDGET (self->done_button), FALSE);
+ }
+ else
+ {
+ release_device (self);
+ g_clear_object (&self->device);
+ }
+}
+
+static void
+cc_fingerprint_dialog_init (CcFingerprintDialog *self)
+{
+ g_autoptr(GtkCssProvider) provider = NULL;
+
+ self->cancellable = g_cancellable_new ();
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ provider = gtk_css_provider_new ();
+ gtk_css_provider_load_from_resource (provider,
+ "/org/gnome/control-center/user-accounts/cc-fingerprint-dialog.css");
+ gtk_style_context_add_provider_for_display (gdk_display_get_default (),
+ GTK_STYLE_PROVIDER (provider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+ on_stack_child_changed (self);
+ g_signal_connect_object (self->stack, "notify::visible-child",
+ G_CALLBACK (on_stack_child_changed), self,
+ G_CONNECT_SWAPPED);
+
+ g_object_bind_property (self->stack, "visible-child-name",
+ self->title, "label", G_BINDING_SYNC_CREATE);
+
+ populate_prints_gallery (self);
+ populate_enrollment_view (self);
+}
+
+static void
+select_device_row (CcFingerprintDialog *self,
+ GtkListBoxRow *row,
+ GtkListBox *listbox)
+{
+ CcFprintdDevice *device = g_object_get_data (G_OBJECT (row), "device");
+
+ g_return_if_fail (CC_FPRINTD_DEVICE (device));
+
+ g_set_object (&self->device, device);
+ gtk_stack_set_visible_child (self->stack, self->prints_manager);
+}
+
+static void
+on_devices_list (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autolist (CcFprintdDevice) fprintd_devices = NULL;
+ g_autoptr(DialogStateRemover) state_remover = NULL;
+ g_autoptr(GError) error = NULL;
+ CcFingerprintManager *fingerprint_manager = CC_FINGERPRINT_MANAGER (object);
+ CcFingerprintDialog *self = CC_FINGERPRINT_DIALOG (user_data);
+
+ fprintd_devices = cc_fingerprint_manager_get_devices_finish (fingerprint_manager,
+ res, &error);
+
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
+ state_remover = auto_state_remover (self, DIALOG_STATE_DEVICES_LISTING);
+
+ if (fprintd_devices == NULL)
+ {
+ if (error)
+ {
+ g_autofree char *error_message = NULL;
+
+ error_message = g_strdup_printf (_("Failed to get fingerprint devices: %s"),
+ dbus_error_to_human (self, error));
+ g_warning ("Retrieving fingerprint devices failed: %s", error->message);
+ notify_error (self, error_message);
+ }
+
+ gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->no_devices_found));
+ }
+ else if (fprintd_devices->next == NULL)
+ {
+ /* We have just one device... Skip devices selection */
+ self->device = g_object_ref (fprintd_devices->data);
+ gtk_stack_set_visible_child (self->stack, self->prints_manager);
+ }
+ else
+ {
+ GList *l;
+
+ for (l = fprintd_devices; l; l = l->next)
+ {
+ CcFprintdDevice *device = l->data;
+ CcListRow *device_row;
+
+ device_row = g_object_new (CC_TYPE_LIST_ROW,
+ "visible", TRUE,
+ "icon-name", "go-next-symbolic",
+ "title", cc_fprintd_device_get_name (device),
+ NULL);
+
+ gtk_list_box_insert (self->devices_list, GTK_WIDGET (device_row), -1);
+ g_object_set_data_full (G_OBJECT (device_row), "device",
+ g_object_ref (device), g_object_unref);
+ }
+
+ gtk_stack_set_visible_child (self->stack, self->device_selector);
+ }
+}
+
+static void
+cc_fingerprint_dialog_constructed (GObject *object)
+{
+ CcFingerprintDialog *self = CC_FINGERPRINT_DIALOG (object);
+
+ bindtextdomain ("fprintd", GNOMELOCALEDIR);
+ bind_textdomain_codeset ("fprintd", "UTF-8");
+
+ add_dialog_state (self, DIALOG_STATE_DEVICES_LISTING);
+ cc_fingerprint_manager_get_devices (self->manager, self->cancellable,
+ on_devices_list, self);
+}
+
+static void
+back_button_clicked_cb (CcFingerprintDialog *self)
+{
+ if (gtk_stack_get_visible_child (self->stack) == self->prints_manager)
+ {
+ notify_error (self, NULL);
+ gtk_stack_set_visible_child (self->stack, self->device_selector);
+ return;
+ }
+
+ g_return_if_reached ();
+}
+
+static void
+confirm_deletion_button_clicked_cb (CcFingerprintDialog *self)
+{
+ gtk_widget_hide (self->delete_confirmation_infobar);
+ delete_enrolled_prints (self);
+}
+
+static void
+cancel_deletion_button_clicked_cb (CcFingerprintDialog *self)
+{
+ gtk_widget_set_sensitive (self->prints_manager, TRUE);
+ gtk_widget_hide (self->delete_confirmation_infobar);
+}
+
+static void
+delete_prints_button_clicked_cb (CcFingerprintDialog *self)
+{
+ gtk_widget_set_sensitive (self->prints_manager, FALSE);
+ gtk_widget_show (self->delete_confirmation_infobar);
+}
+
+static void
+cancel_button_clicked_cb (CcFingerprintDialog *self)
+{
+ if (self->dialog_state & DIALOG_STATE_DEVICE_ENROLLING)
+ {
+ g_cancellable_cancel (self->cancellable);
+ g_set_object (&self->cancellable, g_cancellable_new ());
+
+ g_debug ("Cancelling enroll operation");
+ enroll_stop (self);
+ }
+ else
+ {
+ gtk_stack_set_visible_child (self->stack, self->prints_manager);
+ }
+}
+
+static void
+done_button_clicked_cb (CcFingerprintDialog *self)
+{
+ g_return_if_fail (self->dialog_state & DIALOG_STATE_DEVICE_ENROLLING);
+
+ g_debug ("Completing enroll operation");
+ enroll_stop (self);
+}
+
+static gboolean
+cc_fingerprint_dialog_close_request (GtkWindow *window)
+{
+ CcFingerprintDialog *self = CC_FINGERPRINT_DIALOG (window);
+
+ cc_fingerprint_manager_update_state (self->manager, NULL, NULL);
+
+ g_clear_handle_id (&self->enroll_stage_passed_id, g_source_remove);
+
+ if (self->device && (self->dialog_state & DIALOG_STATE_DEVICE_CLAIMED))
+ {
+ disconnect_device_signals (self);
+
+ if (self->dialog_state & DIALOG_STATE_DEVICE_ENROLLING)
+ cc_fprintd_device_call_enroll_stop_sync (self->device, NULL, NULL);
+ cc_fprintd_device_call_release (self->device, NULL, NULL, NULL);
+ }
+
+ g_clear_object (&self->manager);
+ g_clear_object (&self->device);
+ g_clear_pointer (&self->enrolled_fingers, g_strfreev);
+
+ g_cancellable_cancel (self->cancellable);
+ g_clear_object (&self->cancellable);
+
+ return GTK_WINDOW_CLASS (cc_fingerprint_dialog_parent_class)->close_request (window);
+}
+
+static void
+cc_fingerprint_dialog_class_init (CcFingerprintDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GtkWindowClass *window_class = GTK_WINDOW_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/control-center/user-accounts/cc-fingerprint-dialog.ui");
+
+ object_class->constructed = cc_fingerprint_dialog_constructed;
+ object_class->get_property = cc_fingerprint_dialog_get_property;
+ object_class->set_property = cc_fingerprint_dialog_set_property;
+
+ window_class->close_request = cc_fingerprint_dialog_close_request;
+
+ properties[PROP_MANAGER] =
+ g_param_spec_object ("fingerprint-manager",
+ "FingerprintManager",
+ "The CC fingerprint manager",
+ CC_TYPE_FINGERPRINT_MANAGER,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, add_print_popover);
+ gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, add_print_popover_box);
+ gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, back_button);
+ gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, cancel_button);
+ gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, delete_confirmation_infobar);
+ gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, delete_prints_button);
+ gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, device_selector);
+ gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, devices_list);
+ gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, done_button);
+ gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, enroll_message);
+ gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, enroll_print_bin);
+ gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, enroll_print_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, enrollment_view);
+ gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, error_infobar);
+ gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, infobar_error);
+ gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, no_devices_found);
+ gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, prints_gallery);
+ gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, prints_manager);
+ gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, spinner);
+ gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, stack);
+ gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, title);
+ gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, titlebar);
+
+ gtk_widget_class_bind_template_callback (widget_class, back_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, cancel_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, cancel_deletion_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, confirm_deletion_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, delete_prints_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, done_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_print_activated_cb);
+ gtk_widget_class_bind_template_callback (widget_class, select_device_row);
+}
diff --git a/panels/user-accounts/cc-fingerprint-dialog.h b/panels/user-accounts/cc-fingerprint-dialog.h
new file mode 100644
index 0000000..9afac0b
--- /dev/null
+++ b/panels/user-accounts/cc-fingerprint-dialog.h
@@ -0,0 +1,37 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2020 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ * Authors: Marco Trevisan <marco.trevisan@canonical.com>
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include "cc-fingerprint-manager.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_FINGERPRINT_DIALOG (cc_fingerprint_dialog_get_type ())
+
+G_DECLARE_FINAL_TYPE (CcFingerprintDialog, cc_fingerprint_dialog,
+ CC, FINGERPRINT_DIALOG, GtkWindow)
+
+CcFingerprintDialog *cc_fingerprint_dialog_new (CcFingerprintManager *manager);
+
+G_END_DECLS
diff --git a/panels/user-accounts/cc-fingerprint-dialog.ui b/panels/user-accounts/cc-fingerprint-dialog.ui
new file mode 100644
index 0000000..9c74f84
--- /dev/null
+++ b/panels/user-accounts/cc-fingerprint-dialog.ui
@@ -0,0 +1,346 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcFingerprintDialog" parent="GtkWindow">
+ <style>
+ <class name="fingerprint" />
+ </style>
+ <property name="name">fingerprint-dialog</property>
+ <property name="title" translatable="yes">Fingerprint Manager</property>
+ <property name="destroy-with-parent">True</property>
+ <property name="default-width">600</property>
+ <property name="default-height">400</property>
+ <property name="modal">True</property>
+ <property name="hide-on-close">True</property>
+ <child type="titlebar">
+ <object class="AdwHeaderBar" id="titlebar">
+ <property name="show-end-title-buttons">True</property>
+ <property name="show-start-title-buttons">True</property>
+ <child type="title">
+ <object class="GtkLabel" id="title">
+ <property name="label" translatable="yes">Fingerprint</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child type="start">
+ <object class="GtkButton" id="cancel_button">
+ <property name="can_focus">False</property>
+ <property name="receives_default">False</property>
+ <property name="valign">center</property>
+ <property name="use-underline">True</property>
+ <property name="label" translatable="yes">_Cancel</property>
+ <signal name="clicked" handler="cancel_button_clicked_cb" object="CcFingerprintDialog" swapped="yes" />
+ </object>
+ </child>
+ <child type="start">
+ <object class="GtkButton" id="back_button">
+ <property name="can_focus">False</property>
+ <property name="receives_default">False</property>
+ <property name="valign">center</property>
+ <property name="use-underline">True</property>
+ <property name="icon_name">go-previous-symbolic</property>
+ <accessibility>
+ <property name="label" translatable="yes">Back</property>
+ </accessibility>
+ <signal name="clicked" handler="back_button_clicked_cb" object="CcFingerprintDialog" swapped="yes" />
+ <style>
+ <class name="image-button"/>
+ </style>
+ </object>
+ </child>
+
+ <child type="end">
+ <object class="GtkButton" id="done_button">
+ <property name="use-underline">True</property>
+ <property name="sensitive">False</property>
+ <property name="label" translatable="yes">_Done</property>
+ <signal name="clicked" handler="done_button_clicked_cb" object="CcFingerprintDialog" swapped="yes" />
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkSpinner" id="spinner">
+ <property name="can_focus">False</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+
+ <child>
+ <object class="GtkInfoBar" id="delete_confirmation_infobar">
+ <property name="visible">False</property>
+ <child>
+ <object class="GtkBox">
+ <child>
+ <object class="GtkButton">
+ <signal name="clicked" handler="cancel_deletion_button_clicked_cb" object="CcFingerprintDialog" swapped="yes"/>
+ <property name="label" translatable="yes">_No</property>
+ <property name="use-underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <signal name="clicked" handler="confirm_deletion_button_clicked_cb" object="CcFingerprintDialog" swapped="yes"/>
+ <property name="receives_default">True</property>
+ <property name="label" translatable="yes">_Yes</property>
+ <property name="use-underline">True</property>
+ <style>
+ <class name="destructive-action"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="can_focus">False</property>
+ <property name="spacing">16</property>
+ <property name="margin-start">12</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="hexpand">False</property>
+ <property name="wrap">True</property>
+ <property name="label" translatable="yes">Do you want to delete your registered fingerprints so fingerprint login is disabled?</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkInfoBar" id="error_infobar">
+ <property name="name">error_infobar</property>
+ <property name="visible">False</property>
+ <property name="can_focus">False</property>
+ <style>
+ <class name="error"/>
+ </style>
+ <child>
+ <object class="GtkBox">
+ <property name="can_focus">False</property>
+ <property name="spacing">16</property>
+ <child>
+ <object class="GtkLabel" id="infobar_error">
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="hexpand">False</property>
+ <property name="wrap">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="halign">fill</property>
+ <property name="valign">fill</property>
+ <property name="propagate-natural-width">True</property>
+ <property name="can-focus">False</property>
+ <property name="hscrollbar-policy">never</property>
+
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="transition_duration">300</property>
+ <property name="margin-start">20</property>
+ <property name="margin-end">20</property>
+ <property name="margin-top">30</property>
+ <property name="margin-bottom">30</property>
+ <property name="width_request">360</property>
+ <property name="halign">center</property>
+
+ <child>
+ <object class="GtkBox" id="no_devices_found">
+ <property name="name" translatable="yes">No fingerprint device</property>
+ <property name="orientation">vertical</property>
+ <property name="valign">center</property>
+ <property name="spacing">12</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <child>
+ <object class="GtkImage">
+ <property name="icon_name">fingerprint-detection-symbolic</property>
+ <property name="pixel_size">192</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes" comments="Translators: This is the empty state page label which states that there are no devices ready.">No Fingerprint device</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ <attribute name="scale" value="1.6"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Ensure the device is properly connected.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkBox" id="device_selector">
+ <property name="name" translatable="yes">Fingerprint Device</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="spacing">10</property>
+ <property name="orientation">vertical</property>
+
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Choose the fingerprint device you want to configure</property>
+ <property name="halign">start</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="can-focus">False</property>
+ <property name="hscrollbar-policy">never</property>
+ <property name="propagate-natural-height">True</property>
+ <child>
+ <object class="GtkListBox" id="devices_list">
+ <property name="selection-mode">none</property>
+ <property name="valign">center</property>
+ <signal name="row-activated" handler="select_device_row" object="CcFingerprintDialog" swapped="yes"/>
+ <style>
+ <class name="frame" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkBox" id="prints_manager">
+ <property name="name" translatable="yes">Fingerprint Login</property>
+ <property name="orientation">vertical</property>
+ <property name="valign">fill</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Fingerprint login allows you to unlock and log into your computer with your finger</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkFlowBox" id="prints_gallery">
+ <style>
+ <class name="prints-gallery" />
+ </style>
+ <property name="column-spacing">12</property>
+ <property name="row-spacing">12</property>
+ <property name="homogeneous">True</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="vexpand">True</property>
+ <property name="min-children-per-line">1</property>
+ <property name="max-children-per-line">3</property>
+ <property name="activate-on-single-click">True</property>
+ <property name="selection-mode">none</property>
+ <signal name="child-activated" handler="on_print_activated_cb" object="CcFingerprintDialog" swapped="no" />
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkButton" id="delete_prints_button">
+ <property name="visible">False</property>
+ <property name="halign">end</property>
+ <property name="use-underline">True</property>
+ <property name="label" translatable="yes">_Delete Fingerprints</property>
+ <property name="margin-top">10</property>
+ <property name="margin-bottom">10</property>
+ <signal name="clicked" handler="delete_prints_button_clicked_cb" object="CcFingerprintDialog" swapped="yes"/>
+ <style>
+ <class name="destructive-action"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkBox" id="enrollment_view">
+ <property name="name" translatable="yes">Fingerprint Enroll</property>
+ <property name="orientation">vertical</property>
+ <property name="valign">fill</property>
+ <property name="spacing">12</property>
+ <style>
+ <class name="enrollment" />
+ </style>
+ <child>
+ <object class="GtkLabel" id="enroll_message">
+ <property name="wrap">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">12</property>
+ <property name="halign">fill</property>
+ <property name="valign">center</property>
+ <property name="vexpand">True</property>
+ <property name="hexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox" id="enroll_print_bin">
+ <property name="hexpand">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="enroll_print_entry">
+ <property name="valign">end</property>
+ <property name="halign">center</property>
+ <property name="editable">False</property>
+ <property name="sensitive">False</property>
+ <property name="width-request">200</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </template>
+
+ <object class="GtkPopover" id="add_print_popover">
+ <property name="position">bottom</property>
+ <child>
+ <object class="GtkBox" id="add_print_popover_box">
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <property name="orientation">vertical</property>
+ </object>
+ </child>
+ </object>
+
+</interface>
diff --git a/panels/user-accounts/cc-fingerprint-manager.c b/panels/user-accounts/cc-fingerprint-manager.c
new file mode 100644
index 0000000..07a50e7
--- /dev/null
+++ b/panels/user-accounts/cc-fingerprint-manager.c
@@ -0,0 +1,597 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2020 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ * Authors: Marco Trevisan <marco.trevisan@canonical.com>
+ */
+
+#include "cc-fingerprint-manager.h"
+
+#include "cc-fprintd-generated.h"
+#include "cc-user-accounts-enum-types.h"
+
+#define CC_FPRINTD_NAME "net.reactivated.Fprint"
+#define CC_FPRINTD_MANAGER_PATH "/net/reactivated/Fprint/Manager"
+
+struct _CcFingerprintManager
+{
+ GObject parent_instance;
+};
+
+typedef struct
+{
+ ActUser *user;
+ GTask *current_task;
+ CcFingerprintState state;
+ GList *cached_devices;
+} CcFingerprintManagerPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (CcFingerprintManager, cc_fingerprint_manager, G_TYPE_OBJECT)
+
+enum {
+ PROP_0,
+ PROP_USER,
+ PROP_STATE,
+ N_PROPS
+};
+
+static GParamSpec *properties[N_PROPS];
+
+static void cleanup_cached_devices (CcFingerprintManager *self);
+
+CcFingerprintManager *
+cc_fingerprint_manager_new (ActUser *user)
+{
+ return g_object_new (CC_TYPE_FINGERPRINT_MANAGER, "user", user, NULL);
+}
+
+static void
+cc_fingerprint_manager_dispose (GObject *object)
+{
+ CcFingerprintManager *self = CC_FINGERPRINT_MANAGER (object);
+ CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self);
+
+ if (priv->current_task)
+ {
+ g_cancellable_cancel (g_task_get_cancellable (priv->current_task));
+ priv->current_task = NULL;
+ }
+
+ g_clear_object (&priv->user);
+ cleanup_cached_devices (self);
+
+ G_OBJECT_CLASS (cc_fingerprint_manager_parent_class)->dispose (object);
+}
+
+static void
+cc_fingerprint_manager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcFingerprintManager *self = CC_FINGERPRINT_MANAGER (object);
+ CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self);
+
+ switch (prop_id)
+ {
+ case PROP_STATE:
+ g_value_set_enum (value, priv->state);
+ break;
+
+ case PROP_USER:
+ g_value_set_object (value, priv->user);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_fingerprint_manager_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcFingerprintManager *self = CC_FINGERPRINT_MANAGER (object);
+ CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self);
+
+ switch (prop_id)
+ {
+ case PROP_USER:
+ g_set_object (&priv->user, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_fingerprint_manager_constructed (GObject *object)
+{
+ cc_fingerprint_manager_update_state (CC_FINGERPRINT_MANAGER (object), NULL, NULL);
+}
+
+static void
+cc_fingerprint_manager_class_init (CcFingerprintManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructed = cc_fingerprint_manager_constructed;
+ object_class->dispose = cc_fingerprint_manager_dispose;
+ object_class->get_property = cc_fingerprint_manager_get_property;
+ object_class->set_property = cc_fingerprint_manager_set_property;
+
+ properties[PROP_USER] =
+ g_param_spec_object ("user",
+ "User",
+ "The user account we manage the fingerprint for",
+ ACT_TYPE_USER,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+
+ properties[PROP_STATE] =
+ g_param_spec_enum ("state",
+ "State",
+ "The state of the fingerprint for the user",
+ CC_TYPE_FINGERPRINT_STATE, CC_FINGERPRINT_STATE_NONE,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+cc_fingerprint_manager_init (CcFingerprintManager *self)
+{
+}
+
+typedef struct
+{
+ guint waiting_devices;
+ GList *devices;
+} DeviceListData;
+
+static void
+object_list_destroy_notify (gpointer data)
+{
+ GList *list = data;
+ g_list_free_full (list, g_object_unref);
+}
+
+static void
+on_device_owner_changed (CcFingerprintManager *self,
+ GParamSpec *spec,
+ CcFprintdDevice *device)
+{
+ g_autofree char *name_owner = NULL;
+
+ name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (device));
+
+ if (!name_owner)
+ {
+ g_debug ("Fprintd daemon disappeared, cleaning cache...");
+ cleanup_cached_devices (self);
+ }
+}
+
+static void
+cleanup_cached_devices (CcFingerprintManager *self)
+{
+ CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self);
+ CcFprintdDevice *target_device;
+
+ if (!priv->cached_devices)
+ return;
+
+ g_return_if_fail (CC_FPRINTD_IS_DEVICE (priv->cached_devices->data));
+
+ target_device = CC_FPRINTD_DEVICE (priv->cached_devices->data);
+
+ g_signal_handlers_disconnect_by_func (target_device, on_device_owner_changed, self);
+ g_list_free_full (g_steal_pointer (&priv->cached_devices), g_object_unref);
+}
+
+static void
+cache_devices (CcFingerprintManager *self,
+ GList *devices)
+{
+ CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self);
+ CcFprintdDevice *target_device;
+
+ g_return_if_fail (devices && CC_FPRINTD_IS_DEVICE (devices->data));
+
+ cleanup_cached_devices (self);
+ priv->cached_devices = g_list_copy_deep (devices, (GCopyFunc) g_object_ref, NULL);
+
+ /* We can monitor just the first device name, as the owner is just the same */
+ target_device = CC_FPRINTD_DEVICE (priv->cached_devices->data);
+
+ g_signal_connect_object (target_device, "notify::g-name-owner",
+ G_CALLBACK (on_device_owner_changed), self,
+ G_CONNECT_SWAPPED);
+}
+
+static void
+on_device_proxy (GObject *object, GAsyncResult *res, gpointer user_data)
+{
+ g_autoptr(CcFprintdDevice) fprintd_device = NULL;
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ CcFingerprintManager *self = g_task_get_source_object (task);
+ DeviceListData *list_data = g_task_get_task_data (task);
+
+ fprintd_device = cc_fprintd_device_proxy_new_for_bus_finish (res, &error);
+ list_data->waiting_devices--;
+
+ if (error)
+ {
+ if (list_data->waiting_devices == 0)
+ g_task_return_error (task, g_steal_pointer (&error));
+ else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Impossible to ge the device proxy: %s", error->message);
+
+ return;
+ }
+
+ g_debug ("Got fingerprint device %s", cc_fprintd_device_get_name (fprintd_device));
+
+ list_data->devices = g_list_append (list_data->devices, g_steal_pointer (&fprintd_device));
+
+ if (list_data->waiting_devices == 0)
+ {
+ cache_devices (self, list_data->devices);
+ g_task_return_pointer (task, g_steal_pointer (&list_data->devices), object_list_destroy_notify);
+ }
+}
+
+static void
+on_devices_list (GObject *object, GAsyncResult *res, gpointer user_data)
+{
+ CcFprintdManager *fprintd_manager = CC_FPRINTD_MANAGER (object);
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_auto(GStrv) devices_list = NULL;
+ DeviceListData *list_data;
+ guint i;
+
+ cc_fprintd_manager_call_get_devices_finish (fprintd_manager, &devices_list, res, &error);
+
+ if (error)
+ {
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ if (!devices_list || !devices_list[0])
+ {
+ g_task_return_pointer (task, NULL, NULL);
+ return;
+ }
+
+ list_data = g_new0 (DeviceListData, 1);
+ g_task_set_task_data (task, list_data, g_free);
+
+ g_debug ("Fprintd replied with %u device(s)", g_strv_length (devices_list));
+
+ for (i = 0; devices_list[i] != NULL; ++i)
+ {
+ const char *device_path = devices_list[i];
+
+ list_data->waiting_devices++;
+
+ cc_fprintd_device_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ CC_FPRINTD_NAME,
+ device_path,
+ g_task_get_cancellable (task),
+ on_device_proxy,
+ g_object_ref (task));
+ }
+}
+
+static void
+on_manager_proxy (GObject *object, GAsyncResult *res, gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(CcFprintdManager) fprintd_manager = NULL;
+ g_autoptr(GError) error = NULL;
+
+ fprintd_manager = cc_fprintd_manager_proxy_new_for_bus_finish (res, &error);
+
+ if (error)
+ {
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ g_debug ("Fprintd manager connected");
+
+ cc_fprintd_manager_call_get_devices (fprintd_manager,
+ g_task_get_cancellable (task),
+ on_devices_list,
+ g_object_ref (task));
+}
+
+static void
+fprintd_manager_connect (CcFingerprintManager *self,
+ GAsyncReadyCallback callback,
+ GTask *task)
+{
+ g_assert (G_IS_TASK (task));
+
+ cc_fprintd_manager_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
+ CC_FPRINTD_NAME, CC_FPRINTD_MANAGER_PATH,
+ g_task_get_cancellable (task),
+ callback,
+ task);
+}
+
+void
+cc_fingerprint_manager_get_devices (CcFingerprintManager *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self);
+ g_autoptr(GTask) task = NULL;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_source_tag (task, cc_fingerprint_manager_get_devices);
+
+ if (priv->cached_devices)
+ {
+ GList *devices;
+
+ devices = g_list_copy_deep (priv->cached_devices, (GCopyFunc) g_object_ref, NULL);
+ g_task_return_pointer (task, devices, object_list_destroy_notify);
+ return;
+ }
+
+ fprintd_manager_connect (self, on_manager_proxy, g_steal_pointer (&task));
+}
+
+/**
+ * cc_fingerprint_manager_get_devices_finish:
+ * @self: The #CcFingerprintManager
+ * @result: A #GAsyncResult
+ * @error: Return location for errors, or %NULL to ignore
+ *
+ * Finish an asynchronous operation to list all devices.
+ *
+ * Returns: (element-type CcFprintdDevice) (transfer full): List of prints or %NULL on error
+ */
+GList *
+cc_fingerprint_manager_get_devices_finish (CcFingerprintManager *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (res, self), NULL);
+
+ return g_task_propagate_pointer (G_TASK (res), error);
+}
+
+static void
+set_state (CcFingerprintManager *self,
+ CcFingerprintState state)
+{
+ CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self);
+
+ if (priv->state == state)
+ return;
+
+ g_debug ("Fingerprint manager state changed to %d", state);
+
+ priv->state = state;
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_STATE]);
+}
+
+typedef struct
+{
+ guint waiting_devices;
+ CcFingerprintStateUpdated callback;
+ gpointer user_data;
+} UpdateStateData;
+
+static void
+update_state_callback (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcFingerprintManager *self = CC_FINGERPRINT_MANAGER (object);
+ CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self);
+ g_autoptr(GError) error = NULL;
+ CcFingerprintState state;
+ UpdateStateData *data;
+ GTask *task;
+
+ g_return_if_fail (g_task_is_valid (res, self));
+
+ task = G_TASK (res);
+ g_assert (g_steal_pointer (&priv->current_task) == task);
+
+ state = g_task_propagate_int (task, &error);
+ data = g_task_get_task_data (task);
+
+ if (error)
+ {
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
+ g_warning ("Impossible to update fingerprint manager state: %s",
+ error->message);
+
+ state = CC_FINGERPRINT_STATE_NONE;
+ }
+
+ set_state (self, state);
+
+ if (data->callback)
+ data->callback (self, state, data->user_data, error);
+}
+
+static void
+on_device_list_enrolled (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcFprintdDevice *fprintd_device = CC_FPRINTD_DEVICE (object);
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ g_auto(GStrv) enrolled_fingers = NULL;
+ UpdateStateData *data = g_task_get_task_data (task);
+ guint num_enrolled_fingers;
+
+ cc_fprintd_device_call_list_enrolled_fingers_finish (fprintd_device,
+ &enrolled_fingers,
+ res, &error);
+
+ if (data->waiting_devices == 0)
+ return;
+
+ data->waiting_devices--;
+
+ if (error)
+ {
+ g_autofree char *dbus_error = g_dbus_error_get_remote_error (error);
+
+ if (!g_str_equal (dbus_error, CC_FPRINTD_NAME ".Error.NoEnrolledPrints"))
+ {
+ if (data->waiting_devices == 0)
+ g_task_return_error (task, g_steal_pointer (&error));
+ else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Impossible to list enrolled fingers: %s", error->message);
+
+ return;
+ }
+ }
+
+ num_enrolled_fingers = enrolled_fingers ? g_strv_length (enrolled_fingers) : 0;
+
+ g_debug ("Device %s has %u enrolled fingers",
+ cc_fprintd_device_get_name (fprintd_device),
+ num_enrolled_fingers);
+
+ if (num_enrolled_fingers > 0)
+ {
+ data->waiting_devices = 0;
+ g_task_return_int (task, CC_FINGERPRINT_STATE_ENABLED);
+ }
+ else if (data->waiting_devices == 0)
+ {
+ g_task_return_int (task, CC_FINGERPRINT_STATE_DISABLED);
+ }
+}
+
+static void
+on_manager_devices_list (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcFingerprintManager *self = CC_FINGERPRINT_MANAGER (object);
+ CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self);
+ g_autolist(CcFprintdDevice) fprintd_devices = NULL;
+ g_autoptr(GTask) task = G_TASK (user_data);
+ g_autoptr(GError) error = NULL;
+ UpdateStateData *data = g_task_get_task_data (task);
+ const char *user_name;
+ GList *l;
+
+ fprintd_devices = cc_fingerprint_manager_get_devices_finish (self, res, &error);
+
+ if (error)
+ {
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ if (fprintd_devices == NULL)
+ {
+ g_debug ("No fingerprint devices found");
+ g_task_return_int (task, CC_FINGERPRINT_STATE_NONE);
+ return;
+ }
+
+ user_name = act_user_get_user_name (priv->user);
+
+ for (l = fprintd_devices; l; l = l->next)
+ {
+ CcFprintdDevice *device = l->data;
+
+ g_debug ("Connected to device %s, looking for enrolled fingers",
+ cc_fprintd_device_get_name (device));
+
+ data->waiting_devices++;
+ cc_fprintd_device_call_list_enrolled_fingers (device, user_name,
+ g_task_get_cancellable (task),
+ on_device_list_enrolled,
+ g_object_ref (task));
+ }
+}
+
+void
+cc_fingerprint_manager_update_state (CcFingerprintManager *self,
+ CcFingerprintStateUpdated callback,
+ gpointer user_data)
+{
+ CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self);
+ g_autoptr(GCancellable) cancellable = NULL;
+ UpdateStateData *data;
+
+ g_return_if_fail (priv->current_task == NULL);
+
+ if (act_user_get_uid (priv->user) != getuid () ||
+ !act_user_is_local_account (priv->user))
+ {
+ set_state (self, CC_FINGERPRINT_STATE_NONE);
+ return;
+ }
+
+ cancellable = g_cancellable_new ();
+ data = g_new0 (UpdateStateData, 1);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ priv->current_task = g_task_new (self, cancellable, update_state_callback, NULL);
+ g_task_set_source_tag (priv->current_task, cc_fingerprint_manager_update_state);
+ g_task_set_task_data (priv->current_task, data, g_free);
+
+ set_state (self, CC_FINGERPRINT_STATE_UPDATING);
+
+ cc_fingerprint_manager_get_devices (self, cancellable, on_manager_devices_list,
+ priv->current_task);
+}
+
+CcFingerprintState
+cc_fingerprint_manager_get_state (CcFingerprintManager *self)
+{
+ CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self);
+
+ g_return_val_if_fail (CC_IS_FINGERPRINT_MANAGER (self), CC_FINGERPRINT_STATE_NONE);
+
+ return priv->state;
+}
+
+ActUser *
+cc_fingerprint_manager_get_user (CcFingerprintManager *self)
+{
+ CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self);
+
+ g_return_val_if_fail (CC_IS_FINGERPRINT_MANAGER (self), NULL);
+
+ return priv->user;
+}
diff --git a/panels/user-accounts/cc-fingerprint-manager.h b/panels/user-accounts/cc-fingerprint-manager.h
new file mode 100644
index 0000000..d12f52c
--- /dev/null
+++ b/panels/user-accounts/cc-fingerprint-manager.h
@@ -0,0 +1,74 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2020 Canonical Ltd.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ * Authors: Marco Trevisan <marco.trevisan@canonical.com>
+ */
+
+#pragma once
+
+#include <glib-object.h>
+#include <act/act.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_FINGERPRINT_MANAGER (cc_fingerprint_manager_get_type ())
+
+G_DECLARE_FINAL_TYPE (CcFingerprintManager, cc_fingerprint_manager, CC, FINGERPRINT_MANAGER, GObject)
+
+/**
+ * CcFingerprintManager:
+ * @CC_FINGERPRINT_STATE_NONE: Fingerprint recognition is not available
+ * @CC_FINGERPRINT_STATE_UPDATING: Fingerprint recognition is being fetched
+ * @CC_FINGERPRINT_STATE_ENABLED: Fingerprint recognition is enabled
+ * @CC_FINGERPRINT_STATE_DISABLED: Fingerprint recognition is disabled
+ *
+ * The status of the fingerprint support.
+ */
+typedef enum {
+ CC_FINGERPRINT_STATE_NONE,
+ CC_FINGERPRINT_STATE_UPDATING,
+ CC_FINGERPRINT_STATE_ENABLED,
+ CC_FINGERPRINT_STATE_DISABLED,
+} CcFingerprintState;
+
+typedef void (*CcFingerprintStateUpdated) (CcFingerprintManager *fp_manager,
+ CcFingerprintState state,
+ gpointer user_data,
+ GError *error);
+
+CcFingerprintManager * cc_fingerprint_manager_new (ActUser *user);
+
+CcFingerprintState cc_fingerprint_manager_get_state (CcFingerprintManager *fp_manager);
+
+ActUser * cc_fingerprint_manager_get_user (CcFingerprintManager *fp_manager);
+
+void cc_fingerprint_manager_update_state (CcFingerprintManager *fp_manager,
+ CcFingerprintStateUpdated callback,
+ gpointer user_data);
+
+void cc_fingerprint_manager_get_devices (CcFingerprintManager *fp_manager,
+ GCancellable *cancellable,
+ GAsyncReadyCallback res,
+ gpointer user_data);
+
+GList *cc_fingerprint_manager_get_devices_finish (CcFingerprintManager *fp_manager,
+ GAsyncResult *res,
+ GError **error);
+
+G_END_DECLS
diff --git a/panels/user-accounts/cc-login-history-dialog.c b/panels/user-accounts/cc-login-history-dialog.c
new file mode 100644
index 0000000..fcb7457
--- /dev/null
+++ b/panels/user-accounts/cc-login-history-dialog.c
@@ -0,0 +1,346 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Ondrej Holy <oholy@redhat.com>
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <adwaita.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <act/act.h>
+
+#include "cc-login-history-dialog.h"
+#include "cc-user-accounts-resources.h"
+#include "cc-util.h"
+#include "user-utils.h"
+
+struct _CcLoginHistoryDialog
+{
+ GtkDialog parent_instance;
+
+ GtkHeaderBar *header_bar;
+ GtkLabel *title_label;
+ GtkListBox *history_box;
+ GtkButton *next_button;
+ GtkButton *previous_button;
+
+ GDateTime *week;
+ GDateTime *current_week;
+
+ ActUser *user;
+};
+
+G_DEFINE_TYPE (CcLoginHistoryDialog, cc_login_history_dialog, GTK_TYPE_DIALOG)
+
+typedef struct {
+ gint64 login_time;
+ gint64 logout_time;
+ const gchar *type;
+} CcLoginHistory;
+
+static void
+show_week_label (CcLoginHistoryDialog *self)
+{
+ g_autofree gchar *label = NULL;
+ GTimeSpan span;
+
+ span = g_date_time_difference (self->current_week, self->week);
+ if (span == 0) {
+ label = g_strdup (_("This Week"));
+ }
+ else if (span == G_TIME_SPAN_DAY * 7) {
+ label = g_strdup (_("Last Week"));
+ }
+ else {
+ g_autofree gchar *from = NULL;
+ g_autofree gchar *to = NULL;
+ g_autoptr(GDateTime) date = NULL;
+
+ date = g_date_time_add_days (self->week, 6);
+ /* Translators: This is a date format string in the style of "Feb 18",
+ shown as the first day of a week on login history dialog. */
+ from = g_date_time_format (self->week, C_("login history week label","%b %e"));
+ if (g_date_time_get_year (self->week) == g_date_time_get_year (self->current_week)) {
+ /* Translators: This is a date format string in the style of "Feb 24",
+ shown as the last day of a week on login history dialog. */
+ to = g_date_time_format (date, C_("login history week label","%b %e"));
+ }
+ else {
+ /* Translators: This is a date format string in the style of "Feb 24, 2013",
+ shown as the last day of a week on login history dialog. */
+ to = g_date_time_format (date, C_("login history week label","%b %e, %Y"));
+ }
+
+ /* Translators: This indicates a week label on a login history.
+ The first %s is the first day of a week, and the second %s the last day. */
+ label = g_strdup_printf(C_("login history week label", "%s — %s"), from, to);
+ }
+
+ gtk_label_set_label (self->title_label, label);
+}
+
+static void
+clear_history (CcLoginHistoryDialog *self)
+{
+ GtkWidget *child;
+
+ child = gtk_widget_get_first_child (GTK_WIDGET (self->history_box));
+ while (child) {
+ GtkWidget *next = gtk_widget_get_next_sibling (child);
+
+ if (ADW_ACTION_ROW (child))
+ gtk_list_box_remove (self->history_box, GTK_WIDGET (child));
+
+ child = next;
+ }
+}
+
+static GArray *
+get_login_history (ActUser *user)
+{
+ GArray *login_history;
+ GVariantIter *iter, *iter2;
+ GVariant *variant;
+ const GVariant *value;
+ const gchar *key;
+ CcLoginHistory history;
+
+ login_history = NULL;
+ value = act_user_get_login_history (user);
+ g_variant_get ((GVariant *) value, "a(xxa{sv})", &iter);
+ while (g_variant_iter_loop (iter, "(xxa{sv})", &history.login_time, &history.logout_time, &iter2)) {
+ while (g_variant_iter_loop (iter2, "{&sv}", &key, &variant)) {
+ if (g_strcmp0 (key, "type") == 0) {
+ history.type = g_variant_get_string (variant, NULL);
+ }
+ }
+
+ if (login_history == NULL) {
+ login_history = g_array_new (FALSE, TRUE, sizeof (CcLoginHistory));
+ }
+
+ g_array_append_val (login_history, history);
+ }
+
+ return login_history;
+}
+
+static void
+set_sensitivity (CcLoginHistoryDialog *self)
+{
+ g_autoptr(GArray) login_history = NULL;
+ CcLoginHistory history;
+ gboolean sensitive = FALSE;
+
+ login_history = get_login_history (self->user);
+ if (login_history != NULL) {
+ history = g_array_index (login_history, CcLoginHistory, 0);
+ sensitive = g_date_time_to_unix (self->week) > history.login_time;
+ }
+ gtk_widget_set_sensitive (GTK_WIDGET (self->previous_button), sensitive);
+
+ sensitive = (g_date_time_compare (self->current_week, self->week) == 1);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->next_button), sensitive);
+}
+
+static void
+add_record (CcLoginHistoryDialog *self, GDateTime *datetime, gchar *record_string, gint line)
+{
+ g_autofree gchar *date = NULL;
+ g_autofree gchar *time = NULL;
+ g_autofree gchar *str = NULL;
+ GtkWidget *row;
+
+ date = cc_util_get_smart_date (datetime);
+ /* Translators: This is a time format string in the style of "22:58".
+ It indicates a login time which follows a date. */
+ time = g_date_time_format (datetime, C_("login date-time", "%k:%M"));
+ /* Translators: This indicates a login date-time.
+ The first %s is a date, and the second %s a time. */
+ str = g_strdup_printf(C_("login date-time", "%s, %s"), date, time);
+
+ row = adw_action_row_new ();
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row), record_string);
+ adw_action_row_set_subtitle (ADW_ACTION_ROW (row), str);
+
+ gtk_list_box_insert (self->history_box, row, line);
+}
+
+static void
+show_week (CcLoginHistoryDialog *self)
+{
+ g_autoptr(GArray) login_history = NULL;
+ g_autoptr(GDateTime) datetime = NULL;
+ g_autoptr(GDateTime) temp = NULL;
+ gint64 from, to;
+ gint i, line;
+ CcLoginHistory history;
+
+ show_week_label (self);
+ clear_history (self);
+ set_sensitivity (self);
+
+ login_history = get_login_history (self->user);
+ if (login_history == NULL) {
+ return;
+ }
+
+ /* Find first record for week */
+ from = g_date_time_to_unix (self->week);
+ temp = g_date_time_add_weeks (self->week, 1);
+ to = g_date_time_to_unix (temp);
+ for (i = login_history->len - 1; i >= 0; i--) {
+ history = g_array_index (login_history, CcLoginHistory, i);
+ if (history.login_time < to) {
+ break;
+ }
+ }
+
+ /* Add new session records */
+ line = 0;
+ for (;i >= 0; i--) {
+ history = g_array_index (login_history, CcLoginHistory, i);
+
+ /* Display only x-session and tty records */
+ if (!g_str_has_prefix (history.type, ":") &&
+ !g_str_has_prefix (history.type, "tty")) {
+ continue;
+ }
+
+ if (history.logout_time > 0 && history.logout_time < from) {
+ break;
+ }
+
+ if (history.logout_time > 0 && history.logout_time < to) {
+ datetime = g_date_time_new_from_unix_local (history.logout_time);
+ add_record (self, datetime, _("Session Ended"), line);
+ line++;
+ }
+
+ if (history.login_time >= from) {
+ datetime = g_date_time_new_from_unix_local (history.login_time);
+ add_record (self, datetime, _("Session Started"), line);
+ line++;
+ }
+ }
+}
+
+static void
+previous_button_clicked_cb (CcLoginHistoryDialog *self)
+{
+ g_autoptr(GDateTime) temp = NULL;
+
+ temp = self->week;
+ self->week = g_date_time_add_weeks (self->week, -1);
+
+ show_week (self);
+}
+
+static void
+next_button_clicked_cb (CcLoginHistoryDialog *self)
+{
+ g_autoptr(GDateTime) temp = NULL;
+
+ temp = self->week;
+ self->week = g_date_time_add_weeks (self->week, 1);
+
+ show_week (self);
+}
+
+static void
+cc_login_history_dialog_dispose (GObject *object)
+{
+ CcLoginHistoryDialog *self = CC_LOGIN_HISTORY_DIALOG (object);
+
+ g_clear_object (&self->user);
+ g_clear_pointer (&self->week, g_date_time_unref);
+ g_clear_pointer (&self->current_week, g_date_time_unref);
+
+ G_OBJECT_CLASS (cc_login_history_dialog_parent_class)->dispose (object);
+}
+
+void
+cc_login_history_dialog_class_init (CcLoginHistoryDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_login_history_dialog_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/user-accounts/cc-login-history-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcLoginHistoryDialog, header_bar);
+ gtk_widget_class_bind_template_child (widget_class, CcLoginHistoryDialog, title_label);
+ gtk_widget_class_bind_template_child (widget_class, CcLoginHistoryDialog, history_box);
+ gtk_widget_class_bind_template_child (widget_class, CcLoginHistoryDialog, next_button);
+ gtk_widget_class_bind_template_child (widget_class, CcLoginHistoryDialog, previous_button);
+
+ gtk_widget_class_bind_template_callback (widget_class, next_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, previous_button_clicked_cb);
+}
+
+void
+cc_login_history_dialog_init (CcLoginHistoryDialog *self)
+{
+ g_resources_register (cc_user_accounts_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+CcLoginHistoryDialog *
+cc_login_history_dialog_new (ActUser *user)
+{
+ CcLoginHistoryDialog *self;
+ g_autoptr(GDateTime) temp = NULL;
+ g_autoptr(GDateTime) local = NULL;
+ g_autofree gchar *title = NULL;
+
+ g_return_val_if_fail (ACT_IS_USER (user), NULL);
+
+ self = g_object_new (CC_TYPE_LOGIN_HISTORY_DIALOG,
+ "use-header-bar", 1,
+ NULL);
+
+ self->user = g_object_ref (user);
+
+ /* Set the first day of this week */
+ local = g_date_time_new_now_local ();
+ temp = g_date_time_new_local (g_date_time_get_year (local),
+ g_date_time_get_month (local),
+ g_date_time_get_day_of_month (local),
+ 0, 0, 0);
+ self->week = g_date_time_add_days (temp, 1 - g_date_time_get_day_of_week (temp));
+ self->current_week = g_date_time_ref (self->week);
+
+ /* Translators: This is the title of the "Account Activity" dialog.
+ The %s is the user real name. */
+ title = g_strdup_printf (_("%s — Account Activity"),
+ act_user_get_real_name (self->user));
+ gtk_label_set_label (self->title_label, title);
+
+ show_week (self);
+
+ return self;
+}
diff --git a/panels/user-accounts/cc-login-history-dialog.h b/panels/user-accounts/cc-login-history-dialog.h
new file mode 100644
index 0000000..e71f160
--- /dev/null
+++ b/panels/user-accounts/cc-login-history-dialog.h
@@ -0,0 +1,33 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Ondrej Holy <oholy@redhat.com>
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <act/act-user.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_LOGIN_HISTORY_DIALOG (cc_login_history_dialog_get_type ())
+G_DECLARE_FINAL_TYPE (CcLoginHistoryDialog, cc_login_history_dialog, CC, LOGIN_HISTORY_DIALOG, GtkDialog)
+
+CcLoginHistoryDialog *cc_login_history_dialog_new (ActUser *user);
+
+G_END_DECLS
diff --git a/panels/user-accounts/cc-login-history-dialog.ui b/panels/user-accounts/cc-login-history-dialog.ui
new file mode 100644
index 0000000..f12f9f1
--- /dev/null
+++ b/panels/user-accounts/cc-login-history-dialog.ui
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcLoginHistoryDialog" parent="GtkDialog">
+ <property name="default-width">400</property>
+ <property name="default-height">400</property>
+ <property name="modal">True</property>
+ <property name="icon_name">system-users</property>
+ <accessibility>
+ <relation name="labelled-by">title_label</relation>
+ </accessibility>
+ <child internal-child="headerbar">
+ <object class="GtkHeaderBar" id="header_bar">
+ <property name="title-widget">
+ <object class="GtkLabel" id="title_label">
+ <style>
+ <class name="title"/>
+ </style>
+ </object>
+ </property>
+ <child>
+ <object class="GtkBox">
+ <style>
+ <class name="linked"/>
+ </style>
+ <child>
+ <object class="GtkButton" id="previous_button">
+ <property name="icon_name">go-previous-symbolic</property>
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Previous</property>
+ </accessibility>
+ <signal name="clicked" handler="previous_button_clicked_cb" object="CcLoginHistoryDialog" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="next_button">
+ <property name="icon_name">go-next-symbolic</property>
+ <property name="valign">center</property>
+ <accessibility>
+ <property name="label" translatable="yes">Next</property>
+ </accessibility>
+ <signal name="clicked" handler="next_button_clicked_cb" object="CcLoginHistoryDialog" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="GtkListBox" id="history_box">
+ <property name="hexpand">True</property>
+ <style>
+ <class name="boxed-list" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/user-accounts/cc-password-dialog.c b/panels/user-accounts/cc-password-dialog.c
new file mode 100644
index 0000000..1f71825
--- /dev/null
+++ b/panels/user-accounts/cc-password-dialog.c
@@ -0,0 +1,530 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2009-2010 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <adwaita.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <act/act.h>
+
+#include "cc-password-dialog.h"
+#include "cc-user-accounts-resources.h"
+#include "pw-utils.h"
+#include "run-passwd.h"
+#include "user-utils.h"
+
+#define PASSWORD_CHECK_TIMEOUT 600
+
+struct _CcPasswordDialog
+{
+ AdwWindow parent_instance;
+
+ GtkCheckButton *action_login_radio;
+ GtkCheckButton *action_now_radio;
+ GtkButton *generate_password_button;
+ GtkButton *ok_button;
+ AdwPasswordEntryRow *old_password_entry;
+ AdwPreferencesGroup *password_group;
+ AdwPreferencesGroup *password_on_next_login_group;
+ AdwPasswordEntryRow *password_entry;
+ GtkLabel *password_hint_label;
+ GtkLevelBar *strength_indicator;
+ AdwPasswordEntryRow *verify_entry;
+ GtkLabel *verify_label;
+
+ gint password_entry_timeout_id;
+
+ ActUser *user;
+ ActUserPasswordMode password_mode;
+
+ gboolean old_password_ok;
+ gint old_password_entry_timeout_id;
+
+ PasswdHandler *passwd_handler;
+};
+
+G_DEFINE_TYPE (CcPasswordDialog, cc_password_dialog, ADW_TYPE_WINDOW)
+
+static gint
+update_password_strength (CcPasswordDialog *self)
+{
+ const gchar *password;
+ const gchar *old_password;
+ const gchar *username;
+ gint strength_level;
+ const gchar *hint;
+ const gchar *verify;
+
+ password = gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+ old_password = gtk_editable_get_text (GTK_EDITABLE (self->old_password_entry));
+ username = act_user_get_user_name (self->user);
+
+ pw_strength (password, old_password, username,
+ &hint, &strength_level);
+
+ gtk_level_bar_set_value (self->strength_indicator, strength_level);
+ gtk_label_set_label (self->password_hint_label, hint);
+
+ if (strength_level > 1) {
+ gtk_widget_remove_css_class (GTK_WIDGET (self->password_entry), "error");
+ } else if (strlen (password) == 0) {
+ //gtk_widget_hide (GTK_WIDGET (self->password_entry_status_icon));
+ //gtk_widget_show (GTK_WIDGET (self->generate_password_button));
+ } else {
+ gtk_widget_add_css_class (GTK_WIDGET (self->password_entry), "error");
+ }
+
+ verify = gtk_editable_get_text (GTK_EDITABLE (self->verify_entry));
+ if (strlen (verify) == 0) {
+ gtk_widget_set_sensitive (GTK_WIDGET (self->verify_entry), strength_level > 1);
+ }
+
+ return strength_level;
+}
+
+static void
+password_changed_cb (PasswdHandler *handler,
+ GError *error,
+ CcPasswordDialog *self)
+{
+ GtkWidget *dialog;
+ const gchar *primary_text;
+ const gchar *secondary_text;
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self), TRUE);
+
+ if (!error) {
+ gtk_window_close (GTK_WINDOW (self));
+ return;
+ }
+
+ if (error->code == PASSWD_ERROR_REJECTED) {
+ primary_text = error->message;
+ secondary_text = _("Please choose another password.");
+
+ gtk_editable_set_text (GTK_EDITABLE (self->password_entry), "");
+ gtk_widget_grab_focus (GTK_WIDGET (self->password_entry));
+
+ gtk_editable_set_text (GTK_EDITABLE (self->verify_entry), "");
+ }
+ else if (error->code == PASSWD_ERROR_AUTH_FAILED) {
+ primary_text = error->message;
+ secondary_text = _("Please type your current password again.");
+
+ gtk_editable_set_text (GTK_EDITABLE (self->old_password_entry), "");
+ gtk_widget_grab_focus (GTK_WIDGET (self->old_password_entry));
+ }
+ else {
+ primary_text = _("Password could not be changed");
+ secondary_text = error->message;
+ }
+
+ dialog = gtk_message_dialog_new (GTK_WINDOW (self),
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ "%s", primary_text);
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s", secondary_text);
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+static void
+ok_button_clicked_cb (CcPasswordDialog *self)
+{
+ const gchar *password;
+
+ password = gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+
+ switch (self->password_mode) {
+ case ACT_USER_PASSWORD_MODE_REGULAR:
+ if (act_user_get_uid (self->user) == getuid ()) {
+ /* When setting a password for the current user,
+ * use passwd directly, to preserve the audit trail
+ * and to e.g. update the keyring password.
+ */
+ passwd_change_password (self->passwd_handler, password,
+ (PasswdCallback) password_changed_cb, self);
+ gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
+ return;
+ }
+
+ act_user_set_password_mode (self->user, ACT_USER_PASSWORD_MODE_REGULAR);
+ act_user_set_password (self->user, password, "");
+ break;
+
+ case ACT_USER_PASSWORD_MODE_SET_AT_LOGIN:
+ act_user_set_password_mode (self->user, self->password_mode);
+ act_user_set_automatic_login (self->user, FALSE);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ gtk_window_close (GTK_WINDOW (self));
+}
+
+static void
+update_sensitivity (CcPasswordDialog *self)
+{
+ const gchar *password, *verify;
+ gboolean can_change;
+ int strength;
+
+ password = gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+ verify = gtk_editable_get_text (GTK_EDITABLE (self->verify_entry));
+
+ if (self->password_mode == ACT_USER_PASSWORD_MODE_REGULAR) {
+ strength = update_password_strength (self);
+ can_change = strength > 1 && strcmp (password, verify) == 0 &&
+ (self->old_password_ok || !gtk_widget_get_visible (GTK_WIDGET (self->old_password_entry)));
+ }
+ else {
+ can_change = TRUE;
+ }
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->ok_button), can_change);
+}
+
+static void
+mode_change (CcPasswordDialog *self,
+ ActUserPasswordMode mode)
+{
+ gboolean active;
+
+ active = (mode == ACT_USER_PASSWORD_MODE_REGULAR);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->password_entry), active);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->verify_entry), active);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->old_password_entry), active);
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->action_now_radio), active);
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->action_login_radio), !active);
+
+ self->password_mode = mode;
+ update_sensitivity (self);
+}
+
+static void
+action_now_radio_toggled_cb (CcPasswordDialog *self)
+{
+ gint active;
+ ActUserPasswordMode mode;
+
+ active = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->action_now_radio));
+ mode = active ? ACT_USER_PASSWORD_MODE_REGULAR : ACT_USER_PASSWORD_MODE_SET_AT_LOGIN;
+ mode_change (self, mode);
+}
+
+static void
+update_password_match (CcPasswordDialog *self)
+{
+ const gchar *password;
+ const gchar *verify;
+
+ password = gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+ verify = gtk_editable_get_text (GTK_EDITABLE (self->verify_entry));
+
+ if (strlen (verify) > 0) {
+ if (strcmp (password, verify) != 0) {
+ gtk_widget_set_visible (GTK_WIDGET (self->verify_label), TRUE);
+ gtk_widget_add_css_class (GTK_WIDGET (self->verify_entry), "error");
+ }
+ else {
+ gtk_widget_set_visible (GTK_WIDGET (self->verify_label), FALSE);
+ gtk_widget_remove_css_class (GTK_WIDGET (self->verify_entry), "error");
+
+ }
+ }
+}
+
+static gboolean
+password_entry_timeout (CcPasswordDialog *self)
+{
+ update_password_strength (self);
+ update_sensitivity (self);
+ update_password_match (self);
+
+ self->password_entry_timeout_id = 0;
+
+ return FALSE;
+}
+
+static void
+recheck_password_match (CcPasswordDialog *self)
+{
+ if (self->password_entry_timeout_id != 0) {
+ g_source_remove (self->password_entry_timeout_id);
+ self->password_entry_timeout_id = 0;
+ }
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->ok_button), FALSE);
+
+ self->password_entry_timeout_id = g_timeout_add (PASSWORD_CHECK_TIMEOUT,
+ (GSourceFunc) password_entry_timeout,
+ self);
+}
+
+static void
+password_entry_changed (CcPasswordDialog *self)
+{
+ gtk_widget_add_css_class (GTK_WIDGET (self->password_entry), "error");
+ gtk_widget_add_css_class (GTK_WIDGET (self->verify_entry), "error");
+ recheck_password_match (self);
+}
+
+static void
+verify_entry_changed (CcPasswordDialog *self)
+{
+ gtk_widget_add_css_class (GTK_WIDGET (self->verify_entry), "error");
+ recheck_password_match (self);
+}
+
+static gboolean
+password_entry_focus_out_cb (CcPasswordDialog *self)
+{
+ if (self->password_entry_timeout_id != 0) {
+ g_source_remove (self->password_entry_timeout_id);
+ self->password_entry_timeout_id = 0;
+ }
+
+ if (self->user != NULL)
+ password_entry_timeout (self);
+
+ return FALSE;
+}
+
+
+static gboolean
+password_entry_key_press_cb (GtkEventControllerKey *controller,
+ guint keyval,
+ guint keycode,
+ GdkModifierType state,
+ CcPasswordDialog *self)
+{
+ if (self->password_entry_timeout_id != 0) {
+ g_source_remove (self->password_entry_timeout_id);
+ self->password_entry_timeout_id = 0;
+ }
+
+ if (keyval == GDK_KEY_Tab)
+ password_entry_timeout (self);
+
+ return FALSE;
+}
+
+static void
+auth_cb (PasswdHandler *handler,
+ GError *error,
+ CcPasswordDialog *self)
+{
+ if (error) {
+ self->old_password_ok = FALSE;
+ }
+ else {
+ self->old_password_ok = TRUE;
+ gtk_widget_remove_css_class (GTK_WIDGET (self->old_password_entry), "error");
+ }
+
+ update_sensitivity (self);
+}
+
+static gboolean
+old_password_entry_timeout (CcPasswordDialog *self)
+{
+ const gchar *text;
+
+ update_sensitivity (self);
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self->old_password_entry));
+ if (!self->old_password_ok) {
+ passwd_authenticate (self->passwd_handler, text, (PasswdCallback)auth_cb, self);
+ }
+
+ self->old_password_entry_timeout_id = 0;
+
+ return FALSE;
+}
+
+static gboolean
+old_password_entry_focus_out_cb (CcPasswordDialog *self)
+{
+ if (self->old_password_entry_timeout_id != 0) {
+ g_source_remove (self->old_password_entry_timeout_id);
+ self->old_password_entry_timeout_id = 0;
+ }
+
+ if (self->user != NULL)
+ old_password_entry_timeout (self);
+
+ return FALSE;
+}
+
+static void
+old_password_entry_changed (CcPasswordDialog *self)
+{
+ if (self->old_password_entry_timeout_id != 0) {
+ g_source_remove (self->old_password_entry_timeout_id);
+ self->old_password_entry_timeout_id = 0;
+ }
+
+ gtk_widget_add_css_class (GTK_WIDGET (self->old_password_entry), "error");
+ gtk_widget_set_sensitive (GTK_WIDGET (self->ok_button), FALSE);
+
+ self->old_password_ok = FALSE;
+ self->old_password_entry_timeout_id = g_timeout_add (PASSWORD_CHECK_TIMEOUT,
+ (GSourceFunc) old_password_entry_timeout,
+ self);
+}
+
+static void
+generate_password (CcPasswordDialog *self)
+{
+ g_autofree gchar *pwd = NULL;
+
+ pwd = pw_generate ();
+ if (pwd == NULL)
+ return;
+
+ gtk_editable_set_text (GTK_EDITABLE (self->password_entry), pwd);
+ gtk_editable_set_text (GTK_EDITABLE (self->verify_entry), pwd);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->verify_entry), TRUE);
+
+ gtk_widget_hide (GTK_WIDGET (self->generate_password_button));
+}
+
+static void
+cc_password_dialog_dispose (GObject *object)
+{
+ CcPasswordDialog *self = CC_PASSWORD_DIALOG (object);
+
+ g_clear_object (&self->user);
+
+ if (self->passwd_handler) {
+ passwd_destroy (self->passwd_handler);
+ self->passwd_handler = NULL;
+ }
+
+ if (self->old_password_entry_timeout_id != 0) {
+ g_source_remove (self->old_password_entry_timeout_id);
+ self->old_password_entry_timeout_id = 0;
+ }
+
+ if (self->password_entry_timeout_id != 0) {
+ g_source_remove (self->password_entry_timeout_id);
+ self->password_entry_timeout_id = 0;
+ }
+
+ G_OBJECT_CLASS (cc_password_dialog_parent_class)->dispose (object);
+}
+
+static void
+cc_password_dialog_class_init (CcPasswordDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = cc_password_dialog_dispose;
+
+ gtk_widget_class_add_binding_action (widget_class, GDK_KEY_Escape, 0, "window.close", NULL);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/user-accounts/cc-password-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcPasswordDialog, action_login_radio);
+ gtk_widget_class_bind_template_child (widget_class, CcPasswordDialog, action_now_radio);
+ gtk_widget_class_bind_template_child (widget_class, CcPasswordDialog, generate_password_button);
+ gtk_widget_class_bind_template_child (widget_class, CcPasswordDialog, ok_button);
+ gtk_widget_class_bind_template_child (widget_class, CcPasswordDialog, old_password_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcPasswordDialog, password_group);
+ gtk_widget_class_bind_template_child (widget_class, CcPasswordDialog, password_on_next_login_group);
+ gtk_widget_class_bind_template_child (widget_class, CcPasswordDialog, password_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcPasswordDialog, password_hint_label);
+ gtk_widget_class_bind_template_child (widget_class, CcPasswordDialog, strength_indicator);
+ gtk_widget_class_bind_template_child (widget_class, CcPasswordDialog, verify_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcPasswordDialog, verify_label);
+
+ gtk_widget_class_bind_template_callback (widget_class, action_now_radio_toggled_cb);
+ gtk_widget_class_bind_template_callback (widget_class, generate_password);
+ gtk_widget_class_bind_template_callback (widget_class, old_password_entry_changed);
+ gtk_widget_class_bind_template_callback (widget_class, old_password_entry_focus_out_cb);
+ gtk_widget_class_bind_template_callback (widget_class, ok_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, password_entry_changed);
+ gtk_widget_class_bind_template_callback (widget_class, password_entry_focus_out_cb);
+ gtk_widget_class_bind_template_callback (widget_class, password_entry_key_press_cb);
+ gtk_widget_class_bind_template_callback (widget_class, verify_entry_changed);
+}
+
+static void
+cc_password_dialog_init (CcPasswordDialog *self)
+{
+ g_resources_register (cc_user_accounts_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+CcPasswordDialog *
+cc_password_dialog_new (ActUser *user)
+{
+ CcPasswordDialog *self;
+ GtkWindow *window;
+
+ g_return_val_if_fail (ACT_IS_USER (user), NULL);
+
+ self = g_object_new (CC_TYPE_PASSWORD_DIALOG,
+ NULL);
+
+ self->user = g_object_ref (user);
+
+ if (act_user_get_uid (self->user) == getuid ()) {
+ gboolean visible;
+
+ mode_change (self, ACT_USER_PASSWORD_MODE_REGULAR);
+ gtk_widget_hide (GTK_WIDGET (self->password_on_next_login_group));
+
+ visible = (act_user_get_password_mode (user) != ACT_USER_PASSWORD_MODE_NONE);
+ gtk_widget_set_visible (GTK_WIDGET (self->old_password_entry), visible);
+ self->old_password_ok = !visible;
+
+ self->passwd_handler = passwd_init ();
+ }
+ else {
+ mode_change (self, ACT_USER_PASSWORD_MODE_SET_AT_LOGIN);
+ gtk_widget_show (GTK_WIDGET (self->password_on_next_login_group));
+
+ gtk_widget_hide (GTK_WIDGET (self->old_password_entry));
+ self->old_password_ok = TRUE;
+ }
+
+ if (self->old_password_ok == FALSE)
+ gtk_widget_grab_focus (GTK_WIDGET (self->old_password_entry));
+ else
+ gtk_widget_grab_focus (GTK_WIDGET (self->password_entry));
+
+ window = (GtkWindow *) gtk_widget_get_native (GTK_WIDGET (self));
+ gtk_window_set_default_widget (window, GTK_WIDGET (self->ok_button));
+
+ return self;
+}
diff --git a/panels/user-accounts/cc-password-dialog.h b/panels/user-accounts/cc-password-dialog.h
new file mode 100644
index 0000000..3820d6d
--- /dev/null
+++ b/panels/user-accounts/cc-password-dialog.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2009-2010 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#pragma once
+
+#include <adwaita.h>
+#include <gtk/gtk.h>
+#include <act/act.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_PASSWORD_DIALOG (cc_password_dialog_get_type ())
+G_DECLARE_FINAL_TYPE (CcPasswordDialog, cc_password_dialog, CC, PASSWORD_DIALOG, AdwWindow)
+
+CcPasswordDialog *cc_password_dialog_new (ActUser *user);
+
+G_END_DECLS
diff --git a/panels/user-accounts/cc-password-dialog.ui b/panels/user-accounts/cc-password-dialog.ui
new file mode 100644
index 0000000..84e1455
--- /dev/null
+++ b/panels/user-accounts/cc-password-dialog.ui
@@ -0,0 +1,184 @@
+<?xml version="1.0"?>
+<interface>
+ <template class="CcPasswordDialog" parent="AdwWindow">
+ <property name="title" translatable="yes">Change Password</property>
+ <property name="modal">True</property>
+ <property name="hide-on-close">True</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="icon_name">system-users</property>
+ <property name="default-width">640</property>
+ <property name="default-height">420</property>
+ <property name="content">
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="AdwHeaderBar">
+ <property name="show-start-title-buttons">False</property>
+ <property name="show-end-title-buttons">False</property>
+ <child type="start">
+ <object class="GtkButton">
+ <property name="label" translatable="yes">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="visible">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ <property name="valign">center</property>
+ <signal name="clicked" handler="gtk_window_destroy" object="CcPasswordDialog" swapped="yes"/>
+ <style>
+ <class name="text-button"/>
+ </style>
+ </object>
+ </child>
+ <child type="end">
+ <object class="GtkButton" id="ok_button">
+ <property name="label" translatable="yes">Ch_ange</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ <property name="valign">center</property>
+ <signal name="clicked" handler="ok_button_clicked_cb" object="CcPasswordDialog" swapped="yes"/>
+ <style>
+ <class name="text-button"/>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup" id="password_group">
+ <child>
+ <object class="AdwPasswordEntryRow" id="old_password_entry">
+ <property name="title" translatable="yes">Current Password</property>
+ <signal name="notify::text" handler="old_password_entry_changed" object="CcPasswordDialog" swapped="yes"/>
+ <signal name="activate" handler="old_password_entry_focus_out_cb" object="CcPasswordDialog" swapped="yes"/>
+ <style>
+ <class name="error"/>
+ </style>
+ <child>
+ <object class="GtkEventControllerFocus">
+ <signal name="leave" handler="old_password_entry_focus_out_cb" object="CcPasswordDialog" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPasswordEntryRow" id="password_entry">
+ <property name="title" translatable="yes">New Password</property>
+ <signal name="notify::text" handler="password_entry_changed" object="CcPasswordDialog" swapped="yes"/>
+ <signal name="activate" handler="password_entry_focus_out_cb" object="CcPasswordDialog" swapped="yes"/>
+ <style>
+ <class name="error"/>
+ </style>
+ <child>
+ <object class="GtkEventControllerKey">
+ <signal name="key-pressed" handler="password_entry_key_press_cb" object="CcPasswordDialog" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEventControllerFocus">
+ <signal name="leave" handler="password_entry_focus_out_cb" object="CcPasswordDialog" swapped="yes"/>
+ </object>
+ </child>
+ <child type="suffix">
+ <object class="GtkButton" id="generate_password_button">
+ <property name="visible">False</property>
+ <property name="icon-name">emblem-system-symbolic</property>
+ <property name="valign">center</property>
+ <signal name="clicked" handler="generate_password" object="CcPasswordDialog" swapped="yes"/>
+ <style>
+ <class name="flat"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPasswordEntryRow" id="verify_entry">
+ <property name="title" translatable="yes">Confirm Password</property>
+ <signal name="notify::text" handler="verify_entry_changed" object="CcPasswordDialog" swapped="yes"/>
+ <signal name="activate" handler="password_entry_focus_out_cb" object="CcPasswordDialog" swapped="yes"/>
+ <style>
+ <class name="error"/>
+ </style>
+ <child>
+ <object class="GtkEventControllerFocus">
+ <signal name="leave" handler="password_entry_focus_out_cb" object="CcPasswordDialog" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="verify_label">
+ <property name="label" translatable="yes">The passwords do not match.</property>
+ <property name="visible">False</property>
+ <property name="margin-top">12</property>
+ <style>
+ <class name="error"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLevelBar" id="strength_indicator">
+ <property name="mode">continuous</property>
+ <property name="max-value">5</property>
+ <property name="margin-top">12</property>
+ <offsets>
+ <offset name="strength-weak" value="1"/>
+ <offset name="strength-low" value="2"/>
+ <offset name="strength-medium" value="3"/>
+ <offset name="strength-good" value="4"/>
+ <offset name="strength-high" value="5"/>
+ </offsets>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="password_hint_label">
+ <property name="halign">start</property>
+ <property name="margin-top">12</property>
+ <property name="wrap">True</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup" id="password_on_next_login_group">
+ <property name="visible">False</property>
+ <child>
+ <object class="AdwActionRow" id="action_login_row">
+ <property name="title" translatable="yes">Allow user to change their password on next login</property>
+ <property name="activatable_widget">action_login_radio</property>
+ <child type="prefix">
+ <object class="GtkCheckButton" id="action_login_radio">
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="action_now_row">
+ <property name="title" translatable="yes">Set a password now</property>
+ <property name="activatable_widget">action_now_radio</property>
+ <child type="prefix">
+ <object class="GtkCheckButton" id="action_now_radio">
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="group">action_login_radio</property>
+ <signal name="toggled" handler="action_now_radio_toggled_cb" object="CcPasswordDialog" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </property>
+ </template>
+</interface>
diff --git a/panels/user-accounts/cc-realm-manager.c b/panels/user-accounts/cc-realm-manager.c
new file mode 100644
index 0000000..bc43e6d
--- /dev/null
+++ b/panels/user-accounts/cc-realm-manager.c
@@ -0,0 +1,788 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2009-2012 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Stef Walter <stefw@gnome.org>
+ */
+
+#include "config.h"
+
+#include "cc-realm-manager.h"
+
+#include <krb5/krb5.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+
+
+struct _CcRealmManager {
+ CcRealmObjectManagerClient parent_instance;
+
+ CcRealmProvider *provider;
+ guint diagnostics_sig;
+};
+
+enum {
+ REALM_ADDED,
+ NUM_SIGNALS,
+};
+
+static gint signals[NUM_SIGNALS] = { 0, };
+
+G_DEFINE_TYPE (CcRealmManager, cc_realm_manager, CC_REALM_TYPE_OBJECT_MANAGER_CLIENT);
+
+GQuark
+cc_realm_error_get_quark (void)
+{
+ static GQuark quark = 0;
+ if (quark == 0)
+ quark = g_quark_from_static_string ("cc-realm-error");
+ return quark;
+}
+
+static gboolean
+is_realm_with_kerberos_and_membership (gpointer object)
+{
+ g_autoptr(GDBusInterface) kerberos_interface = NULL;
+ g_autoptr(GDBusInterface) kerberos_membership_interface = NULL;
+
+ if (!G_IS_DBUS_OBJECT (object))
+ return FALSE;
+
+ kerberos_interface = g_dbus_object_get_interface (object, "org.freedesktop.realmd.Kerberos");
+ if (kerberos_interface == NULL)
+ return FALSE;
+
+ kerberos_membership_interface = g_dbus_object_get_interface (object, "org.freedesktop.realmd.KerberosMembership");
+ if (kerberos_membership_interface == NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+on_interface_added (CcRealmManager *self,
+ GDBusObject *object,
+ GDBusInterface *interface)
+{
+ g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (interface), G_MAXINT);
+}
+
+static void
+on_object_added (CcRealmManager *self,
+ GDBusObject *object)
+{
+ GList *interfaces, *l;
+
+ interfaces = g_dbus_object_get_interfaces (object);
+ for (l = interfaces; l != NULL; l = g_list_next (l))
+ on_interface_added (self, object, l->data);
+ g_list_free_full (interfaces, g_object_unref);
+
+ if (is_realm_with_kerberos_and_membership (object)) {
+ g_debug ("Saw realm: %s", g_dbus_object_get_object_path (object));
+ g_signal_emit (self, signals[REALM_ADDED], 0, object);
+ }
+}
+
+static void
+cc_realm_manager_init (CcRealmManager *self)
+{
+ g_signal_connect (self, "object-added", G_CALLBACK (on_object_added), NULL);
+ g_signal_connect (self, "interface-added", G_CALLBACK (on_interface_added), NULL);
+}
+
+static void
+cc_realm_manager_dispose (GObject *obj)
+{
+ CcRealmManager *self = CC_REALM_MANAGER (obj);
+ GDBusConnection *connection;
+
+ g_clear_object (&self->provider);
+
+ if (self->diagnostics_sig) {
+ connection = g_dbus_object_manager_client_get_connection (G_DBUS_OBJECT_MANAGER_CLIENT (self));
+ if (connection != NULL)
+ g_dbus_connection_signal_unsubscribe (connection, self->diagnostics_sig);
+ self->diagnostics_sig = 0;
+ }
+
+ G_OBJECT_CLASS (cc_realm_manager_parent_class)->dispose (obj);
+}
+
+static void
+cc_realm_manager_class_init (CcRealmManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = cc_realm_manager_dispose;
+
+ signals[REALM_ADDED] = g_signal_new ("realm-added", CC_TYPE_REALM_MANAGER,
+ G_SIGNAL_RUN_FIRST, 0, NULL, NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_NONE, 1, CC_REALM_TYPE_OBJECT);
+}
+
+static void
+on_realm_diagnostics (GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ const gchar *message;
+ const gchar *unused;
+
+ if (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(ss)"))) {
+ /* Data is already formatted appropriately for stderr */
+ g_variant_get (parameters, "(&s&s)", &message, &unused);
+ g_printerr ("%s", message);
+ }
+}
+
+static void
+on_provider_new (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ CcRealmManager *manager = g_task_get_task_data (task);
+ GError *error = NULL;
+
+ manager->provider = cc_realm_provider_proxy_new_finish (result, &error);
+ if (error == NULL) {
+ g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (manager->provider), -1);
+ g_debug ("Created realm manager");
+ g_task_return_pointer (task, g_object_ref (manager), g_object_unref);
+ } else {
+ g_task_return_error (task, error);
+ }
+}
+
+static void
+on_manager_new (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ CcRealmManager *manager;
+ GDBusConnection *connection;
+ GError *error = NULL;
+ GObject *object;
+ guint sig;
+
+ object = g_async_initable_new_finish (G_ASYNC_INITABLE (source), result, &error);
+ if (error == NULL) {
+ manager = CC_REALM_MANAGER (object);
+ connection = g_dbus_object_manager_client_get_connection (G_DBUS_OBJECT_MANAGER_CLIENT (object));
+
+ g_debug ("Connected to realmd");
+
+ sig = g_dbus_connection_signal_subscribe (connection,
+ "org.freedesktop.realmd",
+ "org.freedesktop.realmd.Service",
+ "Diagnostics",
+ NULL,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ on_realm_diagnostics,
+ NULL,
+ NULL);
+ manager->diagnostics_sig = sig;
+
+ g_task_set_task_data (task, manager, g_object_unref);
+
+ cc_realm_provider_proxy_new (connection,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
+ "org.freedesktop.realmd",
+ "/org/freedesktop/realmd",
+ g_task_get_cancellable (task),
+ on_provider_new, task);
+ g_steal_pointer (&task);
+ } else {
+ g_task_return_error (task, error);
+ }
+}
+
+void
+cc_realm_manager_new (GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+
+ g_debug ("Connecting to realmd...");
+
+ task = g_task_new (NULL, cancellable, callback, user_data);
+ g_task_set_source_tag (task, cc_realm_manager_new);
+
+ g_async_initable_new_async (CC_TYPE_REALM_MANAGER, G_PRIORITY_DEFAULT,
+ cancellable, on_manager_new, task,
+ "flags", G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
+ "name", "org.freedesktop.realmd",
+ "bus-type", G_BUS_TYPE_SYSTEM,
+ "object-path", "/org/freedesktop/realmd",
+ "get-proxy-type-func", cc_realm_object_manager_client_get_proxy_type,
+ NULL);
+}
+
+CcRealmManager *
+cc_realm_manager_new_finish (GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (result, NULL), NULL);
+ g_return_val_if_fail (g_async_result_is_tagged (result, cc_realm_manager_new), NULL);
+
+ return g_task_propagate_pointer (G_TASK (result), error);
+}
+
+static void
+realms_free (gpointer data)
+{
+ g_list_free_full (data, g_object_unref);
+}
+
+static void
+on_provider_discover (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ CcRealmManager *manager = g_task_get_source_object (task);
+ GError *error = NULL;
+ gboolean no_membership = FALSE;
+ gchar **realms;
+ gint relevance;
+ gint i;
+ GList *kerberos_realms = NULL;
+
+ cc_realm_provider_call_discover_finish (CC_REALM_PROVIDER (source), &relevance,
+ &realms, result, &error);
+ if (error == NULL) {
+ for (i = 0; realms[i]; i++) {
+ g_autoptr(GDBusObject) object = NULL;
+
+ object = g_dbus_object_manager_get_object (G_DBUS_OBJECT_MANAGER (manager), realms[i]);
+ if (object == NULL) {
+ g_warning ("Realm is not in object manager: %s", realms[i]);
+ } else {
+ if (is_realm_with_kerberos_and_membership (object)) {
+ g_debug ("Discovered realm: %s", realms[i]);
+ kerberos_realms = g_list_prepend (kerberos_realms, g_steal_pointer (&object));
+ } else {
+ g_debug ("Realm does not support kerberos membership: %s", realms[i]);
+ no_membership = TRUE;
+ }
+ }
+ }
+ g_strfreev (realms);
+
+ if (!kerberos_realms && no_membership) {
+ g_task_return_new_error (task, CC_REALM_ERROR, CC_REALM_ERROR_GENERIC,
+ _("Cannot automatically join this type of domain"));
+ } else if (!kerberos_realms) {
+ g_task_return_new_error (task, CC_REALM_ERROR, CC_REALM_ERROR_GENERIC,
+ _("No such domain or realm found"));
+ } else {
+ kerberos_realms = g_list_reverse (kerberos_realms);
+ g_task_return_pointer (task, kerberos_realms, realms_free);
+ }
+ } else {
+ g_task_return_error (task, error);
+ }
+}
+
+void
+cc_realm_manager_discover (CcRealmManager *self,
+ const gchar *input,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+ GVariant *options;
+
+ g_return_if_fail (CC_IS_REALM_MANAGER (self));
+ g_return_if_fail (input != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ g_debug ("Discovering realms for: %s", input);
+
+ task = g_task_new (G_OBJECT (self), cancellable, callback, user_data);
+ g_task_set_source_tag (task, cc_realm_manager_discover);
+
+ options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0);
+
+ cc_realm_provider_call_discover (self->provider, input, options, cancellable,
+ on_provider_discover, task);
+}
+
+GList *
+cc_realm_manager_discover_finish (CcRealmManager *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (CC_IS_REALM_MANAGER (self), NULL);
+ g_return_val_if_fail (g_task_is_valid (result, G_OBJECT (self)), NULL);
+ g_return_val_if_fail (g_async_result_is_tagged (result, cc_realm_manager_discover), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ return g_task_propagate_pointer (G_TASK (result), error);
+}
+
+GList *
+cc_realm_manager_get_realms (CcRealmManager *self)
+{
+ GList *objects;
+ GList *realms = NULL;
+ GList *l;
+
+ g_return_val_if_fail (CC_IS_REALM_MANAGER (self), NULL);
+
+ objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (self));
+ for (l = objects; l != NULL; l = g_list_next (l)) {
+ if (is_realm_with_kerberos_and_membership (l->data))
+ realms = g_list_prepend (realms, g_object_ref (l->data));
+ }
+
+ g_list_free_full (objects, g_object_unref);
+ return realms;
+}
+
+static void
+string_replace (GString *string,
+ const gchar *find,
+ const gchar *replace)
+{
+ const gchar *at;
+ gssize pos;
+
+ at = strstr (string->str, find);
+ if (at != NULL) {
+ pos = at - string->str;
+ g_string_erase (string, pos, strlen (find));
+ g_string_insert (string, pos, replace);
+ }
+}
+
+gchar *
+cc_realm_calculate_login (CcRealmCommon *realm,
+ const gchar *username)
+{
+ const gchar *const *formats;
+
+ formats = cc_realm_common_get_login_formats (realm);
+ if (formats[0] != NULL) {
+ GString *string = g_string_new (formats[0]);
+ string_replace (string, "%U", username);
+ string_replace (string, "%D", cc_realm_common_get_name (realm));
+ return g_string_free (string, FALSE);
+ }
+
+ return NULL;
+}
+
+gboolean
+cc_realm_is_configured (CcRealmObject *realm)
+{
+ g_autoptr(CcRealmCommon) common = NULL;
+ const gchar *configured;
+ gboolean is = FALSE;
+
+ common = cc_realm_object_get_common (realm);
+ if (common != NULL) {
+ configured = cc_realm_common_get_configured (common);
+ is = configured != NULL && !g_str_equal (configured, "");
+ }
+
+ return is;
+}
+
+static const gchar *
+find_supported_credentials (CcRealmKerberosMembership *membership,
+ const gchar *owner)
+{
+ const gchar *cred_owner;
+ const gchar *cred_type;
+ GVariant *supported;
+ GVariantIter iter;
+
+ supported = cc_realm_kerberos_membership_get_supported_join_credentials (membership);
+ g_return_val_if_fail (supported != NULL, NULL);
+
+ g_variant_iter_init (&iter, supported);
+ while (g_variant_iter_loop (&iter, "(&s&s)", &cred_type, &cred_owner)) {
+ if (g_str_equal (owner, cred_owner)) {
+ if (g_str_equal (cred_type, "ccache") ||
+ g_str_equal (cred_type, "password")) {
+ return g_intern_string (cred_type);
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static gboolean
+realm_join_as_owner (CcRealmObject *realm,
+ const gchar *owner,
+ const gchar *login,
+ const gchar *password,
+ GBytes *credentials,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(CcRealmKerberosMembership) membership = NULL;
+ GVariant *contents;
+ GVariant *options;
+ GVariant *option;
+ GVariant *creds;
+ const gchar *type;
+
+ membership = cc_realm_object_get_kerberos_membership (realm);
+ g_return_val_if_fail (membership != NULL, FALSE);
+
+ type = find_supported_credentials (membership, owner);
+ if (type == NULL) {
+ g_debug ("Couldn't find supported credential type for owner: %s", owner);
+ return FALSE;
+ }
+
+ if (g_str_equal (type, "ccache")) {
+ g_debug ("Using a kerberos credential cache to join the realm");
+ contents = g_variant_new_from_data (G_VARIANT_TYPE ("ay"),
+ g_bytes_get_data (credentials, NULL),
+ g_bytes_get_size (credentials),
+ TRUE, (GDestroyNotify)g_bytes_unref, credentials);
+
+ } else if (g_str_equal (type, "password")) {
+ g_debug ("Using a user/password to join the realm");
+ contents = g_variant_new ("(ss)", login, password);
+
+ } else {
+ g_assert_not_reached ();
+ }
+
+ creds = g_variant_new ("(ssv)", type, owner, contents);
+ option = g_variant_new ("{sv}", "manage-system", g_variant_new_boolean (FALSE));
+ options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), &option, 1);
+
+ g_debug ("Calling the Join() method with %s credentials", owner);
+
+ cc_realm_kerberos_membership_call_join (membership, creds, options,
+ cancellable, callback, user_data);
+
+ return TRUE;
+}
+
+gboolean
+cc_realm_join_as_user (CcRealmObject *realm,
+ const gchar *login,
+ const gchar *password,
+ GBytes *credentials,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_val_if_fail (CC_REALM_IS_OBJECT (realm), FALSE);
+ g_return_val_if_fail (credentials != NULL, FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (login != NULL, FALSE);
+ g_return_val_if_fail (password != NULL, FALSE);
+ g_return_val_if_fail (credentials != NULL, FALSE);
+
+ return realm_join_as_owner (realm, "user", login, password,
+ credentials, cancellable, callback, user_data);
+}
+
+gboolean
+cc_realm_join_as_admin (CcRealmObject *realm,
+ const gchar *login,
+ const gchar *password,
+ GBytes *credentials,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_val_if_fail (CC_REALM_IS_OBJECT (realm), FALSE);
+ g_return_val_if_fail (credentials != NULL, FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (login != NULL, FALSE);
+ g_return_val_if_fail (password != NULL, FALSE);
+ g_return_val_if_fail (credentials != NULL, FALSE);
+
+ return realm_join_as_owner (realm, "administrator", login, password, credentials,
+ cancellable, callback, user_data);
+}
+
+gboolean
+cc_realm_join_finish (CcRealmObject *realm,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_autoptr(CcRealmKerberosMembership) membership = NULL;
+ g_autoptr(GError) call_error = NULL;
+ g_autofree gchar *dbus_error = NULL;
+
+ g_return_val_if_fail (CC_REALM_IS_OBJECT (realm), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ membership = cc_realm_object_get_kerberos_membership (realm);
+ g_return_val_if_fail (membership != NULL, FALSE);
+
+ if (cc_realm_kerberos_membership_call_join_finish (membership, result, &call_error)) {
+ g_debug ("Completed Join() method call");
+ return TRUE;
+ }
+
+ dbus_error = g_dbus_error_get_remote_error (call_error);
+ if (dbus_error == NULL) {
+ g_debug ("Join() failed because of %s", call_error->message);
+ g_propagate_error (error, g_steal_pointer (&call_error));
+ return FALSE;
+ }
+
+ g_dbus_error_strip_remote_error (call_error);
+
+ if (g_str_equal (dbus_error, "org.freedesktop.realmd.Error.AuthenticationFailed")) {
+ g_debug ("Join() failed because of invalid/insufficient credentials");
+ g_set_error (error, CC_REALM_ERROR, CC_REALM_ERROR_BAD_LOGIN,
+ "%s", call_error->message);
+ } else {
+ g_debug ("Join() failed because of %s", call_error->message);
+ g_propagate_error (error, g_steal_pointer (&call_error));
+ }
+
+ return FALSE;
+}
+
+typedef struct {
+ gchar *domain;
+ gchar *realm;
+ gchar *user;
+ gchar *password;
+} LoginClosure;
+
+static void
+login_closure_free (gpointer data)
+{
+ LoginClosure *login = data;
+ g_clear_pointer (&login->domain, g_free);
+ g_clear_pointer (&login->realm, g_free);
+ g_clear_pointer (&login->user, g_free);
+ g_clear_pointer (&login->password, g_free);
+ g_slice_free (LoginClosure, login);
+}
+
+static krb5_error_code
+login_perform_kinit (krb5_context k5,
+ const gchar *realm,
+ const gchar *login,
+ const gchar *password,
+ const gchar *filename)
+{
+ krb5_get_init_creds_opt *opts;
+ krb5_error_code code;
+ krb5_principal principal;
+ krb5_ccache ccache;
+ krb5_creds creds;
+ g_autofree gchar *name = NULL;
+
+ name = g_strdup_printf ("%s@%s", login, realm);
+ code = krb5_parse_name (k5, name, &principal);
+
+ if (code != 0) {
+ g_debug ("Couldn't parse principal name: %s: %s",
+ name, krb5_get_error_message (k5, code));
+ return code;
+ }
+
+ g_debug ("Using principal name to kinit: %s", name);
+
+ if (filename == NULL)
+ code = krb5_cc_default (k5, &ccache);
+ else
+ code = krb5_cc_resolve (k5, filename, &ccache);
+
+ if (code != 0) {
+ krb5_free_principal (k5, principal);
+ g_debug ("Couldn't open credential cache: %s: %s",
+ filename ? filename : "<default>",
+ krb5_get_error_message (k5, code));
+ return code;
+ }
+
+ code = krb5_get_init_creds_opt_alloc (k5, &opts);
+ g_return_val_if_fail (code == 0, code);
+
+ code = krb5_get_init_creds_opt_set_out_ccache (k5, opts, ccache);
+ g_return_val_if_fail (code == 0, code);
+
+ code = krb5_get_init_creds_password (k5, &creds, principal,
+ (char *)password,
+ NULL, 0, 0, NULL, opts);
+
+ krb5_get_init_creds_opt_free (k5, opts);
+ krb5_cc_close (k5, ccache);
+ krb5_free_principal (k5, principal);
+
+ if (code == 0) {
+ g_debug ("kinit succeeded");
+ krb5_free_cred_contents (k5, &creds);
+ } else {
+ g_debug ("kinit failed: %s", krb5_get_error_message (k5, code));
+ }
+
+ return code;
+}
+
+static void
+kinit_thread_func (GTask *t,
+ gpointer object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ g_autoptr(GTask) task = t;
+ LoginClosure *login = task_data;
+ krb5_context k5 = NULL;
+ krb5_error_code code;
+ g_autofree gchar *filename = NULL;
+ gchar *contents;
+ gsize length;
+ gint temp_fd;
+
+ filename = g_build_filename (g_get_user_runtime_dir (),
+ "um-krb5-creds.XXXXXX", NULL);
+ temp_fd = g_mkstemp_full (filename, O_RDWR, S_IRUSR | S_IWUSR);
+ if (temp_fd == -1) {
+ g_warning ("Couldn't create credential cache file: %s: %s",
+ filename, g_strerror (errno));
+ g_clear_pointer (&filename, g_free);
+ } else {
+ close (temp_fd);
+ }
+
+ code = krb5_init_context (&k5);
+ if (code == 0) {
+ code = login_perform_kinit (k5, login->realm, login->user,
+ login->password, filename);
+ }
+
+ switch (code) {
+ case 0:
+ if (filename != NULL) {
+ g_autoptr(GError) error = NULL;
+
+ if (g_file_get_contents (filename, &contents, &length, &error)) {
+ g_debug ("Read in credential cache: %s", filename);
+ } else {
+ g_warning ("Couldn't read credential cache: %s: %s",
+ filename, error->message);
+ }
+
+ g_task_return_pointer (task, g_bytes_new_take (contents, length), (GDestroyNotify) g_bytes_unref);
+ }
+ break;
+
+ case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
+ case KRB5KDC_ERR_POLICY:
+ g_task_return_new_error (task, CC_REALM_ERROR, CC_REALM_ERROR_BAD_LOGIN,
+ _("Cannot log in as %s at the %s domain"),
+ login->user, login->domain);
+ break;
+ case KRB5KDC_ERR_PREAUTH_FAILED:
+ case KRB5KRB_AP_ERR_BAD_INTEGRITY:
+ g_task_return_new_error (task, CC_REALM_ERROR, CC_REALM_ERROR_BAD_PASSWORD,
+ _("Invalid password, please try again"));
+ break;
+ case KRB5_PREAUTH_FAILED:
+ case KRB5KDC_ERR_KEY_EXP:
+ case KRB5KDC_ERR_CLIENT_REVOKED:
+ case KRB5KDC_ERR_ETYPE_NOSUPP:
+ case KRB5_PROG_ETYPE_NOSUPP:
+ g_task_return_new_error (task, CC_REALM_ERROR, CC_REALM_ERROR_CANNOT_AUTH,
+ _("Cannot log in as %s at the %s domain"),
+ login->user, login->domain);
+ break;
+ default:
+ g_task_return_new_error (task, CC_REALM_ERROR, CC_REALM_ERROR_GENERIC,
+ _("Couldn’t connect to the %s domain: %s"),
+ login->domain, krb5_get_error_message (k5, code));
+ break;
+ }
+
+ if (filename) {
+ g_unlink (filename);
+ g_debug ("Deleted credential cache: %s", filename);
+ }
+
+ if (k5)
+ krb5_free_context (k5);
+}
+
+void
+cc_realm_login (CcRealmObject *realm,
+ const gchar *user,
+ const gchar *password,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+ LoginClosure *login;
+ g_autoptr(CcRealmKerberos) kerberos = NULL;
+
+ g_return_if_fail (CC_REALM_IS_OBJECT (realm));
+ g_return_if_fail (user != NULL);
+ g_return_if_fail (password != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ kerberos = cc_realm_object_get_kerberos (realm);
+ g_return_if_fail (kerberos != NULL);
+
+ task = g_task_new (NULL, cancellable, callback, user_data);
+ g_task_set_source_tag (task, cc_realm_login);
+
+ login = g_slice_new0 (LoginClosure);
+ login->domain = g_strdup (cc_realm_kerberos_get_domain_name (kerberos));
+ login->realm = g_strdup (cc_realm_kerberos_get_realm_name (kerberos));
+ login->user = g_strdup (user);
+ login->password = g_strdup (password);
+ g_task_set_task_data (task, login, login_closure_free);
+
+ g_task_set_return_on_cancel (task, TRUE);
+ g_task_run_in_thread (task, kinit_thread_func);
+}
+
+GBytes *
+cc_realm_login_finish (GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (result, NULL), FALSE);
+ g_return_val_if_fail (g_async_result_is_tagged (result, cc_realm_login), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ return g_task_propagate_pointer (G_TASK (result), error);
+}
diff --git a/panels/user-accounts/cc-realm-manager.h b/panels/user-accounts/cc-realm-manager.h
new file mode 100644
index 0000000..7e68e8e
--- /dev/null
+++ b/panels/user-accounts/cc-realm-manager.h
@@ -0,0 +1,97 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Stef Walter <stefw@gnome.org>
+ */
+
+#pragma once
+
+#include "cc-realm-generated.h"
+
+G_BEGIN_DECLS
+
+typedef enum {
+ CC_REALM_ERROR_BAD_LOGIN,
+ CC_REALM_ERROR_BAD_PASSWORD,
+ CC_REALM_ERROR_CANNOT_AUTH,
+ CC_REALM_ERROR_GENERIC,
+} CcRealmErrors;
+
+#define CC_REALM_ERROR (cc_realm_error_get_quark ())
+
+GQuark cc_realm_error_get_quark (void) G_GNUC_CONST;
+
+#define CC_TYPE_REALM_MANAGER (cc_realm_manager_get_type ())
+G_DECLARE_FINAL_TYPE (CcRealmManager, cc_realm_manager, CC, REALM_MANAGER, CcRealmObjectManagerClient)
+
+void cc_realm_manager_new (GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+CcRealmManager * cc_realm_manager_new_finish (GAsyncResult *result,
+ GError **error);
+
+void cc_realm_manager_discover (CcRealmManager *self,
+ const gchar *input,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GList * cc_realm_manager_discover_finish (CcRealmManager *self,
+ GAsyncResult *result,
+ GError **error);
+
+GList * cc_realm_manager_get_realms (CcRealmManager *self);
+
+void cc_realm_login (CcRealmObject *realm,
+ const gchar *login,
+ const gchar *password,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GBytes * cc_realm_login_finish (GAsyncResult *result,
+ GError **error);
+
+gboolean cc_realm_join_as_user (CcRealmObject *realm,
+ const gchar *login,
+ const gchar *password,
+ GBytes *credentials,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+ G_GNUC_WARN_UNUSED_RESULT;
+
+gboolean cc_realm_join_as_admin (CcRealmObject *realm,
+ const gchar *login,
+ const gchar *password,
+ GBytes *credentials,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+ G_GNUC_WARN_UNUSED_RESULT;
+
+gboolean cc_realm_join_finish (CcRealmObject *realm,
+ GAsyncResult *result,
+ GError **error);
+
+gboolean cc_realm_is_configured (CcRealmObject *realm);
+
+gchar * cc_realm_calculate_login (CcRealmCommon *realm,
+ const gchar *username);
+
+G_END_DECLS
diff --git a/panels/user-accounts/cc-user-panel.c b/panels/user-accounts/cc-user-panel.c
new file mode 100644
index 0000000..4eed0da
--- /dev/null
+++ b/panels/user-accounts/cc-user-panel.c
@@ -0,0 +1,1603 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2009-2010 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#include "config.h"
+
+#include "cc-user-panel.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <locale.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <polkit/polkit.h>
+#include <act/act.h>
+#include <cairo-gobject.h>
+
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnome-desktop/gnome-languages.h>
+
+#ifdef HAVE_MALCONTENT
+#include <libmalcontent/malcontent.h>
+#endif
+
+#include "cc-add-user-dialog.h"
+#include "cc-avatar-chooser.h"
+#include "cc-language-chooser.h"
+#include "cc-login-history-dialog.h"
+#include "cc-password-dialog.h"
+#include "cc-realm-manager.h"
+#include "cc-user-accounts-resources.h"
+#include "cc-fingerprint-manager.h"
+#include "cc-fingerprint-dialog.h"
+#include "user-utils.h"
+
+#include "cc-common-language.h"
+#include "cc-permission-infobar.h"
+#include "cc-util.h"
+
+#define USER_ACCOUNTS_PERMISSION "org.gnome.controlcenter.user-accounts.administration"
+
+struct _CcUserPanel {
+ CcPanel parent_instance;
+
+ ActUserManager *um;
+ GSettings *login_screen_settings;
+
+ GtkBox *account_settings_box;
+ GtkListBoxRow *account_type_row;
+ GtkSwitch *account_type_switch;
+ GtkWidget *add_user_button;
+ GtkListBoxRow *autologin_row;
+ GtkSwitch *autologin_switch;
+ GtkButton *back_button;
+ GtkLabel *fingerprint_state_label;
+ GtkListBoxRow *fingerprint_row;
+ GtkStack *full_name_stack;
+ GtkLabel *full_name_label;
+ GtkToggleButton *full_name_edit_button;
+ GtkEntry *full_name_entry;
+ GtkLabel *language_button_label;
+ GtkListBoxRow *language_row;
+ GtkLabel *last_login_button_label;
+ GtkListBoxRow *last_login_row;
+ GtkWidget *no_users_box;
+ GtkRevealer *notification_revealer;
+ AdwPreferencesGroup *other_users;
+ GtkListBox *other_users_listbox;
+ AdwPreferencesRow *other_users_row;
+ GtkLabel *password_button_label;
+#ifdef HAVE_MALCONTENT
+ GtkLabel *parental_controls_button_label;
+ GtkListBoxRow *parental_controls_row;
+#endif
+ GtkListBoxRow *password_row;
+ CcPermissionInfobar *permission_infobar;
+ GtkButton *remove_user_button;
+ GtkStack *stack;
+ AdwAvatar *user_avatar;
+ GtkMenuButton *user_avatar_edit_button;
+ GtkOverlay *users_overlay;
+
+ ActUser *selected_user;
+ ActUser *pending_show_user;
+ GPermission *permission;
+ CcLanguageChooser *language_chooser;
+ GListStore *other_users_model;
+
+ CcAvatarChooser *avatar_chooser;
+
+ CcFingerprintManager *fingerprint_manager;
+};
+
+CC_PANEL_REGISTER (CcUserPanel, cc_user_panel)
+
+static void show_restart_notification (CcUserPanel *self, const gchar *locale);
+
+typedef struct {
+ CcUserPanel *self;
+ GCancellable *cancellable;
+ gchar *login;
+} AsyncDeleteData;
+
+static void
+async_delete_data_free (AsyncDeleteData *data)
+{
+ g_clear_object (&data->self);
+ g_clear_object (&data->cancellable);
+ g_clear_pointer (&data->login, g_free);
+ g_slice_free (AsyncDeleteData, data);
+}
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (AsyncDeleteData, async_delete_data_free)
+
+static void
+show_error_dialog (CcUserPanel *self,
+ const gchar *message,
+ GError *error)
+{
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (self))),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_USE_HEADER_BAR,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ "%s", message);
+
+ if (error != NULL) {
+ g_dbus_error_strip_remote_error (error);
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s", error->message);
+ }
+
+ g_signal_connect (dialog, "response", G_CALLBACK (gtk_window_destroy), NULL);
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+static void show_user (ActUser *user, CcUserPanel *self);
+
+static ActUser *
+get_selected_user (CcUserPanel *self)
+{
+ return self->selected_user;
+}
+
+static void
+set_selected_user (CcUserPanel *self,
+ AdwActionRow *row)
+{
+ uid_t uid;
+
+ uid = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (row), "uid"));
+ g_set_object (&self->selected_user,
+ act_user_manager_get_user_by_id (self->um, uid));
+ show_user (self->selected_user, self);
+}
+
+static void
+show_current_user (CcUserPanel *self)
+{
+ ActUser *user;
+
+ user = act_user_manager_get_user_by_id (self->um, getuid ());
+ if (user != NULL)
+ show_user (user, self);
+}
+
+
+static void
+on_back_button_clicked_cb (CcUserPanel *self)
+{
+
+ if (act_user_get_uid (self->selected_user) == getuid ()) {
+ gtk_widget_activate_action (GTK_WIDGET (self),
+ "window.navigate",
+ "i",
+ ADW_NAVIGATION_DIRECTION_BACK);
+ } else {
+ show_current_user (self);
+ }
+}
+
+static const gchar *
+get_real_or_user_name (ActUser *user)
+{
+ const gchar *name;
+
+ name = act_user_get_real_name (user);
+ if (name == NULL)
+ name = act_user_get_user_name (user);
+
+ return name;
+}
+
+static void
+setup_avatar_for_user (AdwAvatar *avatar, ActUser *user)
+{
+ const gchar *avatar_file;
+
+ adw_avatar_set_custom_image (avatar, NULL);
+ adw_avatar_set_text (avatar, get_real_or_user_name (user));
+
+ avatar_file = act_user_get_icon_file (user);
+ if (avatar_file) {
+ g_autoptr(GdkPixbuf) pixbuf = NULL;
+
+ pixbuf = gdk_pixbuf_new_from_file_at_size (avatar_file,
+ adw_avatar_get_size (avatar),
+ adw_avatar_get_size (avatar),
+ NULL);
+ if (pixbuf) {
+ adw_avatar_set_custom_image (avatar,
+ GDK_PAINTABLE (gdk_texture_new_for_pixbuf (pixbuf)));
+ }
+ }
+}
+
+static GtkWidget *
+create_user_row (gpointer item,
+ gpointer user_data)
+{
+ ActUser *user = ACT_USER (item);
+ GtkWidget *row, *user_image;
+
+ row = adw_action_row_new ();
+ g_object_set_data (G_OBJECT (row), "uid", GINT_TO_POINTER (act_user_get_uid (user)));
+ gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), TRUE);
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row),
+ get_real_or_user_name (user));
+ user_image = adw_avatar_new (48, NULL, TRUE);
+ setup_avatar_for_user (ADW_AVATAR (user_image), user);
+ adw_action_row_add_prefix (ADW_ACTION_ROW (row), user_image);
+
+ return row;
+}
+
+static gint
+sort_users (gconstpointer a, gconstpointer b, gpointer user_data)
+{
+ ActUser *ua, *ub;
+
+ ua = ACT_USER (a);
+ ub = ACT_USER (b);
+
+ /* Make sure the current user is shown first */
+ if (act_user_get_uid (ua) == getuid ()) {
+ return -G_MAXINT32;
+ }
+ else if (act_user_get_uid (ub) == getuid ()) {
+ return G_MAXINT32;
+ }
+ else {
+ g_autofree gchar *name1 = NULL;
+ g_autofree gchar *name2 = NULL;
+
+ name1 = g_utf8_collate_key (get_real_or_user_name (ua), -1);
+ name2 = g_utf8_collate_key (get_real_or_user_name (ub), -1);
+
+ return strcmp (name1, name2);
+ }
+}
+
+static void
+user_changed (CcUserPanel *self, ActUser *user)
+{
+ GSList *user_list, *l;
+ gboolean show;
+
+ g_list_store_remove_all (self->other_users_model);
+ user_list = act_user_manager_list_users (self->um);
+ for (l = user_list; l; l = l->next) {
+ ActUser *other_user = ACT_USER (l->data);
+
+ if (act_user_is_system_account (other_user)) {
+ continue;
+ }
+
+ if (act_user_get_uid (other_user) == getuid ()) {
+ continue;
+ }
+
+ g_list_store_insert_sorted (self->other_users_model,
+ other_user,
+ sort_users,
+ self);
+ }
+
+ if (self->selected_user == user)
+ show_user (user, self);
+
+ show = g_list_model_get_n_items (G_LIST_MODEL (self->other_users_model)) > 0;
+ gtk_widget_set_visible (GTK_WIDGET (self->other_users_row), show);
+}
+
+static void
+on_add_user_dialog_response (CcUserPanel *self,
+ gint response,
+ CcAddUserDialog *dialog)
+{
+ ActUser *user;
+
+ user = cc_add_user_dialog_get_user (dialog);
+ if (user != NULL) {
+ set_default_avatar (user);
+ show_user (user, self);
+ }
+
+ gtk_window_destroy (GTK_WINDOW (dialog));
+}
+
+static void
+add_user (CcUserPanel *self)
+{
+ CcAddUserDialog *dialog;
+ GtkWindow *toplevel;
+
+ dialog = cc_add_user_dialog_new (self->permission);
+ toplevel = GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (self)));
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), toplevel);
+
+ gtk_window_present (GTK_WINDOW (dialog));
+ g_signal_connect_object (dialog, "response", G_CALLBACK (on_add_user_dialog_response),
+ self, G_CONNECT_SWAPPED);
+}
+
+static void
+delete_user_done (ActUserManager *manager,
+ GAsyncResult *res,
+ CcUserPanel *self)
+{
+ g_autoptr(GError) error = NULL;
+
+ if (!act_user_manager_delete_user_finish (manager, res, &error)) {
+ if (!g_error_matches (error, ACT_USER_MANAGER_ERROR,
+ ACT_USER_MANAGER_ERROR_PERMISSION_DENIED))
+ show_error_dialog (self, _("Failed to delete user"), error);
+ }
+
+ show_current_user (self);
+}
+
+static void
+delete_user_response (CcUserPanel *self,
+ gint response_id,
+ GtkWidget *dialog)
+{
+ ActUser *user;
+ gboolean remove_files;
+
+ gtk_window_destroy (GTK_WINDOW (dialog));
+
+ if (response_id == GTK_RESPONSE_CANCEL) {
+ return;
+ }
+ else if (response_id == GTK_RESPONSE_NO) {
+ remove_files = TRUE;
+ }
+ else {
+ remove_files = FALSE;
+ }
+
+ user = get_selected_user (self);
+
+ /* remove autologin */
+ if (act_user_get_automatic_login (user)) {
+ act_user_set_automatic_login (user, FALSE);
+ }
+
+ act_user_manager_delete_user_async (self->um,
+ user,
+ remove_files,
+ NULL,
+ (GAsyncReadyCallback)delete_user_done,
+ self);
+}
+
+static void
+enterprise_user_revoked (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(AsyncDeleteData) data = user_data;
+ CcUserPanel *self = data->self;
+ CcRealmCommon *common = CC_REALM_COMMON (source);
+ g_autoptr(GError) error = NULL;
+
+ if (g_cancellable_is_cancelled (data->cancellable)) {
+ return;
+ }
+
+ cc_realm_common_call_change_login_policy_finish (common, result, &error);
+ if (error != NULL) {
+ show_error_dialog (self, _("Failed to revoke remotely managed user"), error);
+ }
+}
+
+static CcRealmCommon *
+find_matching_realm (CcRealmManager *realm_manager, const gchar *login)
+{
+ CcRealmCommon *common = NULL;
+ GList *realms;
+
+ realms = cc_realm_manager_get_realms (realm_manager);
+ for (GList *l = realms; l != NULL; l = g_list_next (l)) {
+ const gchar * const *permitted_logins;
+ gint i;
+
+ common = cc_realm_object_get_common (l->data);
+ if (common == NULL)
+ continue;
+
+ permitted_logins = cc_realm_common_get_permitted_logins (common);
+ for (i = 0; permitted_logins[i] != NULL; i++) {
+ if (g_strcmp0 (permitted_logins[i], login) == 0)
+ break;
+ }
+
+ if (permitted_logins[i] != NULL)
+ break;
+
+ g_clear_object (&common);
+ }
+ g_list_free_full (realms, g_object_unref);
+
+ return common;
+}
+
+static void
+realm_manager_found (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(AsyncDeleteData) data = user_data;
+ CcUserPanel *self = data->self;
+ g_autoptr(CcRealmCommon) common = NULL;
+ CcRealmManager *realm_manager;
+ const gchar *add[1];
+ const gchar *remove[2];
+ GVariant *options;
+ g_autoptr(GError) error = NULL;
+
+ if (g_cancellable_is_cancelled (data->cancellable)) {
+ return;
+ }
+
+ realm_manager = cc_realm_manager_new_finish (result, &error);
+ if (error != NULL) {
+ show_error_dialog (self, _("Failed to revoke remotely managed user"), error);
+ return;
+ }
+
+ /* Find matching realm */
+ common = find_matching_realm (realm_manager, data->login);
+ if (common == NULL) {
+ /* The realm was probably left */
+ return;
+ }
+
+ /* Remove the user from permitted logins */
+ g_debug ("Denying future login for: %s", data->login);
+
+ add[0] = NULL;
+ remove[0] = data->login;
+ remove[1] = NULL;
+
+ options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0);
+ cc_realm_common_call_change_login_policy (common, "",
+ add, remove, options,
+ data->cancellable,
+ enterprise_user_revoked,
+ g_steal_pointer (&data));
+}
+
+static void
+enterprise_user_uncached (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(AsyncDeleteData) data = user_data;
+ CcUserPanel *self = data->self;
+ ActUserManager *manager = ACT_USER_MANAGER (source);
+ g_autoptr(GError) error = NULL;
+
+ if (g_cancellable_is_cancelled (data->cancellable)) {
+ return;
+ }
+
+ act_user_manager_uncache_user_finish (manager, res, &error);
+ if (error == NULL) {
+ /* Find realm manager */
+ cc_realm_manager_new (cc_panel_get_cancellable (CC_PANEL (self)), realm_manager_found, g_steal_pointer (&data));
+ }
+ else {
+ show_error_dialog (self, _("Failed to revoke remotely managed user"), error);
+ }
+}
+
+static void
+delete_enterprise_user_response (CcUserPanel *self,
+ gint response_id,
+ GtkWidget *dialog)
+{
+ AsyncDeleteData *data;
+ ActUser *user;
+
+ gtk_window_destroy (GTK_WINDOW (dialog));
+
+ if (response_id != GTK_RESPONSE_ACCEPT) {
+ return;
+ }
+
+ user = get_selected_user (self);
+
+ data = g_slice_new (AsyncDeleteData);
+ data->self = g_object_ref (self);
+ data->cancellable = g_object_ref (cc_panel_get_cancellable (CC_PANEL (self)));
+ data->login = g_strdup (act_user_get_user_name (user));
+
+ /* Uncache the user account from the accountsservice */
+ g_debug ("Uncaching remote user: %s", data->login);
+
+ act_user_manager_uncache_user_async (self->um, data->login,
+ data->cancellable,
+ enterprise_user_uncached,
+ data);
+}
+
+static void
+delete_user (CcUserPanel *self)
+{
+ ActUser *user;
+ GtkWidget *dialog;
+
+ user = get_selected_user (self);
+ if (user == NULL) {
+ return;
+ }
+ else if (act_user_get_uid (user) == getuid ()) {
+ dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (self))),
+ 0,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_CLOSE,
+ _("You cannot delete your own account."));
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (gtk_window_destroy), NULL);
+ }
+ else if (act_user_is_logged_in_anywhere (user)) {
+ dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (self))),
+ 0,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_CLOSE,
+ _("%s is still logged in"),
+ get_real_or_user_name (user));
+
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ _("Deleting a user while they are logged in can leave the system in an inconsistent state."));
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (gtk_window_destroy), NULL);
+ }
+ else if (act_user_is_local_account (user)) {
+ dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (self))),
+ 0,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_NONE,
+ _("Do you want to keep %s’s files?"),
+ get_real_or_user_name (user));
+
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ _("It is possible to keep the home directory, mail spool and temporary files around when deleting a user account."));
+
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ _("_Delete Files"), GTK_RESPONSE_NO,
+ _("_Keep Files"), GTK_RESPONSE_YES,
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ NULL);
+
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), "system-users");
+
+ g_signal_connect_object (dialog, "response",
+ G_CALLBACK (delete_user_response), self, G_CONNECT_SWAPPED);
+ }
+ else {
+ dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (self))),
+ 0,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_NONE,
+ _("Are you sure you want to revoke remotely managed %s’s account?"),
+ get_real_or_user_name (user));
+
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ _("_Delete"), GTK_RESPONSE_ACCEPT,
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ NULL);
+
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), "system-users");
+
+ g_signal_connect_object (dialog, "response",
+ G_CALLBACK (delete_enterprise_user_response), self, G_CONNECT_SWAPPED);
+ }
+
+ g_signal_connect (dialog, "close",
+ G_CALLBACK (gtk_window_destroy), NULL);
+
+ gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+static const gchar *
+get_invisible_text (void)
+{
+ GtkWidget *entry;
+ gunichar invisible_char;
+ static gchar invisible_text[40];
+ gchar *p;
+ gint i;
+
+ entry = gtk_entry_new ();
+ invisible_char = gtk_entry_get_invisible_char (GTK_ENTRY (entry));
+ if (invisible_char == 0)
+ invisible_char = 0x2022;
+
+ g_object_ref_sink (entry);
+ g_object_unref (entry);
+
+ /* five bullets */
+ p = invisible_text;
+ for (i = 0; i < 5; i++)
+ p += g_unichar_to_utf8 (invisible_char, p);
+ *p = 0;
+
+ return invisible_text;
+}
+
+static const gchar *
+get_password_mode_text (ActUser *user)
+{
+ const gchar *text;
+
+ if (act_user_get_locked (user)) {
+ text = C_("Password mode", "Account disabled");
+ }
+ else {
+ switch (act_user_get_password_mode (user)) {
+ case ACT_USER_PASSWORD_MODE_REGULAR:
+ text = get_invisible_text ();
+ break;
+ case ACT_USER_PASSWORD_MODE_SET_AT_LOGIN:
+ text = C_("Password mode", "To be set at next login");
+ break;
+ case ACT_USER_PASSWORD_MODE_NONE:
+ text = C_("Password mode", "None");
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ }
+
+ return text;
+}
+
+static void
+autologin_changed (CcUserPanel *self)
+{
+ gboolean active;
+ ActUser *user;
+
+ active = gtk_switch_get_active (self->autologin_switch);
+ user = get_selected_user (self);
+
+ if (active != act_user_get_automatic_login (user)) {
+ act_user_set_automatic_login (user, active);
+ if (act_user_get_automatic_login (user)) {
+ GSList *list;
+ GSList *l;
+ list = act_user_manager_list_users (self->um);
+ for (l = list; l != NULL; l = l->next) {
+ ActUser *u = l->data;
+ if (act_user_get_uid (u) != act_user_get_uid (user)) {
+ act_user_set_automatic_login (user, FALSE);
+ }
+ }
+ g_slist_free (list);
+ }
+ }
+}
+
+static gchar *
+get_login_time_text (ActUser *user)
+{
+ gint64 time;
+
+ time = act_user_get_login_time (user);
+ if (act_user_is_logged_in (user)) {
+ return g_strdup (_("Logged in"));
+ }
+ else if (time > 0) {
+ g_autoptr(GDateTime) date_time = NULL;
+ g_autofree gchar *date_str = NULL;
+ g_autofree gchar *time_str = NULL;
+
+ date_time = g_date_time_new_from_unix_local (time);
+ date_str = cc_util_get_smart_date (date_time);
+
+ /* Translators: This is a time format string in the style of "22:58".
+ It indicates a login time which follows a date. */
+ time_str = g_date_time_format (date_time, C_("login date-time", "%k:%M"));
+
+ /* Translators: This indicates a login date-time.
+ The first %s is a date, and the second %s a time. */
+ return g_strdup_printf(C_("login date-time", "%s, %s"), date_str, time_str);
+ }
+ else {
+ return g_strdup ("—");
+ }
+}
+
+static gboolean
+get_autologin_possible (ActUser *user)
+{
+ gboolean locked;
+ gboolean set_password_at_login;
+
+ locked = act_user_get_locked (user);
+ set_password_at_login = (act_user_get_password_mode (user) == ACT_USER_PASSWORD_MODE_SET_AT_LOGIN);
+
+ return !(locked || set_password_at_login);
+}
+
+static void on_permission_changed (CcUserPanel *self);
+static void full_name_edit_button_toggled (CcUserPanel *self);
+
+#ifdef HAVE_MALCONTENT
+static gboolean
+is_parental_controls_enabled_for_user (ActUser *user)
+{
+ g_autoptr(MctManager) manager = NULL;
+ g_autoptr(MctAppFilter) app_filter = NULL;
+ g_autoptr(GDBusConnection) system_bus = NULL;
+ g_autoptr(GError) error = NULL;
+
+ /* FIXME: should become asynchronous */
+ system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (system_bus == NULL) {
+ g_warning ("Error getting system bus while trying to show user details: %s", error->message);
+ return FALSE;
+ }
+
+ manager = mct_manager_new (system_bus);
+ app_filter = mct_manager_get_app_filter (manager,
+ act_user_get_uid (user),
+ MCT_GET_APP_FILTER_FLAGS_NONE,
+ NULL,
+ &error);
+ if (error) {
+ if (!g_error_matches (error, MCT_MANAGER_ERROR, MCT_MANAGER_ERROR_DISABLED))
+ g_warning ("Error retrieving app filter for user %s: %s",
+ act_user_get_user_name (user),
+ error->message);
+
+ return FALSE;
+ }
+
+ return mct_app_filter_is_enabled (app_filter);
+}
+#endif
+
+static void
+update_fingerprint_row_state (CcUserPanel *self, GParamSpec *spec, CcFingerprintManager *fingerprint_manager)
+{
+ CcFingerprintState state = cc_fingerprint_manager_get_state (fingerprint_manager);
+
+ if (state != CC_FINGERPRINT_STATE_UPDATING) {
+ gtk_widget_set_visible (GTK_WIDGET (self->fingerprint_row),
+ state != CC_FINGERPRINT_STATE_NONE);
+ }
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->fingerprint_row),
+ state != CC_FINGERPRINT_STATE_UPDATING);
+
+ if (state == CC_FINGERPRINT_STATE_ENABLED)
+ gtk_label_set_text (self->fingerprint_state_label, _("Enabled"));
+ else if (state == CC_FINGERPRINT_STATE_DISABLED)
+ gtk_label_set_text (self->fingerprint_state_label, _("Disabled"));
+}
+
+static void
+show_or_hide_back_button (CcUserPanel *self)
+{
+ gboolean show;
+ gboolean folded;
+
+ g_object_get(self, "folded", &folded, NULL);
+
+ show = folded || act_user_get_uid (self->selected_user) != getuid();
+
+ gtk_widget_set_visible (GTK_WIDGET (self->back_button), show);
+}
+
+static void
+on_pending_show_user_is_loaded (ActUser *user,
+ GParamSpec *param,
+ CcUserPanel *self)
+{
+ if (!act_user_is_loaded (user)) {
+ return;
+ }
+
+ show_user (user, self);
+}
+
+static void
+show_user (ActUser *user, CcUserPanel *self)
+{
+ g_autofree gchar *lang = NULL;
+ g_autofree gchar *name = NULL;
+ gboolean show, enable;
+ ActUser *current;
+#ifdef HAVE_MALCONTENT
+ g_autofree gchar *malcontent_control_path = NULL;
+#endif
+
+ if (self->pending_show_user != NULL) {
+ g_signal_handlers_disconnect_by_func (G_OBJECT (self->pending_show_user),
+ on_pending_show_user_is_loaded,
+ self);
+ g_clear_object (&self->pending_show_user);
+ }
+
+ if (!act_user_is_loaded (user)) {
+ g_set_object (&self->pending_show_user, user);
+ g_signal_connect_object (G_OBJECT (self->pending_show_user),
+ "notify::is-loaded",
+ G_CALLBACK (on_pending_show_user_is_loaded),
+ self,
+ 0);
+ return;
+ }
+
+ g_set_object (&self->selected_user, user);
+
+ setup_avatar_for_user (self->user_avatar, user);
+ cc_avatar_chooser_set_user (self->avatar_chooser, user);
+
+ gtk_label_set_label (self->full_name_label, get_real_or_user_name (user));
+ gtk_editable_set_text (GTK_EDITABLE (self->full_name_entry), gtk_label_get_label (self->full_name_label));
+ gtk_widget_set_tooltip_text (GTK_WIDGET (self->full_name_label), get_real_or_user_name (user));
+
+ g_signal_handlers_block_by_func (self->full_name_edit_button, full_name_edit_button_toggled, self);
+ gtk_stack_set_visible_child (self->full_name_stack, GTK_WIDGET (self->full_name_label));
+ gtk_toggle_button_set_active (self->full_name_edit_button, FALSE);
+ g_signal_handlers_unblock_by_func (self->full_name_edit_button, full_name_edit_button_toggled, self);
+
+ enable = (act_user_get_account_type (user) == ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR);
+ gtk_switch_set_active (self->account_type_switch, enable);
+
+ gtk_label_set_label (self->password_button_label, get_password_mode_text (user));
+ enable = act_user_is_local_account (user);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->password_button_label), enable);
+
+ g_signal_handlers_block_by_func (self->autologin_switch, autologin_changed, self);
+ gtk_switch_set_active (self->autologin_switch, act_user_get_automatic_login (user));
+ g_signal_handlers_unblock_by_func (self->autologin_switch, autologin_changed, self);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->autologin_switch), get_autologin_possible (user));
+
+ lang = g_strdup (act_user_get_language (user));
+ if (lang && *lang != '\0') {
+ name = gnome_get_language_from_locale (lang, NULL);
+ } else {
+ name = g_strdup ("—");
+ }
+ gtk_label_set_label (self->language_button_label, name);
+
+ /* Fingerprint: show when self, local, enabled, and possible */
+ show = (act_user_get_uid (user) == getuid() &&
+ act_user_is_local_account (user) &&
+ (self->login_screen_settings &&
+ g_settings_get_boolean (self->login_screen_settings,
+ "enable-fingerprint-authentication")));
+
+ if (show) {
+ if (!self->fingerprint_manager) {
+ self->fingerprint_manager = cc_fingerprint_manager_new (user);
+ g_signal_connect_object (self->fingerprint_manager,
+ "notify::state",
+ G_CALLBACK (update_fingerprint_row_state),
+ self, G_CONNECT_SWAPPED);
+ }
+
+ update_fingerprint_row_state (self, NULL, self->fingerprint_manager);
+ } else {
+ gtk_widget_set_visible (GTK_WIDGET (self->fingerprint_row), FALSE);
+ }
+
+ /* Autologin: show when local account */
+ show = act_user_is_local_account (user);
+ gtk_widget_set_visible (GTK_WIDGET (self->autologin_row), show);
+
+#ifdef HAVE_MALCONTENT
+ /* Parental Controls: Unavailable if user is admin or if
+ * malcontent-control is not available (which can happen if
+ * libmalcontent is installed but malcontent-control is not). */
+ malcontent_control_path = g_find_program_in_path ("malcontent-control");
+
+ if (act_user_get_account_type (user) == ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR ||
+ malcontent_control_path == NULL) {
+ gtk_widget_hide (GTK_WIDGET (self->parental_controls_row));
+ } else {
+ GtkStyleContext *context = gtk_widget_get_style_context (GTK_WIDGET (self->parental_controls_button_label));
+
+ if (is_parental_controls_enabled_for_user (user))
+ /* TRANSLATORS: Status of Parental Controls setup */
+ gtk_label_set_text (self->parental_controls_button_label, _("Enabled"));
+ else
+ /* TRANSLATORS: Status of Parental Controls setup */
+ gtk_label_set_text (self->parental_controls_button_label, _("Disabled"));
+
+ gtk_style_context_remove_class (context, "dim-label");
+ gtk_widget_show (GTK_WIDGET (self->parental_controls_row));
+ }
+#endif
+
+ /* Current user */
+ show = act_user_get_uid (user) == getuid();
+ gtk_widget_set_visible (GTK_WIDGET (self->account_settings_box), !show);
+ gtk_widget_set_visible (GTK_WIDGET (self->remove_user_button), !show);
+ gtk_widget_set_visible (GTK_WIDGET (self->back_button), !show);
+ show_or_hide_back_button(self);
+ gtk_widget_set_visible (GTK_WIDGET (self->other_users), show);
+
+ /* Last login: show when administrator or current user */
+ current = act_user_manager_get_user_by_id (self->um, getuid ());
+ show = act_user_get_uid (user) == getuid () ||
+ act_user_get_account_type (current) == ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR;
+ if (show) {
+ g_autofree gchar *text = NULL;
+
+ text = get_login_time_text (user);
+ gtk_label_set_label (self->last_login_button_label, text);
+ }
+ gtk_widget_set_visible (GTK_WIDGET (self->last_login_row), show);
+
+ enable = act_user_get_login_history (user) != NULL;
+ gtk_widget_set_sensitive (GTK_WIDGET (self->last_login_row), enable);
+
+ if (self->permission != NULL)
+ on_permission_changed (self);
+}
+
+static void
+full_name_entry_activate (CcUserPanel *self)
+{
+ const gchar *text;
+ ActUser *user;
+
+ user = get_selected_user (self);
+ text = gtk_editable_get_text (GTK_EDITABLE (self->full_name_entry));
+ if (g_strcmp0 (text, act_user_get_real_name (user)) != 0 &&
+ is_valid_name (text)) {
+ act_user_set_real_name (user, text);
+ }
+
+ gtk_toggle_button_set_active (self->full_name_edit_button, FALSE);
+}
+
+static void
+full_name_edit_button_toggled (CcUserPanel *self)
+{
+ if (gtk_stack_get_visible_child (self->full_name_stack) == GTK_WIDGET (self->full_name_label)) {
+ gtk_stack_set_visible_child (self->full_name_stack, GTK_WIDGET (self->full_name_entry));
+
+ gtk_widget_grab_focus (GTK_WIDGET (self->full_name_entry));
+ } else {
+ gtk_stack_set_visible_child (self->full_name_stack, GTK_WIDGET (self->full_name_label));
+
+ full_name_entry_activate (self);
+ }
+}
+
+static gboolean
+full_name_entry_key_press_cb (GtkEventController *controller,
+ guint keyval,
+ guint keycode,
+ GdkModifierType state,
+ CcUserPanel *self)
+{
+ if (keyval == GDK_KEY_Escape) {
+ gtk_editable_set_text (GTK_EDITABLE (self->full_name_entry), act_user_get_real_name (self->selected_user));
+
+ full_name_entry_activate (self);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+account_type_changed (CcUserPanel *self)
+{
+ ActUser *user;
+ gboolean self_selected;
+ gboolean is_admin;
+ ActUserAccountType account_type;
+
+ user = get_selected_user (self);
+ self_selected = act_user_get_uid (user) == geteuid ();
+ is_admin = gtk_switch_get_active (self->account_type_switch);
+
+ account_type = is_admin ? ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR : ACT_USER_ACCOUNT_TYPE_STANDARD;
+ if (account_type != act_user_get_account_type (user)) {
+ act_user_set_account_type (user, account_type);
+
+ if (self_selected)
+ show_restart_notification (self, NULL);
+ }
+}
+
+static void
+dismiss_notification (CcUserPanel *self)
+{
+ gtk_revealer_set_reveal_child (self->notification_revealer, FALSE);
+}
+
+static void
+restart_now (CcUserPanel *self)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+
+ gtk_revealer_set_reveal_child (self->notification_revealer, FALSE);
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+ g_dbus_connection_call (bus,
+ "org.gnome.SessionManager",
+ "/org/gnome/SessionManager",
+ "org.gnome.SessionManager",
+ "Logout",
+ g_variant_new ("(u)", 0),
+ NULL, 0, G_MAXINT,
+ NULL, NULL, NULL);
+}
+
+static void
+show_restart_notification (CcUserPanel *self, const gchar *locale)
+{
+ locale_t current_locale;
+ locale_t new_locale;
+
+ if (locale) {
+ new_locale = newlocale (LC_MESSAGES_MASK, locale, (locale_t) 0);
+ if (new_locale == (locale_t) 0)
+ g_warning ("Failed to create locale %s: %s", locale, g_strerror (errno));
+ else
+ current_locale = uselocale (new_locale);
+ }
+
+ gtk_revealer_set_reveal_child (self->notification_revealer, TRUE);
+
+ if (locale && new_locale != (locale_t) 0) {
+ uselocale (current_locale);
+ freelocale (new_locale);
+ }
+}
+
+static void
+language_response (CcUserPanel *self,
+ gint response_id,
+ GtkDialog *dialog)
+{
+ ActUser *user;
+ const gchar *lang, *account_language;
+
+ if (response_id != GTK_RESPONSE_OK) {
+ gtk_widget_hide (GTK_WIDGET (dialog));
+ return;
+ }
+
+ user = get_selected_user (self);
+ account_language = act_user_get_language (user);
+
+ lang = cc_language_chooser_get_language (CC_LANGUAGE_CHOOSER (dialog));
+ if (lang) {
+ g_autofree gchar *name = NULL;
+ if (g_strcmp0 (lang, account_language) != 0) {
+ act_user_set_language (user, lang);
+ }
+
+ name = gnome_get_language_from_locale (lang, NULL);
+ gtk_label_set_label (self->language_button_label, name);
+ }
+
+ gtk_widget_hide (GTK_WIDGET (dialog));
+}
+
+static void
+change_language (CcUserPanel *self)
+{
+ const gchar *current_language;
+ ActUser *user;
+
+ user = get_selected_user (self);
+ current_language = act_user_get_language (user);
+
+ if (self->language_chooser) {
+ cc_language_chooser_clear_filter (self->language_chooser);
+ cc_language_chooser_set_language (self->language_chooser, NULL);
+ }
+ else {
+ self->language_chooser = cc_language_chooser_new ();
+ gtk_window_set_transient_for (GTK_WINDOW (self->language_chooser),
+ GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (self))));
+
+ g_signal_connect_object (self->language_chooser, "response",
+ G_CALLBACK (language_response), self, G_CONNECT_SWAPPED);
+ }
+
+ if (current_language && *current_language != '\0')
+ cc_language_chooser_set_language (self->language_chooser, current_language);
+ gtk_window_present (GTK_WINDOW (self->language_chooser));
+}
+
+static void
+change_password (CcUserPanel *self)
+{
+ ActUser *user;
+ CcPasswordDialog *dialog;
+ GtkWindow *parent;
+
+ user = get_selected_user (self);
+ dialog = cc_password_dialog_new (user);
+
+ parent = (GtkWindow *) gtk_widget_get_native (GTK_WIDGET (self));
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+static void
+change_fingerprint (CcUserPanel *self)
+{
+ ActUser *user;
+ GtkWindow *parent;
+ CcFingerprintDialog *dialog;
+
+ user = get_selected_user (self);
+ parent = (GtkWindow *) gtk_widget_get_native (GTK_WIDGET (self));
+
+ g_assert (g_strcmp0 (g_get_user_name (), act_user_get_user_name (user)) == 0);
+
+ dialog = cc_fingerprint_dialog_new (self->fingerprint_manager);
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+static void
+show_history (CcUserPanel *self)
+{
+ CcLoginHistoryDialog *dialog;
+ ActUser *user;
+ GtkWindow *parent;
+
+ user = get_selected_user (self);
+ dialog = cc_login_history_dialog_new (user);
+
+ parent = (GtkWindow *) gtk_widget_get_native (GTK_WIDGET (self));
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+#ifdef HAVE_MALCONTENT
+static void
+spawn_malcontent_control (CcUserPanel *self)
+{
+ ActUser *user;
+
+ user = get_selected_user (self);
+
+ /* no-op if the user is administrator */
+ if (act_user_get_account_type (user) != ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR) {
+ const gchar *argv[] = {
+ "malcontent-control",
+#ifdef HAVE_MALCONTENT_0_10
+ "--user",
+ act_user_get_user_name (user),
+#endif /* HAVE_MALCONTENT_0_10 */
+ NULL
+ };
+ g_autoptr(GError) error = NULL;
+ if (!g_spawn_async (NULL, (char **)argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error))
+ g_debug ("Couldn't launch malcontent-control: %s", error->message);
+ } else {
+ g_debug ("Not launching malcontent because selected user is an admin");
+ }
+}
+#endif
+
+static void
+users_loaded (CcUserPanel *self)
+{
+ GtkWidget *dialog;
+
+ if (act_user_manager_no_service (self->um)) {
+ GtkWidget *toplevel;
+
+ toplevel = (GtkWidget *)gtk_widget_get_native (GTK_WIDGET (self));
+ dialog = gtk_message_dialog_new (GTK_WINDOW (toplevel ),
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_OTHER,
+ GTK_BUTTONS_CLOSE,
+ _("Failed to contact the accounts service"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ _("Please make sure that the AccountService is installed and enabled."));
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (gtk_window_destroy),
+ NULL);
+ gtk_widget_show (dialog);
+
+ gtk_stack_set_visible_child (self->stack, self->no_users_box);
+ } else {
+ gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->users_overlay));
+ show_current_user (self);
+ }
+
+ g_signal_connect_object (self->um, "user-changed", G_CALLBACK (user_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->um, "user-is-logged-in-changed", G_CALLBACK (user_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->um, "user-added", G_CALLBACK (user_changed), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->um, "user-removed", G_CALLBACK (user_changed), self, G_CONNECT_SWAPPED);
+}
+
+static void
+add_unlock_tooltip (GtkWidget *widget)
+{
+ gtk_widget_set_tooltip_text (widget,
+ _("This panel must be unlocked to change this setting"));
+}
+
+static void
+remove_unlock_tooltip (GtkWidget *widget)
+{
+ gtk_widget_set_tooltip_text (widget, NULL);
+}
+
+static guint
+get_num_active_admin (ActUserManager *um)
+{
+ GSList *list;
+ GSList *l;
+ guint num_admin = 0;
+
+ list = act_user_manager_list_users (um);
+ for (l = list; l != NULL; l = l->next) {
+ ActUser *u = l->data;
+ if (act_user_get_account_type (u) == ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR && !act_user_get_locked (u)) {
+ num_admin++;
+ }
+ }
+ g_slist_free (list);
+
+ return num_admin;
+}
+
+static gboolean
+would_demote_only_admin (ActUser *user)
+{
+ ActUserManager *um = act_user_manager_get_default ();
+
+ /* Prevent the user from demoting the only admin account.
+ * Returns TRUE when user is an administrator and there is only
+ * one enabled administrator. */
+
+ if (act_user_get_account_type (user) == ACT_USER_ACCOUNT_TYPE_STANDARD ||
+ act_user_get_locked (user))
+ return FALSE;
+
+ if (get_num_active_admin (um) > 1)
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+on_permission_changed (CcUserPanel *self)
+{
+ gboolean is_authorized;
+ gboolean self_selected;
+ ActUser *user;
+
+ is_authorized = g_permission_get_allowed (G_PERMISSION (self->permission));
+
+ gtk_widget_set_sensitive (self->add_user_button, is_authorized);
+
+ user = get_selected_user (self);
+ if (!user) {
+ return;
+ }
+
+ self_selected = act_user_get_uid (user) == geteuid ();
+ gtk_widget_set_sensitive (GTK_WIDGET (self->remove_user_button), is_authorized && !self_selected
+ && !would_demote_only_admin (user));
+ if (is_authorized) {
+ gtk_widget_set_tooltip_text (GTK_WIDGET (self->remove_user_button), _("Delete the selected user account"));
+ }
+ else {
+ gtk_widget_set_tooltip_text (GTK_WIDGET (self->remove_user_button),
+ _("To delete the selected user account,\nclick the * icon first"));
+ }
+
+ if (!act_user_is_local_account (user)) {
+ gtk_widget_set_visible (GTK_WIDGET (self->account_type_row), FALSE);
+ gtk_widget_set_visible (GTK_WIDGET (self->autologin_row), FALSE);
+ } else if (is_authorized && act_user_is_local_account (user)) {
+ if (would_demote_only_admin (user)) {
+ gtk_widget_set_visible (GTK_WIDGET (self->account_type_row), FALSE);
+ } else {
+ gtk_widget_set_visible (GTK_WIDGET (self->account_type_row), TRUE);
+ }
+
+ if (get_autologin_possible (user)) {
+ gtk_widget_set_visible (GTK_WIDGET (self->autologin_row), TRUE);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->autologin_row), TRUE);
+ }
+ }
+ else {
+ gtk_widget_set_visible (GTK_WIDGET (self->account_type_row), FALSE);
+ if (would_demote_only_admin (user)) {
+ gtk_widget_set_visible (GTK_WIDGET (self->account_type_row), FALSE);
+ } else {
+ gtk_widget_set_visible (GTK_WIDGET (self->account_type_row), TRUE);
+ }
+ gtk_widget_set_sensitive (GTK_WIDGET (self->autologin_row), FALSE);
+ add_unlock_tooltip (GTK_WIDGET (self->autologin_row));
+ }
+
+ /* The full name entry: insensitive if remote or not authorized and not self */
+ if (!act_user_is_local_account (user)) {
+ gtk_widget_set_sensitive (GTK_WIDGET (self->full_name_edit_button), FALSE);
+ remove_unlock_tooltip (GTK_WIDGET (self->full_name_stack));
+
+ } else if (is_authorized || self_selected) {
+ gtk_widget_set_sensitive (GTK_WIDGET (self->full_name_edit_button), TRUE);
+ remove_unlock_tooltip (GTK_WIDGET (self->full_name_stack));
+
+ } else {
+ gtk_widget_set_sensitive (GTK_WIDGET (self->full_name_edit_button), FALSE);
+ add_unlock_tooltip (GTK_WIDGET (self->full_name_stack));
+ }
+
+ if (is_authorized || self_selected) {
+ CcFingerprintState fingerprint_state = CC_FINGERPRINT_STATE_NONE;
+
+ if (self->fingerprint_manager)
+ fingerprint_state = cc_fingerprint_manager_get_state (self->fingerprint_manager);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->user_avatar_edit_button), TRUE);
+ remove_unlock_tooltip (GTK_WIDGET (self->user_avatar_edit_button));
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->language_row), TRUE);
+ remove_unlock_tooltip (GTK_WIDGET (self->language_row));
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->password_row), TRUE);
+ remove_unlock_tooltip (GTK_WIDGET (self->password_row));
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->fingerprint_row),
+ fingerprint_state != CC_FINGERPRINT_STATE_UPDATING);
+ remove_unlock_tooltip (GTK_WIDGET (self->fingerprint_row));
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->last_login_row), TRUE);
+ remove_unlock_tooltip (GTK_WIDGET (self->last_login_row));
+ }
+ else {
+ gtk_widget_set_sensitive (GTK_WIDGET (self->user_avatar_edit_button), FALSE);
+ add_unlock_tooltip (GTK_WIDGET (self->user_avatar_edit_button));
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->language_row), FALSE);
+ add_unlock_tooltip (GTK_WIDGET (self->language_row));
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->password_row), FALSE);
+ add_unlock_tooltip (GTK_WIDGET (self->password_row));
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->fingerprint_row), FALSE);
+ add_unlock_tooltip (GTK_WIDGET (self->fingerprint_row));
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->last_login_row), FALSE);
+ add_unlock_tooltip (GTK_WIDGET (self->last_login_row));
+ }
+}
+
+static void
+setup_main_window (CcUserPanel *self)
+{
+ g_autoptr(GError) error = NULL;
+ gboolean loaded;
+
+ self->other_users_model = g_list_store_new (ACT_TYPE_USER);
+ gtk_list_box_bind_model (self->other_users_listbox,
+ G_LIST_MODEL (self->other_users_model),
+ (GtkListBoxCreateWidgetFunc)create_user_row,
+ self,
+ NULL);
+
+ add_unlock_tooltip (GTK_WIDGET (self->user_avatar));
+
+ self->permission = (GPermission *)polkit_permission_new_sync (USER_ACCOUNTS_PERMISSION, NULL, NULL, &error);
+ if (self->permission != NULL) {
+ g_signal_connect_object (self->permission, "notify",
+ G_CALLBACK (on_permission_changed), self, G_CONNECT_SWAPPED);
+ on_permission_changed (self);
+ } else {
+ g_warning ("Cannot create '%s' permission: %s", USER_ACCOUNTS_PERMISSION, error->message);
+ }
+
+#ifdef HAVE_MALCONTENT
+ g_signal_connect_object (self->parental_controls_row, "activated", G_CALLBACK (spawn_malcontent_control), self, G_CONNECT_SWAPPED);
+#endif
+
+ gtk_widget_set_tooltip_text (GTK_WIDGET (self->remove_user_button),
+ _("To delete the selected user account,\nclick the * icon first"));
+
+ self->avatar_chooser = cc_avatar_chooser_new (GTK_WIDGET (self));
+ gtk_menu_button_set_popover (self->user_avatar_edit_button,
+ GTK_WIDGET (self->avatar_chooser));
+
+ g_object_get (self->um, "is-loaded", &loaded, NULL);
+ if (loaded) {
+ users_loaded (self);
+ user_changed (self, NULL);
+ } else {
+ g_signal_connect_object (self->um, "notify::is-loaded", G_CALLBACK (users_loaded), self, G_CONNECT_SWAPPED);
+ }
+}
+
+static GSettings *
+settings_or_null (const gchar *schema)
+{
+ GSettingsSchemaSource *source = NULL;
+ gchar **non_relocatable = NULL;
+ gchar **relocatable = NULL;
+ GSettings *settings = NULL;
+
+ source = g_settings_schema_source_get_default ();
+ if (!source)
+ return NULL;
+
+ g_settings_schema_source_list_schemas (source, TRUE, &non_relocatable, &relocatable);
+
+ if (g_strv_contains ((const gchar * const *)non_relocatable, schema) ||
+ g_strv_contains ((const gchar * const *)relocatable, schema))
+ settings = g_settings_new (schema);
+
+ g_strfreev (non_relocatable);
+ g_strfreev (relocatable);
+ return settings;
+}
+
+static void
+cc_user_panel_constructed (GObject *object)
+{
+ CcUserPanel *self = CC_USER_PANEL (object);
+
+ G_OBJECT_CLASS (cc_user_panel_parent_class)->constructed (object);
+
+ cc_permission_infobar_set_permission (self->permission_infobar, self->permission);
+ cc_permission_infobar_set_title (self->permission_infobar, _("Unlock to Add Users and Change Settings"));
+}
+
+static void
+cc_user_panel_init (CcUserPanel *self)
+{
+ volatile GType type G_GNUC_UNUSED;
+ g_autoptr(GtkCssProvider) provider = NULL;
+
+ g_resources_register (cc_user_accounts_get_resource ());
+
+ /* register types that the builder might need */
+ type = cc_permission_infobar_get_type ();
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->um = act_user_manager_get_default ();
+
+ provider = gtk_css_provider_new ();
+ gtk_css_provider_load_from_resource (provider, "/org/gnome/control-center/user-accounts/user-accounts-dialog.css");
+ gtk_style_context_add_provider_for_display (gdk_display_get_default (),
+ GTK_STYLE_PROVIDER (provider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+ self->login_screen_settings = settings_or_null ("org.gnome.login-screen");
+
+ setup_main_window (self);
+
+ g_signal_connect_swapped (self,
+ "notify::folded",
+ G_CALLBACK (show_or_hide_back_button),
+ self);
+}
+
+static void
+cc_user_panel_dispose (GObject *object)
+{
+ CcUserPanel *self = CC_USER_PANEL (object);
+
+ g_clear_object (&self->selected_user);
+ g_clear_object (&self->pending_show_user);
+ g_clear_object (&self->login_screen_settings);
+ g_clear_pointer ((GtkWindow **)&self->language_chooser, gtk_window_destroy);
+ g_clear_object (&self->permission);
+
+ G_OBJECT_CLASS (cc_user_panel_parent_class)->dispose (object);
+}
+
+static const char *
+cc_user_panel_get_help_uri (CcPanel *panel)
+{
+ return "help:gnome-help/user-accounts";
+}
+
+static void
+cc_user_panel_class_init (CcUserPanelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+
+ object_class->dispose = cc_user_panel_dispose;
+ object_class->constructed = cc_user_panel_constructed;
+
+ panel_class->get_help_uri = cc_user_panel_get_help_uri;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/user-accounts/cc-user-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, account_settings_box);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, account_type_row);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, account_type_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, add_user_button);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, autologin_row);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, autologin_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, back_button);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, fingerprint_state_label);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, fingerprint_row);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, full_name_stack);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, full_name_label);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, full_name_edit_button);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, full_name_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, language_button_label);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, language_row);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, last_login_button_label);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, last_login_row);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, no_users_box);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, notification_revealer);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, other_users);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, other_users_row);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, other_users_listbox);
+#ifdef HAVE_MALCONTENT
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, parental_controls_button_label);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, parental_controls_row);
+#endif
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, password_button_label);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, password_row);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, permission_infobar);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, remove_user_button);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, stack);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, user_avatar);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, user_avatar_edit_button);
+ gtk_widget_class_bind_template_child (widget_class, CcUserPanel, users_overlay);
+
+ gtk_widget_class_bind_template_callback (widget_class, account_type_changed);
+ gtk_widget_class_bind_template_callback (widget_class, add_user);
+ gtk_widget_class_bind_template_callback (widget_class, autologin_changed);
+ gtk_widget_class_bind_template_callback (widget_class, change_fingerprint);
+ gtk_widget_class_bind_template_callback (widget_class, change_language);
+ gtk_widget_class_bind_template_callback (widget_class, full_name_edit_button_toggled);
+ gtk_widget_class_bind_template_callback (widget_class, full_name_entry_activate);
+ gtk_widget_class_bind_template_callback (widget_class, full_name_entry_key_press_cb);
+ gtk_widget_class_bind_template_callback (widget_class, change_password);
+ gtk_widget_class_bind_template_callback (widget_class, delete_user);
+ gtk_widget_class_bind_template_callback (widget_class, dismiss_notification);
+ gtk_widget_class_bind_template_callback (widget_class, restart_now);
+ gtk_widget_class_bind_template_callback (widget_class, set_selected_user);
+ gtk_widget_class_bind_template_callback (widget_class, on_back_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, show_history);
+}
diff --git a/panels/user-accounts/cc-user-panel.h b/panels/user-accounts/cc-user-panel.h
new file mode 100644
index 0000000..6f0aa5a
--- /dev/null
+++ b/panels/user-accounts/cc-user-panel.h
@@ -0,0 +1,29 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2009-2010 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (CcUserPanel, cc_user_panel, CC, USER_PANEL, CcPanel)
+
+G_END_DECLS
diff --git a/panels/user-accounts/cc-user-panel.ui b/panels/user-accounts/cc-user-panel.ui
new file mode 100644
index 0000000..3f0362b
--- /dev/null
+++ b/panels/user-accounts/cc-user-panel.ui
@@ -0,0 +1,407 @@
+<interface>
+ <object class="GtkListStore" id="shortname-model">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkListStore" id="language-model">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ <!-- column-name gchararray1 -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <template class="CcUserPanel" parent="CcPanel">
+ <child type="titlebar">
+ <object class="AdwHeaderBar">
+ <property name="show-end-title-buttons">True</property>
+ <property name="show-start-title-buttons">False</property>
+ <property name="title-widget">
+ <object class="AdwWindowTitle">
+ <property name="title" translatable="yes">Users</property>
+ </object>
+ </property>
+ <child type="start">
+ <object class="GtkButton" id="back_button">
+ <property name="visible">False</property>
+ <property name="icon-name">go-previous-symbolic</property>
+ <accessibility>
+ <property name="label" translatable="yes">Back</property>
+ </accessibility>
+ <signal name="clicked" handler="on_back_button_clicked_cb" object="CcUserPanel" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="content">
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="CcPermissionInfobar" id="permission_infobar"/>
+ </child>
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="visible-child">no_users_box</property>
+ <child>
+ <object class="GtkOverlay" id="users_overlay">
+ <child type="overlay">
+ <object class="GtkRevealer" id="notification_revealer">
+ <property name="halign">GTK_ALIGN_CENTER</property>
+ <property name="valign">GTK_ALIGN_START</property>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <style>
+ <class name="app-notification"/>
+ </style>
+ <child>
+ <object class="GtkLabel">
+ <property name="wrap">True</property>
+ <property name="max_width_chars">30</property>
+ <property name="label" translatable="yes">Your session needs to be restarted for changes to take effect</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="can_focus">True</property>
+ <property name="valign">GTK_ALIGN_CENTER</property>
+ <property name="label" translatable="yes">Restart Now</property>
+ <signal name="clicked" handler="restart_now" object="CcUserPanel" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="dismiss_button">
+ <property name="valign">GTK_ALIGN_CENTER</property>
+ <property name="icon_name">window-close-symbolic</property>
+ <accessibility>
+ <property name="label" translatable="yes">Close</property>
+ </accessibility>
+ <signal name="clicked" handler="dismiss_notification" object="CcUserPanel" swapped="yes"/>
+ <style>
+ <class name="flat"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="GtkOverlay">
+ <property name="halign">center</property>
+ <child>
+ <object class="AdwAvatar" id="user_avatar">
+ <property name="show-initials">True</property>
+ <property name="size">120</property>
+ <property name="halign">center</property>
+ </object>
+ </child>
+ <child type="overlay">
+ <object class="AdwBin">
+ <style>
+ <class name="cutout-button"/>
+ </style>
+ <property name="halign">end</property>
+ <property name="valign">end</property>
+ <child>
+ <object class="GtkMenuButton" id="user_avatar_edit_button">
+ <property name="sensitive">False</property>
+ <property name="icon-name">document-edit-symbolic</property>
+ <property name="popover">
+ <object class="CcAvatarChooser" id="avatar_chooser"/>
+ </property>
+ <accessibility>
+ <property name="label" translatable="yes">Edit avatar</property>
+ </accessibility>
+ <style>
+ <class name="circular"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup" id="authentication_and_login_box">
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Name</property>
+ <child>
+ <object class="GtkStack" id="full_name_stack">
+ <property name="hhomogeneous">False</property>
+ <child>
+ <object class="GtkLabel" id="full_name_label">
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="full_name_entry">
+ <property name="max-length">255</property>
+ <property name="width-chars">18</property>
+ <property name="max-width-chars">30</property>
+ <property name="valign">GTK_ALIGN_CENTER</property>
+ <accessibility>
+ <property name="label" translatable="yes">Full name</property>
+ </accessibility>
+ <signal name="activate" handler="full_name_entry_activate" object="CcUserPanel" swapped="yes"/>
+ <child>
+ <object class="GtkEventControllerKey">
+ <property name="propagation-phase">capture</property>
+ <signal name="key-pressed" handler="full_name_entry_key_press_cb" object="CcUserPanel" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="full_name_edit_button">
+ <signal name="toggled" handler="full_name_edit_button_toggled" object="CcUserPanel" swapped="yes"/>
+ <property name="icon-name">document-edit-symbolic</property>
+ <property name="valign">GTK_ALIGN_CENTER</property>
+ <accessibility>
+ <property name="label" translatable="yes">Edit</property>
+ </accessibility>
+ <style>
+ <class name="flat"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="password_row">
+ <property name="title" translatable="yes">_Password</property>
+ <property name="use_underline">True</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="change_password" object="CcUserPanel" swapped="yes"/>
+ <child>
+ <object class="GtkLabel" id="password_button_label"/>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">go-next-symbolic</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="fingerprint_row">
+ <property name="visible">True</property> <!-- FIXME -->
+ <property name="title" translatable="yes">_Fingerprint Login</property>
+ <property name="use_underline">True</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="change_fingerprint" object="CcUserPanel" swapped="yes"/>
+ <child>
+ <object class="GtkLabel" id="fingerprint_state_label">
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">go-next-symbolic</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="autologin_row">
+ <property name="title" translatable="yes">A_utomatic Login</property>
+ <property name="use_underline">True</property>
+ <property name="activatable_widget">autologin_switch</property>
+ <child>
+ <object class="GtkSwitch" id="autologin_switch">
+ <property name="valign">center</property>
+ <signal name="notify::active" handler="autologin_changed" object="CcUserPanel" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="last_login_row">
+ <property name="title" translatable="yes">Account Activity</property>
+ <property name="activatable">True</property>
+ <property name="use_underline">True</property>
+ <signal name="activated" handler="show_history" object="CcUserPanel" swapped="yes"/>
+ <child>
+ <object class="GtkLabel" id="last_login_button_label">
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">go-next-symbolic</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup" id="account_settings_box">
+ <child>
+ <object class="AdwActionRow" id="account_type_row">
+ <property name="title" translatable="yes">_Administrator</property>
+ <property name="subtitle" translatable="yes">Administrators can add and remove other users, and can change settings for all users.</property>
+ <property name="subtitle-lines">0</property>
+ <property name="use_underline">True</property>
+ <property name="activatable-widget">account_type_switch</property>
+ <child>
+ <object class="GtkSwitch" id="account_type_switch">
+ <property name="valign">center</property>
+ <signal name="notify::active" handler="account_type_changed" object="CcUserPanel" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow" id="parental_controls_row">
+ <property name="visible">False</property>
+ <property name="title" translatable="yes">_Parental Controls</property>
+ <property name="subtitle" translatable="yes">Open the Parental Controls application.</property>
+ <property name="subtitle-lines">0</property>
+ <property name="use_underline">True</property>
+ <property name="activatable">True</property>
+ <child>
+ <object class="GtkLabel" id="parental_controls_button_label">
+ <property name="valign">0.5</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage" id="parental_control_go_next">
+ <property name="icon-name">go-next-symbolic</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow" id="language_row">
+ <property name="title" translatable="yes">_Language</property>
+ <property name="use_underline">True</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="change_language" object="CcUserPanel" swapped="yes"/>
+ <child>
+ <object class="GtkLabel" id="language_button_label">
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">go-next-symbolic</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="GtkButton" id="remove_user_button">
+ <property name="visible">False</property>
+ <property name="label" translatable="yes">Remove User…</property>
+ <signal name="clicked" handler="delete_user" object="CcUserPanel" swapped="yes"/>
+ <style>
+ <class name="destructive-action"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup" id="other_users">
+ <property name="visible">False</property>
+ <property name="title" translatable="yes">Other Users</property>
+ <child>
+ <object class="AdwPreferencesRow" id="other_users_row">
+ <child>
+ <object class="GtkListBox" id="other_users_listbox">
+ <property name="selection-mode">none</property>
+ <signal name="row-activated" handler="set_selected_user" object="CcUserPanel" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="add_user_button">
+ <property name="title" translatable="yes">Add User…</property>
+ <property name="icon-name">list-add-symbolic</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="add_user" object="CcUserPanel" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="no_users_box">
+ <property name="orientation">GTK_ORIENTATION_VERTICAL</property>
+ <property name="valign">GTK_ALIGN_CENTER</property>
+ <property name="spacing">12</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <child>
+ <object class="GtkImage">
+ <property name="icon_name">avatar-default-symbolic</property>
+ <property name="pixel_size">192</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes" comments="Translators: This is the empty state page label which states that there are no users to show in the panel.">No Users Found</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ <attribute name="scale" value="1.6"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Unlock to add a user account.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/user-accounts/data/cc-fingerprint-dialog.css b/panels/user-accounts/data/cc-fingerprint-dialog.css
new file mode 100644
index 0000000..800d658
--- /dev/null
+++ b/panels/user-accounts/data/cc-fingerprint-dialog.css
@@ -0,0 +1,83 @@
+.fingerprint-icon {
+ padding: 3px;
+}
+
+.fingerprint-icon > button,
+.fingerprint-icon > image {
+ padding: 15px;
+ min-width: 32px;
+ min-height: 32px;
+ border-radius: 64px;
+ border: 1px solid @borders;
+ background-color: @theme_base_color;
+ color: @insensitive_fg_color;
+}
+
+.fingerprint-print-add image:not(:disabled):not(:backdrop),
+.fingerprint-print-add button:not(:disabled):not(:backdrop) {
+ color: @theme_fg_color;
+}
+
+.fingerprint-icon.enroll-status image {
+ outline-color: @theme_selected_bg_color;
+ outline-offset: 0px;
+ outline-width: 4px;
+}
+
+.fingerprint-icon.enroll-status image:backdrop {
+ outline-color: @theme_unfocused_selected_bg_color;
+}
+
+.fingerprint-icon.enroll-status {
+ font-weight: bold;
+}
+
+.fingerprint-icon.enroll-status.completed image {
+ outline-color: @success_color;
+}
+
+.fingerprint-icon.enroll-status.warning image {
+ outline-color: @warning_color;
+}
+
+.fingerprint-icon.enroll-status.error image {
+ outline-color: @error_color;
+ /* Given we don't have an error image, we can just recolorize the warning one */
+ -gtk-icon-palette: warning @error_color;
+}
+
+.fingerprint-icon.enroll-status.success image:not(:backdrop) {
+ color: @theme_selected_bg_color;
+}
+
+.fingerprint-icon.enroll-status.warning image:not(:backdrop),
+.fingerprint-icon.enroll-status.warning label:not(:backdrop) {
+ color: @warning_color;
+}
+
+.fingerprint-icon.enroll-status.error image:not(:backdrop),
+.fingerprint-icon.enroll-status.error label:not(:backdrop) {
+ color: @error_color;
+}
+
+@keyframes wiggle {
+ /* Unfortunately we can't use translation or xalign, so here's the workaround */
+ 0% { padding-left: 0; padding-right: 0; }
+ 10% { padding-left: 0; padding-right: 2px; }
+ 20% { padding-left: 4px; padding-right: 0; }
+ 30% { padding-left: 0; padding-right: 8px; }
+ 40% { padding-left: 8px; padding-right: 0; }
+ 50% { padding-left: 0; padding-right: 8px; }
+ 60% { padding-left: 8px; padding-right: 0; }
+ 70% { padding-left: 0; padding-right: 8px; }
+ 80% { padding-left: 4px; padding-right: 0; }
+ 90% { padding-left: 0; padding-right: 2px; }
+ 100% { padding-left: 0; padding-right: 0; }
+}
+
+.fingerprint-icon.enroll-status.retry label {
+ animation-name: wiggle;
+ animation-duration: 850ms;
+ animation-timing-function: ease-in;
+ animation-iteration-count: 1;
+}
diff --git a/panels/user-accounts/data/faces/bicycle.jpg b/panels/user-accounts/data/faces/bicycle.jpg
new file mode 100644
index 0000000..c598251
--- /dev/null
+++ b/panels/user-accounts/data/faces/bicycle.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/book.jpg b/panels/user-accounts/data/faces/book.jpg
new file mode 100644
index 0000000..abda4b7
--- /dev/null
+++ b/panels/user-accounts/data/faces/book.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/calculator.jpg b/panels/user-accounts/data/faces/calculator.jpg
new file mode 100644
index 0000000..43ece1e
--- /dev/null
+++ b/panels/user-accounts/data/faces/calculator.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/cat.jpg b/panels/user-accounts/data/faces/cat.jpg
new file mode 100644
index 0000000..99275b2
--- /dev/null
+++ b/panels/user-accounts/data/faces/cat.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/coffee2.jpg b/panels/user-accounts/data/faces/coffee2.jpg
new file mode 100644
index 0000000..4be830d
--- /dev/null
+++ b/panels/user-accounts/data/faces/coffee2.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/flower2.jpg b/panels/user-accounts/data/faces/flower2.jpg
new file mode 100644
index 0000000..b77e717
--- /dev/null
+++ b/panels/user-accounts/data/faces/flower2.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/gamepad.jpg b/panels/user-accounts/data/faces/gamepad.jpg
new file mode 100644
index 0000000..9843758
--- /dev/null
+++ b/panels/user-accounts/data/faces/gamepad.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/guitar2.jpg b/panels/user-accounts/data/faces/guitar2.jpg
new file mode 100644
index 0000000..f1ad374
--- /dev/null
+++ b/panels/user-accounts/data/faces/guitar2.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/headphones.jpg b/panels/user-accounts/data/faces/headphones.jpg
new file mode 100644
index 0000000..2ad9175
--- /dev/null
+++ b/panels/user-accounts/data/faces/headphones.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/hummingbird.jpg b/panels/user-accounts/data/faces/hummingbird.jpg
new file mode 100644
index 0000000..d06a3cf
--- /dev/null
+++ b/panels/user-accounts/data/faces/hummingbird.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/legacy/astronaut.jpg b/panels/user-accounts/data/faces/legacy/astronaut.jpg
new file mode 100644
index 0000000..4b79f0e
--- /dev/null
+++ b/panels/user-accounts/data/faces/legacy/astronaut.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/legacy/baseball.png b/panels/user-accounts/data/faces/legacy/baseball.png
new file mode 100644
index 0000000..0d6dfdb
--- /dev/null
+++ b/panels/user-accounts/data/faces/legacy/baseball.png
Binary files differ
diff --git a/panels/user-accounts/data/faces/legacy/butterfly.png b/panels/user-accounts/data/faces/legacy/butterfly.png
new file mode 100644
index 0000000..66b813c
--- /dev/null
+++ b/panels/user-accounts/data/faces/legacy/butterfly.png
Binary files differ
diff --git a/panels/user-accounts/data/faces/legacy/cat-eye.jpg b/panels/user-accounts/data/faces/legacy/cat-eye.jpg
new file mode 100644
index 0000000..c818bd5
--- /dev/null
+++ b/panels/user-accounts/data/faces/legacy/cat-eye.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/legacy/chess.jpg b/panels/user-accounts/data/faces/legacy/chess.jpg
new file mode 100644
index 0000000..7abb8a4
--- /dev/null
+++ b/panels/user-accounts/data/faces/legacy/chess.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/legacy/coffee.jpg b/panels/user-accounts/data/faces/legacy/coffee.jpg
new file mode 100644
index 0000000..46e8fc5
--- /dev/null
+++ b/panels/user-accounts/data/faces/legacy/coffee.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/legacy/dice.jpg b/panels/user-accounts/data/faces/legacy/dice.jpg
new file mode 100644
index 0000000..641b124
--- /dev/null
+++ b/panels/user-accounts/data/faces/legacy/dice.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/legacy/energy-arc.jpg b/panels/user-accounts/data/faces/legacy/energy-arc.jpg
new file mode 100644
index 0000000..9f4c892
--- /dev/null
+++ b/panels/user-accounts/data/faces/legacy/energy-arc.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/legacy/fish.jpg b/panels/user-accounts/data/faces/legacy/fish.jpg
new file mode 100644
index 0000000..fc363d6
--- /dev/null
+++ b/panels/user-accounts/data/faces/legacy/fish.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/legacy/flake.jpg b/panels/user-accounts/data/faces/legacy/flake.jpg
new file mode 100644
index 0000000..5546d7e
--- /dev/null
+++ b/panels/user-accounts/data/faces/legacy/flake.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/legacy/flower.jpg b/panels/user-accounts/data/faces/legacy/flower.jpg
new file mode 100644
index 0000000..3e41ba4
--- /dev/null
+++ b/panels/user-accounts/data/faces/legacy/flower.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/legacy/grapes.jpg b/panels/user-accounts/data/faces/legacy/grapes.jpg
new file mode 100644
index 0000000..3d31daf
--- /dev/null
+++ b/panels/user-accounts/data/faces/legacy/grapes.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/legacy/guitar.jpg b/panels/user-accounts/data/faces/legacy/guitar.jpg
new file mode 100644
index 0000000..9e8834f
--- /dev/null
+++ b/panels/user-accounts/data/faces/legacy/guitar.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/legacy/launch.jpg b/panels/user-accounts/data/faces/legacy/launch.jpg
new file mode 100644
index 0000000..7c7bf43
--- /dev/null
+++ b/panels/user-accounts/data/faces/legacy/launch.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/legacy/leaf.jpg b/panels/user-accounts/data/faces/legacy/leaf.jpg
new file mode 100644
index 0000000..5354103
--- /dev/null
+++ b/panels/user-accounts/data/faces/legacy/leaf.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/legacy/lightning.jpg b/panels/user-accounts/data/faces/legacy/lightning.jpg
new file mode 100644
index 0000000..736ccd5
--- /dev/null
+++ b/panels/user-accounts/data/faces/legacy/lightning.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/legacy/penguin.jpg b/panels/user-accounts/data/faces/legacy/penguin.jpg
new file mode 100644
index 0000000..2a8dfd6
--- /dev/null
+++ b/panels/user-accounts/data/faces/legacy/penguin.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/legacy/puppy.jpg b/panels/user-accounts/data/faces/legacy/puppy.jpg
new file mode 100644
index 0000000..ab55a8b
--- /dev/null
+++ b/panels/user-accounts/data/faces/legacy/puppy.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/legacy/sky.jpg b/panels/user-accounts/data/faces/legacy/sky.jpg
new file mode 100644
index 0000000..841f90e
--- /dev/null
+++ b/panels/user-accounts/data/faces/legacy/sky.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/legacy/soccerball.png b/panels/user-accounts/data/faces/legacy/soccerball.png
new file mode 100644
index 0000000..56588a9
--- /dev/null
+++ b/panels/user-accounts/data/faces/legacy/soccerball.png
Binary files differ
diff --git a/panels/user-accounts/data/faces/legacy/sunflower.jpg b/panels/user-accounts/data/faces/legacy/sunflower.jpg
new file mode 100644
index 0000000..6102b8b
--- /dev/null
+++ b/panels/user-accounts/data/faces/legacy/sunflower.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/legacy/sunset.jpg b/panels/user-accounts/data/faces/legacy/sunset.jpg
new file mode 100644
index 0000000..48b6223
--- /dev/null
+++ b/panels/user-accounts/data/faces/legacy/sunset.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/legacy/tennis-ball.png b/panels/user-accounts/data/faces/legacy/tennis-ball.png
new file mode 100644
index 0000000..a1beb50
--- /dev/null
+++ b/panels/user-accounts/data/faces/legacy/tennis-ball.png
Binary files differ
diff --git a/panels/user-accounts/data/faces/legacy/yellow-rose.jpg b/panels/user-accounts/data/faces/legacy/yellow-rose.jpg
new file mode 100644
index 0000000..7f1de96
--- /dev/null
+++ b/panels/user-accounts/data/faces/legacy/yellow-rose.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/mountain.jpg b/panels/user-accounts/data/faces/mountain.jpg
new file mode 100644
index 0000000..8425e0d
--- /dev/null
+++ b/panels/user-accounts/data/faces/mountain.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/plane.jpg b/panels/user-accounts/data/faces/plane.jpg
new file mode 100644
index 0000000..a0c4506
--- /dev/null
+++ b/panels/user-accounts/data/faces/plane.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/surfer.jpg b/panels/user-accounts/data/faces/surfer.jpg
new file mode 100644
index 0000000..47f19b0
--- /dev/null
+++ b/panels/user-accounts/data/faces/surfer.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/tomatoes.jpg b/panels/user-accounts/data/faces/tomatoes.jpg
new file mode 100644
index 0000000..ebdb6ba
--- /dev/null
+++ b/panels/user-accounts/data/faces/tomatoes.jpg
Binary files differ
diff --git a/panels/user-accounts/data/faces/tree.jpg b/panels/user-accounts/data/faces/tree.jpg
new file mode 100644
index 0000000..8a619d3
--- /dev/null
+++ b/panels/user-accounts/data/faces/tree.jpg
Binary files differ
diff --git a/panels/user-accounts/data/gnome-user-accounts-panel.desktop.in.in b/panels/user-accounts/data/gnome-user-accounts-panel.desktop.in.in
new file mode 100644
index 0000000..b91b37f
--- /dev/null
+++ b/panels/user-accounts/data/gnome-user-accounts-panel.desktop.in.in
@@ -0,0 +1,19 @@
+[Desktop Entry]
+Name=Users
+Comment=Add or remove users and change your password
+Exec=gnome-control-center user-accounts
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-users-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;X-GNOME-Settings-Panel;X-GNOME-DetailsSettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=user-accounts
+X-GNOME-Bugzilla-Version=@VERSION@
+X-GNOME-Settings-Panel=user-accounts
+# Translators: Search terms to find the Users panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=Login;Name;Fingerprint;Avatar;Logo;Face;Password;Parental Controls;Screen Time;App Restrictions;Web Restrictions;Usage;Usage Limit;Kid;Child;
diff --git a/panels/user-accounts/data/icons/fingerprint-detection-complete-symbolic.svg b/panels/user-accounts/data/icons/fingerprint-detection-complete-symbolic.svg
new file mode 100644
index 0000000..d7f6ce4
--- /dev/null
+++ b/panels/user-accounts/data/icons/fingerprint-detection-complete-symbolic.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 8.467 8.467"><path style="line-height:normal;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;text-orientation:mixed;white-space:normal;shape-padding:0;isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1" d="M16.133.99a12.982 12.982 0 0 0-6.477 1.653c-1.173.646-.194 2.404.973 1.748A10.999 10.999 0 0 1 27 13.994v2c0 1.334 2 1.334 2 0v-2c0-.033-.001-.066-.004-.1a13.007 13.007 0 0 0-6.418-11.119A12.995 12.995 0 0 0 16.133.99ZM5.762 6.64a1 1 0 0 0-.801.485 12.999 12.999 0 0 0-1.957 6.77 1 1 0 0 0-.004.1v10.128c0 1.334 2 1.334 2 0V13.994c0-2.055.575-4.07 1.66-5.814a1 1 0 0 0-.898-1.54ZM16 6.993c-3.813 0-6.928 3.082-6.994 6.881a1 1 0 0 0-.006.121v2c0 1.333 2 1.333 2 0v-2a4.986 4.986 0 0 1 5-5.002c2.773 0 5 2.228 5 5.002v8.131a3 3 0 0 1 1.123.752l.877.877v-9.76a.994.994 0 0 0-.006-.115c-.062-3.802-3.179-6.887-6.994-6.887Zm-.016 5.987A1 1 0 0 0 15 13.994v10.004s0 1.094.27 2.445c.27 1.351.787 3.028 2.023 4.264.942.982 2.395-.471 1.414-1.414-.69-.69-1.139-1.835-1.39-2.898l-.003-.002a3 3 0 0 1-.302-2.14 17.252 17.252 0 0 0-.012-.255V13.994a1 1 0 0 0-1.016-1.015zm-6 8.001A1 1 0 0 0 9 21.996v6.002c0 1.334 2 1.334 2 0v-6.002a1 1 0 0 0-1.016-1.016zm20.998.006a1 1 0 0 0-.687.303l-6.297 6.29-3.291-3.294a1 1 0 1 0-1.41 1.418l4.701 4.703 7.707-7.707a1 1 0 0 0-.723-1.713z" transform="scale(.26458)" class="success" color="#000" font-weight="400" font-family="sans-serif" overflow="visible" fill="#33d17a"/></svg> \ No newline at end of file
diff --git a/panels/user-accounts/data/icons/fingerprint-detection-symbolic.svg b/panels/user-accounts/data/icons/fingerprint-detection-symbolic.svg
new file mode 100644
index 0000000..d91ce24
--- /dev/null
+++ b/panels/user-accounts/data/icons/fingerprint-detection-symbolic.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 8.467 8.467"><path d="M4.268 288.795a3.435 3.435 0 0 0-1.713.438.265.265 0 1 0 .257.462 2.91 2.91 0 0 1 4.332 2.541v.53a.265.265 0 1 0 .529 0v-.53a.265.265 0 0 0-.001-.026 3.442 3.442 0 0 0-3.404-3.415zm-2.744 1.495a.265.265 0 0 0-.211.128 3.44 3.44 0 0 0-.518 1.792.265.265 0 0 0-.001.026v2.68a.265.265 0 0 0 .529 0v-2.68c0-.544.152-1.077.44-1.538a.265.265 0 0 0-.239-.408zm2.71.093a1.856 1.856 0 0 0-1.851 1.82.265.265 0 0 0-.002.033v.529a.265.265 0 1 0 .53 0v-.53c0-.733.589-1.323 1.322-1.323.734 0 1.323.59 1.323 1.324v2.647s.002.182.08.414c.077.232.231.535.527.831a.265.265 0 1 0 .374-.374 1.595 1.595 0 0 1-.399-.624c-.055-.165-.053-.247-.053-.247v-2.647a.265.265 0 0 0-.001-.03 1.856 1.856 0 0 0-1.85-1.823zm-.005 1.584a.265.265 0 0 0-.26.269v2.647s0 .29.071.647c.072.357.208.8.535 1.128a.265.265 0 1 0 .375-.374c-.203-.203-.33-.553-.391-.858-.06-.304-.061-.543-.061-.543v-2.647a.265.265 0 0 0-.269-.269zm-1.587 2.117a.265.265 0 0 0-.26.27v1.587a.265.265 0 1 0 .528 0v-1.588a.265.265 0 0 0-.268-.269zm4.762 0a.265.265 0 0 0-.26.268v.53a.265.265 0 1 0 .529 0v-.53a.265.265 0 0 0-.269-.268z" style="line-height:normal;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;text-orientation:mixed;white-space:normal;shape-padding:0;isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1" color="#000" font-weight="400" font-family="sans-serif" overflow="visible" fill="#3d3846" transform="translate(0 -288.533)"/></svg> \ No newline at end of file
diff --git a/panels/user-accounts/data/icons/fingerprint-detection-warning-symbolic.svg b/panels/user-accounts/data/icons/fingerprint-detection-warning-symbolic.svg
new file mode 100644
index 0000000..4c6e281
--- /dev/null
+++ b/panels/user-accounts/data/icons/fingerprint-detection-warning-symbolic.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 8.467 8.467"><path overflow="visible" font-weight="400" d="M4.268.262a3.435 3.435 0 0 0-1.713.437.265.265 0 1 0 .257.463 2.91 2.91 0 0 1 4.332 2.54v.53a.265.265 0 1 0 .529 0v-.53a.265.265 0 0 0-.001-.026A3.441 3.441 0 0 0 4.268.262ZM1.524 1.757a.265.265 0 0 0-.211.128 3.44 3.44 0 0 0-.518 1.791.265.265 0 0 0-.001.027v2.68a.265.265 0 0 0 .529 0v-2.68c0-.544.152-1.077.44-1.539a.265.265 0 0 0-.239-.407Zm2.71.093a1.856 1.856 0 0 0-1.851 1.82.265.265 0 0 0-.002.033v.529a.265.265 0 0 0 .53 0v-.53c0-.733.589-1.323 1.322-1.323.734 0 1.323.59 1.323 1.324v.708a1.05 1.05 0 0 1 .53-.385v-.323a.265.265 0 0 0-.002-.03 1.856 1.856 0 0 0-1.85-1.823Zm-.005 1.584a.265.265 0 0 0-.26.269v2.646s0 .29.071.647c.009.044.022.092.033.138l.425-.787V3.703a.265.265 0 0 0-.269-.27Zm2.096 1.089c-.139-.008-.275.075-.38.256L4.29 7.846c-.141.255.013.62.29.62h3.48c.26 0 .504-.306.323-.62l-1.67-3.05c-.106-.171-.25-.266-.389-.273ZM2.642 5.55a.265.265 0 0 0-.26.269v1.588a.265.265 0 1 0 .528 0V5.82a.265.265 0 0 0-.268-.269Zm3.7.013a.275.275 0 0 1 .272.273V6.88a.272.272 0 0 1-.264.265.272.272 0 0 1-.265-.265V5.837a.273.273 0 0 1 .215-.264.195.195 0 0 1 .042-.008zm.008 1.844a.265.265 0 1 1 0 .53.265.265 0 0 1 0-.53z" style="line-height:normal;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;text-orientation:mixed;white-space:normal;shape-padding:0;isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1" class="warning" color="#000" font-family="sans-serif" fill="#ff7800"/></svg> \ No newline at end of file
diff --git a/panels/user-accounts/data/icons/left-index-finger.svg b/panels/user-accounts/data/icons/left-index-finger.svg
new file mode 100644
index 0000000..7a79add
--- /dev/null
+++ b/panels/user-accounts/data/icons/left-index-finger.svg
@@ -0,0 +1 @@
+<svg version="1.0" width="48" height="48" viewBox="0 0 40.425 46.214" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="a"><stop offset="0" style="stop-color:#fff;stop-opacity:1"/><stop style="stop-color:#27dc16;stop-opacity:1" offset="1"/></linearGradient></defs><circle style="fill:#8ff0a4;stroke:#2ec27e;stroke-width:.962791;stroke-miterlimit:4;stroke-dasharray:none;stop-color:#000" cx="26.461" cy="9.203" r="5.783"/><g style="stroke-width:1.06881"><path style="fill:#241f31;stroke:none;stroke-width:1.06881px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M437.016 124.536h.029a14.986 14.986 45 0 1 14.985 14.986v54.153a4.504 4.504 45 0 0 4.504 4.504 4.216 4.216 130.946 0 0 3.908-4.504v-63.748a14 14 135 0 1 14-14 13.257 13.257 48.306 0 1 12.47 14v63.897a4.355 4.355 45 0 0 4.355 4.355 4.149 4.149 132.08 0 0 3.932-4.355v-63.897a14 14 135 0 1 14-14 13.11 13.11 49.036 0 1 12.155 14v64.019a4.233 4.233 45 0 0 4.233 4.233h.202a4.233 4.233 135 0 0 4.233-4.233v-40.661a14 14 135 0 1 14-14 13.005 13.005 49.527 0 1 11.946 14L555.833 260a30.038 30.038 135.036 0 1-30.039 30H450a48.284 48.284 22.5 0 1-34.142-14.142l-37.801-37.801a15.702 15.702 86.658 0 1-1.217-20.839 14.154 14.154 173.662 0 1 19.896-2.21l21.76 17.2a2.181 2.181 154.16 0 0 3.534-1.712v-90.974a14.986 14.986 135 0 1 14.986-14.986z" transform="matrix(-.22259 0 0 .22259 123.725 -22.001)"/><path style="fill:#000;fill-opacity:.470966;stroke:none;stroke-width:1.06881px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M374.444 222.919c-1.992 5.044.075 11.54 3.91 15.375l37.503 37.563A48.284 48.284 0 0 0 450 290h75.794c16.569 0 30-13.431 30-30v-10c0 16.569-13.431 30-30 30H450a48.284 48.284 0 0 1-34.143-14.143l-38.377-38.313a13.61 13.61 0 0 1-3.036-4.625z" transform="matrix(-.22259 0 0 .22259 123.725 -22.001)"/></g></svg> \ No newline at end of file
diff --git a/panels/user-accounts/data/icons/left-little-finger.svg b/panels/user-accounts/data/icons/left-little-finger.svg
new file mode 100644
index 0000000..106e8ea
--- /dev/null
+++ b/panels/user-accounts/data/icons/left-little-finger.svg
@@ -0,0 +1 @@
+<svg version="1.0" width="48" height="48" viewBox="0 0 40.425 46.214" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="a"><stop offset="0" style="stop-color:#fff;stop-opacity:1"/><stop style="stop-color:#27dc16;stop-opacity:1" offset="1"/></linearGradient></defs><circle style="fill:#8ff0a4;stroke:#2ec27e;stroke-width:.962792;stroke-miterlimit:4;stroke-dasharray:none;stop-color:#000" cx="2.853" cy="11.617" r="5.207"/><g style="stroke-width:1.06881"><path style="fill:#241f31;stroke:none;stroke-width:1.06881px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M437.016 124.536h.029a14.986 14.986 45 0 1 14.985 14.986v54.153a4.504 4.504 45 0 0 4.504 4.504 4.216 4.216 130.946 0 0 3.908-4.504v-63.748a14 14 135 0 1 14-14 13.257 13.257 48.306 0 1 12.47 14v63.897a4.355 4.355 45 0 0 4.355 4.355 4.149 4.149 132.08 0 0 3.932-4.355v-63.897a14 14 135 0 1 14-14 13.11 13.11 49.036 0 1 12.155 14v64.019a4.233 4.233 45 0 0 4.233 4.233h.202a4.233 4.233 135 0 0 4.233-4.233v-40.661a14 14 135 0 1 14-14 13.005 13.005 49.527 0 1 11.946 14L555.833 260a30.038 30.038 135.036 0 1-30.039 30H450a48.284 48.284 22.5 0 1-34.142-14.142l-37.801-37.801a15.702 15.702 86.658 0 1-1.217-20.839 14.154 14.154 173.662 0 1 19.896-2.21l21.76 17.2a2.181 2.181 154.16 0 0 3.534-1.712v-90.974a14.986 14.986 135 0 1 14.986-14.986z" transform="matrix(-.22259 0 0 .22259 123.725 -22.001)"/><path style="fill:#000;fill-opacity:.470966;stroke:none;stroke-width:1.06881px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M374.444 222.919c-1.992 5.044.075 11.54 3.91 15.375l37.503 37.563A48.284 48.284 0 0 0 450 290h75.794c16.569 0 30-13.431 30-30v-10c0 16.569-13.431 30-30 30H450a48.284 48.284 0 0 1-34.143-14.143l-38.377-38.313a13.61 13.61 0 0 1-3.036-4.625z" transform="matrix(-.22259 0 0 .22259 123.725 -22.001)"/></g></svg> \ No newline at end of file
diff --git a/panels/user-accounts/data/icons/left-middle-finger.svg b/panels/user-accounts/data/icons/left-middle-finger.svg
new file mode 100644
index 0000000..5ae2b1c
--- /dev/null
+++ b/panels/user-accounts/data/icons/left-middle-finger.svg
@@ -0,0 +1 @@
+<svg version="1.0" width="48" height="48" viewBox="0 0 40.425 46.214" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="a"><stop offset="0" style="stop-color:#fff;stop-opacity:1"/><stop style="stop-color:#27dc16;stop-opacity:1" offset="1"/></linearGradient></defs><circle style="fill:#8ff0a4;stroke:#2ec27e;stroke-width:.885327;stroke-miterlimit:4;stroke-dasharray:none;stop-color:#000" cx="18.281" cy="6.839" r="5.318"/><g style="stroke-width:1.06881"><path style="fill:#241f31;stroke:none;stroke-width:1.06881px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M437.016 124.536h.029a14.986 14.986 45 0 1 14.985 14.986v54.153a4.504 4.504 45 0 0 4.504 4.504 4.216 4.216 130.946 0 0 3.908-4.504v-63.748a14 14 135 0 1 14-14 13.257 13.257 48.306 0 1 12.47 14v63.897a4.355 4.355 45 0 0 4.355 4.355 4.149 4.149 132.08 0 0 3.932-4.355v-63.897a14 14 135 0 1 14-14 13.11 13.11 49.036 0 1 12.155 14v64.019a4.233 4.233 45 0 0 4.233 4.233h.202a4.233 4.233 135 0 0 4.233-4.233v-40.661a14 14 135 0 1 14-14 13.005 13.005 49.527 0 1 11.946 14L555.833 260a30.038 30.038 135.036 0 1-30.039 30H450a48.284 48.284 22.5 0 1-34.142-14.142l-37.801-37.801a15.702 15.702 86.658 0 1-1.217-20.839 14.154 14.154 173.662 0 1 19.896-2.21l21.76 17.2a2.181 2.181 154.16 0 0 3.534-1.712v-90.974a14.986 14.986 135 0 1 14.986-14.986z" transform="matrix(-.22259 0 0 .22259 123.725 -22.001)"/><path style="fill:#000;fill-opacity:.470966;stroke:none;stroke-width:1.06881px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M374.444 222.919c-1.992 5.044.075 11.54 3.91 15.375l37.503 37.563A48.284 48.284 0 0 0 450 290h75.794c16.569 0 30-13.431 30-30v-10c0 16.569-13.431 30-30 30H450a48.284 48.284 0 0 1-34.143-14.143l-38.377-38.313a13.61 13.61 0 0 1-3.036-4.625z" transform="matrix(-.22259 0 0 .22259 123.725 -22.001)"/></g></svg> \ No newline at end of file
diff --git a/panels/user-accounts/data/icons/left-ring-finger.svg b/panels/user-accounts/data/icons/left-ring-finger.svg
new file mode 100644
index 0000000..7a9bb4e
--- /dev/null
+++ b/panels/user-accounts/data/icons/left-ring-finger.svg
@@ -0,0 +1 @@
+<svg version="1.0" width="48" height="48" viewBox="0 0 40.425 46.214" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="a"><stop offset="0" style="stop-color:#fff;stop-opacity:1"/><stop style="stop-color:#27dc16;stop-opacity:1" offset="1"/></linearGradient></defs><circle style="fill:#8ff0a4;stroke:#2ec27e;stroke-width:.96279167;stroke-miterlimit:4;stroke-dasharray:none;stop-color:#000" cx="10.432" cy="6.745" r="5.247"/><g style="stroke-width:1.06881"><path style="fill:#241f31;stroke:none;stroke-width:1.06881px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M437.016 124.536h.029a14.986 14.986 45 0 1 14.985 14.986v54.153a4.504 4.504 45 0 0 4.504 4.504 4.216 4.216 130.946 0 0 3.908-4.504v-63.748a14 14 135 0 1 14-14 13.257 13.257 48.306 0 1 12.47 14v63.897a4.355 4.355 45 0 0 4.355 4.355 4.149 4.149 132.08 0 0 3.932-4.355v-63.897a14 14 135 0 1 14-14 13.11 13.11 49.036 0 1 12.155 14v64.019a4.233 4.233 45 0 0 4.233 4.233h.202a4.233 4.233 135 0 0 4.233-4.233v-40.661a14 14 135 0 1 14-14 13.005 13.005 49.527 0 1 11.946 14L555.833 260a30.038 30.038 135.036 0 1-30.039 30H450a48.284 48.284 22.5 0 1-34.142-14.142l-37.801-37.801a15.702 15.702 86.658 0 1-1.217-20.839 14.154 14.154 173.662 0 1 19.896-2.21l21.76 17.2a2.181 2.181 154.16 0 0 3.534-1.712v-90.974a14.986 14.986 135 0 1 14.986-14.986z" transform="matrix(-.22259 0 0 .22259 123.725 -22.001)"/><path style="fill:#000;fill-opacity:.470966;stroke:none;stroke-width:1.06881px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M374.444 222.919c-1.992 5.044.075 11.54 3.91 15.375l37.503 37.563A48.284 48.284 0 0 0 450 290h75.794c16.569 0 30-13.431 30-30v-10c0 16.569-13.431 30-30 30H450a48.284 48.284 0 0 1-34.143-14.143l-38.377-38.313a13.61 13.61 0 0 1-3.036-4.625z" transform="matrix(-.22259 0 0 .22259 123.725 -22.001)"/></g></svg> \ No newline at end of file
diff --git a/panels/user-accounts/data/icons/left-thumb.svg b/panels/user-accounts/data/icons/left-thumb.svg
new file mode 100644
index 0000000..bf28739
--- /dev/null
+++ b/panels/user-accounts/data/icons/left-thumb.svg
@@ -0,0 +1 @@
+<svg version="1.0" width="48" height="48" viewBox="0 0 40.425 46.214" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="a"><stop offset="0" style="stop-color:#fff;stop-opacity:1"/><stop style="stop-color:#27dc16;stop-opacity:1" offset="1"/></linearGradient></defs><circle style="fill:#8ff0a4;stroke:#2ec27e;stroke-width:.949928;stroke-miterlimit:4;stroke-dasharray:none;stop-color:#000" cx="37.026" cy="28.463" r="5.706"/><g style="stroke-width:1.06881"><path style="fill:#241f31;stroke:none;stroke-width:1.06881px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M437.016 124.536h.029a14.986 14.986 45 0 1 14.985 14.986v54.153a4.504 4.504 45 0 0 4.504 4.504 4.216 4.216 130.946 0 0 3.908-4.504v-63.748a14 14 135 0 1 14-14 13.257 13.257 48.306 0 1 12.47 14v63.897a4.355 4.355 45 0 0 4.355 4.355 4.149 4.149 132.08 0 0 3.932-4.355v-63.897a14 14 135 0 1 14-14 13.11 13.11 49.036 0 1 12.155 14v64.019a4.233 4.233 45 0 0 4.233 4.233h.202a4.233 4.233 135 0 0 4.233-4.233v-40.661a14 14 135 0 1 14-14 13.005 13.005 49.527 0 1 11.946 14L555.833 260a30.038 30.038 135.036 0 1-30.039 30H450a48.284 48.284 22.5 0 1-34.142-14.142l-37.801-37.801a15.702 15.702 86.658 0 1-1.217-20.839 14.154 14.154 173.662 0 1 19.896-2.21l21.76 17.2a2.181 2.181 154.16 0 0 3.534-1.712v-90.974a14.986 14.986 135 0 1 14.986-14.986z" transform="matrix(-.22259 0 0 .22259 123.725 -22.001)"/><path style="fill:#000;fill-opacity:.470966;stroke:none;stroke-width:1.06881px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M374.444 222.919c-1.992 5.044.075 11.54 3.91 15.375l37.503 37.563A48.284 48.284 0 0 0 450 290h75.794c16.569 0 30-13.431 30-30v-10c0 16.569-13.431 30-30 30H450a48.284 48.284 0 0 1-34.143-14.143l-38.377-38.313a13.61 13.61 0 0 1-3.036-4.625z" transform="matrix(-.22259 0 0 .22259 123.725 -22.001)"/></g></svg> \ No newline at end of file
diff --git a/panels/user-accounts/data/icons/print_error.svg b/panels/user-accounts/data/icons/print_error.svg
new file mode 100644
index 0000000..5a9d22b
--- /dev/null
+++ b/panels/user-accounts/data/icons/print_error.svg
@@ -0,0 +1 @@
+<svg version="1.0" width="48" height="48" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="f"><stop style="stop-color:#fffffc;stop-opacity:1" offset="0"/><stop style="stop-color:#fffffc;stop-opacity:0" offset="1"/></linearGradient><linearGradient id="e"><stop style="stop-color:#73d216;stop-opacity:1" offset="0"/><stop offset=".315" style="stop-color:#73d216;stop-opacity:1"/><stop style="stop-color:#4e9a06;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="c"><stop offset="0" style="stop-color:#fff;stop-opacity:1"/><stop offset="1" style="stop-color:#fff;stop-opacity:0"/></linearGradient><linearGradient id="b"><stop style="stop-color:#52a714;stop-opacity:1" offset="0"/><stop style="stop-color:#398800;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="a"><stop offset="0" style="stop-color:#398800;stop-opacity:1"/><stop offset="1" style="stop-color:#84c706;stop-opacity:1"/></linearGradient><linearGradient id="d"><stop offset="0" style="stop-color:white;stop-opacity:1"/><stop offset="1" style="stop-color:white;stop-opacity:0"/></linearGradient></defs><path style="color:#000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000;solid-opacity:1;vector-effect:none;fill:#77767b;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:56;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000" d="M17 3c-2.402-.025-4.81.57-6.977 1.781a2 2 0 0 0 1.95 3.492 9.994 9.994 0 0 1 9.941.102A9.991 9.991 0 0 1 26.855 17v1.145l3.739-3.739a13.986 13.986 0 0 0-6.657-9.484A13.986 13.986 0 0 0 17 3zM6.602 8.66a2 2 0 0 0-1.633.942 13.997 13.997 0 0 0-2.094 7.113v.004a2 2 0 0 0-.02.281v10.125a2 2 0 1 0 4 0V17c0-1.868.525-3.7 1.512-5.285A2 2 0 0 0 6.602 8.66zM16.855 9c-4.262 0-7.752 3.4-7.96 7.613a2 2 0 0 0-.04.387v2a2 2 0 1 0 4 0v-2c0-2.233 1.768-4 4-4 2.233 0 4 1.767 4 4v7.145l4-4V17a2 2 0 0 0-.039-.398C24.602 12.393 21.114 9 16.856 9zm0 6a2 2 0 0 0-2 2v10s0 1.19.29 2.64c.01.058.026.118.039.176l3.671-3.671V17a2 2 0 0 0-2-2zm-6 8a2 2 0 0 0-2 2v6a2 2 0 1 0 4 0v-6a2 2 0 0 0-2-2z"/><g style="display:inline;enable-background:new;fill:#ed333b;fill-opacity:1" transform="matrix(1.5 0 0 -1.5 6.149 1050.007)"><path style="display:inline;fill:#ed333b;fill-opacity:1;stroke-width:1.5;stroke-linecap:square;stroke-linejoin:round;enable-background:new" d="M19.794 668.005c-4.377 0-7.893 3.623-7.893 8a8 8 0 1 0 8-8h-.107zm-.56 3.346h1.334c.37 0 .668.297.668.667v1.335c0 .37-.298.667-.668.667h-1.335a.666.666 0 0 1-.667-.667v-1.335c0-.37.298-.667.667-.667zm-.666 3.987h2.666v6h-2.666z"/></g><path style="fill:none;stroke:#77767b;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m9 36 25-25"/></svg> \ No newline at end of file
diff --git a/panels/user-accounts/data/icons/print_ok.svg b/panels/user-accounts/data/icons/print_ok.svg
new file mode 100644
index 0000000..4d84ff0
--- /dev/null
+++ b/panels/user-accounts/data/icons/print_ok.svg
@@ -0,0 +1 @@
+<svg version="1.0" width="48" height="48" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="f"><stop style="stop-color:#fffffc;stop-opacity:1" offset="0"/><stop style="stop-color:#fffffc;stop-opacity:0" offset="1"/></linearGradient><linearGradient id="e"><stop style="stop-color:#73d216;stop-opacity:1" offset="0"/><stop offset=".315" style="stop-color:#73d216;stop-opacity:1"/><stop style="stop-color:#4e9a06;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="c"><stop offset="0" style="stop-color:#fff;stop-opacity:1"/><stop offset="1" style="stop-color:#fff;stop-opacity:0"/></linearGradient><linearGradient id="b"><stop style="stop-color:#52a714;stop-opacity:1" offset="0"/><stop style="stop-color:#398800;stop-opacity:1" offset="1"/></linearGradient><linearGradient id="a"><stop offset="0" style="stop-color:#398800;stop-opacity:1"/><stop offset="1" style="stop-color:#84c706;stop-opacity:1"/></linearGradient><linearGradient id="d"><stop offset="0" style="stop-color:white;stop-opacity:1"/><stop offset="1" style="stop-color:white;stop-opacity:0"/></linearGradient></defs><path style="color:#000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000;solid-opacity:1;vector-effect:none;fill:#77767b;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:56;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000" d="M17 3c-2.402-.025-4.81.57-6.977 1.781a2 2 0 0 0 1.95 3.492 9.994 9.994 0 0 1 9.941.102A9.991 9.991 0 0 1 26.855 17v2a2 2 0 1 0 4 0v-2c0-.077-.006-.154-.015-.23a14.002 14.002 0 0 0-6.902-11.848A13.986 13.986 0 0 0 17 3ZM6.602 8.66a2 2 0 0 0-1.633.942 13.997 13.997 0 0 0-2.094 7.113v.004a2 2 0 0 0-.02.281v10.125a2 2 0 1 0 4 0V17c0-1.868.525-3.7 1.512-5.285A2 2 0 0 0 6.602 8.66ZM16.855 9c-4.262 0-7.752 3.4-7.96 7.613a2 2 0 0 0-.04.387v2a2 2 0 1 0 4 0v-2c0-2.233 1.768-4 4-4 2.233 0 4 1.767 4 4v10s.018.88.352 1.883c.172.515.432 1.107.81 1.728.66-1.69 1.621-3.247 2.838-4.593V17a2 2 0 0 0-.039-.398C24.602 12.393 21.114 9 16.856 9Zm0 6a2 2 0 0 0-2 2v10s0 1.19.29 2.64c.29 1.452.825 3.303 2.296 4.774a2 2 0 0 0 2.829-2.828c-.53-.529-.994-1.678-1.204-2.727-.21-1.048-.21-1.859-.21-1.859V17a2 2 0 0 0-2-2zm-6 8a2 2 0 0 0-2 2v6a2 2 0 1 0 4 0v-6a2 2 0 0 0-2-2z"/><path style="display:inline;fill:#26a269;fill-opacity:1;stroke-width:2.25;stroke-linecap:square;stroke-linejoin:round;enable-background:new" d="M36 24c-6.627 0-12 5.373-12 12 0 6.565 5.275 12 11.84 12H36c6.627 0 12-5.373 12-12s-5.373-12-12-12zm6.154 7.006a2 2 0 0 1 1.364.693 2 2 0 0 1-.217 2.819l-8.406 7.207-5.31-5.31a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l2.69 2.69 5.594-4.793a2 2 0 0 1 1.455-.476z"/></svg> \ No newline at end of file
diff --git a/panels/user-accounts/data/icons/right-index-finger.svg b/panels/user-accounts/data/icons/right-index-finger.svg
new file mode 100644
index 0000000..856ffc9
--- /dev/null
+++ b/panels/user-accounts/data/icons/right-index-finger.svg
@@ -0,0 +1 @@
+<svg version="1.0" width="48" height="48" viewBox="0 0 40.425 46.214" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="a"><stop offset="0" style="stop-color:#fff;stop-opacity:1"/><stop style="stop-color:#27dc16;stop-opacity:1" offset="1"/></linearGradient></defs><circle style="fill:#8ff0a4;stroke:#2ec27e;stroke-width:.962791;stroke-miterlimit:4;stroke-dasharray:none;stop-color:#000" cx="-14.102" cy="9.203" r="5.783" transform="scale(-1 1)"/><g style="stroke-width:1.06881"><path style="fill:#241f31;stroke:none;stroke-width:1.06881px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M437.016 124.536h.029a14.986 14.986 45 0 1 14.985 14.986v54.153a4.504 4.504 45 0 0 4.504 4.504 4.216 4.216 130.946 0 0 3.908-4.504v-63.748a14 14 135 0 1 14-14 13.257 13.257 48.306 0 1 12.47 14v63.897a4.355 4.355 45 0 0 4.355 4.355 4.149 4.149 132.08 0 0 3.932-4.355v-63.897a14 14 135 0 1 14-14 13.11 13.11 49.036 0 1 12.155 14v64.019a4.233 4.233 45 0 0 4.233 4.233h.202a4.233 4.233 135 0 0 4.233-4.233v-40.661a14 14 135 0 1 14-14 13.005 13.005 49.527 0 1 11.946 14L555.833 260a30.038 30.038 135.036 0 1-30.039 30H450a48.284 48.284 22.5 0 1-34.142-14.142l-37.801-37.801a15.702 15.702 86.658 0 1-1.217-20.839 14.154 14.154 173.662 0 1 19.896-2.21l21.76 17.2a2.181 2.181 154.16 0 0 3.534-1.712v-90.974a14.986 14.986 135 0 1 14.986-14.986z" transform="matrix(.22259 0 0 .22259 -83.162 -22.001)"/><path style="fill:#000;fill-opacity:.470966;stroke:none;stroke-width:1.06881px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M374.444 222.919c-1.992 5.044.075 11.54 3.91 15.375l37.503 37.563A48.284 48.284 0 0 0 450 290h75.794c16.569 0 30-13.431 30-30v-10c0 16.569-13.431 30-30 30H450a48.284 48.284 0 0 1-34.143-14.143l-38.377-38.313a13.61 13.61 0 0 1-3.036-4.625z" transform="matrix(.22259 0 0 .22259 -83.162 -22.001)"/></g></svg> \ No newline at end of file
diff --git a/panels/user-accounts/data/icons/right-little-finger.svg b/panels/user-accounts/data/icons/right-little-finger.svg
new file mode 100644
index 0000000..953c56d
--- /dev/null
+++ b/panels/user-accounts/data/icons/right-little-finger.svg
@@ -0,0 +1 @@
+<svg version="1.0" width="48" height="48" viewBox="0 0 40.425 46.214" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="a"><stop offset="0" style="stop-color:#fff;stop-opacity:1"/><stop style="stop-color:#27dc16;stop-opacity:1" offset="1"/></linearGradient></defs><circle style="fill:#8ff0a4;stroke:#2ec27e;stroke-width:.962792;stroke-miterlimit:4;stroke-dasharray:none;stop-color:#000" cx="-37.541" cy="11.617" r="5.207" transform="scale(-1 1)"/><g style="stroke-width:1.06881"><path style="fill:#241f31;stroke:none;stroke-width:1.06881px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M437.016 124.536h.029a14.986 14.986 45 0 1 14.985 14.986v54.153a4.504 4.504 45 0 0 4.504 4.504 4.216 4.216 130.946 0 0 3.908-4.504v-63.748a14 14 135 0 1 14-14 13.257 13.257 48.306 0 1 12.47 14v63.897a4.355 4.355 45 0 0 4.355 4.355 4.149 4.149 132.08 0 0 3.932-4.355v-63.897a14 14 135 0 1 14-14 13.11 13.11 49.036 0 1 12.155 14v64.019a4.233 4.233 45 0 0 4.233 4.233h.202a4.233 4.233 135 0 0 4.233-4.233v-40.661a14 14 135 0 1 14-14 13.005 13.005 49.527 0 1 11.946 14L555.833 260a30.038 30.038 135.036 0 1-30.039 30H450a48.284 48.284 22.5 0 1-34.142-14.142l-37.801-37.801a15.702 15.702 86.658 0 1-1.217-20.839 14.154 14.154 173.662 0 1 19.896-2.21l21.76 17.2a2.181 2.181 154.16 0 0 3.534-1.712v-90.974a14.986 14.986 135 0 1 14.986-14.986z" transform="matrix(.22259 0 0 .22259 -83.332 -22.001)"/><path style="fill:#000;fill-opacity:.470966;stroke:none;stroke-width:1.06881px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M374.444 222.919c-1.992 5.044.075 11.54 3.91 15.375l37.503 37.563A48.284 48.284 0 0 0 450 290h75.794c16.569 0 30-13.431 30-30v-10c0 16.569-13.431 30-30 30H450a48.284 48.284 0 0 1-34.143-14.143l-38.377-38.313a13.61 13.61 0 0 1-3.036-4.625z" transform="matrix(.22259 0 0 .22259 -83.332 -22.001)"/></g></svg> \ No newline at end of file
diff --git a/panels/user-accounts/data/icons/right-middle-finger.svg b/panels/user-accounts/data/icons/right-middle-finger.svg
new file mode 100644
index 0000000..3cf22e5
--- /dev/null
+++ b/panels/user-accounts/data/icons/right-middle-finger.svg
@@ -0,0 +1 @@
+<svg version="1.0" width="48" height="48" viewBox="0 0 40.425 46.214" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="a"><stop offset="0" style="stop-color:#fff;stop-opacity:1"/><stop style="stop-color:#27dc16;stop-opacity:1" offset="1"/></linearGradient></defs><circle style="fill:#8ff0a4;stroke:#2ec27e;stroke-width:.885327;stroke-miterlimit:4;stroke-dasharray:none;stop-color:#000" cx="-22.283" cy="6.839" r="5.318" transform="scale(-1 1)"/><g style="stroke-width:1.06881"><path style="fill:#241f31;stroke:none;stroke-width:1.06881px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M437.016 124.536h.029a14.986 14.986 45 0 1 14.985 14.986v54.153a4.504 4.504 45 0 0 4.504 4.504 4.216 4.216 130.946 0 0 3.908-4.504v-63.748a14 14 135 0 1 14-14 13.257 13.257 48.306 0 1 12.47 14v63.897a4.355 4.355 45 0 0 4.355 4.355 4.149 4.149 132.08 0 0 3.932-4.355v-63.897a14 14 135 0 1 14-14 13.11 13.11 49.036 0 1 12.155 14v64.019a4.233 4.233 45 0 0 4.233 4.233h.202a4.233 4.233 135 0 0 4.233-4.233v-40.661a14 14 135 0 1 14-14 13.005 13.005 49.527 0 1 11.946 14L555.833 260a30.038 30.038 135.036 0 1-30.039 30H450a48.284 48.284 22.5 0 1-34.142-14.142l-37.801-37.801a15.702 15.702 86.658 0 1-1.217-20.839 14.154 14.154 173.662 0 1 19.896-2.21l21.76 17.2a2.181 2.181 154.16 0 0 3.534-1.712v-90.974a14.986 14.986 135 0 1 14.986-14.986z" transform="matrix(.22259 0 0 .22259 -83.162 -22.001)"/><path style="fill:#000;fill-opacity:.470966;stroke:none;stroke-width:1.06881px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M374.444 222.919c-1.992 5.044.075 11.54 3.91 15.375l37.503 37.563A48.284 48.284 0 0 0 450 290h75.794c16.569 0 30-13.431 30-30v-10c0 16.569-13.431 30-30 30H450a48.284 48.284 0 0 1-34.143-14.143l-38.377-38.313a13.61 13.61 0 0 1-3.036-4.625z" transform="matrix(.22259 0 0 .22259 -83.162 -22.001)"/></g></svg> \ No newline at end of file
diff --git a/panels/user-accounts/data/icons/right-ring-finger.svg b/panels/user-accounts/data/icons/right-ring-finger.svg
new file mode 100644
index 0000000..d237017
--- /dev/null
+++ b/panels/user-accounts/data/icons/right-ring-finger.svg
@@ -0,0 +1 @@
+<svg version="1.0" width="48" height="48" viewBox="0 0 40.425 46.214" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="a"><stop offset="0" style="stop-color:#fff;stop-opacity:1"/><stop style="stop-color:#27dc16;stop-opacity:1" offset="1"/></linearGradient></defs><circle style="fill:#8ff0a4;stroke:#2ec27e;stroke-width:.962792;stroke-miterlimit:4;stroke-dasharray:none;stop-color:#000" cx="-30.132" cy="6.745" r="5.247" transform="scale(-1 1)"/><g style="stroke-width:1.06881"><path style="fill:#241f31;stroke:none;stroke-width:1.06881px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M437.016 124.536h.029a14.986 14.986 45 0 1 14.985 14.986v54.153a4.504 4.504 45 0 0 4.504 4.504 4.216 4.216 130.946 0 0 3.908-4.504v-63.748a14 14 135 0 1 14-14 13.257 13.257 48.306 0 1 12.47 14v63.897a4.355 4.355 45 0 0 4.355 4.355 4.149 4.149 132.08 0 0 3.932-4.355v-63.897a14 14 135 0 1 14-14 13.11 13.11 49.036 0 1 12.155 14v64.019a4.233 4.233 45 0 0 4.233 4.233h.202a4.233 4.233 135 0 0 4.233-4.233v-40.661a14 14 135 0 1 14-14 13.005 13.005 49.527 0 1 11.946 14L555.833 260a30.038 30.038 135.036 0 1-30.039 30H450a48.284 48.284 22.5 0 1-34.142-14.142l-37.801-37.801a15.702 15.702 86.658 0 1-1.217-20.839 14.154 14.154 173.662 0 1 19.896-2.21l21.76 17.2a2.181 2.181 154.16 0 0 3.534-1.712v-90.974a14.986 14.986 135 0 1 14.986-14.986z" transform="matrix(.22259 0 0 .22259 -83.162 -22.001)"/><path style="fill:#000;fill-opacity:.470966;stroke:none;stroke-width:1.06881px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M374.444 222.919c-1.992 5.044.075 11.54 3.91 15.375l37.503 37.563A48.284 48.284 0 0 0 450 290h75.794c16.569 0 30-13.431 30-30v-10c0 16.569-13.431 30-30 30H450a48.284 48.284 0 0 1-34.143-14.143l-38.377-38.313a13.61 13.61 0 0 1-3.036-4.625z" transform="matrix(.22259 0 0 .22259 -83.162 -22.001)"/></g></svg> \ No newline at end of file
diff --git a/panels/user-accounts/data/icons/right-thumb.svg b/panels/user-accounts/data/icons/right-thumb.svg
new file mode 100644
index 0000000..50639f2
--- /dev/null
+++ b/panels/user-accounts/data/icons/right-thumb.svg
@@ -0,0 +1 @@
+<svg version="1.0" width="48" height="48" viewBox="0 0 40.425 46.214" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="a"><stop offset="0" style="stop-color:#fff;stop-opacity:1"/><stop style="stop-color:#27dc16;stop-opacity:1" offset="1"/></linearGradient></defs><circle style="fill:#8ff0a4;stroke:#2ec27e;stroke-width:.949928;stroke-miterlimit:4;stroke-dasharray:none;stop-color:#000" cx="-3.418" cy="28.463" r="5.706" transform="scale(-1 1)"/><g style="stroke-width:1.06881"><path style="fill:#241f31;stroke:none;stroke-width:1.06881px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M437.016 124.536h.029a14.986 14.986 45 0 1 14.985 14.986v54.153a4.504 4.504 45 0 0 4.504 4.504 4.216 4.216 130.946 0 0 3.908-4.504v-63.748a14 14 135 0 1 14-14 13.257 13.257 48.306 0 1 12.47 14v63.897a4.355 4.355 45 0 0 4.355 4.355 4.149 4.149 132.08 0 0 3.932-4.355v-63.897a14 14 135 0 1 14-14 13.11 13.11 49.036 0 1 12.155 14v64.019a4.233 4.233 45 0 0 4.233 4.233h.202a4.233 4.233 135 0 0 4.233-4.233v-40.661a14 14 135 0 1 14-14 13.005 13.005 49.527 0 1 11.946 14L555.833 260a30.038 30.038 135.036 0 1-30.039 30H450a48.284 48.284 22.5 0 1-34.142-14.142l-37.801-37.801a15.702 15.702 86.658 0 1-1.217-20.839 14.154 14.154 173.662 0 1 19.896-2.21l21.76 17.2a2.181 2.181 154.16 0 0 3.534-1.712v-90.974a14.986 14.986 135 0 1 14.986-14.986z" transform="matrix(.22259 0 0 .22259 -83.281 -22.001)"/><path style="fill:#000;fill-opacity:.470966;stroke:none;stroke-width:1.06881px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M374.444 222.919c-1.992 5.044.075 11.54 3.91 15.375l37.503 37.563A48.284 48.284 0 0 0 450 290h75.794c16.569 0 30-13.431 30-30v-10c0 16.569-13.431 30-30 30H450a48.284 48.284 0 0 1-34.143-14.143l-38.377-38.313a13.61 13.61 0 0 1-3.036-4.625z" transform="matrix(.22259 0 0 .22259 -83.281 -22.001)"/></g></svg> \ No newline at end of file
diff --git a/panels/user-accounts/data/join-dialog.ui b/panels/user-accounts/data/join-dialog.ui
new file mode 100644
index 0000000..4da78e2
--- /dev/null
+++ b/panels/user-accounts/data/join-dialog.ui
@@ -0,0 +1,166 @@
+<?xml version="1.0"?>
+<interface>
+ <!-- interface-requires gtk+ 3.8 -->
+ <object class="GtkDialog" id="join-dialog">
+ <property name="can_focus">False</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="title" translatable="yes">Add User</property>
+ <property name="use_header_bar">1</property>
+ <child internal-child="headerbar">
+ <object class="GtkHeaderBar" id="join-dialog-header-bar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child type="start">
+ <object class="GtkButton" id="button1">
+ <property name="label" translatable="yes">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="use_underline">True</property>
+ <property name="valign">center</property>
+ <style>
+ <class name="text-button"/>
+ </style>
+ </object>
+ </child>
+ <child type="end">
+ <object class="GtkButton" id="button2">
+ <property name="label" translatable="yes" comments="Translators: This button enrolls the computer in the domain in order to use enterprise logins.">_Enroll</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ <property name="valign">center</property>
+ <style>
+ <class name="text-button"/>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkLabel" id="label71">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Domain Administrator Login</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ <attribute name="scale" value="1.2"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label12">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="label" translatable="yes">In order to use enterprise logins, this computer needs to be
+enrolled in the domain. Please have your network administrator
+type their domain password here.</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_start">12</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="label13">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Domain</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">join-domain</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="join-domain">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">5</property>
+ <property name="margin_bottom">5</property>
+ <property name="xalign">0</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label14">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Administrator _Name</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">join-name</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="join-name">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label15">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Administrator Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">join-password</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="join-password">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="visibility">False</property>
+ <property name="invisible_char">●</property>
+ <property name="activates_default">True</property>
+ <property name="invisible_char_set">True</property>
+ <property name="input_purpose">password</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-6">button1</action-widget>
+ <action-widget response="-5">button2</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/panels/user-accounts/data/net.reactivated.Fprint.Device.xml b/panels/user-accounts/data/net.reactivated.Fprint.Device.xml
new file mode 100644
index 0000000..786d89c
--- /dev/null
+++ b/panels/user-accounts/data/net.reactivated.Fprint.Device.xml
@@ -0,0 +1,585 @@
+<!DOCTYPE node PUBLIC
+"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd" [
+<!ENTITY ERROR_CLAIM_DEVICE "net.reactivated.Fprint.Error.ClaimDevice">
+<!ENTITY ERROR_ALREADY_IN_USE "net.reactivated.Fprint.Error.AlreadyInUse">
+<!ENTITY ERROR_INTERNAL "net.reactivated.Fprint.Error.Internal">
+<!ENTITY ERROR_PERMISSION_DENIED "net.reactivated.Fprint.Error.PermissionDenied">
+<!ENTITY ERROR_NO_ENROLLED_PRINTS "net.reactivated.Fprint.Error.NoEnrolledPrints">
+<!ENTITY ERROR_NO_ACTION_IN_PROGRESS "net.reactivated.Fprint.Error.NoActionInProgress">
+<!ENTITY ERROR_INVALID_FINGERNAME "net.reactivated.Fprint.Error.InvalidFingername">
+]>
+
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+ <interface name="net.reactivated.Fprint.Device">
+ value="fprint_device" />
+
+ <doc:doc>
+ <doc:title id="polkit-integration">
+ PolicyKit integration
+ </doc:title>
+ <doc:para>
+ fprintd uses PolicyKit to check whether users are allowed to access fingerprint data, or the
+ fingerprint readers itself.
+ <doc:list>
+ <doc:item>
+ <doc:term>net.reactivated.fprint.device.verify</doc:term>
+ <doc:definition>
+ Whether the user is allowed to verify fingers against saved fingerprints.
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>net.reactivated.fprint.device.enroll</doc:term>
+ <doc:definition>
+ Whether the user is allowed to enroll new fingerprints.
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>net.reactivated.fprint.device.setusername</doc:term>
+ <doc:definition>
+ Whether the user is allowed to query, verify, or enroll fingerprints for users other than itself.
+ </doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:para>
+
+ <doc:title id="usernames">
+ Usernames
+ </doc:title>
+ <doc:para>
+ When a username argument is used for a method, a PolicyKit check is done on the
+ <doc:tt>net.reactivated.fprint.device.setusername</doc:tt> PolicyKit
+ action to see whether the user the client is running as is allowed to access data from other users.
+ </doc:para>
+ <doc:para>
+ By default, only root is allowed to access fingerprint data for users other than itself. For a normal user,
+ it is recommended that you use an empty string for the username, which will mean "the client the user is
+ running as".
+ </doc:para>
+ <doc:para>
+ See <doc:ref type="description" to="polkit-integration">PolicyKit integration</doc:ref>.
+ </doc:para>
+
+ <doc:title id="fingerprint-names">
+ Fingerprint names
+ </doc:title>
+ <doc:para>
+ When a finger name argument is used for a method, it refers to either a single finger, or
+ "any" finger. See the list of possible values below:
+ <doc:list>
+ <doc:item>
+ <doc:term>left-thumb</doc:term>
+ <doc:definition>
+ Left thumb
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>left-index-finger</doc:term>
+ <doc:definition>
+ Left index finger
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>left-middle-finger</doc:term>
+ <doc:definition>
+ Left middle finger
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>left-ring-finger</doc:term>
+ <doc:definition>
+ Left ring finger
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>left-little-finger</doc:term>
+ <doc:definition>
+ Left little finger
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>right-thumb</doc:term>
+ <doc:definition>
+ Right thumb
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>right-index-finger</doc:term>
+ <doc:definition>
+ Right index finger
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>right-middle-finger</doc:term>
+ <doc:definition>
+ Right middle finger
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>right-ring-finger</doc:term>
+ <doc:definition>
+ Right ring finger
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>right-little-finger</doc:term>
+ <doc:definition>
+ Right little finger
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>any</doc:term>
+ <doc:definition>
+ Any finger. This is only used for <doc:ref type="method" to="Device.VerifyStart">Device.VerifyStart</doc:ref>
+ (select the first finger with a fingerprint associated, or all the fingerprints available for the user when
+ the device supports it) and <doc:ref type="signal" to="Device::VerifyFingerSelected">Device::VerifyFingerSelected</doc:ref>
+ (any finger with an associated fingerprint can be used).
+ </doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:para>
+
+ <doc:title id="verify-statuses">
+ Verify Statuses
+ </doc:title>
+ <doc:para>
+ <doc:list>
+ Possible values for the result passed through <doc:ref type="signal" to="Device::VerifyResult">Device::VerifyResult</doc:ref> are:
+ <doc:item>
+ <doc:term>verify-no-match</doc:term>
+ <doc:definition>
+ The verification did not match, <doc:ref type="method" to="Device.VerifyStop">Device.VerifyStop</doc:ref> should now be called.
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>verify-match</doc:term>
+ <doc:definition>
+ The verification succeeded, <doc:ref type="method" to="Device.VerifyStop">Device.VerifyStop</doc:ref> should now be called.
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>verify-retry-scan</doc:term>
+ <doc:definition>
+ The user should retry scanning their finger, the verification is still ongoing.
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>verify-swipe-too-short</doc:term>
+ <doc:definition>
+ The user's swipe was too short. The user should retry scanning their finger, the verification is still ongoing.
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>verify-finger-not-centered</doc:term>
+ <doc:definition>
+ The user's finger was not centered on the reader. The user should retry scanning their finger, the verification is still ongoing.
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>verify-remove-and-retry</doc:term>
+ <doc:definition>
+ The user should remove their finger from the reader and retry scanning their finger, the verification is still ongoing.
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>verify-disconnected</doc:term>
+ <doc:definition>
+ The device was disconnected during the verification, no other actions should be taken, and you shouldn't use the device any more.
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>verify-unknown-error</doc:term>
+ <doc:definition>
+ An unknown error occurred (usually a driver problem), <doc:ref type="method" to="Device.VerifyStop">Device.VerifyStop</doc:ref> should now be called.
+ </doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:para>
+
+ <doc:title id="enroll-statuses">
+ Enroll Statuses
+ </doc:title>
+ <doc:para>
+ <doc:list>
+ Possible values for the result passed through <doc:ref type="signal" to="Device::EnrollResult">Device::EnrollResult</doc:ref> are:
+ <doc:item>
+ <doc:term>enroll-completed</doc:term>
+ <doc:definition>
+ The enrollment successfully completed, <doc:ref type="method" to="Device.EnrollStop">Device.EnrollStop</doc:ref> should now be called.
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>enroll-failed</doc:term>
+ <doc:definition>
+ The enrollment failed, <doc:ref type="method" to="Device.EnrollStop">Device.EnrollStop</doc:ref> should now be called.
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>enroll-stage-passed</doc:term>
+ <doc:definition>
+ One stage of the enrollment passed, the enrollment is still ongoing.
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>enroll-retry-scan</doc:term>
+ <doc:definition>
+ The user should retry scanning their finger, the enrollment is still ongoing.
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>enroll-swipe-too-short</doc:term>
+ <doc:definition>
+ The user's swipe was too short. The user should retry scanning their finger, the enrollment is still ongoing.
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>enroll-finger-not-centered</doc:term>
+ <doc:definition>
+ The user's finger was not centered on the reader. The user should retry scanning their finger, the enrollment is still ongoing.
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>enroll-remove-and-retry</doc:term>
+ <doc:definition>
+ The user should remove their finger from the reader and retry scanning their finger, the enrollment is still ongoing.
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>enroll-data-full</doc:term>
+ <doc:definition>
+ No further prints can be enrolled on this device, <doc:ref type="method" to="Device.EnrollStop">Device.EnrollStop</doc:ref> should now be called.
+
+ <doc:ref type="method" to="DeleteEnrolledFingers2">Delete other prints</doc:ref> from the device first to continue
+ (e.g. from other users). Note that old prints or prints from other operating systems may be deleted automatically
+ to resolve this error without any notification.
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>enroll-disconnected</doc:term>
+ <doc:definition>
+ The device was disconnected during the enrollment, no other actions should be taken, and you shouldn't use the device any more.
+
+ </doc:definition>
+ </doc:item>
+ <doc:item>
+ <doc:term>enroll-unknown-error</doc:term>
+ <doc:definition>
+ An unknown error occurred (usually a driver problem), <doc:ref type="method" to="Device.EnrollStop">Device.EnrollStop</doc:ref> should now be called.
+
+ </doc:definition>
+ </doc:item>
+ </doc:list>
+ </doc:para>
+ </doc:doc>
+
+ <!-- ************************************************************ -->
+
+ <method name="ListEnrolledFingers">
+ <arg type="s" name="username" direction="in">
+ <doc:doc><doc:summary>The username for whom to list the enrolled fingerprints. See <doc:ref type="description" to="usernames">Usernames</doc:ref>.</doc:summary></doc:doc>
+ </arg>
+ <arg type="as" name="enrolled_fingers" direction="out">
+ <doc:doc><doc:summary>An array of strings representing the enrolled fingerprints. See <doc:ref type="description" to="fingerprint-names">Fingerprint names</doc:ref>.</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ List all the enrolled fingerprints for the chosen user.
+ </doc:para>
+ </doc:description>
+
+ <doc:errors>
+ <doc:error name="&ERROR_PERMISSION_DENIED;">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="&ERROR_NO_ENROLLED_PRINTS;">if the chosen user doesn't have any fingerprints enrolled</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <method name="DeleteEnrolledFingers">
+ <arg type="s" name="username" direction="in">
+ <doc:doc><doc:summary>The username for whom to delete the enrolled fingerprints. See <doc:ref type="description" to="usernames">Usernames</doc:ref>.</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Delete all the enrolled fingerprints for the chosen user.
+ </doc:para>
+ <doc:para>
+ This call only exists for compatibility reasons, you should instead claim the device using
+ <doc:ref type="method" to="Device.Claim">Device.Claim</doc:ref> and then call
+ <doc:ref type="method" to="DeleteEnrolledFingers2">DeleteEnrolledFingers2</doc:ref>.
+ </doc:para>
+ </doc:description>
+
+ <doc:errors>
+ <doc:error name="&ERROR_PERMISSION_DENIED;">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <method name="DeleteEnrolledFingers2">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Delete all the enrolled fingerprints for the user currently claiming the device with <doc:ref type="method" to="Device.Claim">Device.Claim</doc:ref>.
+ </doc:para>
+ </doc:description>
+
+ <doc:errors>
+ <doc:error name="&ERROR_PERMISSION_DENIED;">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <method name="Claim">
+ <arg type="s" name="username" direction="in">
+ <doc:doc><doc:summary>The username for whom to claim the device. See <doc:ref type="description" to="usernames">Usernames</doc:ref>.</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Claim the device for the chosen user.
+ </doc:para>
+ </doc:description>
+
+ <doc:errors>
+ <doc:error name="&ERROR_PERMISSION_DENIED;">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="&ERROR_ALREADY_IN_USE;">if the device is already claimed</doc:error>
+ <doc:error name="&ERROR_INTERNAL;">if the device couldn't be claimed</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <method name="Release">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Release a device claimed with <doc:ref type="method" to="Device.Claim">Device.Claim</doc:ref>.
+ </doc:para>
+ </doc:description>
+
+ <doc:errors>
+ <doc:error name="&ERROR_PERMISSION_DENIED;">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="&ERROR_CLAIM_DEVICE;">if the device was not claimed</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <method name="VerifyStart">
+ <arg type="s" name="finger_name" direction="in">
+ <doc:doc><doc:summary>A string representing the finger to verify. See <doc:ref type="description" to="fingerprint-names">Fingerprint names</doc:ref>.</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Check the chosen finger against a saved fingerprint. You need to have claimed the device using
+ <doc:ref type="method" to="Device.Claim">Device.Claim</doc:ref>. The finger selected is sent to the front-end
+ using <doc:ref type="signal" to="Device::VerifyFingerSelected">Device::VerifyFingerSelected</doc:ref> and
+ verification status through <doc:ref type="signal" to="Device::VerifyStatus">Device::VerifyStatus</doc:ref>.
+ </doc:para>
+ </doc:description>
+
+ <doc:errors>
+ <doc:error name="&ERROR_PERMISSION_DENIED;">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="&ERROR_CLAIM_DEVICE;">if the device was not claimed</doc:error>
+ <doc:error name="&ERROR_ALREADY_IN_USE;">if the device was already being used</doc:error>
+ <doc:error name="&ERROR_NO_ENROLLED_PRINTS;">if there are no enrolled prints for the chosen user</doc:error>
+ <doc:error name="&ERROR_INTERNAL;">if there was an internal error</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <method name="VerifyStop">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Stop an on-going fingerprint verification started with <doc:ref type="method" to="Device.VerifyStart">Device.VerifyStart</doc:ref>.
+ </doc:para>
+ </doc:description>
+
+ <doc:errors>
+ <doc:error name="&ERROR_PERMISSION_DENIED;">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="&ERROR_CLAIM_DEVICE;">if the device was not claimed</doc:error>
+ <doc:error name="&ERROR_NO_ACTION_IN_PROGRESS;">if there was no ongoing verification</doc:error>
+ <doc:error name="&ERROR_INTERNAL;">if there was an internal error</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <signal name="VerifyFingerSelected">
+ <arg type="s" name="finger_name">
+ <doc:doc>
+ <doc:summary>
+ <doc:para>
+ A string representing the finger select to be verified.
+ </doc:para>
+ </doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:seealso>
+ <doc:ref type="description" to="fingerprint-names">Fingerprint names</doc:ref>.
+ </doc:seealso>
+ </doc:doc>
+ </signal>
+
+ <!-- ************************************************************ -->
+
+ <signal name="VerifyStatus">
+ <arg type="s" name="result">
+ <doc:doc>
+ <doc:summary>
+ A string representing the status of the verification.
+ </doc:summary>
+ </doc:doc>
+ </arg>
+
+ <arg type="b" name="done">
+ <doc:doc>
+ <doc:summary>
+ Whether the verification finished and can be stopped.
+ </doc:summary>
+ </doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:seealso>
+ <doc:ref type="description" to="verify-statuses">Verify Statuses</doc:ref> and <doc:ref type="method" to="Device.VerifyStop">Device.VerifyStop</doc:ref>.
+ </doc:seealso>
+ </doc:doc>
+ </signal>
+
+ <!-- ************************************************************ -->
+
+ <method name="EnrollStart">
+ <arg type="s" name="finger_name" direction="in">
+ <doc:doc><doc:summary>A string representing the finger to enroll. See
+ <doc:ref type="description" to="fingerprint-names">Fingerprint names</doc:ref>.
+ Note that "any" is not a valid finger name for this method.</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Start enrollment for the selected finger. You need to have claimed the device using
+ <doc:ref type="method" to="Device.Claim">Device.Claim</doc:ref> before calling
+ this method. Enrollment status is sent through <doc:ref type="signal" to="Device::EnrollStatus">Device::EnrollStatus</doc:ref>.
+ </doc:para>
+ </doc:description>
+
+ <doc:errors>
+ <doc:error name="&ERROR_PERMISSION_DENIED;">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="&ERROR_CLAIM_DEVICE;">if the device was not claimed</doc:error>
+ <doc:error name="&ERROR_ALREADY_IN_USE;">if the device was already being used</doc:error>
+ <doc:error name="&ERROR_INVALID_FINGERNAME;">if the finger name passed is invalid</doc:error>
+ <doc:error name="&ERROR_INTERNAL;">if there was an internal error</doc:error>
+ </doc:errors>
+
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <method name="EnrollStop">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Stop an on-going fingerprint enrollment started with <doc:ref type="method" to="Device.EnrollStart">Device.EnrollStart</doc:ref>.
+ </doc:para>
+ </doc:description>
+
+ <doc:errors>
+ <doc:error name="&ERROR_PERMISSION_DENIED;">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="&ERROR_CLAIM_DEVICE;">if the device was not claimed</doc:error>
+ <doc:error name="&ERROR_NO_ACTION_IN_PROGRESS;">if there was no ongoing verification</doc:error>
+ <doc:error name="&ERROR_INTERNAL;">if there was an internal error</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <signal name="EnrollStatus">
+ <arg type="s" name="result">
+ <doc:doc>
+ <doc:summary>
+ A string representing the status of the enrollment.
+ </doc:summary>
+ </doc:doc>
+ </arg>
+
+ <arg type="b" name="done">
+ <doc:doc>
+ <doc:summary>
+ Whether the enrollment finished and can be stopped.
+ </doc:summary>
+ </doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:seealso>
+ <doc:ref type="description" to="enroll-statuses">Enrollment Statuses</doc:ref> and <doc:ref type="method" to="Device.EnrollStop">Device.EnrollStop</doc:ref>.
+ </doc:seealso>
+ </doc:doc>
+ </signal>
+
+ <!-- ************************************************************ -->
+
+ <property name="name" type="s" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ The product name of the device.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ <!-- ************************************************************ -->
+
+ <property name="num-enroll-stages" type="i" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ The number of enrollment stages for the device. This is only available when the device has been claimed, otherwise it will be undefined (-1).
+ </doc:para>
+ <doc:seealso>
+ <doc:ref type="method" to="Device.Claim">Device.Claim</doc:ref> and <doc:ref type="method" to="Device.EnrollStart">Device.EnrollStart</doc:ref>.
+ </doc:seealso>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ <!-- ************************************************************ -->
+
+ <property name="scan-type" type="s" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ The scan type of the device, either "press" if you place your finger on the device, or "swipe" if you have to swipe your finger.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ </interface>
+</node>
+
diff --git a/panels/user-accounts/data/net.reactivated.Fprint.Manager.xml b/panels/user-accounts/data/net.reactivated.Fprint.Manager.xml
new file mode 100644
index 0000000..f4a38c7
--- /dev/null
+++ b/panels/user-accounts/data/net.reactivated.Fprint.Manager.xml
@@ -0,0 +1,50 @@
+<!DOCTYPE node PUBLIC
+"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd" [
+<!ENTITY ERROR_NO_SUCH_DEVICE "net.reactivated.Fprint.Error.NoSuchDevice">
+]>
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+ <interface name="net.reactivated.Fprint.Manager">
+ <annotation name="org.freedesktop.DBus.GLib.CSymbol"
+ value="fprint_manager" />
+
+ <!-- ************************************************************ -->
+
+ <method name="GetDevices">
+ <arg type="ao" name="devices" direction="out">
+ <doc:doc><doc:summary>An array of object paths for devices.</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Enumerate all the fingerprint readers attached to the system. If there are
+ no devices available, an empty array is returned.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <method name="GetDefaultDevice">
+ <arg type="o" name="device" direction="out">
+ <doc:doc><doc:summary>The object path for the default device.</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Returns the default fingerprint reader device.
+ </doc:para>
+ </doc:description>
+
+ <doc:errors>
+ <doc:error name="&ERROR_NO_SUCH_DEVICE;">if the device does not exist</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ </interface>
+</node>
+
diff --git a/panels/user-accounts/data/org.freedesktop.realmd.xml b/panels/user-accounts/data/org.freedesktop.realmd.xml
new file mode 100644
index 0000000..316213a
--- /dev/null
+++ b/panels/user-accounts/data/org.freedesktop.realmd.xml
@@ -0,0 +1,666 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node name="/">
+
+ <!--
+ org.freedesktop.realmd.Provider:
+ @short_description: a realm provider
+
+ Various realm providers represent different software implementations
+ that provide access to realms or domains.
+
+ This interface is implemented by individual providers, but is
+ aggregated globally at the system bus name
+ <literal>org.freedesktop.realmd</literal>
+ with the object path <literal>/org/freedesktop/realmd</literal>
+ -->
+ <interface name="org.freedesktop.realmd.Provider">
+
+ <!--
+ Name: the name of the provider
+
+ The name of the provider. This is not normally displayed
+ to the user, but may be useful for diagnostics or debugging.
+ -->
+ <property name="Name" type="s" access="read"/>
+
+ <!--
+ Version: the version of the provider
+
+ The version of the provider. This is not normally used in
+ logic, but may be useful for diagnostics or debugging.
+ -->
+ <property name="Version" type="s" access="read"/>
+
+ <!--
+ Realms: a list of realms
+
+ A list of known, enrolled or discovered realms. All realms
+ that this provider knows about are listed here. As realms
+ are discovered they are added to this list.
+
+ Each realm is represented by the DBus object path of the
+ realm object.
+ -->
+ <property name="Realms" type="ao" access="read"/>
+
+ <!--
+ Discover:
+ @string: an input string to discover realms for
+ @options: options for the discovery operation
+ @relevance: the relevance of the returned results
+ @realm: a list of realms discovered
+
+ Discover realms for the given string. The input @string is
+ usually a domain or realm name, perhaps typed by a user. If
+ an empty string is provided the realm provider should try to
+ discover a default realm if possible (eg: from DHCP).
+
+ @options can contain, but is not limited to, the following values:
+ <itemizedlist>
+ <listitem><para><literal>operation</literal>: a string
+ identifier chosen by the client, which can then later be
+ passed to org.freedesktop.realmd.Service.Cancel() in order
+ to cancel the operation</para></listitem>
+ </itemizedlist>
+
+ The @relevance returned can be used to rank results from
+ different discover calls to different providers. Implementors
+ should return a positive number if the provider highly
+ recommends that the realms be handled by this provider,
+ or a zero if it can possibly handle the realms. Negative
+ should be returned if no realms are found.
+
+ This method does not return an error when no realms are
+ discovered. It simply returns an @realm list.
+
+ To see diagnostic information about the discovery process
+ connect to the org.freedesktop.realmd.Service::Diagnostics
+ signal.
+
+ This method requires authorization for the PolicyKit action
+ called <literal>org.freedesktop.realmd.discover-realm</literal>.
+
+ In addition to common DBus error results, this method may
+ return:
+ <itemizedlist>
+ <listitem><para><literal>org.freedesktop.realmd.Error.Failed</literal>:
+ may be returned if the discovery could not be run for some reason.</para></listitem>
+ <listitem><para><literal>org.freedesktop.realmd.Error.Cancelled</literal>:
+ returned if the operation was cancelled.</para></listitem>
+ <listitem><para><literal>org.freedesktop.realmd.Error.NotAuthorized</literal>:
+ returned if the calling client is not permitted to perform a discovery
+ operation.</para></listitem>
+ </itemizedlist>
+ -->
+ <method name="Discover">
+ <arg name="string" type="s" direction="in"/>
+ <arg name="options" type="a{sv}" direction="in"/>
+ <arg name="relevance" type="i" direction="out"/>
+ <arg name="realm" type="ao" direction="out"/>
+ </method>
+
+ </interface>
+
+ <!--
+ org.freedesktop.realmd.Service:
+ @short_description: the realmd service
+
+ Global calls for managing the realmd service. Usually you'll want
+ to use #org.freedesktop.realmd.Provider instead.
+
+ This interface is implemented by the realmd service, and is always
+ available at the object path <literal>/org/freedesktop/realmd</literal>
+
+ The service also implements the
+ <literal>org.freedesktop.DBus.ObjectManager</literal> interface which
+ makes it easy to retrieve all realmd objects and properties in one go.
+ -->
+ <interface name="org.freedesktop.realmd.Service">
+
+ <!--
+ Cancel:
+ @operation: the operation to cancel
+
+ Cancel a realmd operation. To be able to cancel an operation
+ pass a uniquely chosen <literal>operation</literal> string
+ identifier as an option in the methods <literal>options</literal>
+ argument.
+
+ These operation string identifiers should be unique per client
+ calling the realmd service.
+
+ It is not guaranteed that the service can or will cancel the
+ operation. For example the operation may have already completed
+ by the time this method is handled. The caller of the operation
+ method will receive a
+ <literal>org.freedesktop.realmd.Error.Cancelled</literal>
+ if the operation was cancelled.
+ -->
+ <method name="Cancel">
+ <arg name="operation" type="s" direction="in"/>
+ </method>
+
+ <!--
+ SetLocale:
+ @locale: the locale for the client
+
+ Set the language @locale for the client. This locale is used
+ for error messages. The locale is used until the next time
+ this method is called, the client disconnects, or the client
+ calls #org.freedesktop.realmd.Service.Release().
+ -->
+ <method name="SetLocale">
+ <arg name="locale" type="s" direction="in"/>
+ </method>
+
+ <!--
+ Diagnostics:
+ @data: diagnostic data
+ @operation: the operation this data resulted from
+
+ This signal is fired when diagnostics result from an operation
+ in the provider or one of its realms.
+
+ It is not guaranteed that this signal is emitted once per line.
+ More than one line may be contained in @data, or a partial
+ line. New line characters are embedded in @data.
+
+ This signal is sent explicitly to the client which invoked
+ operation method. In order to tell which operation this
+ diagnostic data results from, pass a unique
+ <literal>operation</literal> string identifier in the
+ <literal>options</literal> argument of the operation method.
+ That same identifier will be passed back via the @operation
+ argument of this signal.
+ -->
+ <signal name="Diagnostics">
+ <arg name="data" type="s"/>
+ <arg name="operation" type="s"/>
+ </signal>
+
+ <!--
+ Release:
+
+ Normally realmd waits until all clients have disconnected
+ before exiting itself, sometime later. For long lived clients
+ they can call this method to allow the realmd service to quit.
+ This is an optimization. The daemon will not exit immediately.
+ It is safe to call this multiple times.
+ -->
+ <method name="Release">
+ <!-- no arguments -->
+ </method>
+
+ </interface>
+
+ <!--
+ org.freedesktop.realmd.Realm:
+ @short_description: a realm
+
+ Represents one realm.
+
+ Contains generic information about a realm, and useful properties for
+ introspecting what kind of realm this is and how to work with
+ the realm.
+
+ Use #org.freedesktop.realmd.Provider:Realms or
+ #org.freedesktop.realmd.Provider.Discover() to get access to some
+ kerberos realm objects.
+
+ Realms will always implement additional interfaces, such as
+ #org.freedesktop.realmd.Kerberos. Do not assume that all realms
+ implement that kerberos interface. Use the
+ #org.freedesktop.realmd.Realm:SupportedInterfaces property to see
+ which interfaces are set.
+
+ Different realms support various ways to configure them on the
+ system. Use the #org.freedesktop.realmd.Realm:Configured property
+ to determine if a realm is configured. If it is configured the
+ property will be set to the interface of the mechanism that was
+ used to configure it.
+
+ To configure a realm, look in the
+ #org.freedesktop.realmd.Realm:SupportedInterfaces property for a
+ recognized purpose specific interface that can be used for
+ configuration, such as the
+ #org.freedesktop.realmd.KerberosMembership interface and its
+ #org.freedesktop.realmd.KerberosMembership.Join() method.
+
+ To deconfigure a realm from the current system, you can use the
+ #org.freedesktop.realmd.Realm.Deconfigure() method. In additon some
+ of the configuration specific interfaces provide methods to
+ deconfigure a realm in a specific way, such as
+ #org.freedesktop.realmd.KerberosMembership.Leave() method.
+
+ The various properties are guaranteed to have been updated before
+ the operation methods return, if they change state.
+ -->
+ <interface name="org.freedesktop.realmd.Realm">
+
+ <!--
+ Name: the realm name
+
+ This is the name of the realm, appropriate for display to
+ end users where necessary.
+ -->
+ <property name="Name" type="s" access="read"/>
+
+ <!--
+ Configured: whether this domain is configured and how
+
+ If this property is an empty string, then the realm is not
+ configured. Otherwise the realm is configured, and contains
+ a string which is the interface that represents how it was
+ configured, for example #org.freedesktop.realmd.KerberosMembership.
+ -->
+ <property name="Configured" type="s" access="read"/>
+
+ <!--
+ Deconfigure: deconfigure this realm
+
+ Deconfigure this realm from the local machine with standard
+ default behavior.
+
+ The behavior of this method depends on the which configuration
+ interface is present in the
+ #org.freedesktop.realmd.Realm.Configured property. It does not
+ always delete membership accounts in the realm, but just
+ reconfigures the local machine so it no longer is configured
+ for the given realm. In some cases the implementation may try
+ to update membership accounts, but this is not guaranteed.
+
+ Various configuration interfaces may support more specific ways
+ to deconfigure a realm in a specific way, such as the
+ #org.freedesktop.realmd.KerberosMembership.Leave() method.
+
+ @options can contain, but is not limited to, the following values:
+ <itemizedlist>
+ <listitem><para><literal>operation</literal>: a string
+ identifier chosen by the client, which can then later be
+ passed to org.freedesktop.realmd.Service.Cancel() in order
+ to cancel the operation</para></listitem>
+ </itemizedlist>
+
+ This method requires authorization for the PolicyKit action
+ called <literal>org.freedesktop.realmd.deconfigure-realm</literal>.
+
+ In addition to common DBus error results, this method may return:
+ <itemizedlist>
+ <listitem><para><literal>org.freedesktop.realmd.Error.Failed</literal>:
+ may be returned if the deconfigure failed for a generic reason.</para></listitem>
+ <listitem><para><literal>org.freedesktop.realmd.Error.Cancelled</literal>:
+ returned if the operation was cancelled.</para></listitem>
+ <listitem><para><literal>org.freedesktop.realmd.Error.NotAuthorized</literal>:
+ returned if the calling client is not permitted to deconfigure a
+ realm.</para></listitem>
+ <listitem><para><literal>org.freedesktop.realmd.Error.NotConfigured</literal>:
+ returned if this realm is not configured on the machine.</para></listitem>
+ <listitem><para><literal>org.freedesktop.realmd.Error.Busy</literal>:
+ returned if the service is currently performing another operation like
+ join or leave.</para></listitem>
+ </itemizedlist>
+ -->
+ <method name="Deconfigure">
+ <arg name="options" type="a{sv}" direction="in"/>
+ </method>
+
+ <!--
+ SupportedInterfaces:
+
+ Additional supported interfaces of this realm. This includes
+ interfaces that contain more information about the realm,
+ such as #org.freedesktop.realmd.Kerberos and interfaces
+ which contain methods for configuring a realm, such as
+ #org.freedesktop.realmd.KerberosMembership.
+ -->
+ <property name="SupportedInterfaces" type="as" access="read"/>
+
+ <!--
+ Details: informational details about the realm
+
+ Informational details about the realm. The following values
+ should be present:
+ <itemizedlist>
+ <listitem><para><literal>server-software</literal>:
+ identifier of the software running on the server (eg:
+ <literal>active-directory</literal>).</para></listitem>
+ <listitem><para><literal>client-software</literal>:
+ identifier of the software running on the client (eg:
+ <literal>sssd</literal>).</para></listitem>
+ </itemizedlist>
+ -->
+ <property name="Details" type="a(ss)" access="read"/>
+
+ <!--
+ LoginFormats: supported formats for login names
+
+ Supported formats for login to this realm. This is only
+ relevant once the realm has been enrolled. The formats
+ will contain a <literal>%U</literal> in the string, which
+ indicate where the user name should be placed. The formats
+ may contain a <literal>%D</literal> in the string which
+ indicate where a domain name should be placed.
+
+ The first format in the list is the preferred format for
+ login names.
+ -->
+ <property name="LoginFormats" type="as" access="read"/>
+
+ <!--
+ LoginPolicy: the policy for logins using this realm
+
+ The policy for logging into this computer using this realm.
+
+ The policy can be changed using the
+ #org.freedesktop.realmd.Realm.ChangeLoginPolicy() method.
+
+ The following policies are predefined. Not all providers
+ support all these policies and there may be provider specific
+ policies or multiple policies represented in the string:
+ <itemizedlist>
+ <listitem><para><literal>allow-any-login</literal>: allow
+ login by any authenticated user present in this
+ realm.</para></listitem>
+ <listitem><para><literal>allow-permitted-logins</literal>:
+ only allow the logins permitted in the
+ #org.freedesktop.realmd.Realm:PermittedLogins
+ property.</para></listitem>
+ <listitem><para><literal>deny-any-login</literal>:
+ don't allow any logins via authenticated users of this
+ realm.</para></listitem>
+ </itemizedlist>
+ -->
+ <property name="LoginPolicy" type="s" access="read"/>
+
+ <!--
+ PermittedLogins: the permitted login names
+
+ The list of permitted authenticated users allowed to login
+ into this computer. This is only relevant if the
+ #org.freedesktop.realmd.Realm:LoginPolicy property
+ contains the <literal>allow-permitted-logins</literal>
+ string.
+ -->
+ <property name="PermittedLogins" type="as" access="read"/>
+
+ <!--
+ ChangeLoginPolicy:
+ @login_policy: the new login policy, or an empty string
+ @permitted_add: a list of logins to permit
+ @permitted_remove: a list of logins to not permit
+ @options: options for this operation
+
+ Change the login policy and/or permitted logins for this realm.
+
+ Not all realms support the all the various login policies. An
+ error will be returned if the new login policy is not supported.
+ You may specify an empty string for the @login_policy argument
+ which will cause no change in the policy itself. If the policy
+ is changed, it will be reflected in the
+ #org.freedesktop.realmd.Realm:LoginPolicy property.
+
+ The @permitted_add and @permitted_remove arguments represent
+ lists of login names that should be added and removed from
+ the #org.freedesktop.realmd.Kerberos:PermittedLogins property.
+
+ @options can contain, but is not limited to, the following values:
+ <itemizedlist>
+ <listitem><para><literal>operation</literal>: a string
+ identifier chosen by the client, which can then later be
+ passed to org.freedesktop.realmd.Service.Cancel() in order
+ to cancel the operation</para></listitem>
+ </itemizedlist>
+
+ This method requires authorization for the PolicyKit action
+ called <literal>org.freedesktop.realmd.login-policy</literal>.
+
+ In addition to common DBus error results, this method may return:
+ <itemizedlist>
+ <listitem><para><literal>org.freedesktop.realmd.Error.Failed</literal>:
+ may be returned if the policy change failed for a generic reason.</para></listitem>
+ <listitem><para><literal>org.freedesktop.realmd.Error.Cancelled</literal>:
+ returned if the operation was cancelled.</para></listitem>
+ <listitem><para><literal>org.freedesktop.realmd.Error.NotAuthorized</literal>:
+ returned if the calling client is not permitted to change login policy
+ operation.</para></listitem>
+ <listitem><para><literal>org.freedesktop.realmd.Error.NotConfigured</literal>:
+ returned if the realm is not configured.</para></listitem>
+ <listitem><para><literal>org.freedesktop.realmd.Error.Busy</literal>:
+ returned if the service is currently performing another operation like
+ join or leave.</para></listitem>
+ </itemizedlist>
+ -->
+ <method name="ChangeLoginPolicy">
+ <arg name="login_policy" type="s" direction="in"/>
+ <arg name="permitted_add" type="as" direction="in"/>
+ <arg name="permitted_remove" type="as" direction="in"/>
+ <arg name="options" type="a{sv}" direction="in"/>
+ </method>
+
+ </interface>
+
+ <!--
+ org.freedesktop.realmd.Kerberos:
+ @short_description: a kerberos realm
+
+ An interface that describes a kerberos realm in more detail. This
+ is always implemented on an DBus object path that also implements
+ the #org.freedesktop.realmd.Realm interface.
+ -->
+ <interface name="org.freedesktop.realmd.Kerberos">
+
+ <!--
+ RealmName: the kerberos realm name
+
+ The kerberos name for this realm. This is usually in upper
+ case.
+ -->
+ <property name="RealmName" type="s" access="read"/>
+
+ <!--
+ DomainName: the DNS domain name
+
+ The DNS domain name for this realm.
+ -->
+ <property name="DomainName" type="s" access="read"/>
+
+ </interface>
+
+ <!--
+ org.freedesktop.realmd.KerberosMembership:
+
+ An interface used to configure this machine by joining a realm.
+
+ It sets up a computer/host account in the realm for this machine
+ and a keytab to track the credentials for that account.
+
+ The various properties are guaranteed to have been updated before
+ the operation methods return, if they change state.
+ -->
+ <interface name="org.freedesktop.realmd.KerberosMembership">
+
+ <!--
+ SuggestedAdministrator: common administrator name
+
+ The common administrator name for this type of realm. This
+ can be used by clients as a hint when prompting the user for
+ administrative authentication.
+ -->
+ <property name="SuggestedAdministrator" type="s" access="read"/>
+
+ <!--
+ SupportedJoinCredentials: credentials supported for joining
+
+ Various kinds of credentials that are supported when calling the
+ #org.freedesktop.realmd.Kerberos.Join() method.
+
+ Each credential is represented by a type, and an owner. The type
+ denotes which kind of credential is passed to the method. The
+ owner indicates to the client how to prompt the user or obtain
+ the credential, and to the service how to use the credential.
+
+ The various types are:
+ <itemizedlist>
+ <listitem><para><literal>ccache</literal>:
+ the credentials should contain an array of bytes as a
+ <literal>ay</literal> containing the data from a kerberos
+ credential cache file.</para></listitem>
+ <listitem><para><literal>password</literal>:
+ the credentials should contain a pair of strings as a
+ <literal>(ss)</literal> representing a name and
+ password. The name may contain a realm in the standard
+ kerberos format. If missing, it will default to this
+ realm. The name may be empty for a computer or one time
+ password.</para></listitem>
+ <listitem><para><literal>automatic</literal>:
+ the credentials should contain an empty string as a
+ <literal>s</literal>. Using <literal>automatic</literal>
+ indicates that default or system credentials are to be
+ used.</para></listitem>
+ </itemizedlist>
+
+ The various owners are:
+ <itemizedlist>
+ <listitem><para><literal>administrator</literal>:
+ the credentials belong to a kerberos user principal.
+ The caller may use this as a hint to prompt the user
+ for administrative credentials.</para></listitem>
+ <listitem><para><literal>user</literal>:
+ the credentials belong to a kerberos user principal.
+ The caller may use this as a hint to prompt the user
+ for his (possibly non-administrative)
+ credentials.</para></listitem>
+ <listitem><para><literal>computer</literal>:
+ the credentials belong to the computer realmd is
+ being run on.</para></listitem>
+ <listitem><para><literal>secret</literal>:
+ the credentials are a one time password or other secret
+ used to join or leave the computer.</para></listitem>
+ </itemizedlist>
+ -->
+ <property name="SupportedJoinCredentials" type="a(ss)" access="read"/>
+
+ <!--
+ SupportedLeaveCredentials: credentials supported for leaving
+
+ Various kinds of credentials that are supported when calling the
+ #org.freedesktop.realmd.Kerberos.Leave() method.
+
+ See #org.freedesktop.realmd.Kerberos:SupportedJoinCredentials for
+ a discussion of what the values represent.
+ -->
+ <property name="SupportedLeaveCredentials" type="a(ss)" access="read"/>
+
+ <!--
+ Join:
+
+ Join this machine to the realm and enroll the machine.
+
+ If this method returns successfully then the machine will be
+ joined to the realm. It is not necessary to restart services or the
+ machine afterward. Relevant properties on the realm will be updated
+ before the method returns.
+
+ The @credentials should be set according to one of the
+ supported credentials returned by
+ #org.freedesktop.realmd.Kerberos:SupportedJoinCredentials.
+ The first string in the tuple is the type, the second string
+ is the owner, and the variant contains the credential contents
+ See the discussion at
+ #org.freedesktop.realmd.Kerberos:SupportedJoinCredentials
+ for more information.
+
+ @options can contain, but is not limited to, the following values:
+ <itemizedlist>
+ <listitem><para><literal>operation</literal>: a string
+ identifier chosen by the client, which can then later be
+ passed to org.freedesktop.realmd.Service.Cancel() in order
+ to cancel the operation</para></listitem>
+ </itemizedlist>
+
+ This method requires authorization for the PolicyKit action
+ called <literal>org.freedesktop.realmd.configure-realm</literal>.
+
+ In addition to common DBus error results, this method may return:
+ <itemizedlist>
+ <listitem><para><literal>org.freedesktop.realmd.Error.Failed</literal>:
+ may be returned if the join failed for a generic reason.</para></listitem>
+ <listitem><para><literal>org.freedesktop.realmd.Error.Cancelled</literal>:
+ returned if the operation was cancelled.</para></listitem>
+ <listitem><para><literal>org.freedesktop.realmd.Error.NotAuthorized</literal>:
+ returned if the calling client is not permitted to perform an join
+ operation.</para></listitem>
+ <listitem><para><literal>org.freedesktop.realmd.Error.AuthenicationFailed</literal>:
+ returned if the credentials passed did not authenticate against the realm
+ correctly. It is appropriate to prompt the user again.</para></listitem>
+ <listitem><para><literal>org.freedesktop.realmd.Error.AlreadyEnrolled</literal>:
+ returned if already enrolled in this realm, or another realm and enrolling
+ in multiple realms is not supported.</para></listitem>
+ <listitem><para><literal>org.freedesktop.realmd.Error.Busy</literal>:
+ returned if the service is currently performing another operation like
+ join or leave.</para></listitem>
+ </itemizedlist>
+ -->
+ <method name="Join">
+ <arg name="credentials" type="(ssv)" direction="in"/>
+ <arg name="options" type="a{sv}" direction="in"/>
+ </method>
+
+ <!--
+ Leave:
+
+ Leave the realm and unenroll the machine.
+
+ If this method returns successfully then the machine will have
+ left the domain and been unenrolled. It is not necessary to restart
+ services or the machine afterward. Relevant properties on the realm
+ will be updated before the method returns.
+
+ The @credentials should be set according to one of the
+ supported credentials returned by
+ #org.freedesktop.realmd.Kerberos:SupportedUnenrollCredentials.
+ The first string in the tuple is the type, the second string
+ is the owner, and the variant contains the credential contents
+ See the discussion at
+ #org.freedesktop.realmd.Kerberos:SupportedEnrollCredentials
+ for more information.
+
+ @options can contain, but is not limited to, the following values:
+ <itemizedlist>
+ <listitem><para><literal>operation</literal>: a string
+ identifier chosen by the client, which can then later be
+ passed to org.freedesktop.realmd.Service.Cancel() in order
+ to cancel the operation</para></listitem>
+ </itemizedlist>
+
+ This method requires authorization for the PolicyKit action
+ called <literal>org.freedesktop.realmd.deconfigure-realm</literal>.
+
+ In addition to common DBus error results, this method may return:
+ <itemizedlist>
+ <listitem><para><literal>org.freedesktop.realmd.Error.Failed</literal>:
+ may be returned if the unenroll failed for a generic reason.</para></listitem>
+ <listitem><para><literal>org.freedesktop.realmd.Error.Cancelled</literal>:
+ returned if the operation was cancelled.</para></listitem>
+ <listitem><para><literal>org.freedesktop.realmd.Error.NotAuthorized</literal>:
+ returned if the calling client is not permitted to perform an unenroll
+ operation.</para></listitem>
+ <listitem><para><literal>org.freedesktop.realmd.Error.AuthenicationFailed</literal>:
+ returned if the credentials passed did not authenticate against the realm
+ correctly. It is appropriate to prompt the user again.</para></listitem>
+ <listitem><para><literal>org.freedesktop.realmd.Error.NotEnrolled</literal>:
+ returned if not enrolled in this realm.</para></listitem>
+ <listitem><para><literal>org.freedesktop.realmd.Error.Busy</literal>:
+ returned if the service is currently performing another operation like
+ enroll or unenroll.</para></listitem>
+ </itemizedlist>
+ -->
+ <method name="Leave">
+ <arg name="credentials" type="(ssv)" direction="in"/>
+ <arg name="options" type="a{sv}" direction="in"/>
+ </method>
+
+ </interface>
+
+</node>
diff --git a/panels/user-accounts/data/user-accounts-dialog.css b/panels/user-accounts/data/user-accounts-dialog.css
new file mode 100644
index 0000000..7a984a4
--- /dev/null
+++ b/panels/user-accounts/data/user-accounts-dialog.css
@@ -0,0 +1,23 @@
+levelbar .strength-weak {
+ background-color: #cc0000;
+ border-color: #cc0000;
+}
+
+levelbar .strength-low {
+ background-color: #f5ce00;
+ border-color: #f5ce00;
+}
+
+levelbar .strength-medium,
+levelbar .strength-good,
+levelbar .strength-high {
+ background-color: #73d216;
+ border-color: #73d216;
+}
+
+/* This is used for user_avatar_edit_button */
+.cutout-button {
+ background-color: @window_bg_color;
+ border-radius: 9999px;
+ padding: 2px;
+}
diff --git a/panels/user-accounts/fingerprint-strings.h b/panels/user-accounts/fingerprint-strings.h
new file mode 100644
index 0000000..e65491d
--- /dev/null
+++ b/panels/user-accounts/fingerprint-strings.h
@@ -0,0 +1,172 @@
+/*
+ * Helper functions to translate statuses and actions to strings
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
+ *
+ * Experimental code. This will be moved out of fprintd into it's own
+ * package once the system has matured.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+struct {
+ const char *dbus_name;
+ const char *place_str_generic;
+ const char *place_str_specific;
+ const char *swipe_str_generic;
+ const char *swipe_str_specific;
+} fingers[] = {
+ { "any",
+ N_("Place your finger on the fingerprint reader"),
+ N_("Place your finger on %s"),
+ N_("Swipe your finger across the fingerprint reader"),
+ N_("Swipe your finger across %s") },
+ { "left-thumb",
+ N_("Place your left thumb on the fingerprint reader"),
+ N_("Place your left thumb on %s"),
+ N_("Swipe your left thumb across the fingerprint reader"),
+ N_("Swipe your left thumb across %s") },
+ { "left-index-finger",
+ N_("Place your left index finger on the fingerprint reader"),
+ N_("Place your left index finger on %s"),
+ N_("Swipe your left index finger across the fingerprint reader"),
+ N_("Swipe your left index finger across %s") },
+ { "left-middle-finger",
+ N_("Place your left middle finger on the fingerprint reader"),
+ N_("Place your left middle finger on %s"),
+ N_("Swipe your left middle finger across the fingerprint reader"),
+ N_("Swipe your left middle finger across %s") },
+ { "left-ring-finger",
+ N_("Place your left ring finger on the fingerprint reader"),
+ N_("Place your left ring finger on %s"),
+ N_("Swipe your left ring finger across the fingerprint reader"),
+ N_("Swipe your left ring finger across %s") },
+ { "left-little-finger",
+ N_("Place your left little finger on the fingerprint reader"),
+ N_("Place your left little finger on %s"),
+ N_("Swipe your left little finger across the fingerprint reader"),
+ N_("Swipe your left little finger across %s") },
+ { "right-thumb",
+ N_("Place your right thumb on the fingerprint reader"),
+ N_("Place your right thumb on %s"),
+ N_("Swipe your right thumb across the fingerprint reader"),
+ N_("Swipe your right thumb across %s") },
+ { "right-index-finger",
+ N_("Place your right index finger on the fingerprint reader"),
+ N_("Place your right index finger on %s"),
+ N_("Swipe your right index finger across the fingerprint reader"),
+ N_("Swipe your right index finger across %s") },
+ { "right-middle-finger",
+ N_("Place your right middle finger on the fingerprint reader"),
+ N_("Place your right middle finger on %s"),
+ N_("Swipe your right middle finger across the fingerprint reader"),
+ N_("Swipe your right middle finger across %s") },
+ { "right-ring-finger",
+ N_("Place your right ring finger on the fingerprint reader"),
+ N_("Place your right ring finger on %s"),
+ N_("Swipe your right ring finger across the fingerprint reader"),
+ N_("Swipe your right ring finger across %s") },
+ { "right-little-finger",
+ N_("Place your right little finger on the fingerprint reader"),
+ N_("Place your right little finger on %s"),
+ N_("Swipe your right little finger across the fingerprint reader"),
+ N_("Swipe your right little finger across %s") },
+ { NULL, NULL, NULL, NULL, NULL }
+};
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+
+G_GNUC_UNUSED static char *finger_str_to_msg(const char *finger_name, const char *driver_name, gboolean is_swipe)
+{
+ int i;
+
+ if (finger_name == NULL)
+ return NULL;
+
+ for (i = 0; fingers[i].dbus_name != NULL; i++) {
+ if (g_str_equal (fingers[i].dbus_name, finger_name)) {
+ if (is_swipe == FALSE) {
+ if (driver_name)
+ return g_strdup_printf (TR (fingers[i].place_str_specific), driver_name);
+ else
+ return g_strdup (TR (fingers[i].place_str_generic));
+ } else {
+ if (driver_name)
+ return g_strdup_printf (TR (fingers[i].swipe_str_specific), driver_name);
+ else
+ return g_strdup (TR (fingers[i].swipe_str_generic));
+ }
+ }
+ }
+
+ return NULL;
+}
+
+#pragma GCC diagnostic pop
+
+/* Cases not handled:
+ * verify-no-match
+ * verify-match
+ * verify-unknown-error
+ */
+G_GNUC_UNUSED static const char *verify_result_str_to_msg(const char *result, gboolean is_swipe)
+{
+ if (result == NULL)
+ return NULL;
+
+ if (strcmp (result, "verify-retry-scan") == 0) {
+ if (is_swipe == FALSE)
+ return TR (N_("Place your finger on the reader again"));
+ else
+ return TR (N_("Swipe your finger again"));
+ }
+ if (strcmp (result, "verify-swipe-too-short") == 0)
+ return TR (N_("Swipe was too short, try again"));
+ if (strcmp (result, "verify-finger-not-centered") == 0)
+ return TR (N_("Your finger was not centered, try swiping your finger again"));
+ if (strcmp (result, "verify-remove-and-retry") == 0)
+ return TR (N_("Remove your finger, and try swiping your finger again"));
+
+ return NULL;
+}
+
+/* Cases not handled:
+ * enroll-completed
+ * enroll-failed
+ * enroll-unknown-error
+ */
+G_GNUC_UNUSED static const char *enroll_result_str_to_msg(const char *result, gboolean is_swipe)
+{
+ if (result == NULL)
+ return NULL;
+
+ if (strcmp (result, "enroll-retry-scan") == 0 || strcmp (result, "enroll-stage-passed") == 0) {
+ if (is_swipe == FALSE)
+ return TR (N_("Place your finger on the reader again"));
+ else
+ return TR (N_("Swipe your finger again"));
+ }
+ if (strcmp (result, "enroll-swipe-too-short") == 0)
+ return TR (N_("Swipe was too short, try again"));
+ if (strcmp (result, "enroll-finger-not-centered") == 0)
+ return TR (N_("Your finger was not centered, try swiping your finger again"));
+ if (strcmp (result, "enroll-remove-and-retry") == 0)
+ return TR (N_("Remove your finger, and try swiping your finger again"));
+
+ return NULL;
+}
+
diff --git a/panels/user-accounts/icons/meson.build b/panels/user-accounts/icons/meson.build
new file mode 100644
index 0000000..2daa0b3
--- /dev/null
+++ b/panels/user-accounts/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-users-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/user-accounts/icons/scalable/org.gnome.Settings-users-symbolic.svg b/panels/user-accounts/icons/scalable/org.gnome.Settings-users-symbolic.svg
new file mode 100644
index 0000000..15ef7ee
--- /dev/null
+++ b/panels/user-accounts/icons/scalable/org.gnome.Settings-users-symbolic.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <path d="m 5 1 c -1.378906 0 -2.5 1.121094 -2.5 2.5 s 1.121094 2.5 2.5 2.5 s 2.5 -1.121094 2.5 -2.5 s -1.121094 -2.5 -2.5 -2.5 z m 6 3 c -1.378906 0 -2.5 1.121094 -2.5 2.5 s 1.121094 2.5 2.5 2.5 s 2.5 -1.121094 2.5 -2.5 s -1.121094 -2.5 -2.5 -2.5 z m -8 3 c -1.660156 0 -3 1.339844 -3 3 v 2 c 0 0.554688 0.445312 1 1 1 h 4.074219 c 0 -2.042969 1.582031 -3.734375 3.582031 -3.910156 c -0.589844 -0.53125 -0.984375 -1.253906 -1.109375 -2.039063 c -0.175781 -0.03125 -0.359375 -0.050781 -0.546875 -0.050781 z m 6 3 c -1.660156 0 -3 1.339844 -3 3 v 2 c 0 0.554688 0.445312 1 1 1 h 8 c 0.554688 0 1 -0.445312 1 -1 v -2 c 0 -1.660156 -1.339844 -3 -3 -3 z m 0 0" fill="#2e3436"/>
+</svg>
diff --git a/panels/user-accounts/meson.build b/panels/user-accounts/meson.build
new file mode 100644
index 0000000..d9efd1f
--- /dev/null
+++ b/panels/user-accounts/meson.build
@@ -0,0 +1,199 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: 'data/' + desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+image_data = files(
+ 'data/faces/bicycle.jpg',
+ 'data/faces/book.jpg',
+ 'data/faces/calculator.jpg',
+ 'data/faces/cat.jpg',
+ 'data/faces/coffee2.jpg',
+ 'data/faces/flower2.jpg',
+ 'data/faces/gamepad.jpg',
+ 'data/faces/guitar2.jpg',
+ 'data/faces/headphones.jpg',
+ 'data/faces/hummingbird.jpg',
+ 'data/faces/mountain.jpg',
+ 'data/faces/plane.jpg',
+ 'data/faces/surfer.jpg',
+ 'data/faces/tomatoes.jpg',
+ 'data/faces/tree.jpg',
+)
+
+legacy_image_data = files(
+ 'data/faces/legacy/astronaut.jpg',
+ 'data/faces/legacy/baseball.png',
+ 'data/faces/legacy/butterfly.png',
+ 'data/faces/legacy/cat-eye.jpg',
+ 'data/faces/legacy/chess.jpg',
+ 'data/faces/legacy/coffee.jpg',
+ 'data/faces/legacy/dice.jpg',
+ 'data/faces/legacy/energy-arc.jpg',
+ 'data/faces/legacy/fish.jpg',
+ 'data/faces/legacy/flake.jpg',
+ 'data/faces/legacy/flower.jpg',
+ 'data/faces/legacy/grapes.jpg',
+ 'data/faces/legacy/guitar.jpg',
+ 'data/faces/legacy/launch.jpg',
+ 'data/faces/legacy/leaf.jpg',
+ 'data/faces/legacy/lightning.jpg',
+ 'data/faces/legacy/penguin.jpg',
+ 'data/faces/legacy/puppy.jpg',
+ 'data/faces/legacy/sky.jpg',
+ 'data/faces/legacy/soccerball.png',
+ 'data/faces/legacy/sunflower.jpg',
+ 'data/faces/legacy/sunset.jpg',
+ 'data/faces/legacy/tennis-ball.png',
+ 'data/faces/legacy/yellow-rose.jpg',
+)
+
+image_dir = join_paths(control_center_datadir, 'pixmaps', 'faces')
+
+install_data(
+ image_data,
+ install_dir: image_dir
+)
+
+legacy_image_dir = join_paths(image_dir, 'legacy')
+
+install_data(
+ legacy_image_data,
+ install_dir: legacy_image_dir
+)
+
+# create symlinks for legacy images to not break current images for people
+meson.add_install_script('sh', '-c',
+ '''for f in $DESTDIR@0@/*; do
+ ln -sf legacy/$(basename $f) $DESTDIR@1@/$(basename $f);
+ done'''.format(legacy_image_dir, image_dir))
+
+polkit = 'org.gnome.controlcenter.@0@.policy'.format(cappletname)
+
+i18n.merge_file(
+ input: polkit + '.in',
+ output: polkit,
+ po_dir: po_dir,
+ install: true,
+ install_dir: join_paths(control_center_datadir, 'polkit-1', 'actions')
+)
+
+common_sources = files(
+ 'cc-add-user-dialog.c',
+ 'cc-realm-manager.c',
+ 'pw-utils.c',
+ 'user-utils.c',
+)
+
+resource_data = files(
+ 'cc-add-user-dialog.ui',
+ 'cc-avatar-chooser.ui',
+ 'cc-login-history-dialog.ui',
+ 'cc-password-dialog.ui',
+ 'cc-user-panel.ui',
+ 'cc-fingerprint-dialog.ui',
+ 'data/icons/fingerprint-detection-complete-symbolic.svg',
+ 'data/icons/fingerprint-detection-symbolic.svg',
+ 'data/icons/fingerprint-detection-warning-symbolic.svg',
+ 'data/join-dialog.ui',
+ 'data/user-accounts-dialog.css',
+ 'data/cc-fingerprint-dialog.css',
+)
+
+common_sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname.underscorify(),
+ dependencies: resource_data,
+ export: true
+)
+
+realmd_namespace = 'org.freedesktop.realmd'
+
+common_sources += gnome.gdbus_codegen(
+ 'cc-realm-generated',
+ 'data/' + realmd_namespace + '.xml',
+ interface_prefix: realmd_namespace + '.',
+ namespace: 'CcRealm',
+ object_manager: true,
+ annotations: ['org.freedesktop.realmd.Realm', 'org.gtk.GDBus.C.Name', 'Common']
+)
+
+fprintd_namespace = 'net.reactivated.Fprint'
+common_sources += gnome.gdbus_codegen(
+ 'cc-fprintd-generated',
+ sources: [
+ 'data' / fprintd_namespace + '.Manager.xml',
+ 'data' / fprintd_namespace + '.Device.xml',
+ ],
+ interface_prefix: fprintd_namespace + '.',
+ namespace: 'CcFprintd',
+ autocleanup: 'all',
+)
+
+enum_headers = [
+ 'cc-fingerprint-manager.h',
+]
+
+sources = common_sources + files(
+ 'cc-avatar-chooser.c',
+ 'cc-crop-area.c',
+ 'cc-fingerprint-manager.c',
+ 'cc-fingerprint-dialog.c',
+ 'cc-login-history-dialog.c',
+ 'cc-password-dialog.c',
+ 'cc-user-panel.c',
+ 'run-passwd.c',
+)
+
+sources += gnome.mkenums_simple(
+ 'cc-user-accounts-enum-types',
+ sources: files(enum_headers))
+
+# Kerberos support
+krb_dep = dependency('krb5', required: false)
+assert(krb_dep.found(), 'kerberos libraries not found in your path')
+
+deps = common_deps + [
+ accounts_dep,
+ gdk_pixbuf_dep,
+ gnome_desktop_dep,
+ liblanguage_dep,
+ krb_dep,
+ m_dep,
+ polkit_gobject_dep,
+ pwquality_dep,
+]
+
+if enable_malcontent
+ deps += malcontent_dep
+endif
+
+cflags += [
+ '-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir),
+ '-DHAVE_LIBPWQUALITY',
+ '-DUM_PIXMAP_DIR="@0@"'.format(join_paths(control_center_pkgdatadir, 'pixmaps'))
+]
+
+panels_libs += static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [top_inc, shell_inc],
+ dependencies: deps,
+ c_args: cflags
+)
+
+subdir('icons')
diff --git a/panels/user-accounts/org.gnome.controlcenter.user-accounts.policy.in b/panels/user-accounts/org.gnome.controlcenter.user-accounts.policy.in
new file mode 100644
index 0000000..c6f09c1
--- /dev/null
+++ b/panels/user-accounts/org.gnome.controlcenter.user-accounts.policy.in
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE policyconfig PUBLIC
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
+
+<policyconfig>
+ <vendor>The GNOME Project</vendor>
+ <vendor_url>http://www.gnome.org/</vendor_url>
+
+ <action id="org.gnome.controlcenter.user-accounts.administration">
+ <description>Manage user accounts</description>
+ <message>Authentication is required to change user data</message>
+ <defaults>
+ <allow_any>no</allow_any>
+ <allow_inactive>no</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ <annotate key="org.freedesktop.policykit.imply">org.freedesktop.accounts.user-administration org.freedesktop.realmd.configure-realm org.freedesktop.realmd.login-policy org.freedesktop.MalcontentControl.administration com.endlessm.ParentalControls.AppFilter.ReadAny com.endlessm.ParentalControls.AppFilter.ChangeAny com.endlessm.ParentalControls.AppFilter.ReadOwn com.endlessm.ParentalControls.AppFilter.ChangeOwn</annotate>
+ </action>
+
+</policyconfig>
diff --git a/panels/user-accounts/pw-utils.c b/panels/user-accounts/pw-utils.c
new file mode 100644
index 0000000..0f4dfd8
--- /dev/null
+++ b/panels/user-accounts/pw-utils.c
@@ -0,0 +1,177 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#include "config.h"
+
+#include "pw-utils.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <pwquality.h>
+
+static pwquality_settings_t *
+get_pwq (void)
+{
+ static pwquality_settings_t *settings;
+
+ if (settings == NULL) {
+ gchar *err = NULL;
+ gint rv = 0;
+
+ settings = pwquality_default_settings ();
+ pwquality_set_int_value (settings, PWQ_SETTING_MAX_SEQUENCE, 4);
+
+ rv = pwquality_read_config (settings, NULL, (gpointer)&err);
+ if (rv < 0) {
+ g_warning ("failed to read pwquality configuration: %s\n",
+ pwquality_strerror (NULL, 0, rv, err));
+ pwquality_free_settings (settings);
+
+ /* Load just default settings in case of failure. */
+ settings = pwquality_default_settings ();
+ pwquality_set_int_value (settings, PWQ_SETTING_MAX_SEQUENCE, 4);
+ }
+ }
+
+ return settings;
+}
+
+gint
+pw_min_length (void)
+{
+ gint value = 0;
+ gint rv;
+
+ rv = pwquality_get_int_value (get_pwq (), PWQ_SETTING_MIN_LENGTH, &value);
+ if (rv < 0) {
+ g_warning ("Failed to read pwquality setting: %s\n",
+ pwquality_strerror (NULL, 0, rv, NULL));
+ }
+
+ return value;
+}
+
+gchar *
+pw_generate (void)
+{
+ gchar *res;
+ gint rv;
+
+ rv = pwquality_generate (get_pwq (), 0, &res);
+
+ if (rv < 0) {
+ g_warning ("Password generation failed: %s\n",
+ pwquality_strerror (NULL, 0, rv, NULL));
+ return NULL;
+ }
+
+ return res;
+}
+
+static const gchar *
+pw_error_hint (gint error)
+{
+ switch (error) {
+ case PWQ_ERROR_SAME_PASSWORD:
+ return C_("Password hint", "The new password needs to be different from the old one.");
+ case PWQ_ERROR_CASE_CHANGES_ONLY:
+ return C_("Password hint", "Try changing some letters and numbers.");
+ case PWQ_ERROR_TOO_SIMILAR:
+ return C_("Password hint", "Try changing the password a bit more.");
+ case PWQ_ERROR_USER_CHECK:
+ return C_("Password hint", "A password without your user name would be stronger.");
+ case PWQ_ERROR_GECOS_CHECK:
+ return C_("Password hint", "Try to avoid using your name in the password.");
+ case PWQ_ERROR_BAD_WORDS:
+ return C_("Password hint", "Try to avoid some of the words included in the password.");
+ case PWQ_ERROR_ROTATED:
+ return C_("Password hint", "Try changing the password a bit more.");
+ case PWQ_ERROR_CRACKLIB_CHECK:
+ return C_("Password hint", "Try to avoid common words.");
+ case PWQ_ERROR_PALINDROME:
+ return C_("Password hint", "Try to avoid reordering existing words.");
+ case PWQ_ERROR_MIN_DIGITS:
+ return C_("Password hint", "Try to use more numbers.");
+ case PWQ_ERROR_MIN_UPPERS:
+ return C_("Password hint", "Try to use more uppercase letters.");
+ case PWQ_ERROR_MIN_LOWERS:
+ return C_("Password hint", "Try to use more lowercase letters.");
+ case PWQ_ERROR_MIN_OTHERS:
+ return C_("Password hint", "Try to use more special characters, like punctuation.");
+ case PWQ_ERROR_MIN_CLASSES:
+ return C_("Password hint", "Try to use a mixture of letters, numbers and punctuation.");
+ case PWQ_ERROR_MAX_CONSECUTIVE:
+ return C_("Password hint", "Try to avoid repeating the same character.");
+ case PWQ_ERROR_MAX_CLASS_REPEAT:
+ return C_("Password hint", "Try to avoid repeating the same type of character: you need to mix up letters, numbers and punctuation.");
+ case PWQ_ERROR_MAX_SEQUENCE:
+ return C_("Password hint", "Try to avoid sequences like 1234 or abcd.");
+ case PWQ_ERROR_MIN_LENGTH:
+ return C_("Password hint", "Password needs to be longer. Try to add more letters, numbers and punctuation.");
+ case PWQ_ERROR_EMPTY_PASSWORD:
+ return C_("Password hint", "Mix uppercase and lowercase and try to use a number or two.");
+ default:
+ return C_("Password hint", "Adding more letters, numbers and punctuation will make the password stronger.");
+ }
+}
+
+gdouble
+pw_strength (const gchar *password,
+ const gchar *old_password,
+ const gchar *username,
+ const gchar **hint,
+ gint *strength_level)
+{
+ gint rv, level, length = 0;
+ gdouble strength = 0.0;
+ void *auxerror;
+
+ rv = pwquality_check (get_pwq (),
+ password, old_password, username,
+ &auxerror);
+
+ if (password != NULL)
+ length = strlen (password);
+
+ strength = CLAMP (0.01 * rv, 0.0, 1.0);
+ if (rv < 0) {
+ level = (length > 0) ? 1 : 0;
+ }
+ else if (strength < 0.50) {
+ level = 2;
+ } else if (strength < 0.75) {
+ level = 3;
+ } else if (strength < 0.90) {
+ level = 4;
+ } else {
+ level = 5;
+ }
+
+ if (length && length < pw_min_length())
+ *hint = pw_error_hint (PWQ_ERROR_MIN_LENGTH);
+ else
+ *hint = pw_error_hint (rv);
+
+ if (strength_level)
+ *strength_level = level;
+
+ return strength;
+}
diff --git a/panels/user-accounts/pw-utils.h b/panels/user-accounts/pw-utils.h
new file mode 100644
index 0000000..d7df491
--- /dev/null
+++ b/panels/user-accounts/pw-utils.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#pragma once
+
+#include <glib.h>
+
+gint pw_min_length (void);
+gchar *pw_generate (void);
+gdouble pw_strength (const gchar *password,
+ const gchar *old_password,
+ const gchar *username,
+ const gchar **hint,
+ gint *strength_level);
diff --git a/panels/user-accounts/run-passwd.c b/panels/user-accounts/run-passwd.c
new file mode 100644
index 0000000..edbc998
--- /dev/null
+++ b/panels/user-accounts/run-passwd.c
@@ -0,0 +1,737 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* run-passwd.c: this file is part of users-admin, a gnome-system-tools frontend
+ * for user administration.
+ *
+ * Copyright (C) 2002 Diego Gonzalez
+ * Copyright (C) 2006 Johannes H. Jensen
+ * Copyright (C) 2010 Milan Bouchet-Valat
+ *
+ * Written by: Diego Gonzalez <diego@pemas.net>
+ * Modified by: Johannes H. Jensen <joh@deworks.net>,
+ * Milan Bouchet-Valat <nalimilan@club.fr>.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Most of this code originally comes from gnome-about-me-password.c,
+ * from gnome-control-center.
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/wait.h>
+
+#if __sun
+#include <sys/types.h>
+#include <signal.h>
+#endif
+
+#include "run-passwd.h"
+
+/* Passwd states */
+typedef enum {
+ PASSWD_STATE_NONE, /* Passwd is not asking for anything */
+ PASSWD_STATE_AUTH, /* Passwd is asking for our current password */
+ PASSWD_STATE_NEW, /* Passwd is asking for our new password */
+ PASSWD_STATE_RETYPE, /* Passwd is asking for our retyped new password */
+ PASSWD_STATE_DONE, /* Passwd succeeded but has not yet exited */
+ PASSWD_STATE_ERR /* Passwd reported an error but has not yet exited */
+} PasswdState;
+
+struct PasswdHandler {
+ const char *current_password;
+ const char *new_password;
+
+ /* Communication with the passwd program */
+ GPid backend_pid;
+
+ GIOChannel *backend_stdin;
+ GIOChannel *backend_stdout;
+
+ GQueue *backend_stdin_queue; /* Write queue to backend_stdin */
+
+ /* GMainLoop IDs */
+ guint backend_child_watch_id; /* g_child_watch_add (PID) */
+ guint backend_stdout_watch_id; /* g_io_add_watch (stdout) */
+
+ /* State of the passwd program */
+ PasswdState backend_state;
+ gboolean changing_password;
+
+ PasswdCallback auth_cb;
+ gpointer auth_cb_data;
+
+ PasswdCallback chpasswd_cb;
+ gpointer chpasswd_cb_data;
+};
+
+/* Buffer size for backend output */
+#define BUFSIZE 64
+
+
+static GQuark
+passwd_error_quark (void)
+{
+ static GQuark q = 0;
+
+ if (q == 0) {
+ q = g_quark_from_static_string("passwd_error");
+ }
+
+ return q;
+}
+
+/* Error handling */
+#define PASSWD_ERROR (passwd_error_quark ())
+
+
+static void
+stop_passwd (PasswdHandler *passwd_handler);
+
+static void
+free_passwd_resources (PasswdHandler *passwd_handler);
+
+static gboolean
+io_watch_stdout (GIOChannel *source, GIOCondition condition, PasswdHandler *passwd_handler);
+
+
+/*
+ * Spawning and closing of backend {{
+ */
+
+/* Child watcher */
+static void
+child_watch_cb (GPid pid, gint status, PasswdHandler *passwd_handler)
+{
+ if (WIFEXITED (status)) {
+ if (WEXITSTATUS (status) >= 255) {
+ g_warning ("Child exited unexpectedly");
+ }
+ if (WEXITSTATUS (status) == 0) {
+ if (passwd_handler->backend_state == PASSWD_STATE_RETYPE) {
+ passwd_handler->backend_state = PASSWD_STATE_DONE;
+ if (passwd_handler->chpasswd_cb)
+ passwd_handler->chpasswd_cb (passwd_handler,
+ NULL,
+ passwd_handler->chpasswd_cb_data);
+ }
+ }
+ }
+
+ free_passwd_resources (passwd_handler);
+}
+
+static void
+child_setup_cb (gpointer data)
+{
+ signal (SIGPIPE, SIG_IGN);
+ dup2 (fileno (stdout), fileno (stderr));
+}
+
+/* Spawn passwd backend
+ * Returns: TRUE on success, FALSE otherwise and sets error appropriately */
+static gboolean
+spawn_passwd (PasswdHandler *passwd_handler, GError **error)
+{
+ gchar *argv[2];
+ gchar **envp;
+ gint my_stdin, my_stdout;
+
+ argv[0] = "/usr/bin/passwd"; /* Is it safe to rely on a hard-coded path? */
+ argv[1] = NULL;
+
+ envp = g_get_environ ();
+ envp = g_environ_setenv (envp, "LC_ALL", "C", TRUE);
+
+ if (!g_spawn_async_with_pipes (NULL, /* Working directory */
+ argv, /* Argument vector */
+ envp, /* Environment */
+ G_SPAWN_DO_NOT_REAP_CHILD, /* Flags */
+ child_setup_cb, /* Child setup */
+ NULL, /* Data to child setup */
+ &passwd_handler->backend_pid, /* PID */
+ &my_stdin, /* Stdin */
+ &my_stdout, /* Stdout */
+ NULL, /* Stderr */
+ error)) { /* GError */
+
+ /* An error occurred */
+ free_passwd_resources (passwd_handler);
+
+ g_strfreev (envp);
+
+ return FALSE;
+ }
+
+ g_strfreev (envp);
+
+ /* Open IO Channels */
+ passwd_handler->backend_stdin = g_io_channel_unix_new (my_stdin);
+ passwd_handler->backend_stdout = g_io_channel_unix_new (my_stdout);
+
+ /* Set raw encoding */
+ /* Set nonblocking mode */
+ if (g_io_channel_set_encoding (passwd_handler->backend_stdin, NULL, error) != G_IO_STATUS_NORMAL ||
+ g_io_channel_set_encoding (passwd_handler->backend_stdout, NULL, error) != G_IO_STATUS_NORMAL ||
+ g_io_channel_set_flags (passwd_handler->backend_stdin, G_IO_FLAG_NONBLOCK, error) != G_IO_STATUS_NORMAL ||
+ g_io_channel_set_flags (passwd_handler->backend_stdout, G_IO_FLAG_NONBLOCK, error) != G_IO_STATUS_NORMAL ) {
+
+ /* Clean up */
+ stop_passwd (passwd_handler);
+ return FALSE;
+ }
+
+ /* Turn off buffering */
+ g_io_channel_set_buffered (passwd_handler->backend_stdin, FALSE);
+ g_io_channel_set_buffered (passwd_handler->backend_stdout, FALSE);
+
+ /* Add IO Channel watcher */
+ passwd_handler->backend_stdout_watch_id = g_io_add_watch (passwd_handler->backend_stdout,
+ G_IO_IN | G_IO_PRI,
+ (GIOFunc) io_watch_stdout, passwd_handler);
+
+ /* Add child watcher */
+ passwd_handler->backend_child_watch_id = g_child_watch_add (passwd_handler->backend_pid, (GChildWatchFunc) child_watch_cb, passwd_handler);
+
+ /* Success! */
+
+ return TRUE;
+}
+
+/* Stop passwd backend */
+static void
+stop_passwd (PasswdHandler *passwd_handler)
+{
+ /* This is the standard way of returning from the dialog with passwd.
+ * If we return this way we can safely kill passwd as it has completed
+ * its task.
+ */
+
+ if (passwd_handler->backend_pid != -1) {
+ kill (passwd_handler->backend_pid, 9);
+ }
+
+ /* We must run free_passwd_resources here and not let our child
+ * watcher do it, since it will access invalid memory after the
+ * dialog has been closed and cleaned up.
+ *
+ * If we had more than a single thread we'd need to remove
+ * the child watch before trying to kill the child.
+ */
+ free_passwd_resources (passwd_handler);
+}
+
+/* Clean up passwd resources */
+static void
+free_passwd_resources (PasswdHandler *passwd_handler)
+{
+ /* Remove the child watcher */
+ if (passwd_handler->backend_child_watch_id != 0) {
+
+ g_source_remove (passwd_handler->backend_child_watch_id);
+
+ passwd_handler->backend_child_watch_id = 0;
+ }
+
+
+ /* Close IO channels (internal file descriptors are automatically closed) */
+ if (passwd_handler->backend_stdin != NULL) {
+ g_autoptr(GError) error = NULL;
+
+ if (g_io_channel_shutdown (passwd_handler->backend_stdin, TRUE, &error) != G_IO_STATUS_NORMAL) {
+ g_warning ("Could not shutdown backend_stdin IO channel: %s", error->message);
+ }
+
+ g_clear_pointer (&passwd_handler->backend_stdin, g_io_channel_unref);
+ }
+
+ if (passwd_handler->backend_stdout != NULL) {
+ g_autoptr(GError) error = NULL;
+
+ if (g_io_channel_shutdown (passwd_handler->backend_stdout, TRUE, &error) != G_IO_STATUS_NORMAL) {
+ g_warning ("Could not shutdown backend_stdout IO channel: %s", error->message);
+ }
+
+ g_clear_pointer (&passwd_handler->backend_stdout, g_io_channel_unref);
+ }
+
+ /* Remove IO watcher */
+ if (passwd_handler->backend_stdout_watch_id != 0) {
+
+ g_source_remove (passwd_handler->backend_stdout_watch_id);
+
+ passwd_handler->backend_stdout_watch_id = 0;
+ }
+
+ /* Close PID */
+ if (passwd_handler->backend_pid != -1) {
+
+ g_spawn_close_pid (passwd_handler->backend_pid);
+
+ passwd_handler->backend_pid = -1;
+ }
+
+ /* Clear backend state */
+ passwd_handler->backend_state = PASSWD_STATE_NONE;
+}
+
+/*
+ * }} Spawning and closing of backend
+ */
+
+/*
+ * Backend communication code {{
+ */
+
+/* Write the first element of queue through channel */
+static void
+io_queue_pop (GQueue *queue, GIOChannel *channel)
+{
+ g_autofree gchar *buf = NULL;
+ gsize bytes_written;
+ g_autoptr(GError) error = NULL;
+
+ buf = g_queue_pop_head (queue);
+
+ if (buf != NULL) {
+
+ if (g_io_channel_write_chars (channel, buf, -1, &bytes_written, &error) != G_IO_STATUS_NORMAL) {
+ g_warning ("Could not write queue element \"%s\" to channel: %s", buf, error->message);
+ }
+
+ /* Ensure passwords are cleared from memory */
+ memset (buf, 0, strlen (buf));
+ }
+}
+
+/* Goes through the argument list, checking if one of them occurs in str
+ * Returns: TRUE as soon as an element is found to match, FALSE otherwise */
+static gboolean
+is_string_complete (gchar *str, ...)
+{
+ va_list ap;
+ gchar *arg;
+
+ if (strlen (str) == 0) {
+ return FALSE;
+ }
+
+ va_start (ap, str);
+
+ while ((arg = va_arg (ap, char *)) != NULL) {
+ if (strstr (str, arg) != NULL) {
+ va_end (ap);
+ return TRUE;
+ }
+ }
+
+ va_end (ap);
+
+ return FALSE;
+}
+
+/*
+ * IO watcher for stdout, called whenever there is data to read from the backend.
+ * This is where most of the actual IO handling happens.
+ */
+static gboolean
+io_watch_stdout (GIOChannel *source, GIOCondition condition, PasswdHandler *passwd_handler)
+{
+ static GString *str = NULL; /* Persistent buffer */
+
+ gchar buf[BUFSIZE]; /* Temporary buffer */
+ gsize bytes_read;
+ g_autoptr(GError) gio_error = NULL;
+
+ gboolean reinit = FALSE;
+
+ /* Initialize buffer */
+ if (str == NULL) {
+ str = g_string_new ("");
+ }
+
+ if (g_io_channel_read_chars (source, buf, BUFSIZE, &bytes_read, &gio_error)
+ != G_IO_STATUS_NORMAL) {
+ g_warning ("IO Channel read error: %s", gio_error->message);
+ return TRUE;
+ }
+
+ str = g_string_append_len (str, buf, bytes_read);
+
+ /* In which state is the backend? */
+ switch (passwd_handler->backend_state) {
+ case PASSWD_STATE_AUTH:
+ /* Passwd is asking for our current password */
+
+ if (is_string_complete (str->str, "assword: ", "failure", "wrong", "error", NULL)) {
+
+ if (strstr (str->str, "assword: ") != NULL &&
+ strstr (str->str, "incorrect") == NULL &&
+ strstr (str->str, "urrent") == NULL) {
+ /* Authentication successful */
+
+ passwd_handler->backend_state = PASSWD_STATE_NEW;
+
+ /* Trigger callback to update authentication status */
+ if (passwd_handler->auth_cb)
+ passwd_handler->auth_cb (passwd_handler,
+ NULL,
+ passwd_handler->auth_cb_data);
+
+ } else {
+ /* Authentication failed */
+ g_autoptr(GError) error = NULL;
+
+ error = g_error_new_literal (PASSWD_ERROR, PASSWD_ERROR_AUTH_FAILED,
+ _("Authentication failed"));
+
+ passwd_handler->changing_password = FALSE;
+
+ /* This error can happen both while authenticating or while changing password:
+ * if chpasswd_cb is set, this means we're already changing password */
+ if (passwd_handler->chpasswd_cb)
+ passwd_handler->chpasswd_cb (passwd_handler,
+ error,
+ passwd_handler->chpasswd_cb_data);
+ else if (passwd_handler->auth_cb)
+ passwd_handler->auth_cb (passwd_handler,
+ error,
+ passwd_handler->auth_cb_data);
+ }
+
+ reinit = TRUE;
+ }
+ break;
+ case PASSWD_STATE_NEW:
+ /* Passwd is asking for our new password */
+
+ if (is_string_complete (str->str, "assword: ", NULL)) {
+ /* Advance to next state */
+ passwd_handler->backend_state = PASSWD_STATE_RETYPE;
+
+ /* Pop retyped password from queue and into IO channel */
+ io_queue_pop (passwd_handler->backend_stdin_queue, passwd_handler->backend_stdin);
+
+ reinit = TRUE;
+ }
+ break;
+ case PASSWD_STATE_RETYPE:
+ /* Passwd is asking for our retyped new password */
+
+ if (is_string_complete (str->str,
+ "successfully",
+ "short",
+ "longer",
+ "palindrome",
+ "dictionary",
+ "simple",
+ "simplistic",
+ "similar",
+ "case",
+ "different",
+ "wrapped",
+ "recovered",
+ "recent",
+ "unchanged",
+ "match",
+ "1 numeric or special",
+ "failure",
+ "DIFFERENT",
+ "BAD PASSWORD",
+ NULL)) {
+
+ if (strstr (str->str, "successfully") != NULL) {
+ /* Hooray! */
+
+ passwd_handler->backend_state = PASSWD_STATE_DONE;
+ /* Trigger callback to update status */
+ if (passwd_handler->chpasswd_cb)
+ passwd_handler->chpasswd_cb (passwd_handler,
+ NULL,
+ passwd_handler->chpasswd_cb_data);
+ }
+ else {
+ /* Ohnoes! */
+ g_autoptr(GError) error = NULL;
+
+ if (strstr (str->str, "recovered") != NULL) {
+ /* What does this indicate?
+ * "Authentication information cannot be recovered?" from libpam? */
+ error = g_error_new_literal (PASSWD_ERROR, PASSWD_ERROR_UNKNOWN,
+ str->str);
+ } else if (strstr (str->str, "short") != NULL ||
+ strstr (str->str, "longer") != NULL) {
+ error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_REJECTED,
+ _("The new password is too short"));
+ } else if (strstr (str->str, "palindrome") != NULL ||
+ strstr (str->str, "simple") != NULL ||
+ strstr (str->str, "simplistic") != NULL ||
+ strstr (str->str, "dictionary") != NULL) {
+ error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_REJECTED,
+ _("The new password is too simple"));
+ } else if (strstr (str->str, "similar") != NULL ||
+ strstr (str->str, "different") != NULL ||
+ strstr (str->str, "case") != NULL ||
+ strstr (str->str, "wrapped") != NULL) {
+ error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_REJECTED,
+ _("The old and new passwords are too similar"));
+ } else if (strstr (str->str, "recent") != NULL) {
+ error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_REJECTED,
+ _("The new password has already been used recently."));
+ } else if (strstr (str->str, "1 numeric or special") != NULL) {
+ error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_REJECTED,
+ _("The new password must contain numeric or special characters"));
+ } else if (strstr (str->str, "unchanged") != NULL ||
+ strstr (str->str, "match") != NULL) {
+ error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_REJECTED,
+ _("The old and new passwords are the same"));
+ } else if (strstr (str->str, "failure") != NULL) {
+ /* Authentication failure */
+ error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_AUTH_FAILED,
+ _("Your password has been changed since you initially authenticated!"));
+ }
+ else if (strstr (str->str, "DIFFERENT")) {
+ error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_REJECTED,
+ _("The new password does not contain enough different characters"));
+ }
+ else {
+ error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_UNKNOWN,
+ _("Unknown error"));
+ }
+
+ /* At this point, passwd might have exited, in which case
+ * child_watch_cb should clean up for us and remove this watcher.
+ * On some error conditions though, passwd just re-prompts us
+ * for our new password. */
+ passwd_handler->backend_state = PASSWD_STATE_ERR;
+
+ passwd_handler->changing_password = FALSE;
+
+ /* Trigger callback to update status */
+ if (passwd_handler->chpasswd_cb)
+ passwd_handler->chpasswd_cb (passwd_handler,
+ error,
+ passwd_handler->chpasswd_cb_data);
+ }
+
+ reinit = TRUE;
+
+ /* child_watch_cb should clean up for us now */
+ }
+ break;
+ case PASSWD_STATE_NONE:
+ /* Passwd is not asking for anything yet */
+ if (is_string_complete (str->str, "assword: ", NULL)) {
+
+ /* If the user does not have a password set,
+ * passwd will immediately ask for the new password,
+ * so skip the AUTH phase */
+ if (is_string_complete (str->str, "new", "New", NULL)) {
+ g_autofree gchar *pw = NULL;
+
+ passwd_handler->backend_state = PASSWD_STATE_NEW;
+
+ /* since passwd didn't ask for our old password
+ * in this case, simply remove it from the queue */
+ pw = g_queue_pop_head (passwd_handler->backend_stdin_queue);
+
+ /* Pop the IO queue, i.e. send new password */
+ io_queue_pop (passwd_handler->backend_stdin_queue, passwd_handler->backend_stdin);
+
+ } else {
+
+ passwd_handler->backend_state = PASSWD_STATE_AUTH;
+
+ /* Pop the IO queue, i.e. send current password */
+ io_queue_pop (passwd_handler->backend_stdin_queue, passwd_handler->backend_stdin);
+ }
+
+ reinit = TRUE;
+ }
+ break;
+ default:
+ /* Passwd has returned an error */
+ reinit = TRUE;
+ break;
+ }
+
+ if (reinit) {
+ g_string_free (str, TRUE);
+ str = NULL;
+ }
+
+ /* Continue calling us */
+ return TRUE;
+}
+
+/*
+ * }} Backend communication code
+ */
+
+/* Adds the current password to the IO queue */
+static void
+authenticate (PasswdHandler *passwd_handler)
+{
+ gchar *s;
+
+ s = g_strdup_printf ("%s\n", passwd_handler->current_password);
+
+ g_queue_push_tail (passwd_handler->backend_stdin_queue, s);
+}
+
+/* Adds the new password twice to the IO queue */
+static void
+update_password (PasswdHandler *passwd_handler)
+{
+ gchar *s;
+
+ s = g_strdup_printf ("%s\n", passwd_handler->new_password);
+
+ g_queue_push_tail (passwd_handler->backend_stdin_queue, s);
+ /* We need to allocate new space because io_queue_pop() g_free()s
+ * every element of the queue after it's done */
+ g_queue_push_tail (passwd_handler->backend_stdin_queue, g_strdup (s));
+}
+
+
+PasswdHandler *
+passwd_init (void)
+{
+ PasswdHandler *passwd_handler;
+
+ passwd_handler = g_new0 (PasswdHandler, 1);
+
+ /* Initialize backend_pid. -1 means the backend is not running */
+ passwd_handler->backend_pid = -1;
+
+ /* Initialize IO Channels */
+ passwd_handler->backend_stdin = NULL;
+ passwd_handler->backend_stdout = NULL;
+
+ /* Initialize write queue */
+ passwd_handler->backend_stdin_queue = g_queue_new ();
+
+ /* Initialize watchers */
+ passwd_handler->backend_child_watch_id = 0;
+ passwd_handler->backend_stdout_watch_id = 0;
+
+ /* Initialize backend state */
+ passwd_handler->backend_state = PASSWD_STATE_NONE;
+ passwd_handler->changing_password = FALSE;
+
+ return passwd_handler;
+}
+
+void
+passwd_destroy (PasswdHandler *passwd_handler)
+{
+ g_queue_free (passwd_handler->backend_stdin_queue);
+ stop_passwd (passwd_handler);
+ g_free (passwd_handler);
+}
+
+void
+passwd_authenticate (PasswdHandler *passwd_handler,
+ const char *current_password,
+ PasswdCallback cb,
+ const gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+
+ /* Don't stop if we've already started changing password */
+ if (passwd_handler->changing_password)
+ return;
+
+ /* Clear data from possible previous attempts to change password */
+ passwd_handler->new_password = NULL;
+ passwd_handler->chpasswd_cb = NULL;
+ passwd_handler->chpasswd_cb_data = NULL;
+ g_queue_foreach (passwd_handler->backend_stdin_queue, (GFunc) g_free, NULL);
+ g_queue_clear (passwd_handler->backend_stdin_queue);
+
+ passwd_handler->current_password = current_password;
+ passwd_handler->auth_cb = cb;
+ passwd_handler->auth_cb_data = user_data;
+
+ /* Spawn backend */
+ stop_passwd (passwd_handler);
+
+ if (!spawn_passwd (passwd_handler, &error)) {
+ g_warning ("%s", error->message);
+ return;
+ }
+
+ authenticate (passwd_handler);
+
+ /* Our IO watcher should now handle the rest */
+}
+
+gboolean
+passwd_change_password (PasswdHandler *passwd_handler,
+ const char *new_password,
+ PasswdCallback cb,
+ const gpointer user_data)
+{
+ passwd_handler->changing_password = TRUE;
+
+ passwd_handler->new_password = new_password;
+ passwd_handler->chpasswd_cb = cb;
+ passwd_handler->chpasswd_cb_data = user_data;
+
+ /* Stop passwd if an error occurred and it is still running */
+ if (passwd_handler->backend_state == PASSWD_STATE_ERR) {
+
+ /* Stop passwd, free resources */
+ stop_passwd (passwd_handler);
+ }
+
+ /* Check that the backend is still running, or that an error
+ * has occurred but it has not yet exited */
+ if (passwd_handler->backend_pid == -1) {
+ /* If it is not, re-run authentication */
+ g_autoptr(GError) error = NULL;
+
+ /* Spawn backend */
+ stop_passwd (passwd_handler);
+
+ if (!spawn_passwd (passwd_handler, &error)) {
+ g_warning ("%s", error->message);
+ return FALSE;
+ }
+
+ /* Add current and new passwords to queue */
+ authenticate (passwd_handler);
+ update_password (passwd_handler);
+ } else {
+ /* Only add new passwords to queue */
+ update_password (passwd_handler);
+ }
+
+ /* Pop new password through the backend.
+ * If user has no password, popping the queue would output current
+ * password, while 'passwd' is waiting for the new one. So wait for
+ * io_watch_stdout() to remove current password from the queue,
+ * and output the new one for us.
+ */
+ if (passwd_handler->current_password)
+ io_queue_pop (passwd_handler->backend_stdin_queue, passwd_handler->backend_stdin);
+
+ /* Our IO watcher should now handle the rest */
+
+ return TRUE;
+}
diff --git a/panels/user-accounts/run-passwd.h b/panels/user-accounts/run-passwd.h
new file mode 100644
index 0000000..c0362bd
--- /dev/null
+++ b/panels/user-accounts/run-passwd.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* run-passwd.h: this file is part of users-admin, a gnome-system-tools frontend
+ * for user administration.
+ *
+ * Copyright (C) 2010 Milan Bouchet-Valat
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Milan Bouchet-Valat <nalimilan@club.fr>
+ */
+
+#pragma once
+
+struct PasswdHandler;
+
+typedef struct PasswdHandler PasswdHandler;
+
+typedef void (*PasswdCallback) (PasswdHandler *passwd_handler, GError *error, const gpointer user_data);
+
+/* Error codes */
+typedef enum {
+ PASSWD_ERROR_REJECTED, /* New password is not secure enough */
+ PASSWD_ERROR_AUTH_FAILED, /* Wrong old password, or PAM failure */
+ PASSWD_ERROR_REAUTH_FAILED, /* Password has changed since first authentication */
+ PASSWD_ERROR_BACKEND, /* Backend error */
+ PASSWD_ERROR_UNKNOWN /* General error */
+} PasswdError;
+
+
+PasswdHandler *passwd_init (void);
+
+void passwd_destroy (PasswdHandler *passwd_handler);
+
+void passwd_authenticate (PasswdHandler *passwd_handler,
+ const char *current_password,
+ PasswdCallback cb,
+ gpointer user_data);
+
+gboolean passwd_change_password (PasswdHandler *passwd_handler,
+ const char *new_password,
+ PasswdCallback cb,
+ const gpointer user_data);
+
diff --git a/panels/user-accounts/user-accounts.gresource.xml b/panels/user-accounts/user-accounts.gresource.xml
new file mode 100644
index 0000000..ac8756a
--- /dev/null
+++ b/panels/user-accounts/user-accounts.gresource.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/user-accounts">
+ <file preprocess="xml-stripblanks">cc-add-user-dialog.ui</file>
+ <file preprocess="xml-stripblanks">cc-avatar-chooser.ui</file>
+ <file preprocess="xml-stripblanks">cc-login-history-dialog.ui</file>
+ <file preprocess="xml-stripblanks">cc-password-dialog.ui</file>
+ <file preprocess="xml-stripblanks">cc-user-panel.ui</file>
+ <file preprocess="xml-stripblanks">cc-fingerprint-dialog.ui</file>
+ <file alias="join-dialog.ui" preprocess="xml-stripblanks">data/join-dialog.ui</file>
+ <file alias="user-accounts-dialog.css">data/user-accounts-dialog.css</file>
+ <file alias="cc-fingerprint-dialog.css">data/cc-fingerprint-dialog.css</file>
+ </gresource>
+
+ <gresource prefix="/org/gnome/Settings/icons/scalable/status">
+ <file preprocess="xml-stripblanks" alias="fingerprint-detection-complete-symbolic.svg">data/icons/fingerprint-detection-complete-symbolic.svg</file>
+ <file preprocess="xml-stripblanks" alias="fingerprint-detection-symbolic.svg">data/icons/fingerprint-detection-symbolic.svg</file>
+ <file preprocess="xml-stripblanks" alias="fingerprint-detection-warning-symbolic.svg">data/icons/fingerprint-detection-warning-symbolic.svg</file>
+ </gresource>
+</gresources>
diff --git a/panels/user-accounts/user-utils.c b/panels/user-accounts/user-utils.c
new file mode 100644
index 0000000..5b7bc1f
--- /dev/null
+++ b/panels/user-accounts/user-utils.c
@@ -0,0 +1,471 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2009-2010 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#include "config.h"
+
+#include <math.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <limits.h>
+#include <unistd.h>
+#include <utmpx.h>
+#include <pwd.h>
+
+#ifdef __FreeBSD__
+#include <sysexits.h>
+#endif
+
+#include <gio/gio.h>
+#include <gio/gunixoutputstream.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+
+#include "user-utils.h"
+
+#define IMAGE_SIZE 512
+
+/* Taken from defines.h in shadow-utils. On Linux, this value is much smaller
+ * than the sysconf limit LOGIN_NAME_MAX, and values larger than this will
+ * result in failure when running useradd. We could check UT_NAMESIZE instead,
+ * but that is nonstandard. Better to use POSIX utmpx.
+ */
+gsize
+get_username_max_length (void)
+{
+ return sizeof (((struct utmpx *)NULL)->ut_user);
+}
+
+gboolean
+is_username_used (const gchar *username)
+{
+ struct passwd *pwent;
+
+ if (username == NULL || username[0] == '\0') {
+ return FALSE;
+ }
+
+ pwent = getpwnam (username);
+
+ return pwent != NULL;
+}
+
+gboolean
+is_valid_name (const gchar *name)
+{
+ gboolean is_empty = TRUE;
+ gboolean found_comma = FALSE;
+ const gchar *c;
+
+ if (name == NULL)
+ return is_empty;
+
+ /* Valid names must contain:
+ * 1) at least one character.
+ * 2) at least one non-"space" character.
+ * 3) comma character not allowed. Issue #888
+ */
+ for (c = name; *c; c++) {
+ gunichar unichar;
+
+ unichar = g_utf8_get_char_validated (c, -1);
+
+ /* Partial UTF-8 sequence or end of string */
+ if (unichar == (gunichar) -1 || unichar == (gunichar) -2)
+ break;
+
+ /* Check for non-space character */
+ if (is_empty && !g_unichar_isspace (unichar)) {
+ is_empty = FALSE;
+ }
+
+ if (unichar == ',') {
+ found_comma = TRUE;
+ break;
+ }
+ }
+
+ return !is_empty && !found_comma;
+}
+
+typedef struct {
+ gchar *username;
+ gchar *tip;
+} isValidUsernameData;
+
+static void
+is_valid_username_data_free (isValidUsernameData *data)
+{
+ g_clear_pointer (&data->username, g_free);
+ g_clear_pointer (&data->tip, g_free);
+ g_free (data);
+}
+
+#ifdef __FreeBSD__
+/* Taken from pw(8) man page. */
+#define E_SUCCESS EX_OK
+#define E_BAD_ARG EX_DATAERR
+#define E_NOTFOUND EX_NOUSER
+#else
+/* Taken from usermod.c in shadow-utils. */
+#define E_SUCCESS 0
+#define E_BAD_ARG 3
+#define E_NOTFOUND 6
+#endif
+
+static void
+is_valid_username_child_watch_cb (GPid pid,
+ gint status,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = G_TASK (user_data);
+ isValidUsernameData *data = g_task_get_task_data (task);
+ GError *error = NULL;
+ gboolean valid = FALSE;
+ const gchar *tip = NULL;
+
+ if (WIFEXITED (status)) {
+ switch (WEXITSTATUS (status)) {
+ case E_NOTFOUND:
+ valid = TRUE;
+ break;
+ case E_BAD_ARG:
+ tip = _("The username should usually only consist of lower case letters from a-z, digits and the following characters: - _");
+ valid = FALSE;
+ break;
+ case E_SUCCESS:
+ tip = _("Sorry, that user name isn’t available. Please try another.");
+ valid = FALSE;
+ break;
+ }
+ }
+
+ if (valid || tip != NULL) {
+ data->tip = g_strdup (tip);
+ g_task_return_boolean (task, valid);
+ }
+ else {
+ g_spawn_check_wait_status (status, &error);
+ g_task_return_error (task, error);
+ }
+
+ g_spawn_close_pid (pid);
+}
+
+void
+is_valid_username_async (const gchar *username,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ g_autoptr(GTask) task = NULL;
+ isValidUsernameData *data;
+ gchar *argv[6];
+ GPid pid;
+ GError *error = NULL;
+
+ task = g_task_new (NULL, cancellable, callback, callback_data);
+ g_task_set_source_tag (task, is_valid_username_async);
+
+ data = g_new0 (isValidUsernameData, 1);
+ data->username = g_strdup (username);
+ g_task_set_task_data (task, data, (GDestroyNotify) is_valid_username_data_free);
+
+ if (username == NULL || username[0] == '\0') {
+ g_task_return_boolean (task, FALSE);
+ return;
+ }
+ else if (strlen (username) > get_username_max_length ()) {
+ data->tip = g_strdup (_("The username is too long."));
+ g_task_return_boolean (task, FALSE);
+ return;
+ }
+
+#ifdef __FreeBSD__
+ /* Abuse "pw usershow -n <name>" in the same way as the code below. We
+ * don't use "pw usermod -n <name> -N -l <newname>" here because it has
+ * a special case for "root" to reject changes to the root user.
+ */
+ argv[0] = "pw";
+ argv[1] = "usershow";
+ argv[2] = "-n";
+ argv[3] = data->username;
+ argv[4] = NULL;
+#else
+ /* "usermod --login" is meant to be used to change a username, but the
+ * exit codes can be safely abused to check the validity of username.
+ * However, the current "usermod" implementation may change in the
+ * future, so it would be nice to have some official way for this
+ * instead of relying on the current "--login" implementation.
+ */
+ argv[0] = "/usr/sbin/usermod";
+ argv[1] = "--login";
+ argv[2] = data->username;
+ argv[3] = "--";
+ argv[4] = data->username;
+ argv[5] = NULL;
+#endif
+
+ if (!g_spawn_async (NULL, argv, NULL,
+ G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD |
+ G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL,
+ NULL, NULL, &pid, &error)) {
+ g_task_return_error (task, error);
+ return;
+ }
+
+ g_child_watch_add (pid, (GChildWatchFunc) is_valid_username_child_watch_cb, task);
+ g_steal_pointer (&task);
+}
+
+gboolean
+is_valid_username_finish (GAsyncResult *result,
+ gchar **tip,
+ gchar **username,
+ GError **error)
+{
+ GTask *task;
+ isValidUsernameData *data;
+
+ g_return_val_if_fail (g_task_is_valid (result, NULL), FALSE);
+
+ task = G_TASK (result);
+ data = g_task_get_task_data (task);
+
+ if (tip != NULL) {
+ *tip = g_steal_pointer (&data->tip);
+ }
+
+ if (username != NULL)
+ *username = g_steal_pointer (&data->username);
+
+ return g_task_propagate_boolean (task, error);
+}
+
+GdkPixbuf *
+round_image (GdkPixbuf *pixbuf)
+{
+ GdkPixbuf *dest = NULL;
+ cairo_surface_t *surface;
+ cairo_t *cr;
+ gint size;
+
+ size = gdk_pixbuf_get_width (pixbuf);
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, size, size);
+ cr = cairo_create (surface);
+
+ /* Clip a circle */
+ cairo_arc (cr, size/2, size/2, size/2, 0, 2 * G_PI);
+ cairo_clip (cr);
+ cairo_new_path (cr);
+
+ gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
+ cairo_paint (cr);
+
+ dest = gdk_pixbuf_get_from_surface (surface, 0, 0, size, size);
+ cairo_surface_destroy (surface);
+ cairo_destroy (cr);
+
+ return dest;
+}
+
+static gchar *
+extract_initials_from_name (const gchar *name)
+{
+ GString *initials;
+ g_autofree gchar *p = NULL;
+ g_autofree gchar *normalized = NULL;
+ gunichar unichar;
+ gpointer q = NULL;
+
+ g_return_val_if_fail (name != NULL, NULL);
+
+ p = g_utf8_strup (name, -1);
+ normalized = g_utf8_normalize (g_strstrip (p), -1, G_NORMALIZE_DEFAULT_COMPOSE);
+ if (normalized == NULL) {
+ return NULL;
+ }
+
+ initials = g_string_new ("");
+
+ unichar = g_utf8_get_char (normalized);
+ g_string_append_unichar (initials, unichar);
+
+ q = g_utf8_strrchr (normalized, -1, ' ');
+ if (q != NULL && g_utf8_next_char (q) != NULL) {
+ q = g_utf8_next_char (q);
+
+ unichar = g_utf8_get_char (q);
+ g_string_append_unichar (initials, unichar);
+ }
+
+ return g_string_free (initials, FALSE);
+}
+
+static GdkRGBA
+get_color_for_name (const gchar *name)
+{
+ // https://gitlab.gnome.org/Community/Design/HIG-app-icons/blob/master/GNOME%20HIG.gpl
+ static gdouble gnome_color_palette[][3] = {
+ { 98, 160, 234 },
+ { 53, 132, 228 },
+ { 28, 113, 216 },
+ { 26, 95, 180 },
+ { 87, 227, 137 },
+ { 51, 209, 122 },
+ { 46, 194, 126 },
+ { 38, 162, 105 },
+ { 248, 228, 92 },
+ { 246, 211, 45 },
+ { 245, 194, 17 },
+ { 229, 165, 10 },
+ { 255, 163, 72 },
+ { 255, 120, 0 },
+ { 230, 97, 0 },
+ { 198, 70, 0 },
+ { 237, 51, 59 },
+ { 224, 27, 36 },
+ { 192, 28, 40 },
+ { 165, 29, 45 },
+ { 192, 97, 203 },
+ { 163, 71, 186 },
+ { 129, 61, 156 },
+ { 97, 53, 131 },
+ { 181, 131, 90 },
+ { 152, 106, 68 },
+ { 134, 94, 60 },
+ { 99, 69, 44 }
+ };
+
+ GdkRGBA color = { 255, 255, 255, 1.0 };
+ guint hash;
+ gint number_of_colors;
+ gint idx;
+
+ if (name == NULL || strlen (name) == 0)
+ return color;
+
+ hash = g_str_hash (name);
+ number_of_colors = G_N_ELEMENTS (gnome_color_palette);
+ idx = hash % number_of_colors;
+
+ color.red = gnome_color_palette[idx][0];
+ color.green = gnome_color_palette[idx][1];
+ color.blue = gnome_color_palette[idx][2];
+
+ return color;
+}
+
+static cairo_surface_t *
+generate_user_picture (const gchar *name, gint size)
+{
+ PangoFontDescription *font_desc;
+ g_autofree gchar *initials = extract_initials_from_name (name);
+ g_autofree gchar *font = g_strdup_printf ("Sans %d", (int)ceil (size / 2.5));
+ PangoLayout *layout;
+ GdkRGBA color = get_color_for_name (name);
+ cairo_surface_t *surface;
+ gint width, height;
+ cairo_t *cr;
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ size,
+ size);
+ cr = cairo_create (surface);
+ cairo_rectangle (cr, 0, 0, size, size);
+ cairo_set_source_rgb (cr, color.red/255.0, color.green/255.0, color.blue/255.0);
+ cairo_fill (cr);
+
+ /* Draw the initials on top */
+ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+ layout = pango_cairo_create_layout (cr);
+ pango_layout_set_text (layout, initials, -1);
+ font_desc = pango_font_description_from_string (font);
+ pango_layout_set_font_description (layout, font_desc);
+ pango_font_description_free (font_desc);
+
+ pango_layout_get_size (layout, &width, &height);
+ cairo_translate (cr, size/2, size/2);
+ cairo_move_to (cr, - ((double)width / PANGO_SCALE)/2, - ((double)height/PANGO_SCALE)/2);
+ pango_cairo_show_layout (cr, layout);
+ cairo_destroy (cr);
+
+ return surface;
+}
+
+void
+set_user_icon_data (ActUser *user,
+ GdkPixbuf *pixbuf)
+{
+ g_autofree gchar *path = NULL;
+ gint fd;
+ g_autoptr(GOutputStream) stream = NULL;
+ g_autoptr(GError) error = NULL;
+
+ path = g_build_filename (g_get_tmp_dir (), "gnome-control-center-user-icon-XXXXXX", NULL);
+ fd = g_mkstemp (path);
+
+ if (fd == -1) {
+ g_warning ("failed to create temporary file for image data");
+ return;
+ }
+
+ stream = g_unix_output_stream_new (fd, TRUE);
+
+ if (!gdk_pixbuf_save_to_stream (pixbuf, stream, "png", NULL, &error, NULL)) {
+ g_warning ("failed to save image: %s", error->message);
+ return;
+ }
+
+ act_user_set_icon_file (user, path);
+
+ /* if we ever make the dbus call async, the g_remove call needs
+ * to wait for its completion
+ */
+ g_remove (path);
+}
+
+GdkPixbuf *
+generate_default_avatar (ActUser *user, gint size)
+{
+ const gchar *name;
+ GdkPixbuf *pixbuf = NULL;
+ cairo_surface_t *surface;
+
+ name = act_user_get_real_name (user);
+ if (name == NULL)
+ name = "";
+ surface = generate_user_picture (name, size);
+
+ pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0, size, size);
+ cairo_surface_destroy (surface);
+
+ return pixbuf;
+}
+
+void
+set_default_avatar (ActUser *user)
+{
+ g_autoptr(GdkPixbuf) pixbuf = NULL;
+
+ pixbuf = generate_default_avatar (user, IMAGE_SIZE);
+
+ set_user_icon_data (user, pixbuf);
+}
diff --git a/panels/user-accounts/user-utils.h b/panels/user-accounts/user-utils.h
new file mode 100644
index 0000000..0ce08b7
--- /dev/null
+++ b/panels/user-accounts/user-utils.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2009-2010 Red Hat, Inc,
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <act/act.h>
+
+G_BEGIN_DECLS
+
+void set_entry_generation_icon (GtkEntry *entry);
+void set_entry_validation_checkmark (GtkEntry *entry);
+void set_entry_validation_error (GtkEntry *entry,
+ const gchar *text);
+void clear_entry_validation_error (GtkEntry *entry);
+
+gsize get_username_max_length (void);
+gboolean is_username_used (const gchar *username);
+gboolean is_valid_name (const gchar *name);
+void is_valid_username_async (const gchar *username,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data);
+gboolean is_valid_username_finish (GAsyncResult *result,
+ gchar **tip,
+ gchar **username,
+ GError **error);
+GdkPixbuf *round_image (GdkPixbuf *pixbuf);
+GdkPixbuf *generate_default_avatar (ActUser *user,
+ gint size);
+void set_default_avatar (ActUser *user);
+void set_user_icon_data (ActUser *user,
+ GdkPixbuf *pixbuf);
+
+G_END_DECLS
diff --git a/panels/wacom/button-mapping.ui b/panels/wacom/button-mapping.ui
new file mode 100644
index 0000000..401aa12
--- /dev/null
+++ b/panels/wacom/button-mapping.ui
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkDialog" id="button-mapping-dialog">
+ <property name="width_request">600</property>
+ <property name="height_request">450</property>
+ <property name="title" translatable="yes">Map Buttons</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="default_width">600</property>
+ <property name="default_height">450</property>
+ <child>
+ <object class="GtkBox" id="top_vbox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkBox" id="shortcuts_vbox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="xalign">0</property>
+ <property name="margin-top">12</property>
+ <property name="label" translatable="yes">Map buttons to functions</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="actions_swindow">
+ <property name="hscrollbar_policy">never</property>
+ <child>
+ <object class="GtkListBox" id="shortcuts_list">
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="hbox1">
+ <property name="margin-top">5</property>
+ <property name="margin-bottom">5</property>
+ <property name="margin-start">5</property>
+ <property name="margin-end">5</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="label12">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">To edit a shortcut, choose the “Send Keystroke” action, press the keyboard shortcut button and hold down the new keys or press Backspace to clear.</property>
+ <property name="justify">fill</property>
+ <property name="wrap">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="close_button">
+ <property name="label" translatable="yes">_Close</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="0">close_button</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/panels/wacom/calibrator/COPYING b/panels/wacom/calibrator/COPYING
new file mode 100644
index 0000000..e0a1dc9
--- /dev/null
+++ b/panels/wacom/calibrator/COPYING
@@ -0,0 +1,27 @@
+Copyright (c) 2010 Tias Guns <tias@ulyssis.org> and others
+See the respective files for detailed copyright information.
+
+
+Source code: MIT/X11 License
+------------
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/panels/wacom/calibrator/calibrator-gui.c b/panels/wacom/calibrator/calibrator-gui.c
new file mode 100644
index 0000000..2d5d7ec
--- /dev/null
+++ b/panels/wacom/calibrator/calibrator-gui.c
@@ -0,0 +1,429 @@
+/*
+ * Copyright © 2013 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Carlos Garnacho <carlosg@gnome.org>
+ * (based on previous work by Joaquim Rocha, Tias Guns and Soren Hauberg)
+ */
+
+#include "config.h"
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <glib/gi18n.h>
+#include <gdk/x11/gdkx.h>
+#include <gtk/gtk.h>
+
+#include "calibrator.h"
+#include "calibrator-gui.h"
+#include "cc-clock.h"
+
+struct _CcCalibArea
+{
+ GtkWindow parent_instance;
+
+ struct Calib calibrator;
+ XYinfo axis;
+ gboolean swap;
+ gboolean success;
+ GdkDevice *device;
+
+ GtkWidget *error_revealer;
+ GtkWidget *title_revealer;
+ GtkWidget *subtitle_revealer;
+ GtkWidget *clock;
+ GtkWidget *target1, *target2, *target3, *target4;
+ GtkWidget *stack;
+ GtkWidget *success_page;
+ GtkCssProvider *style_provider;
+
+ FinishCallback callback;
+ gpointer user_data;
+};
+
+G_DEFINE_TYPE (CcCalibArea, cc_calib_area, GTK_TYPE_WINDOW)
+
+/* Timeout parameters */
+#define MAX_TIME 15000 /* 15000 = 15 sec */
+#define END_TIME 750 /* 750 = 0.75 sec */
+
+static void
+cc_calib_area_notify_finish (CcCalibArea *area)
+{
+ gtk_widget_hide (GTK_WIDGET (area));
+
+ (*area->callback) (area, area->user_data);
+}
+
+static gboolean
+on_close_request (GtkWidget *widget,
+ CcCalibArea *area)
+{
+ cc_calib_area_notify_finish (area);
+ return GDK_EVENT_PROPAGATE;
+}
+
+static gboolean
+cc_calib_area_finish_idle_cb (CcCalibArea *area)
+{
+ cc_calib_area_notify_finish (area);
+ return FALSE;
+}
+
+static void
+set_success (CcCalibArea *area)
+{
+ gtk_stack_set_visible_child (GTK_STACK (area->stack), area->success_page);
+}
+
+static void
+set_calibration_status (CcCalibArea *area)
+{
+ area->success = finish (&area->calibrator, &area->axis, &area->swap);
+
+ if (area->success)
+ {
+ set_success (area);
+ g_timeout_add (END_TIME,
+ (GSourceFunc) cc_calib_area_finish_idle_cb,
+ area);
+ }
+ else
+ {
+ g_idle_add ((GSourceFunc) cc_calib_area_finish_idle_cb, area);
+ }
+}
+
+static void
+show_error_message (CcCalibArea *area)
+{
+ gtk_revealer_set_reveal_child (GTK_REVEALER (area->error_revealer), TRUE);
+}
+
+static void
+hide_error_message (CcCalibArea *area)
+{
+ gtk_revealer_set_reveal_child (GTK_REVEALER (area->error_revealer), FALSE);
+}
+
+static void
+set_active_target (CcCalibArea *area,
+ int n_target)
+{
+ GtkWidget *targets[] = {
+ area->target1,
+ area->target2,
+ area->target3,
+ area->target4,
+ };
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (targets); i++)
+ gtk_widget_set_sensitive (targets[i], i == n_target);
+}
+
+static void
+on_gesture_press (GtkGestureClick *gesture,
+ guint n_press,
+ gdouble x,
+ gdouble y,
+ CcCalibArea *area)
+{
+ gint num_clicks;
+ gboolean success;
+ GdkDevice *source;
+
+ if (area->success)
+ return;
+
+ source = gtk_gesture_get_device (GTK_GESTURE (gesture));
+
+ if (gdk_device_get_source (source) == GDK_SOURCE_TOUCHSCREEN)
+ return;
+
+ /* Check matching device if a device was provided */
+ if (area->device && area->device != source)
+ {
+ g_debug ("Ignoring input from device %s",
+ gdk_device_get_name (source));
+ return;
+ }
+
+ /* Handle click */
+ /* FIXME: reset clock */
+ success = add_click(&area->calibrator,
+ (int) x,
+ (int) y);
+
+ num_clicks = area->calibrator.num_clicks;
+
+ if (!success && num_clicks == 0)
+ show_error_message (area);
+ else
+ hide_error_message (area);
+
+ /* Are we done yet? */
+ if (num_clicks >= 4)
+ {
+ set_calibration_status (area);
+ return;
+ }
+
+ set_active_target (area, num_clicks);
+}
+
+static gboolean
+on_key_release (GtkEventControllerKey *controller,
+ guint keyval,
+ guint keycode,
+ GdkModifierType state,
+ CcCalibArea *area)
+{
+ if (area->success || keyval != GDK_KEY_Escape)
+ return GDK_EVENT_PROPAGATE;
+
+ cc_calib_area_notify_finish (area);
+ return GDK_EVENT_STOP;
+}
+
+static void
+on_clock_finished (CcClock *clock,
+ CcCalibArea *area)
+{
+ set_calibration_status (area);
+}
+
+static void
+on_title_revealed (CcCalibArea *area)
+{
+ gtk_revealer_set_reveal_child (GTK_REVEALER (area->subtitle_revealer), TRUE);
+}
+
+static void
+on_fullscreen (GtkWindow *window,
+ GParamSpec *pspec,
+ CcCalibArea *area)
+{
+ if (!gtk_window_is_fullscreen (window))
+ return;
+
+ g_signal_connect_swapped (area->title_revealer,
+ "notify::child-revealed",
+ G_CALLBACK (on_title_revealed),
+ area);
+ gtk_revealer_set_reveal_child (GTK_REVEALER (area->title_revealer), TRUE);
+
+ set_active_target (area, 0);
+}
+
+static void
+cc_calib_area_finalize (GObject *object)
+{
+ CcCalibArea *area = CC_CALIB_AREA (object);
+
+ gtk_style_context_remove_provider_for_display (gtk_widget_get_display (GTK_WIDGET (area)),
+ GTK_STYLE_PROVIDER (area->style_provider));
+
+ G_OBJECT_CLASS (cc_calib_area_parent_class)->finalize (object);
+}
+
+static void
+cc_calib_area_size_allocate (GtkWidget *widget,
+ int width,
+ int height,
+ int baseline)
+{
+ CcCalibArea *calib_area = CC_CALIB_AREA (widget);
+
+ if (calib_area->calibrator.geometry.width != width ||
+ calib_area->calibrator.geometry.height != height)
+ {
+ calib_area->calibrator.geometry.width = width;
+ calib_area->calibrator.geometry.height = height;
+
+ /* reset calibration if already started */
+ reset (&calib_area->calibrator);
+ set_active_target (calib_area, 0);
+ }
+
+ GTK_WIDGET_CLASS (cc_calib_area_parent_class)->size_allocate (widget,
+ width,
+ height,
+ baseline);
+}
+
+static void
+cc_calib_area_class_init (CcCalibAreaClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = cc_calib_area_finalize;
+
+ widget_class->size_allocate = cc_calib_area_size_allocate;
+
+ g_type_ensure (CC_TYPE_CLOCK);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/wacom/calibrator/calibrator.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcCalibArea, error_revealer);
+ gtk_widget_class_bind_template_child (widget_class, CcCalibArea, title_revealer);
+ gtk_widget_class_bind_template_child (widget_class, CcCalibArea, subtitle_revealer);
+ gtk_widget_class_bind_template_child (widget_class, CcCalibArea, clock);
+ gtk_widget_class_bind_template_child (widget_class, CcCalibArea, target1);
+ gtk_widget_class_bind_template_child (widget_class, CcCalibArea, target2);
+ gtk_widget_class_bind_template_child (widget_class, CcCalibArea, target3);
+ gtk_widget_class_bind_template_child (widget_class, CcCalibArea, target4);
+ gtk_widget_class_bind_template_child (widget_class, CcCalibArea, stack);
+ gtk_widget_class_bind_template_child (widget_class, CcCalibArea, success_page);
+}
+
+static void
+cc_calib_area_init (CcCalibArea *calib_area)
+{
+ GtkGesture *click;
+ GtkEventController *key;
+
+ gtk_widget_init_template (GTK_WIDGET (calib_area));
+
+ calib_area->style_provider = gtk_css_provider_new ();
+ gtk_css_provider_load_from_resource (calib_area->style_provider, "/org/gnome/control-center/wacom/calibrator/calibrator.css");
+ gtk_style_context_add_provider_for_display (gtk_widget_get_display (GTK_WIDGET (calib_area)),
+ GTK_STYLE_PROVIDER (calib_area->style_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_USER);
+
+ cc_clock_set_duration (CC_CLOCK (calib_area->clock), MAX_TIME);
+ g_signal_connect (calib_area->clock, "finished",
+ G_CALLBACK (on_clock_finished), calib_area);
+
+#ifndef FAKE_AREA
+ /* No cursor */
+ gtk_widget_realize (GTK_WIDGET (calib_area));
+ gtk_widget_set_cursor_from_name (GTK_WIDGET (calib_area), "blank");
+
+ gtk_widget_set_can_focus (GTK_WIDGET (calib_area), TRUE);
+#endif /* FAKE_AREA */
+
+ g_signal_connect (calib_area,
+ "close-request",
+ G_CALLBACK (on_close_request),
+ calib_area);
+ g_signal_connect (calib_area,
+ "notify::fullscreened",
+ G_CALLBACK (on_fullscreen),
+ calib_area);
+
+ click = gtk_gesture_click_new ();
+ gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (click), GDK_BUTTON_PRIMARY);
+ g_signal_connect (click, "pressed",
+ G_CALLBACK (on_gesture_press), calib_area);
+ gtk_widget_add_controller (GTK_WIDGET (calib_area),
+ GTK_EVENT_CONTROLLER (click));
+
+ key = gtk_event_controller_key_new ();
+ g_signal_connect (key, "key-released",
+ G_CALLBACK (on_key_release), calib_area);
+ gtk_widget_add_controller (GTK_WIDGET (calib_area), key);
+}
+
+/**
+ * Creates the windows and other objects required to do calibration
+ * under GTK. When the window is closed (timed out, calibration finished
+ * or user cancellation), callback will be called, where you should call
+ * cc_calib_area_finish().
+ */
+CcCalibArea *
+cc_calib_area_new (GdkDisplay *display,
+ GdkMonitor *monitor,
+ GdkDevice *device,
+ FinishCallback callback,
+ gpointer user_data,
+ int threshold_doubleclick,
+ int threshold_misclick)
+{
+ CcCalibArea *calib_area;
+
+ g_return_val_if_fail (callback, NULL);
+
+ calib_area = g_object_new (CC_TYPE_CALIB_AREA, NULL);
+ calib_area->callback = callback;
+ calib_area->user_data = user_data;
+ calib_area->device = device;
+ calib_area->calibrator.threshold_doubleclick = threshold_doubleclick;
+ calib_area->calibrator.threshold_misclick = threshold_misclick;
+
+ /* Move to correct screen */
+ if (monitor)
+ gtk_window_fullscreen_on_monitor (GTK_WINDOW (calib_area), monitor);
+ else
+ gtk_window_fullscreen (GTK_WINDOW (calib_area));
+
+ gtk_widget_show (GTK_WIDGET (calib_area));
+
+ return calib_area;
+}
+
+/* Finishes the calibration. Note that CalibArea
+ * needs to be destroyed with Cccalib_area_free() afterwards */
+gboolean
+cc_calib_area_finish (CcCalibArea *area)
+{
+ g_return_val_if_fail (area != NULL, FALSE);
+
+ if (area->success)
+ g_debug ("Final calibration: %f, %f, %f, %f\n",
+ area->axis.x_min,
+ area->axis.y_min,
+ area->axis.x_max,
+ area->axis.y_max);
+ else
+ g_debug ("Calibration was aborted or timed out");
+
+ return area->success;
+}
+
+void
+cc_calib_area_free (CcCalibArea *area)
+{
+ gtk_window_destroy (GTK_WINDOW (area));
+}
+
+void
+cc_calib_area_get_axis (CcCalibArea *area,
+ XYinfo *new_axis,
+ gboolean *swap_xy)
+{
+ g_return_if_fail (area != NULL);
+
+ *new_axis = area->axis;
+ *swap_xy = area->swap;
+}
+
+void
+cc_calib_area_get_padding (CcCalibArea *area,
+ XYinfo *padding)
+{
+ g_return_if_fail (area != NULL);
+
+ /* min/max values are monitor coordinates scaled to be between
+ * 0 and 1, padding starts at 0 on "the edge", and positive
+ * values grow towards the center of the rectangle.
+ */
+ padding->x_min = area->axis.x_min;
+ padding->y_min = area->axis.y_min;
+ padding->x_max = 1 - area->axis.x_max;
+ padding->y_max = 1 - area->axis.y_max;
+}
diff --git a/panels/wacom/calibrator/calibrator-gui.h b/panels/wacom/calibrator/calibrator-gui.h
new file mode 100644
index 0000000..5d6d1ae
--- /dev/null
+++ b/panels/wacom/calibrator/calibrator-gui.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2009 Tias Guns
+ * Copyright (c) 2009 Soren Hauberg
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+/* struct to hold min/max info of the X and Y axis */
+typedef struct
+{
+ gdouble x_min;
+ gdouble x_max;
+ gdouble y_min;
+ gdouble y_max;
+} XYinfo;
+
+#define CC_TYPE_CALIB_AREA cc_calib_area_get_type ()
+G_DECLARE_FINAL_TYPE (CcCalibArea, cc_calib_area, CC, CALIB_AREA, GtkWindow)
+
+typedef void (*FinishCallback) (CcCalibArea *area, gpointer user_data);
+
+CcCalibArea * cc_calib_area_new (GdkDisplay *display,
+ GdkMonitor *monitor,
+ GdkDevice *device,
+ FinishCallback callback,
+ gpointer user_data,
+ int threshold_doubleclick,
+ int threshold_misclick);
+
+gboolean cc_calib_area_finish (CcCalibArea *area);
+
+void cc_calib_area_free (CcCalibArea *area);
+
+void cc_calib_area_get_axis (CcCalibArea *area,
+ XYinfo *new_axis,
+ gboolean *swap_xy);
+
+void cc_calib_area_get_padding (CcCalibArea *area,
+ XYinfo *padding);
+
+G_END_DECLS
diff --git a/panels/wacom/calibrator/calibrator.c b/panels/wacom/calibrator/calibrator.c
new file mode 100644
index 0000000..4ac316e
--- /dev/null
+++ b/panels/wacom/calibrator/calibrator.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2009 Tias Guns
+ * Copyright (c) 2009 Soren Hauberg
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdlib.h>
+
+#include "calibrator.h"
+
+#define SWAP(valtype,x,y) \
+ G_STMT_START { \
+ valtype t; t = (x); x = (y); y = t; \
+ } G_STMT_END
+
+/* reset clicks */
+void
+reset (struct Calib *c)
+{
+ c->num_clicks = 0;
+}
+
+/* check whether the coordinates are along the respective axis */
+static gboolean
+along_axis (struct Calib *c,
+ int xy,
+ int x0,
+ int y0)
+{
+ return ((abs(xy - x0) <= c->threshold_misclick) ||
+ (abs(xy - y0) <= c->threshold_misclick));
+}
+
+/* add a click with the given coordinates */
+gboolean
+add_click (struct Calib *c,
+ int x,
+ int y)
+{
+ g_debug ("Trying to add click (%d, %d)", x, y);
+
+ /* Double-click detection */
+ if (c->threshold_doubleclick > 0 && c->num_clicks > 0)
+ {
+ int i = c->num_clicks-1;
+ while (i >= 0)
+ {
+ if (abs(x - c->clicked_x[i]) <= c->threshold_doubleclick &&
+ abs(y - c->clicked_y[i]) <= c->threshold_doubleclick)
+ {
+ g_debug ("Detected double-click, ignoring");
+ return FALSE;
+ }
+ i--;
+ }
+ }
+
+ /* Mis-click detection */
+ if (c->threshold_misclick > 0 && c->num_clicks > 0)
+ {
+ gboolean misclick = TRUE;
+
+ if (c->num_clicks == 1)
+ {
+ /* check that along one axis of first point */
+ if (along_axis(c, x,c->clicked_x[0],c->clicked_y[0]) ||
+ along_axis(c, y,c->clicked_x[0],c->clicked_y[0]))
+ {
+ misclick = FALSE;
+ }
+ }
+ else if (c->num_clicks == 2)
+ {
+ /* check that along other axis of first point than second point */
+ if ((along_axis(c, y,c->clicked_x[0],c->clicked_y[0]) &&
+ along_axis(c, c->clicked_x[1],c->clicked_x[0],c->clicked_y[0])) ||
+ (along_axis(c, x,c->clicked_x[0],c->clicked_y[0]) &&
+ along_axis(c, c->clicked_y[1],c->clicked_x[0],c->clicked_y[0])))
+ {
+ misclick = FALSE;
+ }
+ }
+ else if (c->num_clicks == 3)
+ {
+ /* check that along both axis of second and third point */
+ if ((along_axis(c, x,c->clicked_x[1],c->clicked_y[1]) &&
+ along_axis(c, y,c->clicked_x[2],c->clicked_y[2])) ||
+ (along_axis(c, y,c->clicked_x[1],c->clicked_y[1]) &&
+ along_axis(c, x,c->clicked_x[2],c->clicked_y[2])))
+ {
+ misclick = FALSE;
+ }
+ }
+
+ if (misclick)
+ {
+ g_debug ("Detected misclick, resetting");
+ reset(c);
+ return FALSE;
+ }
+ }
+
+ g_debug ("Click (%d, %d) added", x, y);
+ c->clicked_x[c->num_clicks] = x;
+ c->clicked_y[c->num_clicks] = y;
+ c->num_clicks++;
+
+ return TRUE;
+}
+
+/* calculate and apply the calibration */
+gboolean
+finish (struct Calib *c,
+ XYinfo *new_axis,
+ gboolean *swap)
+{
+ gboolean swap_xy;
+ float scale_x;
+ float scale_y;
+ float delta_x;
+ float delta_y;
+ XYinfo axis = {-1, -1, -1, -1};
+
+ if (c->num_clicks != 4)
+ return FALSE;
+
+ /* Should x and y be swapped? If the device and output are wider
+ * towards different axes, swapping must be performed
+ *
+ * FIXME: Would be even better to know the actual output orientation,
+ * not just the direction.
+ */
+ swap_xy = (c->geometry.width < c->geometry.height);
+
+ /* Compute the scale to transform from pixel positions to [0..1]. */
+ scale_x = 1 / (float)c->geometry.width;
+ scale_y = 1 / (float)c->geometry.height;
+
+ axis.x_min = ((((c->clicked_x[UL] + c->clicked_x[LL]) / 2)) * scale_x);
+ axis.x_max = ((((c->clicked_x[UR] + c->clicked_x[LR]) / 2)) * scale_x);
+ axis.y_min = ((((c->clicked_y[UL] + c->clicked_y[UR]) / 2)) * scale_y);
+ axis.y_max = ((((c->clicked_y[LL] + c->clicked_y[LR]) / 2)) * scale_y);
+
+ /* Add/subtract the offset that comes from not having the points in the
+ * corners (using the same coordinate system they are currently in)
+ */
+ delta_x = (axis.x_max - axis.x_min) / (float)(NUM_BLOCKS - 2);
+ axis.x_min -= delta_x;
+ axis.x_max += delta_x;
+ delta_y = (axis.y_max - axis.y_min) / (float)(NUM_BLOCKS - 2);
+ axis.y_min -= delta_y;
+ axis.y_max += delta_y;
+
+ /* If x and y has to be swapped we also have to swap the parameters */
+ if (swap_xy)
+ {
+ SWAP (gdouble, axis.x_min, axis.y_min);
+ SWAP (gdouble, axis.x_max, axis.y_max);
+ }
+
+ *new_axis = axis;
+ *swap = swap_xy;
+
+ return TRUE;
+}
+
diff --git a/panels/wacom/calibrator/calibrator.css b/panels/wacom/calibrator/calibrator.css
new file mode 100644
index 0000000..462c766
--- /dev/null
+++ b/panels/wacom/calibrator/calibrator.css
@@ -0,0 +1,47 @@
+#calibrator {
+ background-color: #000;
+}
+
+#calibrator * {
+ color: #fff;
+}
+
+#calibrator label {
+ font-size: larger;
+}
+
+#calibrator #title {
+ font-weight: bold;
+ color: #888;
+}
+
+#calibrator #error {
+ font-weight: bold;
+}
+
+#calibrator #target {
+ background-image: url('target.svg');
+ background-repeat: no-repeat;
+ background-position: 50% 50%;
+}
+
+@keyframes target-enabled-animation {
+ 0% { background-size: 0px; }
+ 90% { background-size: 120px; }
+ 100% { background-size: 100px; }
+}
+
+@keyframes target-disabled-animation {
+ 0% { background-size: 100px; }
+ 100% { background-size: 0px; }
+}
+
+#calibrator #target:not(disabled) {
+ animation: target-enabled-animation 1 ease 0.5s;
+ background-size: 100px;
+}
+
+#calibrator #target:disabled {
+ animation: target-disabled-animation 1 ease 0.2s;
+ background-size: 0px;
+}
diff --git a/panels/wacom/calibrator/calibrator.h b/panels/wacom/calibrator/calibrator.h
new file mode 100644
index 0000000..dab7a2f
--- /dev/null
+++ b/panels/wacom/calibrator/calibrator.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2009 Tias Guns
+ * Copyright (c) 2009 Soren Hauberg
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#pragma once
+
+#include <glib.h>
+#include "calibrator-gui.h"
+
+G_BEGIN_DECLS
+
+/*
+ * Number of blocks. We partition the screen into 'num_blocks' x 'num_blocks'
+ * rectangles of equal size. We then ask the user to press points that are
+ * located at the corner closes to the center of the four blocks in the corners
+ * of the screen. The following ascii art illustrates the situation. We partition
+ * the screen into 8 blocks in each direction. We then let the user press the
+ * points marked with 'O'.
+ *
+ * +--+--+--+--+--+--+--+--+
+ * | | | | | | | | |
+ * +--O--+--+--+--+--+--O--+
+ * | | | | | | | | |
+ * +--+--+--+--+--+--+--+--+
+ * | | | | | | | | |
+ * +--+--+--+--+--+--+--+--+
+ * | | | | | | | | |
+ * +--+--+--+--+--+--+--+--+
+ * | | | | | | | | |
+ * +--+--+--+--+--+--+--+--+
+ * | | | | | | | | |
+ * +--+--+--+--+--+--+--+--+
+ * | | | | | | | | |
+ * +--O--+--+--+--+--+--O--+
+ * | | | | | | | | |
+ * +--+--+--+--+--+--+--+--+
+ */
+#define NUM_BLOCKS 8
+
+/* Names of the points */
+enum
+{
+ UL = 0, /* Upper-left */
+ UR = 1, /* Upper-right */
+ LL = 2, /* Lower-left */
+ LR = 3 /* Lower-right */
+};
+
+struct Calib
+{
+ /* Geometry of the calibration window */
+ GdkRectangle geometry;
+
+ /* nr of clicks registered */
+ int num_clicks;
+
+ /* click coordinates */
+ int clicked_x[4], clicked_y[4];
+
+ /* Threshold to keep the same point from being clicked twice.
+ * Set to zero if you don't want this check
+ */
+ int threshold_doubleclick;
+
+ /* Threshold to detect mis-clicks (clicks not along axes)
+ * A lower value forces more precise calibration
+ * Set to zero if you don't want this check
+ */
+ int threshold_misclick;
+};
+
+void reset (struct Calib *c);
+gboolean add_click (struct Calib *c,
+ int x,
+ int y);
+gboolean finish (struct Calib *c,
+ XYinfo *new_axis,
+ gboolean *swap);
+
+G_END_DECLS
diff --git a/panels/wacom/calibrator/calibrator.ui b/panels/wacom/calibrator/calibrator.ui
new file mode 100644
index 0000000..89d4865
--- /dev/null
+++ b/panels/wacom/calibrator/calibrator.ui
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcCalibArea" parent="GtkWindow">
+ <property name="name">calibrator</property>
+ <property name="child">
+ <object class="GtkStack" id="stack">
+ <property name="transition_duration">0</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="row_homogeneous">1</property>
+ <property name="column_homogeneous">1</property>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ <property name="column-span">8</property>
+ <property name="row-span">8</property>
+ </layout>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="orientation">vertical</property>
+ <property name="vexpand">1</property>
+ </object>
+ </child>
+ <child>
+ <object class="CcClock" id="clock"/>
+ </child>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="orientation">vertical</property>
+ <property name="vexpand">1</property>
+ <child>
+ <object class="GtkRevealer" id="title_revealer">
+ <property name="transition_duration">300</property>
+ <property name="child">
+ <object class="GtkLabel">
+ <property name="name">title</property>
+ <property name="label" translatable="1">Screen Calibration</property>
+ </object>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkRevealer" id="subtitle_revealer">
+ <property name="transition_duration">300</property>
+ <property name="child">
+ <object class="GtkLabel">
+ <property name="name">subtitle</property>
+ <property name="label" translatable="1">Please tap the target markers as they appear on screen to calibrate the tablet.</property>
+ </object>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkRevealer" id="error_revealer">
+ <property name="transition_type">crossfade</property>
+ <property name="transition_duration">500</property>
+ <property name="child">
+ <object class="GtkLabel">
+ <property name="name">error</property>
+ <property name="label" translatable="1">Mis-click detected, restarting…</property>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage" id="target1">
+ <property name="name">target</property>
+ <property name="width_request">100</property>
+ <property name="height_request">100</property>
+ <property name="sensitive">0</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ <property name="column-span">2</property>
+ <property name="row-span">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage" id="target2">
+ <property name="name">target</property>
+ <property name="width_request">100</property>
+ <property name="height_request">100</property>
+ <property name="sensitive">0</property>
+ <layout>
+ <property name="column">6</property>
+ <property name="row">0</property>
+ <property name="column-span">2</property>
+ <property name="row-span">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage" id="target3">
+ <property name="name">target</property>
+ <property name="width_request">100</property>
+ <property name="height_request">100</property>
+ <property name="sensitive">0</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">6</property>
+ <property name="column-span">2</property>
+ <property name="row-span">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage" id="target4">
+ <property name="name">target</property>
+ <property name="width_request">100</property>
+ <property name="height_request">100</property>
+ <property name="sensitive">0</property>
+ <layout>
+ <property name="column">6</property>
+ <property name="row">6</property>
+ <property name="column-span">2</property>
+ <property name="row-span">2</property>
+ </layout>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage" id="success_page">
+ <property name="pixel_size">300</property>
+ <property name="icon_name">emblem-ok-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </property>
+ </template>
+ <object class="GtkSizeGroup">
+ <property name="mode">vertical</property>
+ <widgets>
+ <widget name="box1"/>
+ <widget name="box2"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/panels/wacom/calibrator/cc-clock.c b/panels/wacom/calibrator/cc-clock.c
new file mode 100644
index 0000000..26afd81
--- /dev/null
+++ b/panels/wacom/calibrator/cc-clock.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright © 2018 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Joaquim Rocha <jrocha@redhat.com>
+ * Carlos Garnacho <carlosg@gnome.org>
+ */
+#include "config.h"
+#include "cc-clock.h"
+
+#include <math.h>
+
+#define CLOCK_RADIUS 50
+#define CLOCK_LINE_WIDTH 10
+#define CLOCK_LINE_PADDING 10
+#define EXTRA_SPACE 2
+
+typedef struct _CcClock CcClock;
+
+struct _CcClock
+{
+ GtkWidget parent_instance;
+ guint duration;
+ gint64 start_time;
+ gboolean running;
+};
+
+enum
+{
+ PROP_DURATION = 1,
+ N_PROPS
+};
+
+static GParamSpec *props[N_PROPS] = { 0, };
+
+enum {
+ FINISHED,
+ N_SIGNALS
+};
+
+static guint signals[N_SIGNALS] = { 0, };
+
+G_DEFINE_TYPE (CcClock, cc_clock, GTK_TYPE_WIDGET)
+
+static gint64
+cc_clock_get_time_diff (CcClock *clock)
+{
+ GdkFrameClock *frame_clock;
+ gint64 current_time;
+
+ frame_clock = gtk_widget_get_frame_clock (GTK_WIDGET (clock));
+ current_time = gdk_frame_clock_get_frame_time (frame_clock);
+
+ return current_time - clock->start_time;
+}
+
+static gdouble
+cc_clock_get_angle (CcClock *clock)
+{
+ gint64 time_diff;
+
+ time_diff = cc_clock_get_time_diff (clock);
+
+ if (time_diff > clock->duration * 1000)
+ return 360;
+
+ return ((gdouble) time_diff / (clock->duration * 1000)) * 360;
+}
+
+static void
+cc_clock_snapshot (GtkWidget *widget,
+ GtkSnapshot *snapshot)
+{
+ GtkAllocation allocation;
+ cairo_t *cr;
+ gdouble angle;
+
+ gtk_widget_get_allocation (widget, &allocation);
+ angle = cc_clock_get_angle (CC_CLOCK (widget));
+
+ cr = gtk_snapshot_append_cairo (snapshot,
+ &GRAPHENE_RECT_INIT (0, 0, allocation.width, allocation.height));
+
+ /* Draw the clock background */
+ cairo_arc (cr, allocation.width / 2, allocation.height / 2, CLOCK_RADIUS / 2, 0.0, 2.0 * M_PI);
+ cairo_set_source_rgb (cr, 0.5, 0.5, 0.5);
+ cairo_fill_preserve (cr);
+ cairo_stroke (cr);
+
+ cairo_set_line_width (cr, CLOCK_LINE_WIDTH);
+
+ cairo_arc (cr,
+ allocation.width / 2,
+ allocation.height / 2,
+ (CLOCK_RADIUS - CLOCK_LINE_WIDTH - CLOCK_LINE_PADDING) / 2,
+ 3 * M_PI_2,
+ 3 * M_PI_2 + angle * M_PI / 180.0);
+ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+ cairo_stroke (cr);
+}
+
+static void
+cc_clock_stop (CcClock *clock)
+{
+ GdkFrameClock *frame_clock;
+
+ if (!clock->running)
+ return;
+
+ frame_clock = gtk_widget_get_frame_clock (GTK_WIDGET (clock));
+
+ gdk_frame_clock_end_updating (frame_clock);
+ clock->running = FALSE;
+}
+
+static void
+on_frame_clock_update (CcClock *clock)
+{
+ gint64 time_diff;
+
+ if (!clock->running)
+ return;
+
+ time_diff = cc_clock_get_time_diff (clock);
+
+ if (time_diff > clock->duration * 1000)
+ {
+ g_signal_emit (clock, signals[FINISHED], 0);
+ cc_clock_stop (clock);
+ }
+
+ gtk_widget_queue_draw (GTK_WIDGET (clock));
+}
+
+static void
+cc_clock_map (GtkWidget *widget)
+{
+ GdkFrameClock *frame_clock;
+
+ GTK_WIDGET_CLASS (cc_clock_parent_class)->map (widget);
+
+ frame_clock = gtk_widget_get_frame_clock (widget);
+ g_signal_connect_object (frame_clock, "update",
+ G_CALLBACK (on_frame_clock_update),
+ widget, G_CONNECT_SWAPPED);
+ cc_clock_reset (CC_CLOCK (widget));
+}
+
+static void
+cc_clock_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcClock *clock = CC_CLOCK (object);
+
+ switch (prop_id)
+ {
+ case PROP_DURATION:
+ clock->duration = g_value_get_uint (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_clock_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcClock *clock = CC_CLOCK (object);
+
+ switch (prop_id)
+ {
+ case PROP_DURATION:
+ g_value_set_uint (value, clock->duration);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_clock_measure (GtkWidget *widget,
+ GtkOrientation orientation,
+ gint for_size,
+ gint *minimum,
+ gint *natural,
+ gint *minimum_baseline,
+ gint *natural_baseline)
+{
+ if (minimum)
+ *minimum = CLOCK_RADIUS + EXTRA_SPACE;
+ if (natural)
+ *natural = CLOCK_RADIUS + EXTRA_SPACE;
+}
+
+static void
+cc_clock_class_init (CcClockClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = cc_clock_set_property;
+ object_class->get_property = cc_clock_get_property;
+
+ widget_class->map = cc_clock_map;
+ widget_class->snapshot = cc_clock_snapshot;
+ widget_class->measure = cc_clock_measure;
+
+ signals[FINISHED] =
+ g_signal_new ("finished",
+ CC_TYPE_CLOCK,
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+
+ props[PROP_DURATION] =
+ g_param_spec_uint ("duration",
+ "Duration",
+ "Duration",
+ 0, G_MAXUINT, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS |
+ G_PARAM_CONSTRUCT_ONLY);
+
+ g_object_class_install_properties (object_class, N_PROPS, props);
+}
+
+static void
+cc_clock_init (CcClock *clock)
+{
+}
+
+GtkWidget *
+cc_clock_new (guint duration)
+{
+ return g_object_new (CC_TYPE_CLOCK,
+ "duration", duration,
+ NULL);
+}
+
+void
+cc_clock_reset (CcClock *clock)
+{
+ GdkFrameClock *frame_clock;
+
+ if (!gtk_widget_get_mapped (GTK_WIDGET (clock)))
+ return;
+
+ frame_clock = gtk_widget_get_frame_clock (GTK_WIDGET (clock));
+
+ cc_clock_stop (clock);
+
+ clock->running = TRUE;
+ clock->start_time = g_get_monotonic_time ();
+ gdk_frame_clock_begin_updating (frame_clock);
+}
+
+void
+cc_clock_set_duration (CcClock *clock,
+ guint duration)
+{
+ clock->duration = duration;
+ g_object_notify (G_OBJECT (clock), "duration");
+ cc_clock_reset (clock);
+}
+
+guint
+cc_clock_get_duration (CcClock *clock)
+{
+ return clock->duration;
+}
diff --git a/panels/wacom/calibrator/cc-clock.h b/panels/wacom/calibrator/cc-clock.h
new file mode 100644
index 0000000..9ebf024
--- /dev/null
+++ b/panels/wacom/calibrator/cc-clock.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2018 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Carlos Garnacho <carlosg@gnome.org>
+ */
+
+#pragma once
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_CLOCK (cc_clock_get_type ())
+
+G_DECLARE_FINAL_TYPE (CcClock, cc_clock, CC, CLOCK, GtkWidget)
+
+GtkWidget * cc_clock_new (guint duration);
+
+void cc_clock_reset (CcClock *clock);
+
+void cc_clock_set_duration (CcClock *clock,
+ guint duration);
+guint cc_clock_get_duration (CcClock *clock);
+
+GType cc_clock_get_type (void);
+
+G_END_DECLS
diff --git a/panels/wacom/calibrator/main.c b/panels/wacom/calibrator/main.c
new file mode 100644
index 0000000..71421c7
--- /dev/null
+++ b/panels/wacom/calibrator/main.c
@@ -0,0 +1,421 @@
+/*
+ * Copyright (c) 2009 Tias Guns
+ * Copyright (c) 2009 Soren Hauberg
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <dirent.h>
+#include <glib/gi18n.h>
+
+#include <X11/extensions/XInput.h>
+
+#include "calibrator-gui.h"
+#include "calibrator.h"
+
+static GMainLoop *mainloop = NULL;
+
+/**
+ * find a calibratable touchscreen device (using XInput)
+ *
+ * if pre_device is NULL, the last calibratable device is selected.
+ * retuns number of devices found,
+ * the data of the device is returned in the last 3 function parameters
+ */
+static int find_device(const char* pre_device, gboolean verbose, gboolean list_devices,
+ XID* device_id, const char** device_name, XYinfo* device_axis)
+{
+ gboolean pre_device_is_id = TRUE;
+ int found = 0;
+
+ Display* display = XOpenDisplay(NULL);
+ if (display == NULL) {
+ fprintf(stderr, "Unable to connect to X server\n");
+ exit(1);
+ }
+
+ int xi_opcode, event, error;
+ if (!XQueryExtension(display, "XInputExtension", &xi_opcode, &event, &error)) {
+ fprintf(stderr, "X Input extension not available.\n");
+ exit(1);
+ }
+
+ /* verbose, get Xi version */
+ if (verbose) {
+ XExtensionVersion *version = XGetExtensionVersion(display, INAME);
+
+ if (version && (version != (XExtensionVersion*) NoSuchExtension)) {
+ printf("DEBUG: %s version is %i.%i\n",
+ INAME, version->major_version, version->minor_version);
+ XFree(version);
+ }
+ }
+
+ if (pre_device != NULL) {
+ /* check whether the pre_device is an ID (only digits) */
+ int len = strlen(pre_device);
+ int loop;
+ for (loop=0; loop<len; loop++) {
+ if (!isdigit(pre_device[loop])) {
+ pre_device_is_id = FALSE;
+ break;
+ }
+ }
+ }
+
+
+ if (verbose)
+ printf("DEBUG: Skipping virtual master devices and devices without axis valuators.\n");
+ int ndevices;
+ XDeviceInfoPtr list, slist;
+ slist=list=(XDeviceInfoPtr) XListInputDevices (display, &ndevices);
+ int i;
+ for (i=0; i<ndevices; i++, list++)
+ {
+ if (list->use == IsXKeyboard || list->use == IsXPointer) /* virtual master device */
+ continue;
+
+ /* if we are looking for a specific device */
+ if (pre_device != NULL) {
+ if ((pre_device_is_id && list->id == (XID) atoi(pre_device)) ||
+ (!pre_device_is_id && strcmp(list->name, pre_device) == 0)) {
+ /* OK, fall through */
+ } else {
+ /* skip, not this device */
+ continue;
+ }
+ }
+
+ XAnyClassPtr any = (XAnyClassPtr) (list->inputclassinfo);
+ int j;
+ for (j=0; j<list->num_classes; j++)
+ {
+
+ if (any->class == ValuatorClass)
+ {
+ XValuatorInfoPtr V = (XValuatorInfoPtr) any;
+ XAxisInfoPtr ax = (XAxisInfoPtr) V->axes;
+
+ if (V->mode != Absolute) {
+ if (verbose)
+ printf("DEBUG: Skipping device '%s' id=%i, does not report Absolute events.\n",
+ list->name, (int)list->id);
+ } else if (V->num_axes < 2 ||
+ (ax[0].min_value == -1 && ax[0].max_value == -1) ||
+ (ax[1].min_value == -1 && ax[1].max_value == -1)) {
+ if (verbose)
+ printf("DEBUG: Skipping device '%s' id=%i, does not have two calibratable axes.\n",
+ list->name, (int)list->id);
+ } else {
+ /* a calibratable device (has 2 axis valuators) */
+ found++;
+ *device_id = list->id;
+ *device_name = g_strdup(list->name);
+ device_axis->x_min = ax[0].min_value;
+ device_axis->x_max = ax[0].max_value;
+ device_axis->y_min = ax[1].min_value;
+ device_axis->y_max = ax[1].max_value;
+
+ if (list_devices)
+ printf("Device \"%s\" id=%i\n", *device_name, (int)*device_id);
+ }
+
+ }
+
+ /*
+ * Increment 'any' to point to the next item in the linked
+ * list. The length is in bytes, so 'any' must be cast to
+ * a character pointer before being incremented.
+ */
+ any = (XAnyClassPtr) ((char *) any + any->length);
+ }
+
+ }
+ XFreeDeviceList(slist);
+ XCloseDisplay(display);
+
+ return found;
+}
+
+static void usage(char* cmd, unsigned thr_misclick)
+{
+ fprintf(stderr, "Usage: %s [-h|--help] [-v|--verbose] [--list] [--device <device name or id>] [--precalib <minx> <maxx> <miny> <maxy>] [--misclick <nr of pixels>] [--output-type <auto|xorg.conf.d|hal|xinput>] [--fake]\n", cmd);
+ fprintf(stderr, "\t-h, --help: print this help message\n");
+ fprintf(stderr, "\t-v, --verbose: print debug messages during the process\n");
+ fprintf(stderr, "\t--list: list calibratable input devices and quit\n");
+ fprintf(stderr, "\t--device <device name or id>: select a specific device to calibrate\n");
+ fprintf(stderr, "\t--precalib: manually provide the current calibration setting (eg. the values in xorg.conf)\n");
+ fprintf(stderr, "\t--misclick: set the misclick threshold (0=off, default: %i pixels)\n",
+ thr_misclick);
+ fprintf(stderr, "\t--fake: emulate a fake device (for testing purposes)\n");
+}
+
+static struct Calib* CalibratorXorgPrint(const char* const device_name0, const XYinfo *axis0, const gboolean verbose0, const int thr_misclick, const int thr_doubleclick)
+{
+ struct Calib* c = (struct Calib*)calloc(1, sizeof(struct Calib));
+ c->threshold_misclick = thr_misclick;
+ c->threshold_doubleclick = thr_doubleclick;
+
+ printf("Calibrating standard Xorg driver \"%s\"\n", device_name0);
+ printf("\tcurrent calibration values: min_x=%lf, max_x=%lf and min_y=%lf, max_y=%lf\n",
+ axis0->x_min, axis0->x_max, axis0->y_min, axis0->y_max);
+ printf("\tIf these values are estimated wrong, either supply it manually with the --precalib option, or run the 'get_precalib.sh' script to automatically get it (through HAL).\n");
+
+ return c;
+}
+
+static struct Calib* main_common(int argc, char** argv)
+{
+ gboolean verbose = FALSE;
+ gboolean list_devices = FALSE;
+ gboolean fake = FALSE;
+ gboolean precalib = FALSE;
+ XYinfo pre_axis = {-1, -1, -1, -1};
+ const char* pre_device = NULL;
+ unsigned thr_misclick = 15;
+ unsigned thr_doubleclick = 7;
+
+ /* parse input */
+ if (argc > 1) {
+ int i;
+ for (i=1; i!=argc; i++) {
+ /* Display help ? */
+ if (strcmp("-h", argv[i]) == 0 ||
+ strcmp("--help", argv[i]) == 0) {
+ fprintf(stderr, "xinput_calibrator, v%s\n\n", "0.0.0");
+ usage(argv[0], thr_misclick);
+ exit(0);
+ } else
+
+ /* Verbose output ? */
+ if (strcmp("-v", argv[i]) == 0 ||
+ strcmp("--verbose", argv[i]) == 0) {
+ verbose = TRUE;
+ } else
+
+ /* Just list devices ? */
+ if (strcmp("--list", argv[i]) == 0) {
+ list_devices = TRUE;
+ } else
+
+ /* Select specific device ? */
+ if (strcmp("--device", argv[i]) == 0) {
+ if (argc > i+1)
+ pre_device = argv[++i];
+ else {
+ fprintf(stderr, "Error: --device needs a device name or id as argument; use --list to list the calibratable input devices.\n\n");
+ usage(argv[0], thr_misclick);
+ exit(1);
+ }
+ } else
+
+ /* Get pre-calibration ? */
+ if (strcmp("--precalib", argv[i]) == 0) {
+ precalib = TRUE;
+ if (argc > i+1)
+ pre_axis.x_min = atoi(argv[++i]);
+ if (argc > i+1)
+ pre_axis.x_max = atoi(argv[++i]);
+ if (argc > i+1)
+ pre_axis.y_min = atoi(argv[++i]);
+ if (argc > i+1)
+ pre_axis.y_max = atoi(argv[++i]);
+ } else
+
+ /* Get mis-click threshold ? */
+ if (strcmp("--misclick", argv[i]) == 0) {
+ if (argc > i+1)
+ thr_misclick = atoi(argv[++i]);
+ else {
+ fprintf(stderr, "Error: --misclick needs a number (the pixel threshold) as argument. Set to 0 to disable mis-click detection.\n\n");
+ usage(argv[0], thr_misclick);
+ exit(1);
+ }
+ } else
+
+ /* Fake calibratable device ? */
+ if (strcmp("--fake", argv[i]) == 0) {
+ fake = TRUE;
+ }
+
+ /* unknown option */
+ else {
+ fprintf(stderr, "Unknown option: %s\n\n", argv[i]);
+ usage(argv[0], thr_misclick);
+ exit(0);
+ }
+ }
+ }
+
+
+ /* Choose the device to calibrate */
+ XID device_id = (XID) -1;
+ const char* device_name = NULL;
+ XYinfo device_axis = {-1, -1, -1, -1};
+ if (fake) {
+ /* Fake a calibratable device */
+ device_name = "Fake_device";
+ device_axis.x_min=0;
+ device_axis.x_max=1000;
+ device_axis.y_min=0;
+ device_axis.y_max=1000;
+
+ if (verbose) {
+ printf("DEBUG: Faking device: %s\n", device_name);
+ }
+ } else {
+ /* Find the right device */
+ int nr_found = find_device(pre_device, verbose, list_devices, &device_id, &device_name, &device_axis);
+
+ if (list_devices) {
+ /* printed the list in find_device */
+ if (nr_found == 0)
+ printf("No calibratable devices found.\n");
+ exit(0);
+ }
+
+ if (nr_found == 0) {
+ if (pre_device == NULL)
+ fprintf (stderr, "Error: No calibratable devices found.\n");
+ else
+ fprintf (stderr, "Error: Device \"%s\" not found; use --list to list the calibratable input devices.\n", pre_device);
+ exit(1);
+
+ } else if (nr_found > 1) {
+ printf ("Warning: multiple calibratable devices found, calibrating last one (%s)\n\tuse --device to select another one.\n", device_name);
+ }
+
+ if (verbose) {
+ printf("DEBUG: Selected device: %s\n", device_name);
+ }
+ }
+
+ /* override min/max XY from command line ? */
+ if (precalib) {
+ if (pre_axis.x_min != -1)
+ device_axis.x_min = pre_axis.x_min;
+ if (pre_axis.x_max != -1)
+ device_axis.x_max = pre_axis.x_max;
+ if (pre_axis.y_min != -1)
+ device_axis.y_min = pre_axis.y_min;
+ if (pre_axis.y_max != -1)
+ device_axis.y_max = pre_axis.y_max;
+
+ if (verbose) {
+ printf("DEBUG: Setting precalibration: %lf, %lf, %lf, %lf\n",
+ device_axis.x_min, device_axis.x_max,
+ device_axis.y_min, device_axis.y_max);
+ }
+ }
+
+ /* lastly, presume a standard Xorg driver (evtouch, mutouch, ...) */
+ return CalibratorXorgPrint(device_name, &device_axis,
+ verbose, thr_misclick, thr_doubleclick);
+}
+
+static gboolean output_xorgconfd(const XYinfo new_axis, int swap_xy, int new_swap_xy)
+{
+ const char* sysfs_name = "!!Name_Of_TouchScreen!!";
+
+ /* xorg.conf.d snippet */
+ printf(" copy the snippet below into '/etc/X11/xorg.conf.d/99-calibration.conf'\n");
+ printf("Section \"InputClass\"\n");
+ printf(" Identifier \"calibration\"\n");
+ printf(" MatchProduct \"%s\"\n", sysfs_name);
+ printf(" Option \"MinX\" \"%lf\"\n", new_axis.x_min);
+ printf(" Option \"MaxX\" \"%lf\"\n", new_axis.x_max);
+ printf(" Option \"MinY\" \"%lf\"\n", new_axis.y_min);
+ printf(" Option \"MaxY\" \"%lf\"\n", new_axis.y_max);
+ if (swap_xy != 0)
+ printf(" Option \"SwapXY\" \"%d\" # unless it was already set to 1\n", new_swap_xy);
+ printf("EndSection\n");
+
+ return TRUE;
+}
+
+static gboolean finish_data(const XYinfo new_axis, int swap_xy)
+{
+ gboolean success = TRUE;
+
+ /* we suppose the previous 'swap_xy' value was 0 */
+ /* (unfortunately there is no way to verify this (yet)) */
+ int new_swap_xy = swap_xy;
+
+ printf("\n\n--> Making the calibration permanent <--\n");
+ success &= output_xorgconfd(new_axis, swap_xy, new_swap_xy);
+
+ return success;
+}
+
+static void
+calibration_finished_cb (CcCalibArea *area,
+ gpointer user_data)
+{
+ gboolean success;
+ XYinfo axis;
+ gboolean swap_xy;
+
+ success = cc_calib_area_finish (area);
+ if (success)
+ {
+ cc_calib_area_get_axis (area, &axis, &swap_xy);
+ success = finish_data (axis, swap_xy);
+ }
+ else
+ fprintf(stderr, "Error: unable to apply or save configuration values\n");
+
+ g_main_loop_quit (mainloop);
+}
+
+int main(int argc, char** argv)
+{
+
+ struct Calib* calibrator = main_common(argc, argv);
+ CcCalibArea *calib_area;
+
+ bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ gtk_init ();
+
+ g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
+
+ calib_area = cc_calib_area_new (NULL,
+ NULL, /* monitor */
+ NULL, /* NULL to accept input from any device */
+ calibration_finished_cb,
+ NULL,
+ calibrator->threshold_doubleclick,
+ calibrator->threshold_misclick);
+
+ mainloop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (mainloop);
+
+ cc_calib_area_free (calib_area);
+
+ free(calibrator);
+
+ return 0;
+}
diff --git a/panels/wacom/calibrator/meson.build b/panels/wacom/calibrator/meson.build
new file mode 100644
index 0000000..f894e60
--- /dev/null
+++ b/panels/wacom/calibrator/meson.build
@@ -0,0 +1,35 @@
+calibrator_inc = include_directories('.')
+
+common_sources = files(
+ 'calibrator.c',
+ 'calibrator-gui.c',
+ 'cc-clock.c',
+)
+
+calibrator_deps = deps + [m_dep]
+
+libwacom_calibrator = static_library(
+ cappletname + '-calibrator',
+ sources: common_sources,
+ include_directories: top_inc,
+ dependencies: calibrator_deps,
+ c_args: cflags
+)
+
+libwacom_calibrator_test = static_library(
+ cappletname + '-calibrator-test',
+ sources: common_sources,
+ include_directories: top_inc,
+ dependencies: calibrator_deps,
+ c_args: test_cflags
+)
+
+sources = common_sources + wacom_gresource + files('main.c')
+
+executable(
+ 'test-calibrator',
+ sources,
+ include_directories: top_inc,
+ dependencies: calibrator_deps,
+ c_args: cflags
+)
diff --git a/panels/wacom/calibrator/target.svg b/panels/wacom/calibrator/target.svg
new file mode 100644
index 0000000..60b4cbb
--- /dev/null
+++ b/panels/wacom/calibrator/target.svg
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="200"
+ height="200"
+ viewBox="0 0 52.916666 52.916668"
+ version="1.1"
+ id="svg8"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)"
+ sodipodi:docname="target.svg">
+ <defs
+ id="defs2" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.8"
+ inkscape:cx="26.277089"
+ inkscape:cy="74.824155"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ showgrid="true"
+ units="px"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:window-width="2160"
+ inkscape:window-height="1311"
+ inkscape:window-x="0"
+ inkscape:window-y="55"
+ inkscape:window-maximized="1">
+ <inkscape:grid
+ type="xygrid"
+ id="grid4518" />
+ <sodipodi:guide
+ position="-7.9374999,13.229167"
+ orientation="1,0"
+ id="guide4542"
+ inkscape:locked="false" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-244.08332)">
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:0.5291667px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 0,270.54165 h 52.916667 v 0"
+ id="path4520"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:0.5291667px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 26.458334,244.08331 v 52.91667"
+ id="path4522"
+ inkscape:connector-curvature="0" />
+ <ellipse
+ style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.5291667;stroke-opacity:1"
+ id="path4530"
+ cx="26.458332"
+ cy="270.54163"
+ rx="5.2916665"
+ ry="5.2916679" />
+ <ellipse
+ style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.00000012;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path4534"
+ cx="26.458332"
+ cy="270.54163"
+ rx="15.875"
+ ry="15.875004" />
+ </g>
+</svg>
diff --git a/panels/wacom/cc-drawing-area.c b/panels/wacom/cc-drawing-area.c
new file mode 100644
index 0000000..3f570ad
--- /dev/null
+++ b/panels/wacom/cc-drawing-area.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright © 2016 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Carlos Garnacho <carlosg@gnome.org>
+ */
+
+#include "config.h"
+#include <cairo/cairo.h>
+#include "cc-drawing-area.h"
+
+typedef struct _CcDrawingArea CcDrawingArea;
+
+struct _CcDrawingArea {
+ GtkDrawingArea parent;
+ GtkGesture *stylus_gesture;
+ cairo_surface_t *surface;
+ cairo_t *cr;
+};
+
+G_DEFINE_TYPE (CcDrawingArea, cc_drawing_area, GTK_TYPE_DRAWING_AREA)
+
+static void
+ensure_drawing_surface (CcDrawingArea *area,
+ gint width,
+ gint height)
+{
+ if (!area->surface ||
+ cairo_image_surface_get_width (area->surface) != width ||
+ cairo_image_surface_get_height (area->surface) != height) {
+ cairo_surface_t *surface;
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ width, height);
+ if (area->surface) {
+ cairo_t *cr;
+
+ cr = cairo_create (surface);
+ cairo_set_source_surface (cr, area->surface, 0, 0);
+ cairo_paint (cr);
+
+ cairo_surface_destroy (area->surface);
+ cairo_destroy (area->cr);
+ cairo_destroy (cr);
+ }
+
+ area->surface = surface;
+ area->cr = cairo_create (surface);
+ }
+}
+
+static void
+cc_drawing_area_map (GtkWidget *widget)
+{
+ GtkAllocation allocation;
+
+ GTK_WIDGET_CLASS (cc_drawing_area_parent_class)->map (widget);
+
+ gtk_widget_get_allocation (widget, &allocation);
+ ensure_drawing_surface (CC_DRAWING_AREA (widget),
+ allocation.width, allocation.height);
+}
+
+static void
+cc_drawing_area_unmap (GtkWidget *widget)
+{
+ CcDrawingArea *area = CC_DRAWING_AREA (widget);
+
+ if (area->cr) {
+ cairo_destroy (area->cr);
+ area->cr = NULL;
+ }
+
+ if (area->surface) {
+ cairo_surface_destroy (area->surface);
+ area->surface = NULL;
+ }
+
+ GTK_WIDGET_CLASS (cc_drawing_area_parent_class)->unmap (widget);
+}
+
+static void
+draw_cb (GtkDrawingArea *drawing_area,
+ cairo_t *cr,
+ gint width,
+ gint height,
+ gpointer user_data)
+{
+ CcDrawingArea *area = CC_DRAWING_AREA (drawing_area);
+
+ ensure_drawing_surface (area, width, height);
+
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_paint (cr);
+
+ cairo_set_source_surface (cr, area->surface, 0, 0);
+ cairo_paint (cr);
+
+ cairo_set_source_rgb (cr, 0.6, 0.6, 0.6);
+ cairo_rectangle (cr, 0, 0, width, height);
+ cairo_stroke (cr);
+}
+
+static void
+stylus_down_cb (GtkGestureStylus *gesture,
+ double x,
+ double y,
+ CcDrawingArea *area)
+{
+ cairo_new_path (area->cr);
+}
+
+static void
+stylus_motion_cb (GtkGestureStylus *gesture,
+ double x,
+ double y,
+ CcDrawingArea *area)
+{
+ GdkDeviceTool *tool;
+ gdouble pressure;
+
+ tool = gtk_gesture_stylus_get_device_tool (gesture);
+ gtk_gesture_stylus_get_axis (gesture,
+ GDK_AXIS_PRESSURE,
+ &pressure);
+
+ if (gdk_device_tool_get_tool_type (tool) == GDK_DEVICE_TOOL_TYPE_ERASER) {
+ cairo_set_line_width (area->cr, 10 * pressure);
+ cairo_set_operator (area->cr, CAIRO_OPERATOR_DEST_OUT);
+ } else {
+ cairo_set_line_width (area->cr, 4 * pressure);
+ cairo_set_operator (area->cr, CAIRO_OPERATOR_SATURATE);
+ }
+
+ cairo_set_source_rgba (area->cr, 0, 0, 0, pressure);
+ cairo_line_to (area->cr, x, y);
+ cairo_stroke (area->cr);
+
+ cairo_move_to (area->cr, x, y);
+
+ gtk_widget_queue_draw (GTK_WIDGET (area));
+}
+
+static void
+cc_drawing_area_class_init (CcDrawingAreaClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ widget_class->map = cc_drawing_area_map;
+ widget_class->unmap = cc_drawing_area_unmap;
+}
+
+static void
+cc_drawing_area_init (CcDrawingArea *area)
+{
+ gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (area), draw_cb, NULL, NULL);
+ area->stylus_gesture = gtk_gesture_stylus_new ();
+ g_signal_connect (area->stylus_gesture, "down",
+ G_CALLBACK (stylus_down_cb), area);
+ g_signal_connect (area->stylus_gesture, "motion",
+ G_CALLBACK (stylus_motion_cb), area);
+ gtk_widget_add_controller (GTK_WIDGET (area),
+ GTK_EVENT_CONTROLLER (area->stylus_gesture));
+}
+
+GtkWidget *
+cc_drawing_area_new (void)
+{
+ return g_object_new (CC_TYPE_DRAWING_AREA, NULL);
+}
diff --git a/panels/wacom/cc-drawing-area.h b/panels/wacom/cc-drawing-area.h
new file mode 100644
index 0000000..1d3d6ba
--- /dev/null
+++ b/panels/wacom/cc-drawing-area.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright © 2016 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Carlos Garnacho <carlosg@gnome.org>
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_DRAWING_AREA (cc_drawing_area_get_type ())
+G_DECLARE_FINAL_TYPE (CcDrawingArea, cc_drawing_area, CC, DRAWING_AREA, GtkDrawingArea)
+
+GtkWidget *cc_drawing_area_new (void);
+
+G_END_DECLS
diff --git a/panels/wacom/cc-tablet-tool-map.c b/panels/wacom/cc-tablet-tool-map.c
new file mode 100644
index 0000000..bdc51b9
--- /dev/null
+++ b/panels/wacom/cc-tablet-tool-map.c
@@ -0,0 +1,398 @@
+/*
+ * Copyright © 2016 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Carlos Garnacho <carlosg@gnome.org>
+ *
+ */
+
+#include "config.h"
+#include "cc-tablet-tool-map.h"
+
+#define KEY_TOOL_ID "ID"
+#define KEY_DEVICE_STYLI "Styli"
+#define GENERIC_STYLUS "generic"
+
+typedef struct _CcTabletToolMap CcTabletToolMap;
+
+struct _CcTabletToolMap {
+ GObject parent_instance;
+ GKeyFile *tablets;
+ GKeyFile *tools;
+ GHashTable *tool_map;
+ GHashTable *tablet_map;
+ GHashTable *no_serial_tool_map;
+
+ gchar *tablet_path;
+ gchar *tool_path;
+};
+
+G_DEFINE_TYPE (CcTabletToolMap, cc_tablet_tool_map, G_TYPE_OBJECT)
+
+static void
+load_keyfiles (CcTabletToolMap *map)
+{
+ g_autoptr(GError) devices_error = NULL;
+ g_autoptr(GError) tools_error = NULL;
+ g_autofree gchar *dir = NULL;
+
+ dir = g_build_filename (g_get_user_cache_dir (), "gnome-control-center", "wacom", NULL);
+
+ if (g_mkdir_with_parents (dir, 0700) < 0) {
+ g_warning ("Could not create directory '%s', expect stylus mapping oddities: %m", dir);
+ return;
+ }
+
+ map->tablet_path = g_build_filename (dir, "devices", NULL);
+ g_key_file_load_from_file (map->tablets, map->tablet_path,
+ G_KEY_FILE_NONE, &devices_error);
+
+ if (devices_error && !g_error_matches (devices_error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) {
+ g_warning ("Could not load tablets keyfile '%s': %s",
+ map->tablet_path, devices_error->message);
+ }
+
+ map->tool_path = g_build_filename (dir, "tools", NULL);
+ g_key_file_load_from_file (map->tools, map->tool_path,
+ G_KEY_FILE_NONE, &tools_error);
+
+ if (tools_error && !g_error_matches (tools_error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) {
+ g_warning ("Could not load tools keyfile '%s': %s",
+ map->tool_path, tools_error->message);
+ }
+}
+
+static void
+cache_tools (CcTabletToolMap *map)
+{
+ g_auto(GStrv) serials = NULL;
+ gsize n_serials, i;
+
+ serials = g_key_file_get_groups (map->tools, &n_serials);
+
+ for (i = 0; i < n_serials; i++) {
+ g_autofree gchar *str = NULL;
+ gchar *end;
+ guint64 serial, id;
+ g_autoptr(GError) error = NULL;
+ CcWacomTool *tool;
+
+ serial = g_ascii_strtoull (serials[i], &end, 16);
+
+ if (*end != '\0') {
+ g_warning ("Invalid tool serial %s", serials[i]);
+ continue;
+ }
+
+ str = g_key_file_get_string (map->tools, serials[i], KEY_TOOL_ID, &error);
+ if (str == NULL) {
+ g_warning ("Could not get cached ID for tool with serial %s: %s",
+ serials[i], error->message);
+ continue;
+ }
+
+ id = g_ascii_strtoull (str, &end, 16);
+ if (*end != '\0') {
+ g_warning ("Invalid tool ID %s", str);
+ continue;
+ }
+
+ tool = cc_wacom_tool_new (serial, id, NULL);
+ g_hash_table_insert (map->tool_map, g_strdup (serials[i]), tool);
+ }
+}
+
+static void
+cache_devices (CcTabletToolMap *map)
+{
+ gchar **ids;
+ gsize n_ids, i;
+
+ ids = g_key_file_get_groups (map->tablets, &n_ids);
+
+ for (i = 0; i < n_ids; i++) {
+ gchar **styli;
+ gsize n_styli, j;
+ g_autoptr(GError) error = NULL;
+ GList *tools = NULL;
+
+ styli = g_key_file_get_string_list (map->tablets, ids[i], KEY_DEVICE_STYLI, &n_styli, &error);
+ if (styli == NULL) {
+ g_warning ("Could not get cached styli for with ID %s: %s",
+ ids[i], error->message);
+ continue;
+ }
+
+ for (j = 0; j < n_styli; j++) {
+ CcWacomTool *tool;
+
+ if (g_str_equal (styli[j], GENERIC_STYLUS)) {
+ /* We don't have a GsdDevice yet to create the
+ * serial=0 CcWacomTool, insert a NULL and defer
+ * to device lookups.
+ */
+ g_hash_table_insert (map->no_serial_tool_map,
+ g_strdup (ids[i]), NULL);
+ }
+
+ tool = g_hash_table_lookup (map->tool_map, styli[j]);
+
+ if (tool)
+ tools = g_list_prepend (tools, tool);
+ }
+
+ if (tools) {
+ g_hash_table_insert (map->tablet_map, g_strdup (ids[i]), tools);
+ }
+
+ g_strfreev (styli);
+ }
+
+ g_strfreev (ids);
+}
+
+static void
+cc_tablet_tool_map_finalize (GObject *object)
+{
+ CcTabletToolMap *map = CC_TABLET_TOOL_MAP (object);
+
+ g_key_file_unref (map->tools);
+ g_key_file_unref (map->tablets);
+ g_hash_table_destroy (map->tool_map);
+ g_hash_table_destroy (map->tablet_map);
+ g_hash_table_destroy (map->no_serial_tool_map);
+ g_free (map->tablet_path);
+ g_free (map->tool_path);
+
+ G_OBJECT_CLASS (cc_tablet_tool_map_parent_class)->finalize (object);
+}
+
+static void
+null_safe_unref (gpointer data)
+{
+ if (data != NULL)
+ g_object_unref (data);
+}
+
+static void
+cc_tablet_tool_map_init (CcTabletToolMap *map)
+{
+ map->tablets = g_key_file_new ();
+ map->tools = g_key_file_new ();
+ map->tool_map = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_object_unref);
+ map->tablet_map = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_list_free);
+ map->no_serial_tool_map = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) null_safe_unref);
+ load_keyfiles (map);
+ cache_tools (map);
+ cache_devices (map);
+}
+
+static void
+cc_tablet_tool_map_class_init (CcTabletToolMapClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = cc_tablet_tool_map_finalize;
+}
+
+CcTabletToolMap *
+cc_tablet_tool_map_new (void)
+{
+ return g_object_new (CC_TYPE_TABLET_TOOL_MAP, NULL);
+}
+
+static gchar *
+get_device_key (CcWacomDevice *device)
+{
+ const gchar *vendor, *product;
+ GsdDevice *gsd_device;
+
+ gsd_device = cc_wacom_device_get_device (device);
+ gsd_device_get_device_ids (gsd_device, &vendor, &product);
+
+ return g_strdup_printf ("%s:%s", vendor, product);
+}
+
+static gchar *
+get_tool_key (guint64 serial)
+{
+ return g_strdup_printf ("%lx", serial);
+}
+
+GList *
+cc_tablet_tool_map_list_tools (CcTabletToolMap *map,
+ CcWacomDevice *device)
+{
+ CcWacomTool *no_serial_tool;
+ GList *styli;
+ g_autofree gchar *key = NULL;
+
+ g_return_val_if_fail (CC_IS_TABLET_TOOL_MAP (map), NULL);
+ g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), NULL);
+
+ key = get_device_key (device);
+ styli = g_list_copy (g_hash_table_lookup (map->tablet_map, key));
+
+ if (g_hash_table_lookup_extended (map->no_serial_tool_map, key,
+ NULL, (gpointer) &no_serial_tool)) {
+ if (!no_serial_tool) {
+ no_serial_tool = cc_wacom_tool_new (0, 0, device);
+ g_hash_table_replace (map->no_serial_tool_map,
+ g_strdup (key),
+ no_serial_tool);
+ }
+
+ styli = g_list_prepend (styli, no_serial_tool);
+ }
+
+ return styli;
+}
+
+CcWacomTool *
+cc_tablet_tool_map_lookup_tool (CcTabletToolMap *map,
+ CcWacomDevice *device,
+ guint64 serial)
+{
+ CcWacomTool *tool = NULL;
+ g_autofree gchar *key = NULL;
+
+ g_return_val_if_fail (CC_IS_TABLET_TOOL_MAP (map), FALSE);
+ g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), FALSE);
+
+ if (serial == 0) {
+ key = get_device_key (device);
+ tool = g_hash_table_lookup (map->no_serial_tool_map, key);
+ } else {
+ key = get_tool_key (serial);
+ tool = g_hash_table_lookup (map->tool_map, key);
+ }
+
+ return tool;
+}
+
+static void
+keyfile_add_device_stylus (CcTabletToolMap *map,
+ const gchar *device_key,
+ const gchar *tool_key)
+{
+ g_autoptr(GArray) array = NULL;
+ g_auto(GStrv) styli = NULL;
+ gsize n_styli;
+
+ array = g_array_new (FALSE, FALSE, sizeof (gchar *));
+ styli = g_key_file_get_string_list (map->tablets, device_key,
+ KEY_DEVICE_STYLI, &n_styli,
+ NULL);
+
+ if (styli) {
+ g_array_append_vals (array, styli, n_styli);
+ }
+
+ g_array_append_val (array, tool_key);
+ g_key_file_set_string_list (map->tablets, device_key, KEY_DEVICE_STYLI,
+ (const gchar **) array->data, array->len);
+}
+
+static void
+keyfile_add_stylus (CcTabletToolMap *map,
+ const gchar *tool_key,
+ guint64 id)
+{
+ g_autofree gchar *str = NULL;
+
+ /* Also works for IDs */
+ str = get_tool_key (id);
+ g_key_file_set_string (map->tools, tool_key, KEY_TOOL_ID, str);
+}
+
+void
+cc_tablet_tool_map_add_relation (CcTabletToolMap *map,
+ CcWacomDevice *device,
+ CcWacomTool *tool)
+{
+ gboolean tablets_changed = FALSE, tools_changed = FALSE;
+ gboolean new_tool_without_serial = FALSE;
+ g_autofree gchar *tool_key = NULL;
+ g_autofree gchar *device_key = NULL;
+ guint64 serial, id;
+ GList *styli;
+
+ g_return_if_fail (CC_IS_TABLET_TOOL_MAP (map));
+ g_return_if_fail (CC_IS_WACOM_DEVICE (device));
+ g_return_if_fail (CC_IS_WACOM_TOOL (tool));
+
+ serial = cc_wacom_tool_get_serial (tool);
+ id = cc_wacom_tool_get_id (tool);
+ device_key = get_device_key (device);
+
+ if (serial == 0) {
+ tool_key = g_strdup (GENERIC_STYLUS);
+
+ if (!g_hash_table_contains (map->no_serial_tool_map, device_key)) {
+ g_hash_table_insert (map->no_serial_tool_map,
+ g_strdup (device_key),
+ g_object_ref (tool));
+ new_tool_without_serial = TRUE;
+ }
+ } else {
+ tool_key = get_tool_key (serial);
+
+ if (!g_hash_table_contains (map->tool_map, tool_key)) {
+ keyfile_add_stylus (map, tool_key, id);
+ tools_changed = TRUE;
+ g_hash_table_insert (map->tool_map,
+ g_strdup (tool_key),
+ g_object_ref (tool));
+ }
+ }
+
+ styli = g_hash_table_lookup (map->tablet_map, device_key);
+
+ if (!g_list_find (styli, tool)) {
+ styli = g_list_prepend (styli, tool);
+ g_hash_table_replace (map->tablet_map,
+ g_strdup (device_key),
+ g_list_copy (styli));
+
+ if (serial || new_tool_without_serial) {
+ tablets_changed = TRUE;
+ keyfile_add_device_stylus (map, device_key, tool_key);
+ }
+ }
+
+ if (tools_changed) {
+ g_autoptr(GError) error = NULL;
+
+ if (!g_key_file_save_to_file (map->tools, map->tool_path, &error)) {
+ g_warning ("Error saving tools keyfile: %s",
+ error->message);
+ }
+ }
+
+ if (tablets_changed) {
+ g_autoptr(GError) error = NULL;
+
+ if (!g_key_file_save_to_file (map->tablets, map->tablet_path, &error)) {
+ g_warning ("Error saving tablets keyfile: %s",
+ error->message);
+ }
+ }
+}
diff --git a/panels/wacom/cc-tablet-tool-map.h b/panels/wacom/cc-tablet-tool-map.h
new file mode 100644
index 0000000..a65eb2a
--- /dev/null
+++ b/panels/wacom/cc-tablet-tool-map.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2016 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Carlos Garnacho <carlosg@gnome.org>
+ *
+ */
+
+#pragma once
+
+#include "config.h"
+#include <gtk/gtk.h>
+#include "cc-wacom-device.h"
+#include "cc-wacom-tool.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_TABLET_TOOL_MAP (cc_tablet_tool_map_get_type ())
+G_DECLARE_FINAL_TYPE (CcTabletToolMap, cc_tablet_tool_map, CC, TABLET_TOOL_MAP, GObject)
+
+CcTabletToolMap * cc_tablet_tool_map_new (void);
+
+GList * cc_tablet_tool_map_list_tools (CcTabletToolMap *map,
+ CcWacomDevice *device);
+CcWacomTool * cc_tablet_tool_map_lookup_tool (CcTabletToolMap *map,
+ CcWacomDevice *device,
+ guint64 serial);
+void cc_tablet_tool_map_add_relation (CcTabletToolMap *map,
+ CcWacomDevice *device,
+ CcWacomTool *tool);
+
+G_END_DECLS
diff --git a/panels/wacom/cc-wacom-button-row.c b/panels/wacom/cc-wacom-button-row.c
new file mode 100644
index 0000000..3c8536b
--- /dev/null
+++ b/panels/wacom/cc-wacom-button-row.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright © 2013 Red Hat, Inc.
+ *
+ * Authors: Joaquim Rocha <jrocha@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include "gsd-wacom-key-shortcut-button.h"
+#include "cc-wacom-button-row.h"
+
+#define ACTION_KEY "action"
+#define KEYBINDING_KEY "keybinding"
+
+#define WACOM_C(x) g_dpgettext2(NULL, "Wacom action-type", x)
+
+enum {
+ ACTION_NAME_COLUMN,
+ ACTION_TYPE_COLUMN,
+ ACTION_N_COLUMNS
+};
+
+struct _CcWacomButtonRow {
+ GtkListBoxRow parent_instance;
+ guint button;
+ GSettings *settings;
+ GtkDirectionType direction;
+ GtkComboBox *action_combo;
+ GsdWacomKeyShortcutButton *key_shortcut_button;
+};
+
+G_DEFINE_TYPE (CcWacomButtonRow, cc_wacom_button_row, GTK_TYPE_LIST_BOX_ROW)
+
+static GtkWidget *
+create_actions_combo (void)
+{
+ GtkListStore *model;
+ GtkTreeIter iter;
+ GtkWidget *combo;
+ GtkCellRenderer *renderer;
+ gint i;
+
+ model = gtk_list_store_new (ACTION_N_COLUMNS, G_TYPE_STRING, G_TYPE_INT);
+
+ for (i = 0; i < G_N_ELEMENTS (action_table); i++)
+ {
+ gtk_list_store_append (model, &iter);
+ gtk_list_store_set (model, &iter,
+ ACTION_NAME_COLUMN, WACOM_C(action_table[i].action_name),
+ ACTION_TYPE_COLUMN, action_table[i].action_type, -1);
+ }
+
+ combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (model));
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer,
+ "text", ACTION_NAME_COLUMN, NULL);
+
+
+ return combo;
+}
+
+static void
+cc_wacom_button_row_update_shortcut (CcWacomButtonRow *row,
+ GDesktopPadButtonAction action_type)
+{
+ guint keyval;
+ GdkModifierType mask;
+ g_autofree gchar *shortcut = NULL;
+
+ if (action_type != G_DESKTOP_PAD_BUTTON_ACTION_KEYBINDING)
+ return;
+
+ shortcut = g_settings_get_string (row->settings, KEYBINDING_KEY);
+
+ if (shortcut != NULL)
+ {
+ gtk_accelerator_parse (shortcut, &keyval, &mask);
+
+ g_object_set (row->key_shortcut_button,
+ "key-value", keyval,
+ "key-mods", mask,
+ NULL);
+ }
+}
+
+static void
+cc_wacom_button_row_update_action (CcWacomButtonRow *row,
+ GDesktopPadButtonAction action_type)
+{
+ GtkTreeIter iter;
+ gboolean iter_valid;
+ GDesktopPadButtonAction current_action_type, real_action_type;
+ GtkTreeModel *model;
+
+ model = gtk_combo_box_get_model (row->action_combo);
+ real_action_type = action_type;
+
+ for (iter_valid = gtk_tree_model_get_iter_first (model, &iter); iter_valid;
+ iter_valid = gtk_tree_model_iter_next (model, &iter))
+ {
+ gtk_tree_model_get (model, &iter,
+ ACTION_TYPE_COLUMN, &current_action_type,
+ -1);
+
+ if (current_action_type == real_action_type)
+ {
+ gtk_combo_box_set_active_iter (row->action_combo, &iter);
+ break;
+ }
+ }
+}
+
+static void
+cc_wacom_button_row_update (CcWacomButtonRow *row)
+{
+ GDesktopPadButtonAction current_action_type;
+
+ current_action_type = g_settings_get_enum (row->settings, ACTION_KEY);
+
+ cc_wacom_button_row_update_shortcut (row, current_action_type);
+
+ cc_wacom_button_row_update_action (row, current_action_type);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (row->key_shortcut_button),
+ current_action_type == G_DESKTOP_PAD_BUTTON_ACTION_KEYBINDING);
+}
+
+static void
+change_button_action_type (CcWacomButtonRow *row,
+ GDesktopPadButtonAction type)
+{
+ g_settings_set_enum (row->settings, ACTION_KEY, type);
+ gtk_widget_set_sensitive (GTK_WIDGET (row->key_shortcut_button),
+ type == G_DESKTOP_PAD_BUTTON_ACTION_KEYBINDING);
+}
+
+static void
+on_key_shortcut_edited (CcWacomButtonRow *row)
+{
+ g_autofree gchar *custom_key = NULL;
+ guint keyval;
+ GdkModifierType mask;
+
+ change_button_action_type (row, G_DESKTOP_PAD_BUTTON_ACTION_KEYBINDING);
+
+ g_object_get (row->key_shortcut_button,
+ "key-value", &keyval,
+ "key-mods", &mask,
+ NULL);
+
+ mask &= ~GDK_LOCK_MASK;
+
+ custom_key = gtk_accelerator_name (keyval, mask);
+
+ g_settings_set_string (row->settings, KEYBINDING_KEY, custom_key);
+}
+
+static void
+on_key_shortcut_cleared (CcWacomButtonRow *row)
+{
+ change_button_action_type (row, G_DESKTOP_PAD_BUTTON_ACTION_NONE);
+ cc_wacom_button_row_update_action (row, G_DESKTOP_PAD_BUTTON_ACTION_NONE);
+}
+
+static void
+on_row_action_combo_box_changed (CcWacomButtonRow *row)
+{
+ GDesktopPadButtonAction type;
+ GtkTreeModel *model;
+ GtkListBox *list_box;
+ GtkTreeIter iter;
+
+ if (!gtk_combo_box_get_active_iter (row->action_combo, &iter))
+ return;
+
+ /* Select the row where we changed the combo box (if not yet selected) */
+ list_box = GTK_LIST_BOX (gtk_widget_get_parent (GTK_WIDGET (row)));
+ if (list_box && gtk_list_box_get_selected_row (list_box) != GTK_LIST_BOX_ROW (row))
+ gtk_list_box_select_row (list_box, GTK_LIST_BOX_ROW (row));
+
+ model = gtk_combo_box_get_model (row->action_combo);
+ gtk_tree_model_get (model, &iter, ACTION_TYPE_COLUMN, &type, -1);
+
+ change_button_action_type (row, type);
+}
+
+static gboolean
+on_key_shortcut_button_press_event (CcWacomButtonRow *row)
+{
+ GtkListBox *list_box;
+
+ /* Select the row where we pressed the button (if not yet selected) */
+ list_box = GTK_LIST_BOX (gtk_widget_get_parent (GTK_WIDGET (row)));
+ if (list_box && gtk_list_box_get_selected_row (list_box) != GTK_LIST_BOX_ROW (row))
+ gtk_list_box_select_row (list_box, GTK_LIST_BOX_ROW (row));
+
+ return FALSE;
+}
+
+static void
+cc_wacom_button_row_class_init (CcWacomButtonRowClass *button_row_class)
+{
+}
+
+static void
+cc_wacom_button_row_init (CcWacomButtonRow *button_row)
+{
+}
+
+GtkWidget *
+cc_wacom_button_row_new (guint button,
+ GSettings *settings)
+{
+ CcWacomButtonRow *row;
+ GtkWidget *grid, *combo, *label, *shortcut_button;
+ g_autofree gchar *name = NULL;
+
+ row = CC_WACOM_BUTTON_ROW (g_object_new (CC_WACOM_TYPE_BUTTON_ROW, NULL));
+
+ row->button = button;
+ row->settings = g_object_ref (settings);
+
+ grid = gtk_grid_new ();
+ gtk_widget_show (grid);
+ gtk_grid_set_row_homogeneous (GTK_GRID (grid), TRUE);
+ gtk_grid_set_column_homogeneous (GTK_GRID (grid), TRUE);
+
+ name = g_strdup_printf (_("Button %d"), button);
+ label = gtk_label_new (name);
+ g_object_set (label, "halign", GTK_ALIGN_START, NULL);
+ gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
+ gtk_widget_show (label);
+
+ combo = create_actions_combo ();
+ gtk_grid_attach (GTK_GRID (grid), combo, 1, 0, 1, 1);
+ gtk_widget_show (combo);
+ row->action_combo = GTK_COMBO_BOX (combo);
+ g_signal_connect_object (combo, "changed",
+ G_CALLBACK (on_row_action_combo_box_changed), row, G_CONNECT_SWAPPED);
+
+ shortcut_button = gsd_wacom_key_shortcut_button_new ();
+ g_object_set (shortcut_button, "mode", GSD_WACOM_KEY_SHORTCUT_BUTTON_MODE_ALL, NULL);
+ gtk_grid_attach (GTK_GRID (grid), shortcut_button, 2, 0, 1, 1);
+ gtk_widget_show (shortcut_button);
+ row->key_shortcut_button = GSD_WACOM_KEY_SHORTCUT_BUTTON (shortcut_button);
+ g_signal_connect_object (shortcut_button, "key-shortcut-cleared",
+ G_CALLBACK (on_key_shortcut_cleared),
+ row,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (shortcut_button, "key-shortcut-edited",
+ G_CALLBACK (on_key_shortcut_edited),
+ row,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (shortcut_button, "button-press-event",
+ G_CALLBACK (on_key_shortcut_button_press_event),
+ row,
+ G_CONNECT_SWAPPED);
+
+ gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), grid);
+
+ cc_wacom_button_row_update (CC_WACOM_BUTTON_ROW (row));
+
+ return GTK_WIDGET (row);
+}
diff --git a/panels/wacom/cc-wacom-button-row.h b/panels/wacom/cc-wacom-button-row.h
new file mode 100644
index 0000000..7a30d11
--- /dev/null
+++ b/panels/wacom/cc-wacom-button-row.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright © 2013 Red Hat, Inc.
+ *
+ * Authors: Joaquim Rocha <jrocha@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <gdesktop-enums.h>
+
+G_BEGIN_DECLS
+
+#define CC_WACOM_TYPE_BUTTON_ROW (cc_wacom_button_row_get_type ())
+G_DECLARE_FINAL_TYPE (CcWacomButtonRow, cc_wacom_button_row, CC, WACOM_BUTTON_ROW, GtkListBoxRow)
+
+static struct {
+ GDesktopPadButtonAction action_type;
+ const gchar *action_name;
+} action_table[] = {
+ { G_DESKTOP_PAD_BUTTON_ACTION_NONE, NC_("Wacom action-type", "Application defined") },
+ { G_DESKTOP_PAD_BUTTON_ACTION_KEYBINDING, NC_("Wacom action-type", "Send Keystroke") },
+ { G_DESKTOP_PAD_BUTTON_ACTION_SWITCH_MONITOR, NC_("Wacom action-type", "Switch Monitor") },
+ { G_DESKTOP_PAD_BUTTON_ACTION_HELP, NC_("Wacom action-type", "Show On-Screen Help") }
+};
+
+GtkWidget * cc_wacom_button_row_new (guint button,
+ GSettings *settings);
+
+G_END_DECLS
diff --git a/panels/wacom/cc-wacom-device.c b/panels/wacom/cc-wacom-device.c
new file mode 100644
index 0000000..695b85b
--- /dev/null
+++ b/panels/wacom/cc-wacom-device.c
@@ -0,0 +1,437 @@
+/*
+ * Copyright © 2016 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Carlos Garnacho <carlosg@gnome.org>
+ *
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include "cc-wacom-device.h"
+
+#include <glib/gi18n.h>
+
+enum {
+ PROP_0,
+ PROP_DEVICE,
+ N_PROPS
+};
+
+GParamSpec *props[N_PROPS] = { 0 };
+
+typedef struct _CcWacomDevice CcWacomDevice;
+
+struct _CcWacomDevice {
+ GObject parent_instance;
+
+ GsdDevice *device;
+ WacomDevice *wdevice;
+};
+
+static void cc_wacom_device_initable_iface_init (GInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (CcWacomDevice, cc_wacom_device, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+ cc_wacom_device_initable_iface_init))
+
+WacomDeviceDatabase *
+cc_wacom_device_database_get (void)
+{
+ static WacomDeviceDatabase *db = NULL;
+
+ if (g_once_init_enter (&db)) {
+ gpointer p = libwacom_database_new ();
+ g_once_init_leave (&db, p);
+ }
+
+ return db;
+}
+
+static void
+cc_wacom_device_init (CcWacomDevice *device)
+{
+}
+
+static void
+cc_wacom_device_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcWacomDevice *device = CC_WACOM_DEVICE (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ device->device = g_value_get_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_wacom_device_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcWacomDevice *device = CC_WACOM_DEVICE (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ g_value_set_object (value, device->device);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_wacom_device_finalize (GObject *object)
+{
+ CcWacomDevice *device = CC_WACOM_DEVICE (object);
+
+ g_clear_pointer (&device->wdevice, libwacom_destroy);
+
+ G_OBJECT_CLASS (cc_wacom_device_parent_class)->finalize (object);
+}
+
+static void
+cc_wacom_device_class_init (CcWacomDeviceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = cc_wacom_device_set_property;
+ object_class->get_property = cc_wacom_device_get_property;
+ object_class->finalize = cc_wacom_device_finalize;
+
+ props[PROP_DEVICE] =
+ g_param_spec_object ("device",
+ "device",
+ "device",
+ GSD_TYPE_DEVICE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+
+ g_object_class_install_properties (object_class, N_PROPS, props);
+}
+
+static gboolean
+cc_wacom_device_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ CcWacomDevice *device = CC_WACOM_DEVICE (initable);
+ WacomDeviceDatabase *wacom_db;
+ WacomError *wacom_error;
+ const gchar *node_path;
+
+ wacom_db = cc_wacom_device_database_get ();
+ node_path = gsd_device_get_device_file (device->device);
+ wacom_error = libwacom_error_new ();
+ device->wdevice = libwacom_new_from_path (wacom_db, node_path, FALSE, wacom_error);
+
+ if (!device->wdevice) {
+ g_debug ("libwacom_new_from_path() failed: %s", libwacom_error_get_message (wacom_error));
+ libwacom_error_free (&wacom_error);
+ g_set_error (error, 0, 0, "Tablet description not found");
+ return FALSE;
+ }
+ libwacom_error_free (&wacom_error);
+
+ return TRUE;
+}
+
+static void
+cc_wacom_device_initable_iface_init (GInitableIface *iface)
+{
+ iface->init = cc_wacom_device_initable_init;
+}
+
+CcWacomDevice *
+cc_wacom_device_new (GsdDevice *device)
+{
+ return g_initable_new (CC_TYPE_WACOM_DEVICE,
+ NULL, NULL,
+ "device", device,
+ NULL);
+}
+
+CcWacomDevice *
+cc_wacom_device_new_fake (const gchar *name)
+{
+ CcWacomDevice *device;
+ WacomDevice *wacom_device;
+ WacomError *wacom_error;
+
+ device = g_object_new (CC_TYPE_WACOM_DEVICE,
+ NULL);
+
+ wacom_error = libwacom_error_new ();
+ wacom_device = libwacom_new_from_name (cc_wacom_device_database_get(),
+ name, wacom_error);
+ if (wacom_device == NULL) {
+ g_debug ("libwacom_new_fake() failed: %s", libwacom_error_get_message (wacom_error));
+ libwacom_error_free (&wacom_error);
+ return NULL;
+ }
+ libwacom_error_free (&wacom_error);
+
+ device->wdevice = wacom_device;
+
+ return device;
+}
+
+const gchar *
+cc_wacom_device_get_name (CcWacomDevice *device)
+{
+ g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), NULL);
+
+ return libwacom_get_name (device->wdevice);
+}
+
+const gchar *
+cc_wacom_device_get_icon_name (CcWacomDevice *device)
+{
+ WacomIntegrationFlags integration_flags;
+
+ g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), NULL);
+
+ integration_flags = libwacom_get_integration_flags (device->wdevice);
+
+ if (integration_flags & WACOM_DEVICE_INTEGRATED_SYSTEM) {
+ return "wacom-tablet-pc";
+ } else if (integration_flags & WACOM_DEVICE_INTEGRATED_DISPLAY) {
+ return "wacom-tablet-cintiq";
+ } else {
+ return "wacom-tablet";
+ }
+}
+
+gboolean
+cc_wacom_device_is_reversible (CcWacomDevice *device)
+{
+ g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), FALSE);
+
+ return libwacom_is_reversible (device->wdevice);
+}
+
+WacomIntegrationFlags
+cc_wacom_device_get_integration_flags (CcWacomDevice *device)
+{
+ g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), 0);
+
+ return libwacom_get_integration_flags (device->wdevice);
+}
+
+GsdDevice *
+cc_wacom_device_get_device (CcWacomDevice *device)
+{
+ g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), NULL);
+
+ return device->device;
+}
+
+GSettings *
+cc_wacom_device_get_settings (CcWacomDevice *device)
+{
+ g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), NULL);
+
+ return gsd_device_get_settings (device->device);
+}
+
+const gint *
+cc_wacom_device_get_supported_tools (CcWacomDevice *device,
+ gint *n_tools)
+{
+ *n_tools = 0;
+
+ g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), NULL);
+
+ return libwacom_get_supported_styli (device->wdevice, n_tools);
+}
+
+static GnomeRROutput *
+find_output_by_edid (GnomeRRScreen *rr_screen,
+ const gchar *vendor,
+ const gchar *product,
+ const gchar *serial)
+{
+ GnomeRROutput **rr_outputs;
+ GnomeRROutput *retval = NULL;
+ guint i;
+
+ rr_outputs = gnome_rr_screen_list_outputs (rr_screen);
+
+ for (i = 0; rr_outputs[i] != NULL; i++) {
+ g_autofree gchar *o_vendor = NULL;
+ g_autofree gchar *o_product = NULL;
+ g_autofree gchar *o_serial = NULL;
+ gboolean match;
+
+ gnome_rr_output_get_ids_from_edid (rr_outputs[i],
+ &o_vendor,
+ &o_product,
+ &o_serial);
+
+ g_debug ("Checking for match between '%s','%s','%s' and '%s','%s','%s'", \
+ vendor, product, serial, o_vendor, o_product, o_serial);
+
+ match = (g_strcmp0 (vendor, o_vendor) == 0) && \
+ (g_strcmp0 (product, o_product) == 0) && \
+ (g_strcmp0 (serial, o_serial) == 0);
+
+ if (match) {
+ retval = rr_outputs[i];
+ break;
+ }
+ }
+
+ if (retval == NULL)
+ g_debug ("Did not find a matching output for EDID '%s,%s,%s'",
+ vendor, product, serial);
+
+ return retval;
+}
+
+static GnomeRROutput *
+find_output (GnomeRRScreen *rr_screen,
+ CcWacomDevice *device)
+{
+ g_autoptr(GSettings) settings = NULL;
+ g_autoptr(GVariant) variant = NULL;
+ g_autofree const gchar **edid = NULL;
+ gsize n;
+
+ settings = cc_wacom_device_get_settings (device);
+ variant = g_settings_get_value (settings, "output");
+ edid = g_variant_get_strv (variant, &n);
+
+ if (n != 3) {
+ g_critical ("Expected 'output' key to store %d values; got %"G_GSIZE_FORMAT".", 3, n);
+ return NULL;
+ }
+
+ if (strlen (edid[0]) == 0 || strlen (edid[1]) == 0 || strlen (edid[2]) == 0)
+ return NULL;
+
+ return find_output_by_edid (rr_screen, edid[0], edid[1], edid[2]);
+}
+
+GnomeRROutput *
+cc_wacom_device_get_output (CcWacomDevice *device,
+ GnomeRRScreen *rr_screen)
+{
+ GnomeRROutput *rr_output;
+ GnomeRRCrtc *crtc;
+
+ g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), NULL);
+ g_return_val_if_fail (GNOME_RR_IS_SCREEN (rr_screen), NULL);
+
+ rr_output = find_output (rr_screen, device);
+ if (rr_output == NULL) {
+ return NULL;
+ }
+
+ crtc = gnome_rr_output_get_crtc (rr_output);
+
+ if (!crtc || gnome_rr_crtc_get_current_mode (crtc) == NULL) {
+ g_debug ("Output is not active.");
+ return NULL;
+ }
+
+ return rr_output;
+}
+
+void
+cc_wacom_device_set_output (CcWacomDevice *device,
+ GnomeRROutput *output)
+{
+ g_autoptr(GSettings) settings = NULL;
+ g_autofree gchar *vendor = NULL;
+ g_autofree gchar *product = NULL;
+ g_autofree gchar *serial = NULL;
+ const gchar *values[] = { "", "", "", NULL };
+
+ g_return_if_fail (CC_IS_WACOM_DEVICE (device));
+
+ vendor = product = serial = NULL;
+ settings = cc_wacom_device_get_settings (device);
+
+ if (output != NULL) {
+ gnome_rr_output_get_ids_from_edid (output,
+ &vendor,
+ &product,
+ &serial);
+ values[0] = vendor;
+ values[1] = product;
+ values[2] = serial;
+ }
+
+ g_settings_set_strv (settings, "output", values);
+}
+
+guint
+cc_wacom_device_get_num_buttons (CcWacomDevice *device)
+{
+ g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), 0);
+
+ return libwacom_get_num_buttons (device->wdevice);
+}
+
+GSettings *
+cc_wacom_device_get_button_settings (CcWacomDevice *device,
+ guint button)
+{
+ g_autoptr(GSettings) tablet_settings = NULL;
+ GSettings *settings;
+ g_autofree gchar *path = NULL;
+ g_autofree gchar *button_path = NULL;
+
+ g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), NULL);
+
+ if (button > cc_wacom_device_get_num_buttons (device))
+ return NULL;
+
+ tablet_settings = cc_wacom_device_get_settings (device);
+ g_object_get (tablet_settings, "path", &path, NULL);
+
+ button_path = g_strdup_printf ("%sbutton%c/", path, 'A' + button);
+ settings = g_settings_new_with_path ("org.gnome.desktop.peripherals.tablet.pad-button",
+ button_path);
+
+ return settings;
+}
+
+const gchar *
+cc_wacom_device_get_description (CcWacomDevice *device)
+{
+ WacomIntegrationFlags integration_flags;
+
+ g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), NULL);
+
+ integration_flags = libwacom_get_integration_flags (device->wdevice);
+
+ if (integration_flags & WACOM_DEVICE_INTEGRATED_SYSTEM) {
+ return _("Tablet mounted on laptop panel");
+ } else if (integration_flags & WACOM_DEVICE_INTEGRATED_DISPLAY) {
+ return _("Tablet mounted on external display");
+ } else {
+ return _("External tablet device");
+ }
+}
diff --git a/panels/wacom/cc-wacom-device.h b/panels/wacom/cc-wacom-device.h
new file mode 100644
index 0000000..63d38fb
--- /dev/null
+++ b/panels/wacom/cc-wacom-device.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright © 2016 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Carlos Garnacho <carlosg@gnome.org>
+ *
+ */
+
+#pragma once
+
+#include "config.h"
+#include <glib-object.h>
+#include <libwacom/libwacom.h>
+
+#include "gsd-device-manager.h"
+
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <gnome-rr/gnome-rr.h>
+
+#define CC_TYPE_WACOM_DEVICE (cc_wacom_device_get_type ())
+G_DECLARE_FINAL_TYPE (CcWacomDevice, cc_wacom_device, CC, WACOM_DEVICE, GObject)
+
+WacomDeviceDatabase *
+ cc_wacom_device_database_get (void);
+
+CcWacomDevice * cc_wacom_device_new (GsdDevice *device);
+CcWacomDevice * cc_wacom_device_new_fake (const gchar *name);
+
+const gchar * cc_wacom_device_get_name (CcWacomDevice *device);
+const gchar * cc_wacom_device_get_icon_name (CcWacomDevice *device);
+
+gboolean cc_wacom_device_is_reversible (CcWacomDevice *device);
+
+WacomIntegrationFlags
+ cc_wacom_device_get_integration_flags (CcWacomDevice *device);
+
+GsdDevice * cc_wacom_device_get_device (CcWacomDevice *device);
+GSettings * cc_wacom_device_get_settings (CcWacomDevice *device);
+
+const gint * cc_wacom_device_get_supported_tools (CcWacomDevice *device,
+ gint *n_tools);
+
+GnomeRROutput * cc_wacom_device_get_output (CcWacomDevice *device,
+ GnomeRRScreen *screen);
+void cc_wacom_device_set_output (CcWacomDevice *wacom_device,
+ GnomeRROutput *monitor);
+
+guint cc_wacom_device_get_num_buttons (CcWacomDevice *wacom_device);
+
+GSettings * cc_wacom_device_get_button_settings (CcWacomDevice *device,
+ guint button);
+
+const gchar * cc_wacom_device_get_description (CcWacomDevice *device);
+
diff --git a/panels/wacom/cc-wacom-ekr-page.c b/panels/wacom/cc-wacom-ekr-page.c
new file mode 100644
index 0000000..fb2f3e3
--- /dev/null
+++ b/panels/wacom/cc-wacom-ekr-page.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright © 2022 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Carlos Garnacho <carlosg@gnome.org>
+ */
+
+#include "config.h"
+
+#include "cc-wacom-ekr-page.h"
+#include "cc-wacom-panel.h"
+
+struct _CcWacomEkrPage
+{
+ GtkBox parent_instance;
+ GtkWidget *ekr_section;
+ GtkWidget *ekr_icon;
+ GtkWidget *ekr_map_buttons;
+ CcWacomPanel *panel;
+ CcWacomDevice *device;
+};
+
+enum {
+ PROP_0,
+ PROP_PANEL,
+ PROP_DEVICE,
+ N_PROPS,
+};
+
+static GParamSpec *props[N_PROPS] = { 0, };
+
+G_DEFINE_TYPE (CcWacomEkrPage, cc_wacom_ekr_page, GTK_TYPE_BOX)
+
+static void
+set_osd_visibility_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer data)
+{
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) result = NULL;
+
+ result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error);
+
+ if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Error invoking pad button mapping OSK: %s\n", error->message);
+}
+
+static void
+set_osd_visibility (CcWacomEkrPage *page)
+{
+ GDBusProxy *proxy;
+ GsdDevice *gsd_device;
+ const gchar *device_path;
+
+ proxy = cc_wacom_panel_get_gsd_wacom_bus_proxy (page->panel);
+
+ if (proxy == NULL) {
+ g_warning ("Wacom D-Bus interface is not available");
+ return;
+ }
+
+ gsd_device = cc_wacom_device_get_device (page->device);
+ device_path = gsd_device_get_device_file (gsd_device);
+
+ g_dbus_proxy_call (proxy,
+ "Show",
+ g_variant_new ("(ob)", device_path, TRUE),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ set_osd_visibility_cb,
+ page);
+}
+
+static void
+on_map_buttons_activated (CcWacomEkrPage *self)
+{
+ set_osd_visibility (self);
+}
+
+static void
+cc_wacom_ekr_page_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcWacomEkrPage *page = CC_WACOM_EKR_PAGE (object);
+
+ switch (prop_id) {
+ case PROP_PANEL:
+ g_value_set_object (value, page->panel);
+ break;
+ case PROP_DEVICE:
+ g_value_set_object (value, page->device);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_wacom_ekr_page_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcWacomEkrPage *page = CC_WACOM_EKR_PAGE (object);
+
+ switch (prop_id) {
+ case PROP_PANEL:
+ page->panel = g_value_get_object (value);
+ break;
+ case PROP_DEVICE:
+ page->device = g_value_get_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_wacom_ekr_page_constructed (GObject *object)
+{
+ CcWacomEkrPage *page = CC_WACOM_EKR_PAGE (object);
+
+ G_OBJECT_CLASS (cc_wacom_ekr_page_parent_class)->constructed (object);
+
+ adw_preferences_group_set_title (ADW_PREFERENCES_GROUP (page->ekr_section),
+ cc_wacom_device_get_name (page->device));
+}
+
+static void
+cc_wacom_ekr_page_class_init (CcWacomEkrPageClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->get_property = cc_wacom_ekr_page_get_property;
+ object_class->set_property = cc_wacom_ekr_page_set_property;
+ object_class->constructed = cc_wacom_ekr_page_constructed;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/wacom/cc-wacom-ekr-page.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcWacomEkrPage, ekr_section);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomEkrPage, ekr_icon);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomEkrPage, ekr_map_buttons);
+
+ gtk_widget_class_bind_template_callback (widget_class, on_map_buttons_activated);
+
+ props[PROP_PANEL] = g_param_spec_object ("panel",
+ "panel",
+ "panel",
+ CC_TYPE_WACOM_PANEL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY);
+
+ props[PROP_DEVICE] = g_param_spec_object ("device",
+ "device",
+ "device",
+ CC_TYPE_WACOM_DEVICE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY);
+
+ g_object_class_install_properties (object_class, N_PROPS, props);
+}
+
+static void
+cc_wacom_ekr_page_init (CcWacomEkrPage *page)
+{
+ gtk_widget_init_template (GTK_WIDGET (page));
+}
+
+GtkWidget *
+cc_wacom_ekr_page_new (CcWacomPanel *panel,
+ CcWacomDevice *ekr)
+{
+ return g_object_new (CC_TYPE_WACOM_EKR_PAGE,
+ "panel", panel,
+ "device", ekr,
+ NULL);
+}
diff --git a/panels/wacom/cc-wacom-ekr-page.h b/panels/wacom/cc-wacom-ekr-page.h
new file mode 100644
index 0000000..f8944a1
--- /dev/null
+++ b/panels/wacom/cc-wacom-ekr-page.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2022 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Carlos Garnacho <carlosg@gnome.org>
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include "cc-wacom-panel.h"
+#include "cc-wacom-device.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_WACOM_EKR_PAGE (cc_wacom_ekr_page_get_type ())
+G_DECLARE_FINAL_TYPE (CcWacomEkrPage, cc_wacom_ekr_page, CC, WACOM_EKR_PAGE, GtkBox)
+
+GtkWidget * cc_wacom_ekr_page_new (CcWacomPanel *panel,
+ CcWacomDevice *stylus);
+
+G_END_DECLS
diff --git a/panels/wacom/cc-wacom-ekr-page.ui b/panels/wacom/cc-wacom-ekr-page.ui
new file mode 100644
index 0000000..1d1e403
--- /dev/null
+++ b/panels/wacom/cc-wacom-ekr-page.ui
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcWacomEkrPage" parent="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">24</property>
+ <child>
+ <object class="AdwPreferencesGroup" id="ekr_section">
+ <property name="description" translatable="yes"
+ comments="translators: this is a drawing tablet pad, i.e. a collection of buttons and knobs">External pad device</property>
+ <property name="header-suffix">
+ <object class="GtkPicture" id="ekr_icon">
+ <property name="halign">end</property>
+ <property name="valign">start</property>
+ <property name="file">resource:///org/gnome/control-center/wacom/wacom-tablet.svg</property>
+ </object>
+ </property>
+ <child>
+ <object class="AdwActionRow" id="ekr_map_buttons">
+ <property name="title" translatable="yes">Map Buttons</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="on_map_buttons_activated" object="CcWacomEkrPage" swapped="yes" />
+ <child type="suffix">
+ <object class="GtkImage">
+ <property name="icon-name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/wacom/cc-wacom-page.c b/panels/wacom/cc-wacom-page.c
new file mode 100644
index 0000000..696d71d
--- /dev/null
+++ b/panels/wacom/cc-wacom-page.c
@@ -0,0 +1,865 @@
+/*
+ * Copyright © 2011 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Peter Hutterer <peter.hutterer@redhat.com>
+ * Bastien Nocera <hadess@hadess.net>
+ *
+ */
+
+#include <config.h>
+
+#ifdef FAKE_AREA
+#include <gdk/gdk.h>
+#endif /* FAKE_AREA */
+
+#include <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+#include <gdesktop-enums.h>
+#ifdef GDK_WINDOWING_X11
+#include <gdk/x11/gdkx.h>
+#endif
+#ifdef GDK_WINDOWING_WAYLAND
+#include <gdk/wayland/gdkwayland.h>
+#endif
+
+#include "cc-wacom-device.h"
+#include "cc-wacom-button-row.h"
+#include "cc-wacom-page.h"
+#include "cc-wacom-stylus-page.h"
+#include "gsd-enums.h"
+#include "calibrator-gui.h"
+#include "gsd-input-helper.h"
+
+#include <string.h>
+
+#define MWID(x) (GtkWidget *) gtk_builder_get_object (page->mapping_builder, x)
+
+#define THRESHOLD_MISCLICK 15
+#define THRESHOLD_DOUBLECLICK 7
+
+struct _CcWacomPage
+{
+ GtkBox parent_instance;
+
+ CcWacomPanel *panel;
+ CcWacomDevice *stylus;
+ GList *pads;
+ CcCalibArea *area;
+ GSettings *wacom_settings;
+
+ GtkWidget *tablet_section;
+ GtkWidget *tablet_icon;
+ GtkWidget *tablet_display;
+ GtkWidget *tablet_calibrate;
+ GtkWidget *tablet_map_buttons;
+ GtkWidget *tablet_mode;
+ GtkWidget *tablet_mode_switch;
+ GtkWidget *tablet_left_handed;
+ GtkWidget *tablet_left_handed_switch;
+ GtkWidget *tablet_aspect_ratio;
+ GtkWidget *tablet_aspect_ratio_switch;
+ GtkWidget *display_section;
+
+ GnomeRRScreen *rr_screen;
+
+ /* Button mapping */
+ GtkBuilder *mapping_builder;
+ GtkWindow *button_map;
+ GtkListStore *action_store;
+
+ GCancellable *cancellable;
+
+ /* To reach other grouped devices */
+ GsdDeviceManager *manager;
+};
+
+G_DEFINE_TYPE (CcWacomPage, cc_wacom_page, GTK_TYPE_BOX)
+
+/* Different types of layout for the tablet config */
+enum {
+ LAYOUT_NORMAL, /* tracking mode, button mapping */
+ LAYOUT_REVERSIBLE, /* tracking mode, button mapping, left-hand orientation */
+ LAYOUT_SCREEN /* button mapping, calibration, display resolution */
+};
+
+static int
+get_layout_type (CcWacomDevice *device)
+{
+ int layout;
+
+ if (cc_wacom_device_get_integration_flags (device) &
+ (WACOM_DEVICE_INTEGRATED_DISPLAY | WACOM_DEVICE_INTEGRATED_SYSTEM))
+ layout = LAYOUT_SCREEN;
+ else if (cc_wacom_device_is_reversible (device))
+ layout = LAYOUT_REVERSIBLE;
+ else
+ layout = LAYOUT_NORMAL;
+
+ return layout;
+}
+
+static void
+set_calibration (CcWacomDevice *device,
+ gdouble *cal,
+ gsize ncal,
+ GSettings *settings)
+{
+ GVariant *current; /* current calibration */
+ GVariant *array; /* new calibration */
+ g_autofree GVariant **tmp = NULL;
+ gsize nvalues;
+ gint i;
+
+ current = g_settings_get_value (settings, "area");
+ g_variant_get_fixed_array (current, &nvalues, sizeof (gdouble));
+ if ((ncal != 4) || (nvalues != 4)) {
+ g_warning("Unable to set device calibration property. Got %"G_GSIZE_FORMAT" items to put in %"G_GSIZE_FORMAT" slots; expected %d items.\n", ncal, nvalues, 4);
+ return;
+ }
+
+ tmp = g_malloc (nvalues * sizeof (GVariant*));
+ for (i = 0; i < ncal; i++)
+ tmp[i] = g_variant_new_double (cal[i]);
+
+ array = g_variant_new_array (G_VARIANT_TYPE_DOUBLE, tmp, nvalues);
+ g_settings_set_value (settings, "area", array);
+
+ g_debug ("Setting area to %f, %f, %f, %f (left/right/top/bottom)",
+ cal[0], cal[1], cal[2], cal[3]);
+}
+
+static void
+finish_calibration (CcCalibArea *area,
+ gpointer user_data)
+{
+ CcWacomPage *page = (CcWacomPage *) user_data;
+ XYinfo axis;
+ gdouble cal[4];
+
+ if (cc_calib_area_finish (area)) {
+ cc_calib_area_get_padding (area, &axis);
+ cal[0] = axis.x_min;
+ cal[1] = axis.x_max;
+ cal[2] = axis.y_min;
+ cal[3] = axis.y_max;
+
+ set_calibration (page->stylus,
+ cal, 4, page->wacom_settings);
+ } else {
+ /* Reset the old values */
+ GVariant *old_calibration;
+
+ old_calibration = g_object_get_data (G_OBJECT (page), "old-calibration");
+ g_settings_set_value (page->wacom_settings, "area", old_calibration);
+ g_object_set_data (G_OBJECT (page), "old-calibration", NULL);
+ }
+
+ cc_calib_area_free (area);
+ page->area = NULL;
+ gtk_widget_set_sensitive (page->tablet_calibrate, TRUE);
+}
+
+static GdkDevice *
+cc_wacom_page_get_gdk_device (CcWacomPage *page)
+{
+ GsdDevice *gsd_device;
+ GdkDevice *gdk_device = NULL;
+ GdkDisplay *display;
+ GdkSeat *seat;
+ g_autoptr(GList) slaves = NULL;
+ GList *l;
+
+ gsd_device = cc_wacom_device_get_device (page->stylus);
+ g_return_val_if_fail (GSD_IS_DEVICE (gsd_device), NULL);
+
+ display = gtk_widget_get_display (GTK_WIDGET (page));
+ seat = gdk_display_get_default_seat (display);
+ slaves = gdk_seat_get_devices (seat, GDK_SEAT_CAPABILITY_TABLET_STYLUS);
+
+ for (l = slaves; l && !gdk_device; l = l->next) {
+ g_autofree gchar *device_node = NULL;
+
+ if (gdk_device_get_source (l->data) != GDK_SOURCE_PEN)
+ continue;
+
+#ifdef GDK_WINDOWING_X11
+ if (GDK_IS_X11_DISPLAY (display))
+ device_node = xdevice_get_device_node (gdk_x11_device_get_id (l->data));
+#endif
+#ifdef GDK_WINDOWING_WAYLAND
+ if (GDK_IS_WAYLAND_DISPLAY (display))
+ device_node = g_strdup (gdk_wayland_device_get_node_path (l->data));
+#endif
+
+ if (g_strcmp0 (device_node, gsd_device_get_device_file (gsd_device)) == 0)
+ gdk_device = l->data;
+ }
+
+ return gdk_device;
+}
+
+static gboolean
+run_calibration (CcWacomPage *page,
+ GVariant *old_calibration,
+ gdouble *cal,
+ GdkMonitor *monitor)
+{
+ g_assert (page->area == NULL);
+
+ page->area = cc_calib_area_new (NULL,
+ monitor,
+ cc_wacom_page_get_gdk_device (page),
+ finish_calibration,
+ page,
+ THRESHOLD_MISCLICK,
+ THRESHOLD_DOUBLECLICK);
+
+ g_object_set_data_full (G_OBJECT (page),
+ "old-calibration",
+ old_calibration,
+ (GDestroyNotify) g_variant_unref);
+
+ return FALSE;
+}
+
+static GdkMonitor *
+find_monitor_at_point (GdkDisplay *display,
+ gint x,
+ gint y)
+{
+ GListModel *monitors;
+ int i;
+
+ monitors = gdk_display_get_monitors (display);
+
+ for (i = 0; i < g_list_model_get_n_items (monitors); i++) {
+ g_autoptr(GdkMonitor) m = g_list_model_get_item (monitors, i);
+ GdkRectangle geometry;
+
+ gdk_monitor_get_geometry (m, &geometry);
+ if (gdk_rectangle_contains_point (&geometry, x, y))
+ return g_steal_pointer (&m);
+ }
+
+ return NULL;
+}
+
+static void
+calibrate (CcWacomPage *page)
+{
+ int i;
+ GVariant *old_calibration, *array;
+ g_autofree GVariant **tmp = NULL;
+ g_autofree gdouble *calibration = NULL;
+ gsize ncal;
+ GdkDisplay *display;
+ g_autoptr(GdkMonitor) monitor = NULL;
+ g_autoptr(GnomeRRScreen) rr_screen = NULL;
+ GnomeRROutput *output;
+ g_autoptr(GError) error = NULL;
+ GDBusProxy *input_mapping_proxy;
+ gint x, y;
+
+ display = gdk_display_get_default ();
+ rr_screen = gnome_rr_screen_new (display, &error);
+ if (error) {
+ g_warning ("Could not connect to display manager: %s", error->message);
+ return;
+ }
+
+ output = cc_wacom_device_get_output (page->stylus, rr_screen);
+ input_mapping_proxy = cc_wacom_panel_get_input_mapping_bus_proxy (page->panel);
+
+ if (output) {
+ gnome_rr_output_get_position (output, &x, &y);
+ monitor = find_monitor_at_point (display, x, y);
+ } else if (input_mapping_proxy) {
+ GsdDevice *gsd_device;
+ GVariant *mapping;
+
+ gsd_device = cc_wacom_device_get_device (page->stylus);
+
+ if (gsd_device) {
+ mapping = g_dbus_proxy_call_sync (input_mapping_proxy,
+ "GetDeviceMapping",
+ g_variant_new ("(o)", gsd_device_get_device_file (gsd_device)),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ NULL);
+ if (mapping) {
+ gint x, y, width, height;
+
+ g_variant_get (mapping, "((iiii))", &x, &y, &width, &height);
+ monitor = find_monitor_at_point (display, x, y);
+ }
+ }
+ }
+
+ if (!monitor) {
+ /* The display the tablet should be mapped to could not be located.
+ * This shouldn't happen if the EDID data is good...
+ */
+ g_critical("Output associated with the tablet is not connected. Calibration may appear in wrong monitor.");
+ }
+
+ old_calibration = g_settings_get_value (page->wacom_settings, "area");
+ g_variant_get_fixed_array (old_calibration, &ncal, sizeof (gdouble));
+
+ if (ncal != 4) {
+ g_warning("Device calibration property has wrong length. Got %"G_GSIZE_FORMAT" items; expected %d.\n", ncal, 4);
+ return;
+ }
+
+ calibration = g_new0 (gdouble, ncal);
+
+ /* Reset the current values, to avoid old calibrations
+ * from interfering with the calibration */
+ tmp = g_malloc (ncal * sizeof (GVariant*));
+ for (i = 0; i < ncal; i++) {
+ calibration[i] = 0.0;
+ tmp[i] = g_variant_new_double (calibration[i]);
+ }
+
+ array = g_variant_new_array (G_VARIANT_TYPE_DOUBLE, tmp, ncal);
+ g_settings_set_value (page->wacom_settings, "area", array);
+
+ run_calibration (page, old_calibration, calibration, monitor);
+ gtk_widget_set_sensitive (page->tablet_calibrate, FALSE);
+}
+
+static void
+on_calibrate_activated (CcWacomPage *self)
+{
+ calibrate (self);
+}
+
+/* This avoids us crashing when a newer version of
+ * gnome-control-center has been used, and we load up an
+ * old one, as the action type if unknown to the old g-c-c */
+static gboolean
+action_type_is_valid (GDesktopPadButtonAction action)
+{
+ if (action >= G_N_ELEMENTS (action_table))
+ return FALSE;
+ return TRUE;
+}
+
+static void
+create_row_from_button (GtkWidget *list_box,
+ guint button,
+ GSettings *settings)
+{
+ gtk_list_box_append (GTK_LIST_BOX (list_box),
+ cc_wacom_button_row_new (button, settings));
+}
+
+static void
+setup_button_mapping (CcWacomPage *page)
+{
+ GDesktopPadButtonAction action;
+ CcWacomDevice *pad;
+ GtkWidget *list_box;
+ guint i, n_buttons;
+ GSettings *settings;
+
+ list_box = MWID ("shortcuts_list");
+ pad = page->pads->data;
+ n_buttons = cc_wacom_device_get_num_buttons (pad);
+
+ for (i = 0; i < n_buttons; i++) {
+ settings = cc_wacom_device_get_button_settings (pad, i);
+ if (!settings)
+ continue;
+
+ action = g_settings_get_enum (settings, "action");
+ if (!action_type_is_valid (action))
+ continue;
+
+ create_row_from_button (list_box, i, settings);
+ }
+}
+
+static void
+button_mapping_dialog_closed (CcWacomPage *page)
+{
+ gtk_window_destroy (GTK_WINDOW (MWID ("button-mapping-dialog")));
+ g_clear_object (&page->mapping_builder);
+}
+
+static void
+show_button_mapping_dialog (CcWacomPage *page)
+{
+ GtkWidget *toplevel;
+ g_autoptr(GError) error = NULL;
+ GtkWidget *dialog;
+
+ g_assert (page->mapping_builder == NULL);
+ page->mapping_builder = gtk_builder_new ();
+ gtk_builder_add_from_resource (page->mapping_builder,
+ "/org/gnome/control-center/wacom/button-mapping.ui",
+ &error);
+
+ if (error != NULL) {
+ g_warning ("Error loading UI file: %s", error->message);
+ g_clear_object (&page->mapping_builder);
+ return;
+ }
+
+ setup_button_mapping (page);
+
+ dialog = MWID ("button-mapping-dialog");
+ toplevel = GTK_WIDGET (gtk_widget_get_native (GTK_WIDGET (page)));
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel));
+ gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+ g_signal_connect_object (dialog, "response",
+ G_CALLBACK (button_mapping_dialog_closed), page, G_CONNECT_SWAPPED);
+
+ gtk_widget_show (dialog);
+
+ page->button_map = GTK_WINDOW (dialog);
+ g_object_add_weak_pointer (G_OBJECT (dialog), (gpointer *) &page->button_map);
+}
+
+static void
+set_osd_visibility_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer data)
+{
+ g_autoptr(GError) error = NULL;
+ GVariant *result;
+ CcWacomPage *page;
+
+ page = CC_WACOM_PAGE (data);
+
+ result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error);
+
+ if (result == NULL) {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ g_printerr ("Error setting OSD's visibility: %s\n", error->message);
+ show_button_mapping_dialog (page);
+ } else {
+ return;
+ }
+ }
+}
+
+static void
+set_osd_visibility (CcWacomPage *page)
+{
+ GDBusProxy *proxy;
+ GsdDevice *gsd_device;
+ const gchar *device_path;
+
+ proxy = cc_wacom_panel_get_gsd_wacom_bus_proxy (page->panel);
+
+ /* Pick the first device, the OSD may change later between them */
+ gsd_device = cc_wacom_device_get_device (page->pads->data);
+
+ device_path = gsd_device_get_device_file (gsd_device);
+
+ if (proxy == NULL) {
+ show_button_mapping_dialog (page);
+ return;
+ }
+
+ g_dbus_proxy_call (proxy,
+ "Show",
+ g_variant_new ("(ob)", device_path, TRUE),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ page->cancellable,
+ set_osd_visibility_cb,
+ page);
+}
+
+static void
+on_map_buttons_activated (CcWacomPage *self)
+{
+ set_osd_visibility (self);
+}
+
+static void
+on_display_selected (GtkWidget *widget,
+ GParamSpec *pspec,
+ CcWacomPage *page)
+{
+ GListModel *list;
+ g_autoptr (GObject) obj = NULL;
+ GVariant *variant;
+ gint idx;
+
+ list = adw_combo_row_get_model (ADW_COMBO_ROW (widget));
+ idx = adw_combo_row_get_selected (ADW_COMBO_ROW (widget));
+ obj = g_list_model_get_item (list, idx);
+
+ variant = g_object_get_data (obj, "value-output");
+
+ if (variant)
+ g_settings_set_value (page->wacom_settings, "output", g_variant_ref (variant));
+ else
+ g_settings_reset (page->wacom_settings, "output");
+
+ gtk_widget_set_sensitive (page->tablet_calibrate, variant == NULL);
+}
+
+/* Boilerplate code goes below */
+
+static void
+cc_wacom_page_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+cc_wacom_page_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+cc_wacom_page_dispose (GObject *object)
+{
+ CcWacomPage *self = CC_WACOM_PAGE (object);
+
+ g_cancellable_cancel (self->cancellable);
+ g_clear_object (&self->cancellable);
+ g_clear_pointer (&self->area, cc_calib_area_free);
+ g_clear_pointer (&self->button_map, gtk_window_destroy);
+ g_list_free_full (self->pads, g_object_unref);
+ g_clear_object (&self->rr_screen);
+ self->pads = NULL;
+
+ self->panel = NULL;
+
+ G_OBJECT_CLASS (cc_wacom_page_parent_class)->dispose (object);
+}
+
+static void
+cc_wacom_page_class_init (CcWacomPageClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->get_property = cc_wacom_page_get_property;
+ object_class->set_property = cc_wacom_page_set_property;
+ object_class->dispose = cc_wacom_page_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/wacom/cc-wacom-page.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcWacomPage, tablet_section);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomPage, tablet_icon);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomPage, tablet_display);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomPage, tablet_calibrate);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomPage, tablet_map_buttons);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomPage, tablet_mode);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomPage, tablet_mode_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomPage, tablet_left_handed);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomPage, tablet_left_handed_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomPage, tablet_aspect_ratio);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomPage, tablet_aspect_ratio_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomPage, display_section);
+
+ gtk_widget_class_bind_template_callback (widget_class, on_map_buttons_activated);
+ gtk_widget_class_bind_template_callback (widget_class, on_calibrate_activated);
+ gtk_widget_class_bind_template_callback (widget_class, on_display_selected);
+}
+
+static void
+update_displays_model (CcWacomPage *page)
+{
+ g_autoptr (GtkStringList) list = NULL;
+ GnomeRROutput **outputs, *cur_output;
+ int i, idx = 0, cur = -1, automatic_item = -1;
+ g_autoptr (GObject) obj = NULL;
+ GVariant *variant;
+
+ outputs = gnome_rr_screen_list_outputs (page->rr_screen);
+ list = gtk_string_list_new (NULL);
+ cur_output = cc_wacom_device_get_output (page->stylus,
+ page->rr_screen);
+
+ for (i = 0; outputs[i] != NULL; i++) {
+ GnomeRROutput *output = outputs[i];
+ GnomeRRCrtc *crtc = gnome_rr_output_get_crtc (output);
+ g_autofree gchar *text = NULL;
+ g_autofree gchar *vendor = NULL;
+ g_autofree gchar *product = NULL;
+ g_autofree gchar *serial = NULL;
+ const gchar *name, *disp_name;
+
+ /* Output is turned on? */
+ if (!crtc || gnome_rr_crtc_get_current_mode (crtc) == NULL)
+ continue;
+
+ if (output == cur_output)
+ cur = idx;
+
+ name = gnome_rr_output_get_name (output);
+ disp_name = gnome_rr_output_get_display_name (output);
+ text = g_strdup_printf ("%s (%s)", name, disp_name);
+
+ gnome_rr_output_get_ids_from_edid (output,
+ &vendor,
+ &product,
+ &serial);
+ variant = g_variant_new_strv ((const gchar *[]) { vendor, product, serial }, 3);
+
+ gtk_string_list_append (list, text);
+ obj = g_list_model_get_item (G_LIST_MODEL (list), idx);
+ g_object_set_data_full (G_OBJECT (obj), "value-output",
+ variant, (GDestroyNotify) g_variant_unref);
+ idx++;
+ }
+
+ /* All displays item */
+ gtk_string_list_append (list, _("All Displays"));
+ variant = g_variant_new_strv ((const gchar *[]) { "", "", "" }, 3);
+ obj = g_list_model_get_item (G_LIST_MODEL (list), idx);
+ g_object_set_data_full (G_OBJECT (obj), "value-output",
+ variant, (GDestroyNotify) g_variant_unref);
+ if (cur_output == NULL)
+ cur = idx;
+
+ /* "Automatic" item */
+ if (get_layout_type (page->stylus) == LAYOUT_SCREEN) {
+ g_autoptr (GVariant) user_value = NULL;
+
+ idx++;
+ gtk_string_list_append (list, _("Automatic"));
+ automatic_item = idx;
+
+ user_value = g_settings_get_user_value (page->wacom_settings, "output");
+ if (!user_value)
+ cur = idx;
+ }
+
+ g_signal_handlers_block_by_func (page->tablet_display, on_display_selected, page);
+ adw_combo_row_set_model (ADW_COMBO_ROW (page->tablet_display), G_LIST_MODEL (list));
+ adw_combo_row_set_selected (ADW_COMBO_ROW (page->tablet_display), cur);
+ g_signal_handlers_unblock_by_func (page->tablet_display, on_display_selected, page);
+
+ gtk_widget_set_sensitive (page->tablet_calibrate, cur == automatic_item);
+}
+
+static void
+cc_wacom_page_init (CcWacomPage *page)
+{
+ g_autoptr (GError) error = NULL;
+
+ gtk_widget_init_template (GTK_WIDGET (page));
+ page->rr_screen = gnome_rr_screen_new (gdk_display_get_default (), &error);
+
+ if (error)
+ g_warning ("Could not get RR screen: %s", error->message);
+
+ g_signal_connect_object (page->rr_screen, "changed",
+ G_CALLBACK (update_displays_model),
+ page, G_CONNECT_SWAPPED);
+}
+
+static void
+set_icon_name (CcWacomPage *page,
+ GtkWidget *widget,
+ const char *icon_name)
+{
+ g_autofree gchar *resource = NULL;
+
+ resource = g_strdup_printf ("/org/gnome/control-center/wacom/%s.svg", icon_name);
+ gtk_picture_set_resource (GTK_PICTURE (widget), resource);
+}
+
+static gboolean
+has_monitor (CcWacomPage *page)
+{
+ WacomIntegrationFlags integration_flags;
+
+ integration_flags = cc_wacom_device_get_integration_flags (page->stylus);
+
+ return ((integration_flags &
+ (WACOM_DEVICE_INTEGRATED_DISPLAY | WACOM_DEVICE_INTEGRATED_SYSTEM)) != 0);
+}
+
+static void
+update_pad_availability (CcWacomPage *page)
+{
+ gtk_widget_set_visible (page->tablet_map_buttons, page->pads != NULL);
+}
+
+static void
+check_add_pad (CcWacomPage *page,
+ GsdDevice *gsd_device)
+{
+ g_autoptr(CcWacomDevice) wacom_device = NULL;
+
+ if ((gsd_device_get_device_type (gsd_device) & GSD_DEVICE_TYPE_PAD) == 0)
+ return;
+
+ if (!gsd_device_shares_group (cc_wacom_device_get_device (page->stylus),
+ gsd_device))
+ return;
+
+ wacom_device = cc_wacom_device_new (gsd_device);
+ if (!wacom_device)
+ return;
+
+ page->pads = g_list_prepend (page->pads, g_steal_pointer (&wacom_device));
+ update_pad_availability (page);
+}
+
+static void
+check_remove_pad (CcWacomPage *page,
+ GsdDevice *gsd_device)
+{
+ GList *l;
+
+ if ((gsd_device_get_device_type (gsd_device) & GSD_DEVICE_TYPE_PAD) == 0)
+ return;
+
+ for (l = page->pads; l; l = l->next) {
+ CcWacomDevice *wacom_device = l->data;
+ if (cc_wacom_device_get_device (wacom_device) == gsd_device) {
+ page->pads = g_list_delete_link (page->pads, l);
+ g_object_unref (wacom_device);
+ }
+ }
+
+ update_pad_availability (page);
+}
+
+static GVariant *
+tablet_mode_bind_set (const GValue *value,
+ const GVariantType *expected_type,
+ gpointer user_data)
+{
+ gboolean setting;
+
+ setting = g_value_get_boolean (value);
+
+ return g_variant_new_string (setting ? "absolute" : "relative");
+}
+
+static gboolean
+tablet_mode_bind_get (GValue *value,
+ GVariant *variant,
+ gpointer user_data)
+{
+ g_value_set_boolean (value,
+ g_strcmp0 (g_variant_get_string (variant, NULL),
+ "absolute") == 0);
+ return TRUE;
+}
+
+GtkWidget *
+cc_wacom_page_new (CcWacomPanel *panel,
+ CcWacomDevice *stylus)
+{
+ g_autoptr (GList) pads = NULL;
+ CcWacomPage *page;
+ GList *l;
+
+ g_return_val_if_fail (CC_IS_WACOM_DEVICE (stylus), NULL);
+
+ page = g_object_new (CC_TYPE_WACOM_PAGE, NULL);
+
+ page->panel = panel;
+ page->stylus = stylus;
+
+ gtk_widget_set_visible (page->tablet_left_handed,
+ get_layout_type (stylus) == LAYOUT_REVERSIBLE);
+ gtk_widget_set_visible (page->tablet_calibrate,
+ get_layout_type (stylus) == LAYOUT_SCREEN);
+
+ /* FIXME move this to construct */
+ page->wacom_settings = cc_wacom_device_get_settings (stylus);
+
+ /* Tablet name */
+ adw_preferences_group_set_title (ADW_PREFERENCES_GROUP (page->tablet_section),
+ cc_wacom_device_get_name (stylus));
+ adw_preferences_group_set_description (ADW_PREFERENCES_GROUP (page->tablet_section),
+ cc_wacom_device_get_description (stylus));
+
+ g_settings_bind_with_mapping (page->wacom_settings, "mapping",
+ page->tablet_mode_switch, "active",
+ G_SETTINGS_BIND_DEFAULT,
+ tablet_mode_bind_get,
+ tablet_mode_bind_set,
+ NULL, NULL);
+ g_settings_bind_with_mapping (page->wacom_settings, "mapping",
+ page->display_section, "sensitive",
+ G_SETTINGS_BIND_DEFAULT,
+ tablet_mode_bind_get,
+ tablet_mode_bind_set,
+ NULL, NULL);
+ g_settings_bind (page->wacom_settings, "left-handed",
+ page->tablet_left_handed_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+ g_settings_bind (page->wacom_settings, "keep-aspect",
+ page->tablet_aspect_ratio_switch, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ /* Tablet icon */
+ set_icon_name (page, page->tablet_icon, cc_wacom_device_get_icon_name (stylus));
+
+ /* Listen to changes in related/paired pads */
+ page->manager = gsd_device_manager_get ();
+ g_signal_connect_object (G_OBJECT (page->manager), "device-added",
+ G_CALLBACK (check_add_pad), page,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (G_OBJECT (page->manager), "device-removed",
+ G_CALLBACK (check_remove_pad), page,
+ G_CONNECT_SWAPPED);
+
+ pads = gsd_device_manager_list_devices (page->manager, GSD_DEVICE_TYPE_PAD);
+ for (l = pads; l ; l = l->next)
+ check_add_pad (page, l->data);
+
+ update_pad_availability (page);
+ update_displays_model (page);
+
+ return GTK_WIDGET (page);
+}
+
+void
+cc_wacom_page_calibrate (CcWacomPage *page)
+{
+ g_return_if_fail (CC_IS_WACOM_PAGE (page));
+
+ calibrate (page);
+}
+
+gboolean
+cc_wacom_page_can_calibrate (CcWacomPage *page)
+{
+ g_return_val_if_fail (CC_IS_WACOM_PAGE (page),
+ FALSE);
+
+ return has_monitor (page);
+}
diff --git a/panels/wacom/cc-wacom-page.h b/panels/wacom/cc-wacom-page.h
new file mode 100644
index 0000000..76a16ec
--- /dev/null
+++ b/panels/wacom/cc-wacom-page.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2011 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Peter Hutterer <peter.hutterer@redhat.com>
+ * Bastien Nocera <hadess@hadess.net>
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include "cc-wacom-panel.h"
+#include "cc-wacom-device.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_WACOM_PAGE (cc_wacom_page_get_type ())
+G_DECLARE_FINAL_TYPE (CcWacomPage, cc_wacom_page, CC, WACOM_PAGE, GtkBox)
+
+GtkWidget * cc_wacom_page_new (CcWacomPanel *panel,
+ CcWacomDevice *stylus);
+
+void cc_wacom_page_calibrate (CcWacomPage *page);
+
+gboolean cc_wacom_page_can_calibrate (CcWacomPage *page);
+
+G_END_DECLS
diff --git a/panels/wacom/cc-wacom-page.ui b/panels/wacom/cc-wacom-page.ui
new file mode 100644
index 0000000..327e5a9
--- /dev/null
+++ b/panels/wacom/cc-wacom-page.ui
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcWacomPage" parent="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">24</property>
+ <child>
+ <object class="AdwPreferencesGroup" id="tablet_section">
+ <property name="header-suffix">
+ <object class="GtkPicture" id="tablet_icon">
+ <property name="halign">end</property>
+ <property name="valign">start</property>
+ </object>
+ </property>
+ <child>
+ <object class="AdwActionRow" id="tablet_mode">
+ <property name="title" translatable="yes">Tablet Mode</property>
+ <property name="subtitle" translatable="yes">Use absolute positioning for the pen</property>
+ <property name="activatable_widget">tablet_mode_switch</property>
+ <child>
+ <object class="GtkSwitch" id="tablet_mode_switch">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="tablet_left_handed">
+ <property name="title" translatable="yes">Left Hand Orientation</property>
+ <property name="subtitle" translatable="yes">Tablet and Express Keys™ are rotated for left hand use</property>
+ <property name="activatable_widget">tablet_left_handed_switch</property>
+ <child>
+ <object class="GtkSwitch" id="tablet_left_handed_switch">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="tablet_map_buttons">
+ <property name="title" translatable="yes">Map Buttons</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="on_map_buttons_activated" object="CcWacomPage" swapped="yes" />
+ <child type="suffix">
+ <object class="GtkImage">
+ <property name="icon-name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup" id="display_section">
+ <child>
+ <object class="AdwComboRow" id="tablet_display">
+ <property name="width_request">100</property>
+ <property name="title" translatable="yes" context="display setting">Map to Monitor</property>
+ <signal name="notify::selected-item" handler="on_display_selected" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="tablet_aspect_ratio">
+ <property name="title" translatable="yes">Keep Aspect Ratio</property>
+ <property name="subtitle" translatable="yes">Only use a portion of the tablet surface to keep monitor aspect ratio</property>
+ <property name="activatable_widget">tablet_aspect_ratio_switch</property>
+ <child>
+ <object class="GtkSwitch" id="tablet_aspect_ratio_switch">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="tablet_calibrate">
+ <property name="title" translatable="yes">Calibrate</property>
+ <property name="activatable">True</property>
+ <signal name="activated" handler="on_calibrate_activated" object="CcWacomPage" swapped="yes" />
+ <child type="suffix">
+ <object class="GtkImage">
+ <property name="icon-name">go-next-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/wacom/cc-wacom-panel.c b/panels/wacom/cc-wacom-panel.c
new file mode 100644
index 0000000..36aca06
--- /dev/null
+++ b/panels/wacom/cc-wacom-panel.c
@@ -0,0 +1,753 @@
+/*
+ * Copyright © 2011 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Peter Hutterer <peter.hutterer@redhat.com>
+ * Bastien Nocera <hadess@hadess.net>
+ *
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <gtk/gtk.h>
+#include <glib/gi18n-lib.h>
+
+#include "shell/cc-application.h"
+#include "shell/cc-debug.h"
+#include "cc-wacom-panel.h"
+#include "cc-wacom-page.h"
+#include "cc-wacom-ekr-page.h"
+#include "cc-wacom-stylus-page.h"
+#include "cc-wacom-resources.h"
+#include "cc-drawing-area.h"
+#include "cc-tablet-tool-map.h"
+#include "gsd-device-manager.h"
+
+#ifdef GDK_WINDOWING_WAYLAND
+#include <gdk/wayland/gdkwayland.h>
+#endif
+
+#define EKR_VENDOR "056a"
+#define EKR_PRODUCT "0331"
+
+struct _CcWacomPanel
+{
+ CcPanel parent_instance;
+
+ GtkWidget *test_popover;
+ GtkWidget *test_draw_area;
+ GtkWidget *test_button;
+ GtkWidget *scrollable;
+ GtkWidget *tablets;
+ GtkWidget *styli;
+ GtkWidget *initial_state_stack;
+ GtkWidget *panel_view;
+ GtkWidget *panel_empty_state;
+ GHashTable *devices; /* key=GsdDevice, value=CcWacomDevice */
+ GHashTable *pages; /* key=CcWacomDevice, value=GtkWidget */
+ GHashTable *stylus_pages; /* key=CcWacomTool, value=GtkWidget */
+ guint mock_stylus_id;
+
+ CcTabletToolMap *tablet_tool_map;
+
+ GtkAdjustment *vadjustment;
+ GtkGesture *stylus_gesture;
+
+ GtkWidget *highlighted_widget;
+
+ /* DBus */
+ GDBusProxy *proxy;
+ GDBusProxy *input_mapping_proxy;
+};
+
+CC_PANEL_REGISTER (CcWacomPanel, cc_wacom_panel)
+
+typedef struct {
+ const char *name;
+ CcWacomDevice *stylus;
+ CcWacomDevice *pad;
+} Tablet;
+
+enum {
+ WACOM_PAGE = -1,
+ PLUG_IN_PAGE = 0,
+};
+
+enum {
+ PROP_0,
+ PROP_PARAMETERS
+};
+
+/* Static init function */
+static void
+update_visibility (GsdDeviceManager *manager,
+ GsdDevice *device,
+ gpointer user_data)
+{
+ CcApplication *application;
+ g_autoptr(GList) devices = NULL;
+ guint i;
+
+ devices = gsd_device_manager_list_devices (manager, GSD_DEVICE_TYPE_TABLET);
+ i = g_list_length (devices);
+
+ /* Set the new visibility */
+ application = CC_APPLICATION (g_application_get_default ());
+ cc_shell_model_set_panel_visibility (cc_application_get_model (application),
+ "wacom",
+ i > 0 ? CC_PANEL_VISIBLE : CC_PANEL_VISIBLE_IN_SEARCH);
+
+ g_debug ("Wacom panel visible: %s", i > 0 ? "yes" : "no");
+}
+
+void
+cc_wacom_panel_static_init_func (void)
+{
+ GsdDeviceManager *manager;
+
+ manager = gsd_device_manager_get ();
+ g_signal_connect (G_OBJECT (manager), "device-added",
+ G_CALLBACK (update_visibility), NULL);
+ g_signal_connect (G_OBJECT (manager), "device-removed",
+ G_CALLBACK (update_visibility), NULL);
+ update_visibility (manager, NULL, NULL);
+}
+
+static CcWacomDevice *
+lookup_wacom_device (CcWacomPanel *self,
+ const gchar *name)
+{
+ GHashTableIter iter;
+ CcWacomDevice *wacom_device;
+
+ g_hash_table_iter_init (&iter, self->devices);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &wacom_device)) {
+ if (g_strcmp0 (cc_wacom_device_get_name (wacom_device), name) == 0)
+ return wacom_device;
+ }
+
+ return NULL;
+}
+
+static void
+highlight_widget (CcWacomPanel *self, GtkWidget *widget)
+{
+ double y;
+
+ if (self->highlighted_widget == widget)
+ return;
+
+ gtk_widget_translate_coordinates (widget,
+ self->scrollable,
+ 0, 0,
+ NULL, &y);
+ gtk_adjustment_set_value (self->vadjustment, y);
+ self->highlighted_widget = widget;
+}
+
+static CcWacomPage *
+update_highlighted_device (CcWacomPanel *self, const gchar *device_name)
+{
+ CcWacomPage *page;
+ CcWacomDevice *wacom_device;
+
+ if (device_name == NULL)
+ return NULL;
+
+ wacom_device = lookup_wacom_device (self, device_name);
+ if (!wacom_device) {
+ g_warning ("Failed to find device '%s', supplied in the command line.", device_name);
+ return NULL;
+ }
+
+ page = g_hash_table_lookup (self->pages, wacom_device);
+ highlight_widget (self, GTK_WIDGET (page));
+
+ return page;
+}
+
+static void
+run_operation_from_params (CcWacomPanel *self, GVariant *parameters)
+{
+ g_autoptr(GVariant) v = NULL;
+ g_autoptr(GVariant) v2 = NULL;
+ CcWacomPage *page;
+ const gchar *operation = NULL;
+ const gchar *device_name = NULL;
+ gint n_params;
+
+ n_params = g_variant_n_children (parameters);
+
+ g_variant_get_child (parameters, n_params - 1, "v", &v);
+ device_name = g_variant_get_string (v, NULL);
+
+ if (!g_variant_is_of_type (v, G_VARIANT_TYPE_STRING)) {
+ g_warning ("Wrong type for the second argument GVariant, expected 's' but got '%s'",
+ g_variant_get_type_string (v));
+ return;
+ }
+
+ switch (n_params) {
+ case 3:
+ page = update_highlighted_device (self, device_name);
+ if (page == NULL)
+ return;
+
+ g_variant_get_child (parameters, 1, "v", &v2);
+
+ if (!g_variant_is_of_type (v2, G_VARIANT_TYPE_STRING)) {
+ g_warning ("Wrong type for the operation name argument. A string is expected.");
+ break;
+ }
+
+ operation = g_variant_get_string (v2, NULL);
+ if (g_strcmp0 (operation, "run-calibration") == 0) {
+ if (cc_wacom_page_can_calibrate (page))
+ cc_wacom_page_calibrate (page);
+ else
+ g_warning ("The device %s cannot be calibrated.", device_name);
+ } else {
+ g_warning ("Ignoring unrecognized operation '%s'", operation);
+ }
+ case 2:
+ update_highlighted_device (self, device_name);
+ break;
+ case 1:
+ g_assert_not_reached ();
+ default:
+ g_warning ("Unexpected number of parameters found: %d. Request ignored.", n_params);
+ }
+}
+
+/* Boilerplate code goes below */
+
+static void
+cc_wacom_panel_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+cc_wacom_panel_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcWacomPanel *self;
+ self = CC_WACOM_PANEL (object);
+
+ switch (property_id)
+ {
+ case PROP_PARAMETERS: {
+ GVariant *parameters;
+
+ parameters = g_value_get_variant (value);
+ if (parameters == NULL || g_variant_n_children (parameters) <= 1)
+ return;
+
+ run_operation_from_params (self, parameters);
+
+ break;
+ }
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+cc_wacom_panel_dispose (GObject *object)
+{
+ CcWacomPanel *self = CC_WACOM_PANEL (object);
+ CcShell *shell;
+
+ shell = cc_panel_get_shell (CC_PANEL (self));
+ if (shell) {
+ gtk_widget_remove_controller (GTK_WIDGET (shell),
+ GTK_EVENT_CONTROLLER (self->stylus_gesture));
+ }
+
+
+ g_clear_pointer (&self->devices, g_hash_table_unref);
+ g_clear_object (&self->proxy);
+ g_clear_object (&self->input_mapping_proxy);
+ g_clear_pointer (&self->pages, g_hash_table_unref);
+ g_clear_pointer (&self->stylus_pages, g_hash_table_unref);
+ g_clear_handle_id (&self->mock_stylus_id, g_source_remove);
+
+ G_OBJECT_CLASS (cc_wacom_panel_parent_class)->dispose (object);
+}
+
+static void
+check_remove_stylus_pages (CcWacomPanel *self)
+{
+ GHashTableIter iter;
+ CcWacomDevice *device;
+ CcWacomTool *tool;
+ GtkWidget *page;
+ GList *tools;
+ g_autoptr(GList) total = NULL;
+
+ /* First. Iterate known devices and get the tools */
+ g_hash_table_iter_init (&iter, self->devices);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer*) &device)) {
+ tools = cc_tablet_tool_map_list_tools (self->tablet_tool_map, device);
+ total = g_list_concat (total, tools);
+ }
+
+ /* Second. Iterate through stylus pages and remove the ones whose
+ * tool is no longer in the list.
+ */
+ g_hash_table_iter_init (&iter, self->stylus_pages);
+ while (g_hash_table_iter_next (&iter, (gpointer*) &tool, (gpointer*) &page)) {
+ if (g_list_find (total, tool))
+ continue;
+
+ gtk_box_remove (GTK_BOX (self->styli), page);
+ g_hash_table_iter_remove (&iter);
+ }
+}
+
+static gboolean
+add_stylus (CcWacomPanel *self,
+ CcWacomTool *tool)
+{
+ GtkWidget *page;
+
+ if (g_hash_table_lookup (self->stylus_pages, tool))
+ return FALSE;
+
+ page = cc_wacom_stylus_page_new (tool);
+ gtk_box_append (GTK_BOX (self->styli), page);
+ g_hash_table_insert (self->stylus_pages, tool, page);
+
+ return TRUE;
+}
+
+static void
+update_test_button (CcWacomPanel *self)
+{
+ if (!self->test_button)
+ return;
+
+ if (g_hash_table_size (self->devices) == 0) {
+ gtk_popover_popdown (GTK_POPOVER (self->test_popover));
+ gtk_widget_set_sensitive (self->test_button, FALSE);
+ } else {
+ gtk_widget_set_sensitive (self->test_button, TRUE);
+ }
+}
+
+static void
+update_initial_state (CcWacomPanel *self)
+{
+ gtk_stack_set_visible_child (GTK_STACK (self->initial_state_stack),
+ g_hash_table_size (self->devices) == 0 ?
+ self->panel_empty_state :
+ self->panel_view);
+}
+
+static void
+update_highlighted_stylus (CcWacomPanel *panel,
+ CcWacomTool *stylus)
+{
+ GtkWidget *widget;
+
+ widget = g_hash_table_lookup (panel->stylus_pages, stylus);
+ highlight_widget (panel, widget);
+}
+
+static void
+update_current_tool (CcWacomPanel *panel,
+ GdkDevice *device,
+ GdkDeviceTool *tool)
+{
+ GsdDeviceManager *device_manager;
+ CcWacomDevice *wacom_device;
+ CcWacomTool *stylus;
+ GsdDevice *gsd_device;
+ guint64 serial, id;
+
+ if (!tool)
+ return;
+
+ /* Work our way to the CcWacomDevice */
+ device_manager = gsd_device_manager_get ();
+ gsd_device = gsd_device_manager_lookup_gdk_device (device_manager,
+ device);
+ if (!gsd_device)
+ return;
+
+ wacom_device = g_hash_table_lookup (panel->devices, gsd_device);
+ if (!wacom_device)
+ return;
+
+ /* Check whether we already know this tool, nothing to do then */
+ serial = gdk_device_tool_get_serial (tool);
+
+ /* The wacom driver sends serial-less tools with a serial of
+ * 1, libinput uses 0. No device exists with serial 1, let's reset
+ * it here so everything else works as expected.
+ */
+ if (serial == 1)
+ serial = 0;
+
+ stylus = cc_tablet_tool_map_lookup_tool (panel->tablet_tool_map,
+ wacom_device, serial);
+
+ if (!stylus) {
+ id = gdk_device_tool_get_hardware_id (tool);
+
+ /* The wacom driver sends a hw id of 0x2 for stylus and 0xa
+ * for eraser for devices that don't have a true HW id.
+ * Reset those to 0 so we can use the same code-paths
+ * libinput uses.
+ * The touch ID is 0x3, let's ignore that because we don't
+ * have a touch tool and it only happens when the wacom
+ * driver handles the touch device.
+ */
+ if (id == 0x2 || id == 0xa)
+ id = 0;
+ else if (id == 0x3)
+ return;
+
+ stylus = cc_wacom_tool_new (serial, id, wacom_device);
+ if (!stylus)
+ return;
+ }
+
+ add_stylus (panel, stylus);
+
+ update_highlighted_stylus (panel, stylus);
+
+ cc_tablet_tool_map_add_relation (panel->tablet_tool_map,
+ wacom_device, stylus);
+}
+
+static void
+on_stylus_proximity_cb (GtkGestureStylus *gesture,
+ double x,
+ double y,
+ CcWacomPanel *panel)
+{
+ GdkDevice *device;
+ GdkDeviceTool *tool;
+
+ device = gtk_event_controller_get_current_event_device (GTK_EVENT_CONTROLLER (gesture));
+ tool = gtk_gesture_stylus_get_device_tool (gesture);
+ update_current_tool (panel, device, tool);
+}
+
+static gboolean
+show_mock_stylus_cb (gpointer user_data)
+{
+ CcWacomPanel *panel = user_data;
+ GList *device_list;
+ CcWacomDevice *wacom_device;
+ CcWacomTool *stylus;
+
+ panel->mock_stylus_id = 0;
+
+ device_list = g_hash_table_get_values (panel->devices);
+ if (device_list == NULL) {
+ g_warning ("Could not create fake stylus event because could not find tablet device");
+ return G_SOURCE_REMOVE;
+ }
+
+ wacom_device = device_list->data;
+ g_list_free (device_list);
+
+ stylus = cc_wacom_tool_new (0, 0, wacom_device);
+ add_stylus (panel, stylus);
+ update_highlighted_stylus (panel, stylus);
+ cc_tablet_tool_map_add_relation (panel->tablet_tool_map,
+ wacom_device, stylus);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+cc_wacom_panel_constructed (GObject *object)
+{
+ CcWacomPanel *self = CC_WACOM_PANEL (object);
+ CcShell *shell;
+
+ G_OBJECT_CLASS (cc_wacom_panel_parent_class)->constructed (object);
+
+ /* Add test area button to shell header. */
+ shell = cc_panel_get_shell (CC_PANEL (self));
+
+ self->stylus_gesture = gtk_gesture_stylus_new ();
+ g_signal_connect (self->stylus_gesture, "proximity",
+ G_CALLBACK (on_stylus_proximity_cb), self);
+ gtk_widget_add_controller (GTK_WIDGET (shell),
+ GTK_EVENT_CONTROLLER (self->stylus_gesture));
+
+ if (g_getenv ("UMOCKDEV_DIR") != NULL)
+ self->mock_stylus_id = g_idle_add (show_mock_stylus_cb, self);
+}
+
+static const char *
+cc_wacom_panel_get_help_uri (CcPanel *panel)
+{
+ return "help:gnome-help/wacom";
+}
+
+static void
+cc_wacom_panel_class_init (CcWacomPanelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->get_property = cc_wacom_panel_get_property;
+ object_class->set_property = cc_wacom_panel_set_property;
+ object_class->dispose = cc_wacom_panel_dispose;
+ object_class->constructed = cc_wacom_panel_constructed;
+
+ panel_class->get_help_uri = cc_wacom_panel_get_help_uri;
+
+ g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters");
+
+ g_type_ensure (CC_TYPE_DRAWING_AREA);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/wacom/cc-wacom-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, scrollable);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, test_button);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, test_popover);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, test_draw_area);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, tablets);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, styli);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, initial_state_stack);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, panel_empty_state);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, panel_view);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, vadjustment);
+}
+
+static void
+add_known_device (CcWacomPanel *self,
+ GsdDevice *gsd_device)
+{
+ CcWacomDevice *device;
+ GsdDeviceType device_type;
+ g_autoptr(GList) tools = NULL;
+ GtkWidget *page;
+ gboolean is_ekr = FALSE;
+ GList *l;
+
+ device_type = gsd_device_get_device_type (gsd_device);
+
+ if ((device_type & GSD_DEVICE_TYPE_TABLET) == 0)
+ return;
+
+ if ((device_type &
+ (GSD_DEVICE_TYPE_TOUCHSCREEN |
+ GSD_DEVICE_TYPE_TOUCHPAD)) != 0) {
+ return;
+ }
+
+ if ((device_type & GSD_DEVICE_TYPE_PAD) != 0) {
+ const char *vendor, *product;
+
+ gsd_device_get_device_ids (gsd_device, &vendor, &product);
+ is_ekr = (g_strcmp0 (vendor, EKR_VENDOR) == 0 &&
+ g_strcmp0 (product, EKR_PRODUCT) == 0);
+
+ /* Express key remote is an special case, as it is an
+ * external pad device, we want to distinctly show it
+ * in the list. Other pads are mounted on a tablet, which
+ * get their own entries.
+ */
+ if (!is_ekr)
+ return;
+ }
+
+ device = cc_wacom_device_new (gsd_device);
+ if (!device)
+ return;
+
+ g_hash_table_insert (self->devices, gsd_device, device);
+
+ tools = cc_tablet_tool_map_list_tools (self->tablet_tool_map, device);
+
+ for (l = tools; l != NULL; l = l->next) {
+ add_stylus (self, l->data);
+ }
+
+ if (is_ekr)
+ page = cc_wacom_ekr_page_new (self, device);
+ else
+ page = cc_wacom_page_new (self, device);
+
+ gtk_box_append (GTK_BOX (self->tablets), page);
+ g_hash_table_insert (self->pages, device, page);
+}
+
+static void
+device_removed_cb (CcWacomPanel *self,
+ GsdDevice *gsd_device)
+{
+ CcWacomDevice *device;
+ GtkWidget *page;
+
+ device = g_hash_table_lookup (self->devices, gsd_device);
+ if (!device)
+ return;
+
+ page = g_hash_table_lookup (self->pages, device);
+ if (page) {
+ g_hash_table_remove (self->pages, device);
+ gtk_box_remove (GTK_BOX (self->tablets), page);
+ }
+
+ g_hash_table_remove (self->devices, gsd_device);
+ check_remove_stylus_pages (self);
+ update_test_button (self);
+ update_initial_state (self);
+}
+
+static void
+device_added_cb (CcWacomPanel *self,
+ GsdDevice *device)
+{
+ add_known_device (self, device);
+ update_test_button (self);
+ update_initial_state (self);
+}
+
+void
+cc_wacom_panel_switch_to_panel (CcWacomPanel *self,
+ const char *panel)
+{
+ CcShell *shell;
+ g_autoptr(GError) error = NULL;
+
+ g_return_if_fail (self);
+
+ shell = cc_panel_get_shell (CC_PANEL (self));
+ if (!cc_shell_set_active_panel_from_id (shell, panel, NULL, &error))
+ g_warning ("Failed to activate '%s' panel: %s", panel, error->message);
+}
+
+static void
+got_osd_proxy_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer data)
+{
+ g_autoptr(GError) error = NULL;
+ CcWacomPanel *self;
+
+ self = CC_WACOM_PANEL (data);
+ self->proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+
+ if (self->proxy == NULL) {
+ g_printerr ("Error creating proxy: %s\n", error->message);
+ return;
+ }
+}
+
+static void
+got_input_mapping_proxy_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer data)
+{
+ g_autoptr(GError) error = NULL;
+ CcWacomPanel *self;
+
+ self = CC_WACOM_PANEL (data);
+ self->input_mapping_proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+
+ if (self->input_mapping_proxy == NULL) {
+ g_printerr ("Error creating input mapping proxy: %s\n", error->message);
+ return;
+ }
+}
+
+static void
+cc_wacom_panel_init (CcWacomPanel *self)
+{
+ GsdDeviceManager *device_manager;
+ g_autoptr(GList) devices = NULL;
+ GList *l;
+ g_autoptr(GError) error = NULL;
+
+ g_resources_register (cc_wacom_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->tablet_tool_map = cc_tablet_tool_map_new ();
+
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.gnome.Shell",
+ "/org/gnome/Shell/Wacom",
+ "org.gnome.Shell.Wacom.PadOsd",
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ got_osd_proxy_cb,
+ self);
+
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.gnome.Shell",
+ "/org/gnome/Mutter/InputMapping",
+ "org.gnome.Mutter.InputMapping",
+ cc_panel_get_cancellable (CC_PANEL (self)),
+ got_input_mapping_proxy_cb,
+ self);
+
+ self->devices = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
+ self->pages = g_hash_table_new (NULL, NULL);
+ self->stylus_pages = g_hash_table_new (NULL, NULL);
+
+ device_manager = gsd_device_manager_get ();
+ g_signal_connect_object (device_manager, "device-added",
+ G_CALLBACK (device_added_cb), self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (device_manager, "device-removed",
+ G_CALLBACK (device_removed_cb), self, G_CONNECT_SWAPPED);
+
+ devices = gsd_device_manager_list_devices (device_manager,
+ GSD_DEVICE_TYPE_TABLET);
+ for (l = devices; l ; l = l->next)
+ add_known_device (self, l->data);
+
+ update_test_button (self);
+ update_initial_state (self);
+}
+
+GDBusProxy *
+cc_wacom_panel_get_gsd_wacom_bus_proxy (CcWacomPanel *self)
+{
+ g_return_val_if_fail (CC_IS_WACOM_PANEL (self), NULL);
+
+ return self->proxy;
+}
+
+GDBusProxy *
+cc_wacom_panel_get_input_mapping_bus_proxy (CcWacomPanel *self)
+{
+ g_return_val_if_fail (CC_IS_WACOM_PANEL (self), NULL);
+
+ return self->input_mapping_proxy;
+}
diff --git a/panels/wacom/cc-wacom-panel.h b/panels/wacom/cc-wacom-panel.h
new file mode 100644
index 0000000..68f46aa
--- /dev/null
+++ b/panels/wacom/cc-wacom-panel.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2011 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Peter Hutterer <peter.hutterer@redhat.com>
+ * Bastien Nocera <hadess@hadess.net>
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_WACOM_PANEL (cc_wacom_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcWacomPanel, cc_wacom_panel, CC, WACOM_PANEL, CcPanel)
+
+void cc_wacom_panel_static_init_func (void);
+
+void cc_wacom_panel_switch_to_panel (CcWacomPanel *self,
+ const char *panel);
+
+void cc_wacom_panel_set_osd_visibility (CcWacomPanel *self,
+ guint32 device_id);
+
+GDBusProxy * cc_wacom_panel_get_gsd_wacom_bus_proxy (CcWacomPanel *self);
+
+GDBusProxy * cc_wacom_panel_get_input_mapping_bus_proxy (CcWacomPanel *self);
+
+G_END_DECLS
diff --git a/panels/wacom/cc-wacom-panel.ui b/panels/wacom/cc-wacom-panel.ui
new file mode 100644
index 0000000..77e7e16
--- /dev/null
+++ b/panels/wacom/cc-wacom-panel.ui
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcWacomPanel" parent="CcPanel">
+
+ <child type="titlebar-end">
+ <object class="GtkMenuButton" id="test_button">
+ <property name="use_underline">True</property>
+ <property name="valign">center</property>
+ <property name="label" translatable="yes">Test Your _Settings</property>
+ <property name="popover">test_popover</property>
+ <style>
+ <class name="text-button"/>
+ </style>
+ </object>
+ </child>
+
+ <child type="content">
+ <object class="GtkStack" id="initial_state_stack">
+ <property name="transition_duration">0</property>
+ <child>
+ <object class="GtkScrolledWindow" id="panel_view">
+ <property name="hscrollbar-policy">never</property>
+ <property name="vadjustment">vadjustment</property>
+ <child>
+ <object class="AdwClamp" id="scrollable">
+ <property name="margin_top">32</property>
+ <property name="margin_bottom">32</property>
+ <property name="margin_start">12</property>
+ <property name="margin_end">12</property>
+
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">48</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox" id="tablets">
+ <property name="orientation">vertical</property>
+ <property name="spacing">48</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="styli">
+ <property name="orientation">vertical</property>
+ <property name="spacing">48</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwStatusPage" id="panel_empty_state">
+ <property name="icon-name">input-tablet-symbolic</property>
+ <property name="title" translatable="yes">No tablet detected</property>
+ <property name="description" translatable="yes">Please plug in or turn on your Wacom tablet.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+
+ <object class="GtkAdjustment" id="vadjustment" />
+
+ <!-- Test Popover -->
+ <object class="GtkPopover" id="test_popover">
+ <style>
+ <class name="menu" />
+ </style>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="spacing">6</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="CcDrawingArea" id="test_draw_area">
+ <property name="width-request">400</property>
+ <property name="height-request">300</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/panels/wacom/cc-wacom-stylus-page.c b/panels/wacom/cc-wacom-stylus-page.c
new file mode 100644
index 0000000..01819ad
--- /dev/null
+++ b/panels/wacom/cc-wacom-stylus-page.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright © 2011 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Peter Hutterer <peter.hutterer@redhat.com>
+ * Bastien Nocera <hadess@hadess.net>
+ *
+ */
+
+#include <config.h>
+
+#include <adwaita.h>
+#include <glib/gi18n.h>
+#include "cc-wacom-stylus-page.h"
+#include <gtk/gtk.h>
+#include <gdesktop-enums.h>
+
+#include <string.h>
+
+struct _CcWacomStylusPage
+{
+ GtkBox parent_instance;
+
+ GtkWidget *stylus_section;
+ GtkWidget *stylus_icon;
+ GtkWidget *stylus_button1_action;
+ GtkWidget *stylus_button2_action;
+ GtkWidget *stylus_button3_action;
+ GtkWidget *stylus_eraser_pressure;
+ GtkWidget *stylus_tip_pressure_scale;
+ GtkWidget *stylus_eraser_pressure_scale;
+ GtkAdjustment *stylus_tip_pressure_adjustment;
+ GtkAdjustment *stylus_eraser_pressure_adjustment;
+ CcWacomTool *stylus;
+ GSettings *stylus_settings;
+};
+
+G_DEFINE_TYPE (CcWacomStylusPage, cc_wacom_stylus_page, GTK_TYPE_BOX)
+
+/* GSettings stores pressurecurve as 4 values like the driver. We map slider
+ * scale to these values given the array below. These settings were taken from
+ * wacomcpl, where they've been around for years.
+ */
+#define N_PRESSURE_CURVES 7
+static const gint32 PRESSURE_CURVES[N_PRESSURE_CURVES][4] = {
+ { 0, 75, 25, 100 }, /* soft */
+ { 0, 50, 50, 100 },
+ { 0, 25, 75, 100 },
+ { 0, 0, 100, 100 }, /* neutral */
+ { 25, 0, 100, 75 },
+ { 50, 0, 100, 50 },
+ { 75, 0, 100, 25 } /* firm */
+};
+
+static void
+set_pressurecurve (GtkRange *range, GSettings *settings, const gchar *key)
+{
+ gint slider_val = gtk_range_get_value (range);
+ GVariant *values[4],
+ *array;
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (values); i++)
+ values[i] = g_variant_new_int32 (PRESSURE_CURVES[slider_val][i]);
+
+ array = g_variant_new_array (G_VARIANT_TYPE_INT32, values, G_N_ELEMENTS (values));
+
+ g_settings_set_value (settings, key, array);
+}
+
+static void
+on_tip_pressure_value_changed (CcWacomStylusPage *page)
+{
+ set_pressurecurve (GTK_RANGE (page->stylus_tip_pressure_scale), page->stylus_settings, "pressure-curve");
+}
+
+static void
+on_eraser_pressure_value_changed (CcWacomStylusPage *page)
+{
+ set_pressurecurve (GTK_RANGE (page->stylus_eraser_pressure_scale), page->stylus_settings, "eraser-pressure-curve");
+}
+
+static void
+set_feel_from_gsettings (GtkAdjustment *adjustment, GSettings *settings, const gchar *key)
+{
+ GVariant *variant;
+ const gint32 *values;
+ gsize nvalues;
+ int i;
+
+ variant = g_settings_get_value (settings, key);
+ values = g_variant_get_fixed_array (variant, &nvalues, sizeof (gint32));
+
+ if (nvalues != 4) {
+ g_warning ("Invalid pressure curve format, expected 4 values (got %"G_GSIZE_FORMAT")", nvalues);
+ return;
+ }
+
+ for (i = 0; i < N_PRESSURE_CURVES; i++) {
+ if (memcmp (PRESSURE_CURVES[i], values, sizeof (gint32) * 4) == 0) {
+ gtk_adjustment_set_value (adjustment, i);
+ break;
+ }
+ }
+}
+
+static void
+cc_wacom_stylus_page_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+cc_wacom_stylus_page_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+on_stylus_action_selected (GtkWidget *widget,
+ GParamSpec *pspec,
+ CcWacomStylusPage *page)
+{
+ gint idx;
+
+ idx = adw_combo_row_get_selected (ADW_COMBO_ROW (widget));
+
+ if (widget == page->stylus_button1_action)
+ g_settings_set_enum (page->stylus_settings, "button-action", idx);
+ else if (widget == page->stylus_button2_action)
+ g_settings_set_enum (page->stylus_settings, "secondary-button-action", idx);
+ else if (widget == page->stylus_button3_action)
+ g_settings_set_enum (page->stylus_settings, "tertiary-button-action", idx);
+}
+
+static void
+cc_wacom_stylus_page_class_init (CcWacomStylusPageClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->get_property = cc_wacom_stylus_page_get_property;
+ object_class->set_property = cc_wacom_stylus_page_set_property;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/wacom/cc-wacom-stylus-page.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcWacomStylusPage, stylus_section);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomStylusPage, stylus_icon);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomStylusPage, stylus_button1_action);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomStylusPage, stylus_button2_action);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomStylusPage, stylus_button3_action);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomStylusPage, stylus_eraser_pressure);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomStylusPage, stylus_tip_pressure_scale);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomStylusPage, stylus_eraser_pressure_scale);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomStylusPage, stylus_tip_pressure_adjustment);
+ gtk_widget_class_bind_template_child (widget_class, CcWacomStylusPage, stylus_eraser_pressure_adjustment);
+
+ gtk_widget_class_bind_template_callback (widget_class, on_stylus_action_selected);
+ gtk_widget_class_bind_template_callback (widget_class, on_tip_pressure_value_changed);
+ gtk_widget_class_bind_template_callback (widget_class, on_eraser_pressure_value_changed);
+}
+
+static void
+add_marks (GtkScale *scale)
+{
+#if 0
+ gint i;
+
+ for (i = 0; i < N_PRESSURE_CURVES; i++)
+ gtk_scale_add_mark (scale, i, GTK_POS_BOTTOM, NULL);
+#endif
+}
+
+static void
+cc_wacom_stylus_page_init (CcWacomStylusPage *page)
+{
+ gtk_widget_init_template (GTK_WIDGET (page));
+
+ add_marks (GTK_SCALE (page->stylus_tip_pressure_scale));
+ add_marks (GTK_SCALE (page->stylus_eraser_pressure_scale));
+}
+
+static void
+set_icon_name (CcWacomStylusPage *page,
+ const char *icon_name)
+{
+ g_autofree gchar *resource = NULL;
+
+ resource = g_strdup_printf ("/org/gnome/control-center/wacom/%s.svg", icon_name);
+ gtk_picture_set_resource (GTK_PICTURE (page->stylus_icon), resource);
+}
+
+GtkWidget *
+cc_wacom_stylus_page_new (CcWacomTool *stylus)
+{
+ CcWacomStylusPage *page;
+ guint num_buttons;
+ gboolean has_eraser;
+
+ g_return_val_if_fail (CC_IS_WACOM_TOOL (stylus), NULL);
+
+ page = g_object_new (CC_TYPE_WACOM_STYLUS_PAGE, NULL);
+
+ page->stylus = stylus;
+
+ /* Stylus name */
+ adw_preferences_group_set_title (ADW_PREFERENCES_GROUP (page->stylus_section),
+ cc_wacom_tool_get_name (stylus));
+ adw_preferences_group_set_description (ADW_PREFERENCES_GROUP (page->stylus_section),
+ cc_wacom_tool_get_description (stylus));
+
+ /* Icon */
+ set_icon_name (page, cc_wacom_tool_get_icon_name (stylus));
+
+ /* Settings */
+ page->stylus_settings = cc_wacom_tool_get_settings (stylus);
+ has_eraser = cc_wacom_tool_get_has_eraser (stylus);
+
+ num_buttons = cc_wacom_tool_get_num_buttons (stylus);
+ gtk_widget_set_visible (page->stylus_button3_action,
+ num_buttons >= 3);
+ gtk_widget_set_visible (page->stylus_button2_action,
+ num_buttons >= 2);
+ gtk_widget_set_visible (page->stylus_button1_action,
+ num_buttons >= 1);
+ gtk_widget_set_visible (page->stylus_eraser_pressure,
+ has_eraser);
+
+ adw_combo_row_set_selected (ADW_COMBO_ROW (page->stylus_button1_action),
+ g_settings_get_enum (page->stylus_settings, "button-action"));
+ adw_combo_row_set_selected (ADW_COMBO_ROW (page->stylus_button2_action),
+ g_settings_get_enum (page->stylus_settings, "secondary-button-action"));
+ adw_combo_row_set_selected (ADW_COMBO_ROW (page->stylus_button3_action),
+ g_settings_get_enum (page->stylus_settings, "tertiary-button-action"));
+
+ set_feel_from_gsettings (page->stylus_tip_pressure_adjustment,
+ page->stylus_settings, "pressure-curve");
+ set_feel_from_gsettings (page->stylus_eraser_pressure_adjustment,
+ page->stylus_settings, "eraser-pressure-curve");
+
+ return GTK_WIDGET (page);
+}
+
+CcWacomTool *
+cc_wacom_stylus_page_get_tool (CcWacomStylusPage *page)
+{
+ return page->stylus;
+}
diff --git a/panels/wacom/cc-wacom-stylus-page.h b/panels/wacom/cc-wacom-stylus-page.h
new file mode 100644
index 0000000..51ad7d3
--- /dev/null
+++ b/panels/wacom/cc-wacom-stylus-page.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2011 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Peter Hutterer <peter.hutterer@redhat.com>
+ * Bastien Nocera <hadess@hadess.net>
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include "cc-wacom-tool.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_WACOM_STYLUS_PAGE (cc_wacom_stylus_page_get_type ())
+G_DECLARE_FINAL_TYPE (CcWacomStylusPage, cc_wacom_stylus_page, CC, WACOM_STYLUS_PAGE, GtkBox)
+
+GtkWidget * cc_wacom_stylus_page_new (CcWacomTool *stylus);
+
+CcWacomTool * cc_wacom_stylus_page_get_tool (CcWacomStylusPage *page);
+
+G_END_DECLS
diff --git a/panels/wacom/cc-wacom-stylus-page.ui b/panels/wacom/cc-wacom-stylus-page.ui
new file mode 100644
index 0000000..a7850f7
--- /dev/null
+++ b/panels/wacom/cc-wacom-stylus-page.ui
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="CcWacomStylusPage" parent="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">24</property>
+ <child>
+ <object class="AdwPreferencesGroup" id="stylus_section">
+ <property name="header-suffix">
+ <object class="GtkPicture" id="stylus_icon">
+ <property name="halign">end</property>
+ <property name="valign">start</property>
+ </object>
+ </property>
+ <child>
+ <object class="AdwActionRow" id="stylus_tip_pressure">
+ <property name="title" translatable="yes">Tip Pressure Feel</property>
+ <child>
+ <object class="GtkBox" id="stylus_tip_pressure_box">
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Soft</property>
+ <style>
+ <class name="caption"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScale" id="stylus_tip_pressure_scale">
+ <property name="adjustment">stylus_tip_pressure_adjustment</property>
+ <property name="draw_value">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <signal name="value-changed" handler="on_tip_pressure_value_changed" swapped="yes"/>
+ <accessibility>
+ <property name="label" translatable="yes">Stylus tip pressure</property>
+ </accessibility>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Firm</property>
+ <style>
+ <class name="caption"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwComboRow" id="stylus_button1_action">
+ <property name="width_request">100</property>
+ <property name="title" translatable="yes" context="display setting">Button 1</property>
+ <property name="model">button_model</property>
+ <signal name="notify::selected-item" handler="on_stylus_action_selected" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="AdwComboRow" id="stylus_button2_action">
+ <property name="width_request">100</property>
+ <property name="title" translatable="yes" context="display setting">Button 2</property>
+ <property name="model">button_model</property>
+ <signal name="notify::selected-item" handler="on_stylus_action_selected" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="AdwComboRow" id="stylus_button3_action">
+ <property name="width_request">100</property>
+ <property name="title" translatable="yes" context="display setting">Button 3</property>
+ <property name="model">button_model</property>
+ <signal name="notify::selected-item" handler="on_stylus_action_selected" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="stylus_eraser_pressure">
+ <property name="title" translatable="yes">Eraser Pressure Feel</property>
+ <child>
+ <object class="GtkBox" id="stylus_eraser_pressure_box">
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Soft</property>
+ <style>
+ <class name="caption"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScale" id="stylus_eraser_pressure_scale">
+ <property name="adjustment">stylus_eraser_pressure_adjustment</property>
+ <property name="draw_value">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <signal name="value-changed" handler="on_eraser_pressure_value_changed" swapped="yes"/>
+ <accessibility>
+ <property name="label" translatable="yes">Eraser pressure</property>
+ </accessibility>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Firm</property>
+ <style>
+ <class name="caption"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GtkAdjustment" id="stylus_tip_pressure_adjustment">
+ <property name="upper">6</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">3</property>
+ </object>
+ <object class="GtkAdjustment" id="stylus_eraser_pressure_adjustment">
+ <property name="upper">6</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">3</property>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup_pressure">
+ <widgets>
+ <widget name="stylus_tip_pressure_box" />
+ <widget name="stylus_eraser_pressure_box" />
+ </widgets>
+ </object>
+ <object class="GtkStringList" id="button_model">
+ <items>
+ <item translatable="yes">Default</item>
+ <item translatable="yes">Middle Mouse Button Click</item>
+ <item translatable="yes">Right Mouse Button Click</item>
+ <item translatable="yes">Back</item>
+ <item translatable="yes">Forward</item>
+ </items>
+ </object>
+</interface>
diff --git a/panels/wacom/cc-wacom-tool.c b/panels/wacom/cc-wacom-tool.c
new file mode 100644
index 0000000..5633f5b
--- /dev/null
+++ b/panels/wacom/cc-wacom-tool.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright © 2016 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Carlos Garnacho <carlosg@gnome.org>
+ *
+ */
+
+#include "config.h"
+
+#include "cc-wacom-tool.h"
+
+#include <glib/gi18n.h>
+
+enum {
+ PROP_0,
+ PROP_SERIAL,
+ PROP_ID,
+ PROP_DEVICE,
+ N_PROPS
+};
+
+static GParamSpec *props[N_PROPS] = { 0 };
+
+typedef struct _CcWacomTool CcWacomTool;
+
+struct _CcWacomTool {
+ GObject parent_instance;
+ guint64 serial;
+ guint64 id;
+
+ CcWacomDevice *device; /* Only set for tools with no serial */
+
+ GSettings *settings;
+ const WacomStylus *wstylus;
+};
+
+static void cc_wacom_tool_initable_iface_init (GInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (CcWacomTool, cc_wacom_tool, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+ cc_wacom_tool_initable_iface_init))
+
+static void
+cc_wacom_tool_init (CcWacomTool *tool)
+{
+}
+
+static void
+cc_wacom_tool_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcWacomTool *tool = CC_WACOM_TOOL (object);
+
+ switch (prop_id) {
+ case PROP_SERIAL:
+ tool->serial = g_value_get_uint64 (value);
+ break;
+ case PROP_ID:
+ tool->id = g_value_get_uint64 (value);
+ break;
+ case PROP_DEVICE:
+ tool->device = g_value_get_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_wacom_tool_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcWacomTool *tool = CC_WACOM_TOOL (object);
+
+ switch (prop_id) {
+ case PROP_SERIAL:
+ g_value_set_uint64 (value, tool->serial);
+ break;
+ case PROP_ID:
+ g_value_set_uint64 (value, tool->id);
+ break;
+ case PROP_DEVICE:
+ g_value_set_object (value, tool->device);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_wacom_tool_finalize (GObject *object)
+{
+ CcWacomTool *tool = CC_WACOM_TOOL (object);
+
+ g_clear_object (&tool->settings);
+
+ G_OBJECT_CLASS (cc_wacom_tool_parent_class)->finalize (object);
+}
+
+static void
+cc_wacom_tool_class_init (CcWacomToolClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = cc_wacom_tool_set_property;
+ object_class->get_property = cc_wacom_tool_get_property;
+ object_class->finalize = cc_wacom_tool_finalize;
+
+ props[PROP_SERIAL] =
+ g_param_spec_uint64 ("serial",
+ "serial",
+ "serial",
+ 0, G_MAXUINT64, 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+ props[PROP_ID] =
+ g_param_spec_uint64 ("id",
+ "id",
+ "id",
+ 0, G_MAXUINT64, 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+ props[PROP_DEVICE] =
+ g_param_spec_object ("device",
+ "device",
+ "device",
+ CC_TYPE_WACOM_DEVICE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+
+ g_object_class_install_properties (object_class, N_PROPS, props);
+}
+
+static gboolean
+cc_wacom_tool_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ CcWacomTool *tool = CC_WACOM_TOOL (initable);
+ WacomDeviceDatabase *wacom_db;
+ gchar *path;
+
+ wacom_db = cc_wacom_device_database_get ();
+
+ if (tool->id == 0 && tool->device) {
+ const gint *ids;
+ gint n_supported;
+
+ ids = cc_wacom_device_get_supported_tools (tool->device, &n_supported);
+ if (n_supported > 0)
+ tool->id = ids[0];
+ }
+
+ if (tool->id == 0)
+ tool->wstylus = libwacom_stylus_get_for_id (wacom_db, 0xfffff);
+ else
+ tool->wstylus = libwacom_stylus_get_for_id (wacom_db, tool->id);
+
+ if (!tool->wstylus) {
+ g_set_error (error, 0, 0, "Stylus description not found");
+ return FALSE;
+ }
+
+ if (tool->serial == 0) {
+ const gchar *vendor, *product;
+ GsdDevice *gsd_device;
+
+ gsd_device = cc_wacom_device_get_device (tool->device);
+ gsd_device_get_device_ids (gsd_device, &vendor, &product);
+ path = g_strdup_printf ("/org/gnome/desktop/peripherals/stylus/default-%s:%s/",
+ vendor, product);
+ } else {
+ path = g_strdup_printf ("/org/gnome/desktop/peripherals/stylus/%lx/", tool->serial);
+ }
+
+ tool->settings = g_settings_new_with_path ("org.gnome.desktop.peripherals.tablet.stylus",
+ path);
+ g_free (path);
+
+ return TRUE;
+}
+
+static void
+cc_wacom_tool_initable_iface_init (GInitableIface *iface)
+{
+ iface->init = cc_wacom_tool_initable_init;
+}
+
+CcWacomTool *
+cc_wacom_tool_new (guint64 serial,
+ guint64 id,
+ CcWacomDevice *device)
+{
+ g_return_val_if_fail (serial != 0 || CC_IS_WACOM_DEVICE (device), NULL);
+
+ return g_initable_new (CC_TYPE_WACOM_TOOL,
+ NULL, NULL,
+ "serial", serial,
+ "id", id,
+ "device", device,
+ NULL);
+}
+
+guint64
+cc_wacom_tool_get_serial (CcWacomTool *tool)
+{
+ g_return_val_if_fail (CC_IS_WACOM_TOOL (tool), 0);
+
+ return tool->serial;
+}
+
+guint64
+cc_wacom_tool_get_id (CcWacomTool *tool)
+{
+ g_return_val_if_fail (CC_IS_WACOM_TOOL (tool), 0);
+
+ return tool->id;
+}
+
+const gchar *
+cc_wacom_tool_get_name (CcWacomTool *tool)
+{
+ g_return_val_if_fail (CC_IS_WACOM_TOOL (tool), NULL);
+
+ return libwacom_stylus_get_name (tool->wstylus);
+}
+
+static const char *
+get_icon_name_from_type (const WacomStylus *wstylus)
+{
+ WacomStylusType type = libwacom_stylus_get_type (wstylus);
+
+ switch (type) {
+ case WSTYLUS_INKING:
+ case WSTYLUS_STROKE:
+ /* The stroke pen is the same as the inking pen with
+ * a different nib */
+ return "wacom-stylus-inking";
+ case WSTYLUS_AIRBRUSH:
+ return "wacom-stylus-airbrush";
+ case WSTYLUS_MARKER:
+ return "wacom-stylus-art-pen";
+ case WSTYLUS_CLASSIC:
+ return "wacom-stylus-classic";
+#ifdef HAVE_WACOM_3D_STYLUS
+ case WSTYLUS_3D:
+ return "wacom-stylus-3btn-no-eraser";
+#endif
+ default:
+ if (!libwacom_stylus_has_eraser (wstylus)) {
+ if (libwacom_stylus_get_num_buttons (wstylus) >= 3)
+ return "wacom-stylus-3btn-no-eraser";
+ else
+ return "wacom-stylus-no-eraser";
+ }
+ else {
+ if (libwacom_stylus_get_num_buttons (wstylus) >= 3)
+ return "wacom-stylus-3btn";
+ else
+ return "wacom-stylus";
+ }
+ }
+}
+
+const gchar *
+cc_wacom_tool_get_icon_name (CcWacomTool *tool)
+{
+ g_return_val_if_fail (CC_IS_WACOM_TOOL (tool), NULL);
+
+ return get_icon_name_from_type (tool->wstylus);
+}
+
+GSettings *
+cc_wacom_tool_get_settings (CcWacomTool *tool)
+{
+ g_return_val_if_fail (CC_IS_WACOM_TOOL (tool), NULL);
+
+ return tool->settings;
+}
+
+guint
+cc_wacom_tool_get_num_buttons (CcWacomTool *tool)
+{
+ g_return_val_if_fail (CC_IS_WACOM_TOOL (tool), 0);
+
+ return libwacom_stylus_get_num_buttons (tool->wstylus);
+}
+
+gboolean
+cc_wacom_tool_get_has_eraser (CcWacomTool *tool)
+{
+ g_return_val_if_fail (CC_IS_WACOM_TOOL (tool), FALSE);
+
+ return libwacom_stylus_is_eraser (tool->wstylus);
+}
+
+const gchar *
+cc_wacom_tool_get_description (CcWacomTool *tool)
+{
+ WacomAxisTypeFlags axes;
+
+ axes = libwacom_stylus_get_axes (tool->wstylus);
+
+ if ((~axes & (WACOM_AXIS_TYPE_TILT | WACOM_AXIS_TYPE_PRESSURE | WACOM_AXIS_TYPE_SLIDER)) == 0)
+ return _("Airbrush stylus with pressure, tilt, and integrated slider");
+ else if ((~axes & (WACOM_AXIS_TYPE_TILT | WACOM_AXIS_TYPE_PRESSURE | WACOM_AXIS_TYPE_ROTATION_Z)) == 0)
+ return _("Airbrush stylus with pressure, tilt, and rotation");
+ else if ((~axes & (WACOM_AXIS_TYPE_TILT | WACOM_AXIS_TYPE_PRESSURE)) == 0)
+ return _("Standard stylus with pressure and tilt");
+ else if ((~axes & WACOM_AXIS_TYPE_PRESSURE) == 0)
+ return _("Standard stylus with pressure");
+
+ return NULL;
+}
diff --git a/panels/wacom/cc-wacom-tool.h b/panels/wacom/cc-wacom-tool.h
new file mode 100644
index 0000000..a07659f
--- /dev/null
+++ b/panels/wacom/cc-wacom-tool.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright © 2016 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Carlos Garnacho <carlosg@gnome.org>
+ *
+ */
+
+#pragma once
+
+#include "config.h"
+#include "gsd-device-manager.h"
+#include "cc-wacom-device.h"
+#include <glib.h>
+
+#define CC_TYPE_WACOM_TOOL (cc_wacom_tool_get_type ())
+G_DECLARE_FINAL_TYPE (CcWacomTool, cc_wacom_tool, CC, WACOM_TOOL, GObject)
+
+CcWacomTool * cc_wacom_tool_new (guint64 serial,
+ guint64 id,
+ CcWacomDevice *device);
+
+guint64 cc_wacom_tool_get_serial (CcWacomTool *tool);
+guint64 cc_wacom_tool_get_id (CcWacomTool *tool);
+
+const gchar * cc_wacom_tool_get_name (CcWacomTool *tool);
+const gchar * cc_wacom_tool_get_icon_name (CcWacomTool *tool);
+
+GSettings * cc_wacom_tool_get_settings (CcWacomTool *tool);
+
+guint cc_wacom_tool_get_num_buttons (CcWacomTool *tool);
+gboolean cc_wacom_tool_get_has_eraser (CcWacomTool *tool);
+
+const gchar * cc_wacom_tool_get_description (CcWacomTool *tool);
diff --git a/panels/wacom/gnome-wacom-panel.desktop.in.in b/panels/wacom/gnome-wacom-panel.desktop.in.in
new file mode 100644
index 0000000..87cebd7
--- /dev/null
+++ b/panels/wacom/gnome-wacom-panel.desktop.in.in
@@ -0,0 +1,18 @@
+[Desktop Entry]
+Name=Wacom Tablet
+Comment=Set button mappings and adjust stylus sensitivity for graphics tablets
+Exec=gnome-control-center wacom
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-wacom-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;HardwareSettings;X-GNOME-Settings-Panel;X-GNOME-DevicesSettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=wacom
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: Search terms to find the Wacom Tablet panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=Tablet;Wacom;Stylus;Eraser;Mouse;
diff --git a/panels/wacom/gsd-enums.h b/panels/wacom/gsd-enums.h
new file mode 100644
index 0000000..9cfa48f
--- /dev/null
+++ b/panels/wacom/gsd-enums.h
@@ -0,0 +1,7 @@
+/* We copy gsd-wacom-device from gnome-settings-daemon.
+ * It include "gsd-enums.h" because the include directory
+ * is known. As gnome-settings-daemon's pkg-config file
+ * prefixes this, we need a little help to avoid this
+ * one line difference */
+
+#include <gnome-settings-daemon/gsd-enums.h>
diff --git a/panels/wacom/gsd-wacom-key-shortcut-button.c b/panels/wacom/gsd-wacom-key-shortcut-button.c
new file mode 100644
index 0000000..aa15b0f
--- /dev/null
+++ b/panels/wacom/gsd-wacom-key-shortcut-button.c
@@ -0,0 +1,535 @@
+/*
+ * gsd-wacom-key-shortcut-button.c
+ *
+ * Copyright © 2013 Red Hat, Inc.
+ *
+ * Author: Joaquim Rocha <jrocha@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+#include "gsd-wacom-key-shortcut-button.h"
+
+/**
+ * SECTION:gsd-wacom-key-shortcut-button
+ * @short_description: A button which captures and displays a keyboard shortcut
+ * @title: GsdWacomKeyShortcutButton
+ *
+ * GsdWacomKeyShortcutButton is a button which, when clicked, captures a keyboard
+ * shortcut and displays it.
+ * It works in a similar way to #GtkCellRendererAccel but, being a #GtkWidget,
+ * can be added to e.g. containers.
+ */
+
+#define DEFAULT_CANCEL_KEY GDK_KEY_Escape
+#define DEFAULT_CLEAR_KEY GDK_KEY_BackSpace
+
+enum {
+ KEY_SHORTCUT_EDITED,
+ KEY_SHORTCUT_CLEARED,
+ LAST_SIGNAL
+};
+
+enum {
+ PROP_0,
+ PROP_SHORTCUT_KEY_VAL,
+ PROP_SHORTCUT_KEY_MODS,
+ PROP_SHORTCUT_MODE,
+ PROP_SHORTCUT_CANCEL_KEY,
+ PROP_SHORTCUT_CLEAR_KEY,
+ N_PROPERTIES
+};
+
+struct _GsdWacomKeyShortcutButton
+{
+ GtkButton parent_instance;
+
+ gboolean editing_mode;
+
+ guint keyval;
+ guint keycode;
+ GdkModifierType mods;
+
+ /* Temporary shortcut info used for allowing
+ * modifier-only shortcuts */
+ guint tmp_shortcut_keyval;
+ GdkModifierType tmp_shortcut_mods;
+ guint32 tmp_shortcut_time;
+
+ GsdWacomKeyShortcutButtonMode mode;
+
+ guint cancel_keyval;
+ guint clear_keyval;
+};
+
+G_DEFINE_TYPE (GsdWacomKeyShortcutButton, gsd_wacom_key_shortcut_button, GTK_TYPE_BUTTON);
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
+
+static void gsd_wacom_key_shortcut_button_changed (GsdWacomKeyShortcutButton *self);
+
+static void
+gsd_wacom_key_shortcut_button_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GsdWacomKeyShortcutButton *self = GSD_WACOM_KEY_SHORTCUT_BUTTON (object);
+ gboolean changed = FALSE;
+
+ switch (property_id)
+ {
+ case PROP_SHORTCUT_KEY_VAL:
+ self->keyval = g_value_get_uint (value);
+ changed = TRUE;
+ break;
+
+ case PROP_SHORTCUT_KEY_MODS:
+ self->mods = g_value_get_uint (value);
+ changed = TRUE;
+ break;
+
+ case PROP_SHORTCUT_MODE:
+ self->mode = g_value_get_enum (value);
+ break;
+
+ case PROP_SHORTCUT_CANCEL_KEY:
+ self->cancel_keyval = g_value_get_uint (value);
+ break;
+
+ case PROP_SHORTCUT_CLEAR_KEY:
+ self->clear_keyval = g_value_get_uint (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+
+ if (changed)
+ gsd_wacom_key_shortcut_button_changed (self);
+}
+
+static void
+gsd_wacom_key_shortcut_button_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsdWacomKeyShortcutButton *self = GSD_WACOM_KEY_SHORTCUT_BUTTON (object);
+
+ switch (property_id)
+ {
+ case PROP_SHORTCUT_KEY_VAL:
+ g_value_set_uint (value, self->keyval);
+ break;
+
+ case PROP_SHORTCUT_KEY_MODS:
+ g_value_set_uint (value, self->mods);
+ break;
+
+ case PROP_SHORTCUT_MODE:
+ g_value_set_enum (value, self->mode);
+ break;
+
+ case PROP_SHORTCUT_CANCEL_KEY:
+ g_value_set_uint (value, self->cancel_keyval);
+ break;
+
+ case PROP_SHORTCUT_CLEAR_KEY:
+ g_value_set_uint (value, self->clear_keyval);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gsd_wacom_key_shortcut_set_editing_mode (GsdWacomKeyShortcutButton *self,
+ GdkEvent *event)
+{
+ self->editing_mode = TRUE;
+ gsd_wacom_key_shortcut_button_changed (self);
+ gtk_widget_grab_focus (GTK_WIDGET (self));
+}
+
+static void
+gsd_wacom_key_shortcut_remove_editing_mode (GsdWacomKeyShortcutButton *self)
+{
+ self->editing_mode = FALSE;
+ self->tmp_shortcut_keyval = 0;
+ self->tmp_shortcut_mods = 0;
+ self->tmp_shortcut_time = 0;
+}
+
+static void
+gsd_wacom_key_shortcut_button_changed (GsdWacomKeyShortcutButton *self)
+{
+ g_autofree gchar *text = NULL;
+
+ if (self->editing_mode)
+ {
+ gtk_button_set_label (GTK_BUTTON (self), _("New shortcut…"));
+
+ gtk_widget_set_state_flags (GTK_WIDGET (self),
+ GTK_STATE_FLAG_ACTIVE | GTK_STATE_FLAG_PRELIGHT,
+ FALSE);
+
+ return;
+ }
+
+ if (self->keyval == 0 && self->mods == 0)
+ {
+ gtk_button_set_label (GTK_BUTTON (self), "");
+ return;
+ }
+
+ text = gtk_accelerator_get_label (self->keyval, self->mods);
+ gtk_button_set_label (GTK_BUTTON (self), text);
+}
+
+static void
+gsd_wacom_key_shortcut_button_activate (GtkButton *self)
+{
+ gsd_wacom_key_shortcut_set_editing_mode (GSD_WACOM_KEY_SHORTCUT_BUTTON (self), NULL);
+
+ GTK_BUTTON_CLASS (gsd_wacom_key_shortcut_button_parent_class)->activate (self);
+}
+
+static void
+key_shortcut_finished_editing (GsdWacomKeyShortcutButton *self,
+ guint32 time)
+{
+ self->editing_mode = FALSE;
+
+ gsd_wacom_key_shortcut_remove_editing_mode (self);
+
+ gsd_wacom_key_shortcut_button_changed (self);
+}
+
+static gboolean
+gsd_wacom_key_shortcut_button_key_released_cb (GtkEventController *controller,
+ guint keyval,
+ guint keycode,
+ GdkModifierType state,
+ GsdWacomKeyShortcutButton *self)
+{
+ if (self->tmp_shortcut_keyval == 0)
+ return FALSE;
+
+ self->keyval = self->tmp_shortcut_keyval;
+ self->mods = self->tmp_shortcut_mods;
+
+ key_shortcut_finished_editing (self, self->tmp_shortcut_time);
+
+ g_signal_emit (self, signals[KEY_SHORTCUT_EDITED], 0);
+
+ return TRUE;
+}
+
+static gboolean
+gsd_wacom_key_shortcut_button_key_pressed_cb (GtkEventController *controller,
+ guint keyval,
+ guint keycode,
+ GdkModifierType state,
+ GsdWacomKeyShortcutButton *self)
+{
+ /* This code is based on the gtk_cell_renderer_accel_start_editing */
+ GdkModifierType mods = 0;
+ GdkEvent *event;
+ guint shortcut_keyval;
+ gboolean edited;
+ gboolean cleared;
+
+ event = gtk_event_controller_get_current_event (controller);
+
+ /* GTK and OTHER modes don't allow modifier keyvals */
+ if (gdk_key_event_is_modifier (event) && self->mode != GSD_WACOM_KEY_SHORTCUT_BUTTON_MODE_ALL)
+ return TRUE;
+
+ if (!self->editing_mode)
+ return FALSE;
+
+ edited = FALSE;
+ cleared = FALSE;
+
+ mods = state;
+
+ if (keyval == GDK_KEY_Sys_Req && (mods & GDK_ALT_MASK) != 0)
+ {
+ /* HACK: we don't want to use SysRq as a keybinding (but we do
+ * want Alt+Print), so we avoid translation from Alt+Print to SysRq
+ */
+ keyval = GDK_KEY_Print;
+ }
+
+ shortcut_keyval = gdk_keyval_to_lower (keyval);
+
+ if (shortcut_keyval == GDK_KEY_ISO_Left_Tab)
+ shortcut_keyval = GDK_KEY_Tab;
+
+ mods &= gtk_accelerator_get_default_mod_mask ();
+
+ /* Put shift back if it changed the case of the key, not otherwise.
+ */
+ if (shortcut_keyval != keyval)
+ mods |= GDK_SHIFT_MASK;
+
+ if (mods == 0)
+ {
+ if (keyval == self->cancel_keyval)
+ {
+ /* cancel the edition */
+ goto out;
+ }
+ else if (keyval == self->clear_keyval)
+ {
+ /* clear the current shortcut */
+ cleared = TRUE;
+ goto out;
+ }
+ }
+
+ self->tmp_shortcut_keyval = 0;
+ self->tmp_shortcut_mods = 0;
+ self->tmp_shortcut_time = 0;
+
+ if (gdk_key_event_is_modifier (event))
+ {
+ /* when the user presses a non-modifier key, it readily assigns the
+ * shortcut but since we also support modifiers-only shortcuts, we
+ * cannot assign the shortcut right when the user presses a modifier
+ * key because the user might assign e.g. Alt, Alt+Ctrl, Alt+Ctrl+Shift, etc.
+ * So, we keep track of the pressed shortcut's (keyval, mods and time) if
+ * it is a modifier shortcut and assign them when a key-release happens */
+ self->tmp_shortcut_keyval = shortcut_keyval;
+ self->tmp_shortcut_mods = mods;
+ self->tmp_shortcut_time = gtk_event_controller_get_current_event_time (controller);
+
+ return TRUE;
+ }
+
+ edited = TRUE;
+
+ out:
+
+ if (edited)
+ {
+ self->keyval = shortcut_keyval;
+ self->mods = mods;
+ }
+
+ if (cleared)
+ {
+ self->keyval = 0;
+ self->mods = 0;
+ }
+
+ key_shortcut_finished_editing (self, gtk_event_controller_get_current_event_time (controller));
+
+ if (edited)
+ g_signal_emit (self, signals[KEY_SHORTCUT_EDITED], 0);
+ else if (cleared)
+ g_signal_emit (self, signals[KEY_SHORTCUT_CLEARED], 0);
+
+ return TRUE;
+}
+
+static void
+gsd_wacom_key_shortcut_button_button_pressed_cb (GtkGestureClick *gesture,
+ gint n_press,
+ gdouble x,
+ gdouble y,
+ GsdWacomKeyShortcutButton *self)
+{
+ if (!self->editing_mode)
+ gsd_wacom_key_shortcut_set_editing_mode (self, NULL);
+}
+
+static void
+gsd_wacom_key_shortcut_button_unrealize (GtkWidget *widget)
+{
+ GsdWacomKeyShortcutButton *self;
+
+ self = GSD_WACOM_KEY_SHORTCUT_BUTTON (widget);
+
+ gsd_wacom_key_shortcut_remove_editing_mode (self);
+
+ GTK_WIDGET_CLASS (gsd_wacom_key_shortcut_button_parent_class)->unrealize (widget);
+}
+
+static void
+gsd_wacom_key_shortcut_button_class_init (GsdWacomKeyShortcutButtonClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass);
+
+ gobject_class->set_property = gsd_wacom_key_shortcut_button_set_property;
+ gobject_class->get_property = gsd_wacom_key_shortcut_button_get_property;
+
+ obj_properties[PROP_SHORTCUT_KEY_VAL] =
+ g_param_spec_uint ("key-value",
+ "The key value",
+ "The key value of the shortcut currently set",
+ 0,
+ G_MAXUINT,
+ 0,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS);
+
+ obj_properties[PROP_SHORTCUT_KEY_MODS] =
+ g_param_spec_uint ("key-mods",
+ "The key modifiers",
+ "The key modifiers of the shortcut currently set",
+ 0,
+ G_MAXUINT,
+ 0,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS);
+
+ obj_properties[PROP_SHORTCUT_CANCEL_KEY] =
+ g_param_spec_uint ("cancel-key",
+ "The cancel key",
+ "The key which cancels the edition of the shortcut",
+ 0,
+ G_MAXUINT,
+ DEFAULT_CANCEL_KEY,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS);
+
+ obj_properties[PROP_SHORTCUT_CLEAR_KEY] =
+ g_param_spec_uint ("clear-key",
+ "The clear key",
+ "The key which clears the currently set shortcut",
+ 0,
+ G_MAXUINT,
+ DEFAULT_CLEAR_KEY,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS);
+
+ /**
+ * GsdWacomKeyShortcutButton:mode:
+ *
+ * Determines which type of keys are allowed in the captured shortcuts.
+ * %GSD_WACOM_KEY_SHORTCUT_BUTTON_MODE_ALL is the same as
+ * %GSD_WACOM_KEY_SHORTCUT_BUTTON_MODE_OTHER but allows shortcuts composed of
+ * only modifier keys.
+ */
+ obj_properties[PROP_SHORTCUT_MODE] =
+ g_param_spec_enum ("mode",
+ "The shortcut mode",
+ "The mode with which the shortcuts are captured",
+ GSD_WACOM_TYPE_KEY_SHORTCUT_BUTTON_MODE,
+ GSD_WACOM_KEY_SHORTCUT_BUTTON_MODE_OTHER,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (gobject_class,
+ N_PROPERTIES,
+ obj_properties);
+
+ widget_class->unrealize = gsd_wacom_key_shortcut_button_unrealize;
+
+ button_class->activate = gsd_wacom_key_shortcut_button_activate;
+
+ /**
+ * GsdWacomKeyShortcutButton::key-shortcut-edited:
+ * @keyshortcutbutton: the #GsdWacomKeyShortcutButton
+ *
+ * Emitted when the key shortcut of the @keyshortcutbutton is edited.
+ *
+ * The new shortcut can be retrieved by using the #GsdWacomKeyShortcutButton:key-value
+ * and #GsdWacomKeyShortcutButton:key-mods properties.
+ */
+ signals[KEY_SHORTCUT_EDITED] = g_signal_new ("key-shortcut-edited",
+ GSD_WACOM_TYPE_KEY_SHORTCUT_BUTTON,
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ /**
+ * GsdWacomKeyShortcutButton::key-shortcut-cleared:
+ * @keyshortcutbutton: the #GsdWacomKeyShortcutButton
+ *
+ * Emitted when the key shortcut of the @keyshortcutbutton is cleared.
+ */
+ signals[KEY_SHORTCUT_CLEARED] = g_signal_new ("key-shortcut-cleared",
+ GSD_WACOM_TYPE_KEY_SHORTCUT_BUTTON,
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+gsd_wacom_key_shortcut_button_init (GsdWacomKeyShortcutButton *self)
+{
+ GtkEventController *controller;
+ GtkGesture *gesture;
+
+ self->cancel_keyval = DEFAULT_CANCEL_KEY;
+ self->clear_keyval = DEFAULT_CLEAR_KEY;
+
+ controller = gtk_event_controller_key_new ();
+ g_signal_connect (controller, "key-pressed", G_CALLBACK (gsd_wacom_key_shortcut_button_key_pressed_cb), self);
+ g_signal_connect (controller, "key-released", G_CALLBACK (gsd_wacom_key_shortcut_button_key_released_cb), self);
+ gtk_widget_add_controller (GTK_WIDGET (self), controller);
+
+ gesture = gtk_gesture_click_new ();
+ g_signal_connect (gesture, "pressed", G_CALLBACK (gsd_wacom_key_shortcut_button_button_pressed_cb), self);
+ gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (gesture));
+}
+
+/**
+ * gsd_wacom_key_shortcut_button_new:
+ *
+ * Creates a new #GsdWacomKeyShortcutButton.
+ *
+ * Returns: a new #GsdWacomKeyShortcutButton object.
+ *
+ * Since: 3.10
+ */
+GtkWidget *
+gsd_wacom_key_shortcut_button_new (void)
+{
+ return g_object_new (GSD_WACOM_TYPE_KEY_SHORTCUT_BUTTON, NULL);
+}
+
+GType
+gsd_wacom_key_shortcut_button_mode_type (void)
+{
+ static GType enum_type_id = 0;
+ if (G_UNLIKELY (!enum_type_id))
+ {
+ static const GEnumValue values[] =
+ {
+ { GSD_WACOM_KEY_SHORTCUT_BUTTON_MODE_OTHER, "OTHER", "other" },
+ { GSD_WACOM_KEY_SHORTCUT_BUTTON_MODE_ALL, "ALL", "all" },
+ { 0, NULL, NULL }
+ };
+ enum_type_id = g_enum_register_static ("GsdWacomKeyShortcutButtonMode", values);
+ }
+ return enum_type_id;
+}
diff --git a/panels/wacom/gsd-wacom-key-shortcut-button.h b/panels/wacom/gsd-wacom-key-shortcut-button.h
new file mode 100644
index 0000000..f4d5525
--- /dev/null
+++ b/panels/wacom/gsd-wacom-key-shortcut-button.h
@@ -0,0 +1,40 @@
+/*
+ * gsd-wacom-key-shortcut-button.h
+ *
+ * Copyright © 2013 Red Hat, Inc.
+ *
+ * Author: Joaquim Rocha <jrocha@redhat.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GSD_WACOM_TYPE_KEY_SHORTCUT_BUTTON (gsd_wacom_key_shortcut_button_get_type ())
+G_DECLARE_FINAL_TYPE (GsdWacomKeyShortcutButton, gsd_wacom_key_shortcut_button, GSD, WACOM_KEY_SHORTCUT_BUTTON, GtkButton)
+
+GType gsd_wacom_key_shortcut_button_mode_type (void) G_GNUC_CONST;
+#define GSD_WACOM_TYPE_KEY_SHORTCUT_BUTTON_MODE (gsd_wacom_key_shortcut_button_mode_type ())
+
+typedef enum
+{
+ GSD_WACOM_KEY_SHORTCUT_BUTTON_MODE_OTHER,
+ GSD_WACOM_KEY_SHORTCUT_BUTTON_MODE_ALL
+} GsdWacomKeyShortcutButtonMode;
+
+GtkWidget * gsd_wacom_key_shortcut_button_new (void);
diff --git a/panels/wacom/icons/meson.build b/panels/wacom/icons/meson.build
new file mode 100644
index 0000000..7437a1d
--- /dev/null
+++ b/panels/wacom/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-wacom-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/wacom/icons/scalable/org.gnome.Settings-wacom-symbolic.svg b/panels/wacom/icons/scalable/org.gnome.Settings-wacom-symbolic.svg
new file mode 100644
index 0000000..bc66c02
--- /dev/null
+++ b/panels/wacom/icons/scalable/org.gnome.Settings-wacom-symbolic.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <path d="m 8 0 v 1.5 c 0 0.132812 -0.054688 0.261719 -0.144531 0.355469 c -0.09375 0.09375 -0.21875 0.144531 -0.347657 0.144531 h -3.011718 c -0.535156 0 -1.03125 0.289062 -1.296875 0.75 c -0.265625 0.464844 -0.265625 1.035156 0 1.5 c 0.265625 0.460938 0.761719 0.75 1.296875 0.75 h 3.007812 c 0.179688 0 0.339844 0.09375 0.429688 0.25 c 0.042968 0.074219 0.066406 0.164062 0.066406 0.25 v 0.5 h -5 c -1.644531 0 -3 1.355469 -3 3 v 4 c 0 1.644531 1.355469 3 3 3 h 10 c 1.644531 0 3 -1.355469 3 -3 v -4 c 0 -0.867188 -0.378906 -1.648438 -0.972656 -2.199219 l -1.410156 1.402344 c 0.234374 0.179687 0.382812 0.460937 0.382812 0.796875 v 3 c 0 0.554688 -0.445312 1 -1 1 h -10 c -0.554688 0 -1 -0.445312 -1 -1 v -3 c 0 -0.570312 0.5 -1 1 -1 h 5.191406 l 1.992188 -2 h -1.183594 v -0.5 c 0 -0.257812 -0.066406 -0.515625 -0.199219 -0.75 c -0.265625 -0.460938 -0.761719 -0.75 -1.296875 -0.75 h -3.007812 c -0.179688 0 -0.339844 -0.09375 -0.429688 -0.25 c -0.089844 -0.152344 -0.089844 -0.347656 0 -0.5 c 0.089844 -0.15625 0.25 -0.25 0.429688 -0.25 h 3.011718 c 0.398438 0 0.777344 -0.160156 1.054688 -0.441406 c 0.28125 -0.28125 0.4375 -0.660156 0.4375 -1.058594 v -1.5 z m 7 3 c -0.265625 0 -0.519531 0.105469 -0.703125 0.292969 h -0.003906 l -6.292969 6.316406 v 1.390625 h 1.390625 l 6.316406 -6.292969 l -0.003906 -0.003906 c 0.191406 -0.183594 0.296875 -0.4375 0.296875 -0.703125 c 0 -0.550781 -0.449219 -1 -1 -1 z m 0 0" fill="#2e3436"/>
+</svg>
diff --git a/panels/wacom/meson.build b/panels/wacom/meson.build
new file mode 100644
index 0000000..f65a3db
--- /dev/null
+++ b/panels/wacom/meson.build
@@ -0,0 +1,106 @@
+deps = common_deps + wacom_deps + [
+ gnome_rr_dep,
+ gnome_settings_dep,
+ x11_dep,
+ xi_dep
+]
+
+cflags += ['-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir)]
+
+test_cflags = cflags + ['-DFAKE_AREA']
+
+wacom_gresource = gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ source_dir : '.',
+ c_name : 'cc_' + cappletname,
+ dependencies : resource_data,
+ export : true
+)
+
+subdir('calibrator')
+
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input : desktop + '.in.in',
+ output : desktop + '.in',
+ configuration : desktop_conf
+)
+
+i18n.merge_file(
+ type : 'desktop',
+ input : desktop_in,
+ output : desktop,
+ po_dir : po_dir,
+ install : true,
+ install_dir : control_center_desktopdir
+)
+
+common_sources = files(
+ 'cc-tablet-tool-map.c',
+ 'cc-wacom-button-row.c',
+ 'cc-wacom-device.c',
+ 'cc-wacom-page.c',
+ 'cc-wacom-stylus-page.c',
+ 'cc-wacom-tool.c',
+ 'gsd-wacom-key-shortcut-button.c'
+)
+
+resource_data = files(
+ 'calibrator/calibrator.ui',
+ 'calibrator/calibrator.css',
+ 'calibrator/target.svg',
+ 'button-mapping.ui',
+ 'wacom-stylus-3btn.svg',
+ 'wacom-stylus-3btn-no-eraser.svg',
+ 'wacom-stylus-airbrush.svg',
+ 'wacom-stylus-art-pen.svg',
+ 'wacom-stylus-classic.svg',
+ 'wacom-stylus-inking.svg',
+ 'wacom-stylus-no-eraser.svg',
+ 'wacom-stylus.svg',
+ 'wacom-tablet-cintiq.svg',
+ 'wacom-tablet-pc.svg',
+ 'wacom-tablet.svg'
+)
+
+common_sources += wacom_gresource
+
+sources = common_sources + files(
+ 'cc-' + cappletname + '-panel.c',
+ 'cc-drawing-area.c',
+ 'cc-wacom-ekr-page.c',
+)
+
+deps += libdevice_dep
+
+incs = [
+ top_inc,
+ calibrator_inc
+]
+
+panels_libs += static_library(
+ cappletname + '-properties',
+ sources : sources,
+ include_directories : incs,
+ dependencies : deps,
+ c_args : cflags,
+ link_with : [ libwacom_calibrator ]
+)
+
+name = 'test-wacom'
+
+sources = common_sources + files(name + '.c')
+
+executable(
+ name,
+ sources,
+ include_directories : incs,
+ dependencies : deps,
+ c_args : test_cflags,
+ link_with : [ libwacom_calibrator_test ]
+)
+
+subdir('icons')
diff --git a/panels/wacom/test-wacom.c b/panels/wacom/test-wacom.c
new file mode 100644
index 0000000..5e4cf7e
--- /dev/null
+++ b/panels/wacom/test-wacom.c
@@ -0,0 +1,155 @@
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include "cc-wacom-page.h"
+
+#define FIXED_WIDTH 675
+
+void
+cc_wacom_panel_switch_to_panel (CcWacomPanel *self, const char *panel)
+{
+ g_message ("Should launch %s preferences here", panel);
+}
+
+GDBusProxy *
+cc_wacom_panel_get_gsd_wacom_bus_proxy (CcWacomPanel *self)
+{
+ g_message ("Should get the g-s-d wacom dbus proxy here");
+
+ return NULL;
+}
+
+GDBusProxy *
+cc_wacom_panel_get_input_mapping_bus_proxy (CcWacomPanel *self)
+{
+ g_message ("Should get the mutter input mapping dbus proxy here");
+
+ return NULL;
+}
+
+static void
+add_page (GList *devices,
+ GtkWidget *notebook)
+{
+ GtkWidget *widget;
+ CcWacomDevice *stylus = NULL;
+ GList *l;
+
+ if (devices == NULL)
+ return;
+
+ for (l = devices; l ; l = l->next) {
+ stylus = l->data;
+ }
+ g_list_free (devices);
+
+ widget = cc_wacom_page_new (NULL, stylus);
+ gtk_notebook_append_page (GTK_NOTEBOOK (notebook), widget, NULL);
+ gtk_widget_show (widget);
+}
+
+static GList *
+create_fake_cintiq (void)
+{
+ CcWacomDevice *device;
+ GList *devices;
+
+ device = cc_wacom_device_new_fake ("Wacom Cintiq 21UX2");
+ devices = g_list_prepend (NULL, device);
+
+ return devices;
+}
+
+static GList *
+create_fake_bt (void)
+{
+ CcWacomDevice *device;
+ GList *devices;
+
+ device = cc_wacom_device_new_fake ("Wacom Graphire Wireless");
+ devices = g_list_prepend (NULL, device);
+
+ return devices;
+}
+
+static GList *
+create_fake_x201 (void)
+{
+ CcWacomDevice *device;
+ GList *devices;
+
+ device = cc_wacom_device_new_fake ("Wacom Serial Tablet WACf004");
+ devices = g_list_prepend (NULL, device);
+
+ return devices;
+}
+
+static GList *
+create_fake_intuos4 (void)
+{
+ CcWacomDevice *device;
+ GList *devices;
+
+ device = cc_wacom_device_new_fake ("Wacom Intuos4 6x9");
+ devices = g_list_prepend (NULL, device);
+
+ return devices;
+}
+
+static GList *
+create_fake_h610pro (void)
+{
+ CcWacomDevice *device;
+ GList *devices;
+
+ device = cc_wacom_device_new_fake ("Huion H610 Pro");
+ devices = g_list_prepend (NULL, device);
+
+ return devices;
+}
+
+int main (int argc, char **argv)
+{
+ GtkWidget *window, *notebook;
+ GList *devices;
+
+ bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ gtk_init ();
+
+ window = gtk_window_new ();
+ gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
+ gtk_window_set_default_size (GTK_WINDOW (window), FIXED_WIDTH, -1);
+ notebook = gtk_notebook_new ();
+ gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE);
+ gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE);
+ gtk_widget_set_vexpand (notebook, TRUE);
+ gtk_window_set_child (GTK_WINDOW (window), notebook);
+ gtk_widget_show (notebook);
+
+ devices = create_fake_intuos4 ();
+ add_page (devices, notebook);
+
+ devices = create_fake_cintiq ();
+ add_page (devices, notebook);
+
+ devices = create_fake_bt ();
+ add_page (devices, notebook);
+
+ devices = create_fake_x201 ();
+ add_page (devices, notebook);
+
+ devices = create_fake_h610pro ();
+ add_page (devices, notebook);
+
+ gtk_widget_show (window);
+
+ while (g_list_model_get_n_items (gtk_window_get_toplevels ()) > 0)
+ g_main_context_iteration (NULL, TRUE);
+
+ return 0;
+}
diff --git a/panels/wacom/wacom-panel-scenario-tester.py b/panels/wacom/wacom-panel-scenario-tester.py
new file mode 100755
index 0000000..731d780
--- /dev/null
+++ b/panels/wacom/wacom-panel-scenario-tester.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2021 Red Hat Inc.
+#
+# Author: Bastien Nocera <hadess@hadess.net>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import os
+import gi
+import subprocess
+import sys
+
+gi.require_version('UMockdev', '1.0')
+from gi.repository import UMockdev
+
+def setup_devices(testbed):
+ dev = testbed.add_device('hid',
+ '/devices/pci0000:00/0000:00:14.0/usb3/3-10/3-10:1.2/0003:046D:C52B.0009/0003:046D:4101.000A',
+ None,
+ [], [])
+
+ parent = dev
+ testbed.add_device('input',
+ '/devices/pci0000:00/0000:00:14.0/usb3/3-10/3-10:1.2/0003:046D:C52B.0009/0003:046D:4101.000A/input/input3',
+ parent,
+ ['name', 'Wacom Cintiq 24HD Pad'],
+ ['DEVNAME', 'input/event3',
+ 'ID_INPUT', '1',
+ 'ID_INPUT_TABLET', '1',
+ 'ID_INPUT_TABLET_PAD', '1',
+ 'ID_VENDOR_ID', '0x56a',
+ 'ID_MODEL_ID', '0x0f4',
+ 'ID_INPUT_WIDTH_MM', '50',
+ 'ID_INPUT_HEIGHT_MM', '40',
+ 'PRODUCT', '3/56a/f4/100',
+ 'LIBINPUT_DEVICE_GROUP', '3/56a/f4:usb-0000:00:14.0-5'])
+ testbed.add_device('input',
+ '/devices/pci0000:00/0000:00:14.0/usb3/3-10/3-10:1.2/0003:046D:C52B.0009/0003:046D:4101.000A/input/input4',
+ parent,
+ ['name', 'Wacom Cintiq 24HD Pen'],
+ ['DEVNAME', 'input/event4',
+ 'ID_INPUT', '1',
+ 'ID_INPUT_TABLET', '1',
+ 'ID_VENDOR_ID', '0x56a',
+ 'ID_MODEL_ID', '0x0f4',
+ 'ID_INPUT_WIDTH_MM', '50',
+ 'ID_INPUT_HEIGHT_MM', '40',
+ 'PRODUCT', '3/56a/f4/100',
+ 'LIBINPUT_DEVICE_GROUP', '3/56a/f4:usb-0000:00:14.0-5'])
+
+def wrap_call(testbed):
+ os.environ['GSETTINGS_BACKEND'] = 'memory'
+ os.environ['UMOCKDEV_DIR'] = testbed.get_root_dir()
+
+ wrapper = os.environ.get('WRAPPER')
+ args = ['gnome-control-center', '-v', 'wacom']
+ if wrapper == 'gdb':
+ args = ['gdb', '-ex', 'r', '-ex', 'bt full', '--args'] + args
+ elif wrapper:
+ args = wrapper.split(' ') + args
+
+ print(os.environ)
+
+ p = subprocess.Popen(args, env=os.environ)
+ p.wait()
+
+if __name__ == '__main__':
+ if 'umockdev' not in os.environ.get('LD_PRELOAD', ''):
+ os.execvp('umockdev-wrapper', ['umockdev-wrapper'] + sys.argv)
+
+ # Start mock udev
+ testbed = UMockdev.Testbed.new()
+ setup_devices(testbed)
+ wrap_call(testbed)
diff --git a/panels/wacom/wacom-stylus-3btn-no-eraser.svg b/panels/wacom/wacom-stylus-3btn-no-eraser.svg
new file mode 100644
index 0000000..b52c208
--- /dev/null
+++ b/panels/wacom/wacom-stylus-3btn-no-eraser.svg
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ id="svg86343"
+ version="1.1"
+ inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
+ width="190.35817"
+ height="31.02216"
+ sodipodi:docname="wacom-stylus-3btn-no-eraser.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <metadata
+ id="metadata86349">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs86347" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1080"
+ inkscape:window-height="651"
+ id="namedview86345"
+ showgrid="false"
+ inkscape:snap-nodes="false"
+ inkscape:snap-bbox="true"
+ inkscape:zoom="1.9143497"
+ inkscape:cx="237.93981"
+ inkscape:cy="17.23823"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg86343"
+ borderlayer="true"
+ inkscape:showpageshadow="false"
+ inkscape:pagecheckerboard="0">
+ <inkscape:grid
+ type="xygrid"
+ id="grid86802"
+ empspacing="5"
+ visible="true"
+ enabled="true"
+ snapvisiblegridlinesonly="true"
+ originx="77.933462"
+ originy="-80.812147" />
+ </sodipodi:namedview>
+ <g
+ style="display:inline"
+ transform="rotate(90,-56.008515,534.91126)"
+ id="g10545">
+ <path
+ sodipodi:nodetypes="cscscccccccccccccscscc"
+ inkscape:connector-curvature="0"
+ id="rect10526"
+ transform="translate(-928.4063,-95.84375)"
+ d="m 344.125,384.88832 c -1.9944,0 -3.59375,1.59935 -3.59375,3.59375 V 516 L 338,545.125 c -0.1873,2.15512 1.62589,3.92035 3.75,4.125 l 4.625,10.90625 h 1.53125 v 2.15625 l 3.61536,8.57242 1.18546,0.0214 0.44918,3.78119 0.33938,-3.7414 1.14797,-0.0687 3.76265,-8.53366 v -2.1875 h 1.53125 l 4.65625,-10.96875 c 1.96694,-0.35188 3.54637,-2.02216 3.40625,-4.0625 L 365.53125,516 V 388.48207 c 0,-1.9944 -1.59935,-3.59375 -3.59375,-3.59375 z"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#d3d7cf;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
+ <rect
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+ id="rect10541"
+ width="8.75"
+ height="22"
+ x="-579.65631"
+ y="385.90625"
+ rx="3.25"
+ ry="3.25" />
+ <rect
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+ id="rect10543"
+ width="8.75"
+ height="12.25"
+ x="-579.65631"
+ y="410.90625"
+ rx="3.25"
+ ry="3.2500002" />
+ <rect
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+ id="rect10544"
+ width="8.75"
+ height="8.75"
+ x="-579.65631"
+ y="429.15625"
+ rx="3.25"
+ ry="3.2500002" />
+ </g>
+ <g
+ style="display:inline;opacity:0.2"
+ id="g10631"
+ transform="translate(670.36721,-383.29631)" />
+</svg>
diff --git a/panels/wacom/wacom-stylus-3btn.svg b/panels/wacom/wacom-stylus-3btn.svg
new file mode 100644
index 0000000..99a72fb
--- /dev/null
+++ b/panels/wacom/wacom-stylus-3btn.svg
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ id="svg86343"
+ version="1.1"
+ inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
+ width="190.28186"
+ height="31.02216"
+ sodipodi:docname="wacom-stylus-3btn.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <metadata
+ id="metadata86349">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs86347" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1080"
+ inkscape:window-height="651"
+ id="namedview86345"
+ showgrid="false"
+ inkscape:snap-nodes="false"
+ inkscape:snap-bbox="true"
+ inkscape:zoom="1.8154258"
+ inkscape:cx="167.72924"
+ inkscape:cy="14.872544"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg86343"
+ borderlayer="true"
+ inkscape:showpageshadow="false"
+ inkscape:pagecheckerboard="0">
+ <inkscape:grid
+ type="xygrid"
+ id="grid86802"
+ empspacing="5"
+ visible="true"
+ enabled="true"
+ snapvisiblegridlinesonly="true"
+ originx="77.895312"
+ originy="-80.850297" />
+ </sodipodi:namedview>
+ <g
+ style="display:inline"
+ transform="rotate(90,-56.008515,534.91126)"
+ id="g10545">
+ <path
+ sodipodi:nodetypes="sscsscscccccccccccccscsscsss"
+ inkscape:connector-curvature="0"
+ id="rect10526"
+ transform="translate(-928.4063,-95.84375)"
+ d="m 349.69531,384.96463 c -2.3083,0 -3.2326,1.49535 -3.69531,4.51323 L 345.53125,396 H 344.125 c -1.9944,0 -3.59375,1.59935 -3.59375,3.59375 V 516 L 338,545.125 c -0.1873,2.15512 1.62589,3.92035 3.75,4.125 l 4.625,10.90625 h 1.53125 v 2.15625 l 3.61536,8.57242 1.18546,0.0214 0.44918,3.78119 0.33938,-3.7414 1.14797,-0.0687 3.76265,-8.53366 v -2.1875 h 1.53125 l 4.65625,-10.96875 c 1.96694,-0.35188 3.54637,-2.02216 3.40625,-4.0625 L 365.53125,516 V 399.59375 c 0,-1.9944 -1.59935,-3.59375 -3.59375,-3.59375 h -1.40625 L 360,389.47786 c -0.23272,-2.85711 -1.26201,-4.51323 -3.69531,-4.51323 z"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#d3d7cf;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
+ <rect
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+ id="rect10541"
+ width="8.75"
+ height="22"
+ x="-579.65631"
+ y="385.90625"
+ rx="3.25"
+ ry="3.25" />
+ <rect
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+ id="rect10543"
+ width="8.75"
+ height="12.25"
+ x="-579.65631"
+ y="410.90625"
+ rx="3.25"
+ ry="3.2500002" />
+ <rect
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+ id="rect10544"
+ width="8.75"
+ height="8.75"
+ x="-579.65631"
+ y="429.15625"
+ rx="3.25"
+ ry="3.2500002" />
+ </g>
+</svg>
diff --git a/panels/wacom/wacom-stylus-airbrush.svg b/panels/wacom/wacom-stylus-airbrush.svg
new file mode 100644
index 0000000..763fc7b
--- /dev/null
+++ b/panels/wacom/wacom-stylus-airbrush.svg
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ id="svg86343"
+ version="1.1"
+ inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
+ width="190.54817"
+ height="48.084461"
+ sodipodi:docname="wacom-stylus-airbrush.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <metadata
+ id="metadata86349">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs86347" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1080"
+ inkscape:window-height="651"
+ id="namedview86345"
+ showgrid="false"
+ inkscape:snap-nodes="false"
+ inkscape:snap-bbox="true"
+ inkscape:zoom="1.566601"
+ inkscape:cx="202.66806"
+ inkscape:cy="10.213194"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg86343"
+ borderlayer="true"
+ inkscape:showpageshadow="false"
+ inkscape:pagecheckerboard="0">
+ <inkscape:grid
+ type="xygrid"
+ id="grid86802"
+ empspacing="5"
+ visible="true"
+ enabled="true"
+ snapvisiblegridlinesonly="true"
+ originx="68.241145"
+ originy="-71.955672" />
+ </sodipodi:namedview>
+ <path
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#d3d7cf;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+ d="m 190.04818,14.311086 c 0,1.43276 -1.88644,2.59423 -4.21348,2.59423 -0.06,0 -0.11387,0.002 -0.17315,0 v 0.9224 L 97.4674,27.051651 c -9.23499,-0.9224 -29.69978,17.886897 -29.69978,17.886897 -5.27125,4.02955 -22.05579,3.90834 -27.55716,-3.58982 l -8.31149,-12.4523 -15.23774,-5.073157 v -0.5765 C 10.06256,22.765871 0.5,19.464966 0.5,17.943016 c 0,-2.11004 11.12955,-4.72727 19.16261,-4.72727 0.1448,0 0.28896,-0.002 0.43293,0 0,0 9.2445,-5.3861297 20.17264,-8.1285897 2.81141,-6.28314 13.64962,-5.78289004 16.4982,-0.49916 l 3.91974,0.009 c 0.84067,-0.83292 2.00027,-1.75859 3.53531,-1.75859 1.88597,0 3.49443,0.81769 4.21347,1.98891 l 14.74708,1.15341 102.47958,4.4678397 v 1.26829 c 0.0591,-0.002 0.11321,0 0.17315,0 2.32703,0 4.21347,1.16148 4.21347,2.59423 z"
+ id="path5306"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ssccccccccssccccsccccss" />
+</svg>
diff --git a/panels/wacom/wacom-stylus-art-pen.svg b/panels/wacom/wacom-stylus-art-pen.svg
new file mode 100644
index 0000000..bb0be38
--- /dev/null
+++ b/panels/wacom/wacom-stylus-art-pen.svg
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ id="svg86343"
+ version="1.1"
+ inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
+ width="188.59064"
+ height="31.02191"
+ sodipodi:docname="wacom-stylus-art-pen.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <metadata
+ id="metadata86349">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs86347">
+ <inkscape:path-effect
+ effect="spiro"
+ id="path-effect31574"
+ is_visible="true"
+ lpeversion="0" />
+ </defs>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1080"
+ inkscape:window-height="651"
+ id="namedview86345"
+ showgrid="false"
+ inkscape:snap-nodes="false"
+ inkscape:snap-bbox="true"
+ inkscape:zoom="1.670234"
+ inkscape:cx="146.38667"
+ inkscape:cy="34.725672"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg86343"
+ borderlayer="true"
+ inkscape:showpageshadow="false"
+ inkscape:pagecheckerboard="0">
+ <inkscape:grid
+ type="xygrid"
+ id="grid86802"
+ empspacing="5"
+ visible="true"
+ enabled="true"
+ snapvisiblegridlinesonly="true"
+ originx="77.459407"
+ originy="-79.696633" />
+ </sodipodi:namedview>
+ <g
+ style="display:inline"
+ transform="rotate(90,-56.803429,534.11634)"
+ id="g10545">
+ <path
+ sodipodi:nodetypes="sscsscsccccccccccccccscsscsss"
+ inkscape:connector-curvature="0"
+ id="rect10526"
+ transform="translate(-928.4063,-95.84375)"
+ d="m 351.16741,385.06603 c -2.25232,0 -3.61834,1.53072 -4.16741,4.08946 L 345.53125,396 H 344.125 c -1.9944,0 -3.59375,1.59935 -3.59375,3.59375 V 516 L 338,545.125 c -0.1873,2.15512 1.62589,3.92035 3.75,4.125 l 1.625,6.6639 h 2.20868 l -1.40241,1.58029 c 0,0 3.53964,7.3799 5.83774,7.46829 l 1.42852,-6.9e-4 0.0512,7.31672 3.97602,-2.37893 -0.0292,-4.98639 1.38503,0.0197 c 2.82843,0 5.42789,-7.64858 5.42789,-7.64858 l -1.5299,-1.37038 h 2.20868 l 1.65625,-6.72641 c 1.96694,-0.35188 3.54637,-2.02216 3.40625,-4.0625 L 365.53125,516 V 399.59375 c 0,-1.9944 -1.59935,-3.59375 -3.59375,-3.59375 h -1.40625 L 359,389.15549 c -0.53643,-2.39779 -1.88996,-4.08946 -4.16741,-4.08946 z"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#d3d7cf;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
+ <rect
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+ id="rect10541"
+ width="9.0059462"
+ height="35.214661"
+ x="-579.93378"
+ y="385.90622"
+ rx="3.25"
+ ry="3.2499998" />
+ </g>
+</svg>
diff --git a/panels/wacom/wacom-stylus-classic.svg b/panels/wacom/wacom-stylus-classic.svg
new file mode 100644
index 0000000..4a82793
--- /dev/null
+++ b/panels/wacom/wacom-stylus-classic.svg
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ id="svg86343"
+ version="1.1"
+ inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
+ width="187.83311"
+ height="23.792789"
+ sodipodi:docname="wacom-stylus-classic.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <metadata
+ id="metadata86349">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs86347">
+ <inkscape:path-effect
+ effect="spiro"
+ id="path-effect14408"
+ is_visible="true"
+ lpeversion="0" />
+ </defs>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1080"
+ inkscape:window-height="651"
+ id="namedview86345"
+ showgrid="false"
+ inkscape:snap-nodes="false"
+ inkscape:snap-bbox="true"
+ inkscape:zoom="1.3696365"
+ inkscape:cx="152.96029"
+ inkscape:cy="14.602414"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg86343"
+ borderlayer="true"
+ inkscape:showpageshadow="false"
+ inkscape:pagecheckerboard="0">
+ <inkscape:grid
+ type="xygrid"
+ id="grid86802"
+ empspacing="5"
+ visible="true"
+ enabled="true"
+ snapvisiblegridlinesonly="true"
+ originx="76.060233"
+ originy="-84.128949" />
+ </sodipodi:namedview>
+ <g
+ style="display:inline;opacity:0.2"
+ id="g10631"
+ transform="translate(668.49398,-386.61311)" />
+ <path
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#d3d7cf;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+ d="M 46.887667,3.360306 C 36.117047,3.865161 22.240407,1.93488 22.240407,1.93488 l -1.05225,1.559872 c 0,0 -5.49117,1.362729 -8.2077,1.850845 -2.71653,0.488109 -7.5711996,3.679579 -7.5711996,3.679579 l -1e-5,1.545431 -3.89851,-8e-6 c -1.30925997,-0.03586 -1.38545997,1.983788 -9e-5,1.983788 l 3.89851,8e-6 v 1.451666 c 0,0 4.8546896,3.19148 7.5712196,3.6796 2.71652,0.48811 8.20768,1.85083 8.20768,1.85083 l 1.05226,1.55987 c 0,0 11.863,-1.78649 21.63127,-1.54542 1.0038,0.0248 2.07462,2.59748 3.20226,2.65033 5.78108,0.27099 18.64287,0.70763 26.63126,1.0898 1.13744,0.0544 2.29772,-1.42261 3.48097,-1.37103 7.90158,0.34438 10.82762,0.61119 20.817562,0.61119 18.010761,0 60.275061,-2.76938 77.215201,-4.16159 0.58366,-0.048 0.70379,-1.39578 1.12075,-1.43172 2.25841,-0.19467 7.22786,-1.00842 7.52125,-1.084447 1.88483,-0.488463 3.53687,-2.23225 3.47014,-4.278453 0.002,-0.03684 -0.001,-0.07529 0,-0.11193 0.0688,-2.047734 -1.58423,-3.789705 -3.47014,-4.278452 -0.28392,-0.07358 -5.1712,-0.882492 -7.30532,-1.068191 C 176.0687,6.074088 175.88151,4.715969 175.18201,4.658534 158.21463,3.265341 116.00137,0.499981 98.003683,0.5 76.011317,0.500023 57.658267,2.855443 46.887667,3.360306 Z"
+ id="path14406"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="sccsccccccsccssssssssccssscs" />
+</svg>
diff --git a/panels/wacom/wacom-stylus-inking.svg b/panels/wacom/wacom-stylus-inking.svg
new file mode 100644
index 0000000..aa67724
--- /dev/null
+++ b/panels/wacom/wacom-stylus-inking.svg
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ id="svg86343"
+ version="1.1"
+ inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
+ width="189.31738"
+ height="23.031231"
+ sodipodi:docname="wacom-stylus-inking.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <metadata
+ id="metadata86349">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs86347">
+ <inkscape:path-effect
+ effect="spiro"
+ id="path-effect14408"
+ is_visible="true"
+ lpeversion="0" />
+ </defs>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1080"
+ inkscape:window-height="651"
+ id="namedview86345"
+ showgrid="false"
+ inkscape:snap-nodes="false"
+ inkscape:snap-bbox="true"
+ inkscape:zoom="1.2481956"
+ inkscape:cx="90.93126"
+ inkscape:cy="28.841633"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg86343"
+ borderlayer="true"
+ inkscape:showpageshadow="false"
+ inkscape:pagecheckerboard="0">
+ <inkscape:grid
+ type="xygrid"
+ id="grid86802"
+ empspacing="5"
+ visible="true"
+ enabled="true"
+ snapvisiblegridlinesonly="true"
+ originx="77.183018"
+ originy="-83.767469" />
+ </sodipodi:namedview>
+ <path
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#d3d7cf;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+ d="M 47.073937,3.360306 C 36.294607,3.86557 22.240407,1.93488 22.240407,1.93488 l -1.05225,1.559872 c 0,0 -5.49117,1.362729 -8.2077,1.850845 -2.71653,0.488109 -7.5711996,3.679579 -7.5711996,3.679579 l -1e-5,1.545431 -3.89851,-8e-6 c -1.30925997,-0.03586 -1.38545997,1.983788 -9e-5,1.983788 l 3.89851,8e-6 v 1.451666 c 0,0 4.8546896,3.19148 7.5712196,3.6796 2.71652,0.48811 8.20768,1.85083 8.20768,1.85083 l 1.05226,1.55987 c 0,0 14.0542,-1.93069 24.83354,-1.42541 10.77934,0.50526 28.937381,2.86028 50.929782,2.86028 21.992401,-10e-6 83.129171,-4.12918 85.865071,-4.8382 2.68626,-0.69619 5.04077,-3.181414 4.94566,-6.097669 0.003,-0.0525 -0.002,-0.107307 0,-0.159523 0.098,-2.918438 -2.25786,-5.401094 -4.94566,-6.097665 C 181.13281,4.629146 119.99605,0.499977 98.003683,0.5 76.011318,0.500023 57.853267,2.855035 47.073937,3.360306 Z"
+ id="path14406"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="sccsccccccsccsssccscs" />
+</svg>
diff --git a/panels/wacom/wacom-stylus-no-eraser.svg b/panels/wacom/wacom-stylus-no-eraser.svg
new file mode 100644
index 0000000..5436cf8
--- /dev/null
+++ b/panels/wacom/wacom-stylus-no-eraser.svg
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ id="svg86343"
+ version="1.1"
+ inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
+ width="190.35817"
+ height="31.02216"
+ sodipodi:docname="wacom-stylus-no-eraser.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <metadata
+ id="metadata86349">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs86347" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1080"
+ inkscape:window-height="651"
+ id="namedview86345"
+ showgrid="false"
+ inkscape:snap-nodes="false"
+ inkscape:snap-bbox="true"
+ inkscape:zoom="1.5080049"
+ inkscape:cx="262.26706"
+ inkscape:cy="141.90936"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg86343"
+ borderlayer="true"
+ inkscape:showpageshadow="false"
+ inkscape:pagecheckerboard="0">
+ <inkscape:grid
+ type="xygrid"
+ id="grid86802"
+ empspacing="5"
+ visible="true"
+ enabled="true"
+ snapvisiblegridlinesonly="true"
+ originx="77.933462"
+ originy="-80.812147" />
+ </sodipodi:namedview>
+ <g
+ style="display:inline"
+ transform="rotate(90,-56.008515,534.91126)"
+ id="g10545">
+ <path
+ sodipodi:nodetypes="cscscccccccccccccscscc"
+ inkscape:connector-curvature="0"
+ id="rect10526"
+ transform="translate(-928.4063,-95.84375)"
+ d="m 344.125,384.88832 c -1.9944,0 -3.59375,1.59935 -3.59375,3.59375 V 516 L 338,545.125 c -0.1873,2.15512 1.62589,3.92035 3.75,4.125 l 4.625,10.90625 h 1.53125 v 2.15625 l 3.61536,8.57242 1.18546,0.0214 0.44918,3.78119 0.33938,-3.7414 1.14797,-0.0687 3.76265,-8.53366 v -2.1875 h 1.53125 l 4.65625,-10.96875 c 1.96694,-0.35188 3.54637,-2.02216 3.40625,-4.0625 L 365.53125,516 V 388.48207 c 0,-1.9944 -1.59935,-3.59375 -3.59375,-3.59375 z"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#d3d7cf;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
+ <rect
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+ id="rect10541"
+ width="8.75"
+ height="22"
+ x="-579.65631"
+ y="385.90625"
+ rx="3.25"
+ ry="3.25" />
+ <rect
+ ry="3.2500002"
+ rx="3.25"
+ y="410.90625"
+ x="-579.65631"
+ height="12.25"
+ width="8.75"
+ id="rect10543"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
+ </g>
+ <g
+ style="display:inline;opacity:0.2"
+ id="g10631"
+ transform="translate(670.36721,-383.29631)" />
+</svg>
diff --git a/panels/wacom/wacom-stylus.svg b/panels/wacom/wacom-stylus.svg
new file mode 100644
index 0000000..19122b2
--- /dev/null
+++ b/panels/wacom/wacom-stylus.svg
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ id="svg86343"
+ version="1.1"
+ inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
+ width="190.28186"
+ height="31.02216"
+ sodipodi:docname="wacom-stylus.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <metadata
+ id="metadata86349">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs86347" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1080"
+ inkscape:window-height="651"
+ id="namedview86345"
+ showgrid="false"
+ inkscape:snap-nodes="false"
+ inkscape:snap-bbox="true"
+ inkscape:zoom="1.9779054"
+ inkscape:cx="84.685547"
+ inkscape:cy="92.016534"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg86343"
+ borderlayer="true"
+ inkscape:showpageshadow="false"
+ inkscape:pagecheckerboard="0"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0">
+ <inkscape:grid
+ type="xygrid"
+ id="grid86802"
+ empspacing="5"
+ visible="true"
+ enabled="true"
+ snapvisiblegridlinesonly="true"
+ originx="-0.20774507"
+ originy="-0.50172038" />
+ </sodipodi:namedview>
+ <g
+ style="display:inline"
+ transform="rotate(90,-56.008515,534.91126)"
+ id="g10545">
+ <path
+ sodipodi:nodetypes="sscsscscccccccccccccscsscsss"
+ inkscape:connector-curvature="0"
+ id="rect10526"
+ transform="translate(-928.4063,-95.84375)"
+ d="m 349.69531,384.96463 c -2.3083,0 -3.2326,1.49535 -3.69531,4.51323 L 345.53125,396 H 344.125 c -1.9944,0 -3.59375,1.59935 -3.59375,3.59375 V 516 L 338,545.125 c -0.1873,2.15512 1.62589,3.92035 3.75,4.125 l 4.625,10.90625 h 1.53125 v 2.15625 l 3.61536,8.57242 1.18546,0.0214 0.44918,3.78119 0.33938,-3.7414 1.14797,-0.0687 3.76265,-8.53366 v -2.1875 h 1.53125 l 4.65625,-10.96875 c 1.96694,-0.35188 3.54637,-2.02216 3.40625,-4.0625 L 365.53125,516 V 399.59375 c 0,-1.9944 -1.59935,-3.59375 -3.59375,-3.59375 h -1.40625 L 360,389.47786 c -0.23272,-2.85711 -1.26201,-4.51323 -3.69531,-4.51323 z"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#d3d7cf;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
+ <rect
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+ id="rect10541"
+ width="8.75"
+ height="22"
+ x="-579.65631"
+ y="385.90625"
+ rx="3.25"
+ ry="3.25" />
+ <rect
+ ry="3.2500002"
+ rx="3.25"
+ y="410.90625"
+ x="-579.65631"
+ height="12.25"
+ width="8.75"
+ id="rect10543"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
+ </g>
+</svg>
diff --git a/panels/wacom/wacom-tablet-cintiq.svg b/panels/wacom/wacom-tablet-cintiq.svg
new file mode 100644
index 0000000..42d9005
--- /dev/null
+++ b/panels/wacom/wacom-tablet-cintiq.svg
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ id="svg86858"
+ version="1.1"
+ inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
+ width="117.00018"
+ height="91.995674"
+ sodipodi:docname="wacom-tablet-cintiq.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <metadata
+ id="metadata86864">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs86862" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1080"
+ inkscape:window-height="651"
+ id="namedview86860"
+ showgrid="false"
+ borderlayer="true"
+ inkscape:showpageshadow="false"
+ inkscape:zoom="1"
+ inkscape:cx="-127.5"
+ inkscape:cy="-18"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg86858"
+ inkscape:snap-nodes="false"
+ inkscape:snap-bbox="true"
+ inkscape:pagecheckerboard="0">
+ <inkscape:grid
+ type="xygrid"
+ id="grid86892"
+ empspacing="5"
+ visible="true"
+ enabled="true"
+ snapvisiblegridlinesonly="true"
+ originx="-3.0021704"
+ originy="-2.0021639" />
+ </sodipodi:namedview>
+ <g
+ style="display:inline;enable-background:new"
+ transform="matrix(0.68936116,0,0,0.68936115,462.30735,-77.493976)"
+ id="g4353-3">
+ <path
+ inkscape:connector-curvature="0"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#d3d7cf;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1.45062px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+ d="m 191,253 v 122 h 30.45602 v 10 h 20.32523 v -10 h 65.25887 v 10 h 20.4159 v -10 h 31.81597 V 253 Z"
+ transform="translate(-860.90625,-139.8605)"
+ id="rect22528"
+ sodipodi:nodetypes="ccccccccccccc" />
+ <rect
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#babdb6;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1.45062;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+ id="rect4133-4"
+ width="126.20383"
+ height="79.784019"
+ x="-649.60083"
+ y="130.54378" />
+ </g>
+</svg>
diff --git a/panels/wacom/wacom-tablet-pc.svg b/panels/wacom/wacom-tablet-pc.svg
new file mode 100644
index 0000000..fd523eb
--- /dev/null
+++ b/panels/wacom/wacom-tablet-pc.svg
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ id="svg86858"
+ version="1.1"
+ inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
+ width="117.33909"
+ height="85.952255"
+ sodipodi:docname="wacom-tablet-pc.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <metadata
+ id="metadata86864">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs86862" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1080"
+ inkscape:window-height="651"
+ id="namedview86860"
+ showgrid="false"
+ borderlayer="true"
+ inkscape:showpageshadow="false"
+ inkscape:zoom="1"
+ inkscape:cx="214.5"
+ inkscape:cy="-26"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg86858"
+ inkscape:snap-nodes="false"
+ inkscape:snap-bbox="true"
+ inkscape:pagecheckerboard="0">
+ <inkscape:grid
+ type="xygrid"
+ id="grid86892"
+ empspacing="5"
+ visible="true"
+ enabled="true"
+ snapvisiblegridlinesonly="true"
+ originx="-3.7432745"
+ originy="-4.9999999" />
+ </sodipodi:namedview>
+ <path
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#d3d7cf;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+ d="M 13.793082,0.49999997 V 60.214196 L 0.81922544,85.452254 H 116.49285 l -14.68849,-26.666627 -0.012,-58.28562703 z"
+ id="rect22528"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ <rect
+ y="9.5"
+ x="24.756723"
+ height="42"
+ width="66"
+ id="rect4133-4"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#babdb6;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
+</svg>
diff --git a/panels/wacom/wacom-tablet.svg b/panels/wacom/wacom-tablet.svg
new file mode 100644
index 0000000..270144f
--- /dev/null
+++ b/panels/wacom/wacom-tablet.svg
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ id="svg86858"
+ version="1.1"
+ inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
+ width="112.47625"
+ height="87.658791"
+ sodipodi:docname="wacom-tablet.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <metadata
+ id="metadata86864">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs86862" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1080"
+ inkscape:window-height="651"
+ id="namedview86860"
+ showgrid="false"
+ borderlayer="true"
+ inkscape:showpageshadow="false"
+ inkscape:zoom="1.4142136"
+ inkscape:cx="39.244425"
+ inkscape:cy="86.974132"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="g4353-0"
+ inkscape:pagecheckerboard="0">
+ <inkscape:grid
+ type="xygrid"
+ id="grid86892"
+ empspacing="5"
+ visible="true"
+ enabled="true"
+ snapvisiblegridlinesonly="true"
+ originx="-3.027458"
+ originy="-2.8750015" />
+ </sodipodi:namedview>
+ <g
+ style="display:inline"
+ transform="matrix(0.59415025,0,0,0.67531282,402.41987,-76.934106)"
+ id="g4353-0">
+ <path
+ style="fill:#d3d7cf;fill-opacity:1;stroke:#babdb6;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 4.2812501,3.375 3.53125,85.5 C 31.076436,90.740667 83.579166,92.281216 115,85.5 L 114.25,3.375 Z"
+ transform="matrix(1.683076,0,0,1.4807952,-682.39865,109.66637)"
+ id="path3568-6"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <rect
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#babdb6;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1.5787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+ id="rect10889"
+ width="138.6996"
+ height="82.952255"
+ x="-651.99988"
+ y="129.88136" />
+ </g>
+</svg>
diff --git a/panels/wacom/wacom.gresource.xml b/panels/wacom/wacom.gresource.xml
new file mode 100644
index 0000000..1aa4df2
--- /dev/null
+++ b/panels/wacom/wacom.gresource.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/wacom">
+ <file preprocess="xml-stripblanks">cc-wacom-panel.ui</file>
+ <file preprocess="xml-stripblanks">cc-wacom-page.ui</file>
+ <file preprocess="xml-stripblanks">cc-wacom-ekr-page.ui</file>
+ <file preprocess="xml-stripblanks">cc-wacom-stylus-page.ui</file>
+ <file preprocess="xml-stripblanks">button-mapping.ui</file>
+ <file preprocess="xml-stripblanks">calibrator/calibrator.ui</file>
+ <file>calibrator/calibrator.css</file>
+ <file>calibrator/target.svg</file>
+ <file>wacom-tablet.svg</file>
+ <file>wacom-stylus.svg</file>
+ <file>wacom-stylus-3btn-no-eraser.svg</file>
+ <file>wacom-stylus-3btn.svg</file>
+ <file>wacom-stylus-no-eraser.svg</file>
+ <file>wacom-stylus-airbrush.svg</file>
+ <file>wacom-stylus-inking.svg</file>
+ <file>wacom-stylus-art-pen.svg</file>
+ <file>wacom-stylus-classic.svg</file>
+ <file>wacom-tablet-cintiq.svg</file>
+ <file>wacom-tablet-pc.svg</file>
+ </gresource>
+</gresources>
diff --git a/panels/wwan/cc-wwan-apn-dialog.c b/panels/wwan/cc-wwan-apn-dialog.c
new file mode 100644
index 0000000..a009223
--- /dev/null
+++ b/panels/wwan/cc-wwan-apn-dialog.c
@@ -0,0 +1,428 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-wwan-apn-dialog.c
+ *
+ * Copyright 2019 Purism SPC
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "cc-wwan-apn-dialog"
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include <libmm-glib.h>
+
+#include "cc-wwan-device.h"
+#include "cc-wwan-data.h"
+#include "cc-wwan-apn-dialog.h"
+#include "cc-wwan-resources.h"
+
+/**
+ * @short_description: Dialog to manage Internet Access Points
+ */
+
+struct _CcWwanApnDialog
+{
+ GtkDialog parent_instance;
+
+ GtkButton *add_button;
+ GtkButton *back_button;
+ GtkButton *save_button;
+ GtkEntry *apn_entry;
+ GtkEntry *name_entry;
+ GtkEntry *password_entry;
+ GtkEntry *username_entry;
+ GtkGrid *apn_edit_view;
+ GtkListBox *apn_list;
+ GtkCheckButton *apn_radio_button;
+ GtkScrolledWindow *apn_list_view;
+ GtkStack *apn_settings_stack;
+
+ CcWwanData *wwan_data;
+ CcWwanDataApn *apn_to_save; /* The APN currently being edited */
+ CcWwanDevice *device;
+
+ gboolean enable_data;
+ gboolean enable_roaming;
+};
+
+G_DEFINE_TYPE (CcWwanApnDialog, cc_wwan_apn_dialog, GTK_TYPE_DIALOG)
+
+
+enum {
+ PROP_0,
+ PROP_DEVICE,
+ N_PROPS
+};
+
+static GParamSpec *properties[N_PROPS];
+
+#define CC_TYPE_WWAN_APN_ROW (cc_wwan_apn_row_get_type())
+G_DECLARE_FINAL_TYPE (CcWwanApnRow, cc_wwan_apn_row, CC, WWAN_APN_ROW, GtkListBoxRow)
+
+struct _CcWwanApnRow
+{
+ GtkListBoxRow parent_instance;
+ GtkCheckButton *radio_button;
+ CcWwanDataApn *apn;
+};
+
+G_DEFINE_TYPE (CcWwanApnRow, cc_wwan_apn_row, GTK_TYPE_LIST_BOX_ROW)
+
+static void
+cc_wwan_apn_row_finalize (GObject *object)
+{
+ CcWwanApnRow *row = (CcWwanApnRow *)object;
+
+ g_clear_object (&row->apn);
+
+ G_OBJECT_CLASS (cc_wwan_apn_row_parent_class)->finalize (object);
+}
+
+static void
+cc_wwan_apn_row_class_init (CcWwanApnRowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = cc_wwan_apn_row_finalize;
+}
+
+static void
+cc_wwan_apn_row_init (CcWwanApnRow *row)
+{
+}
+
+static void
+cc_wwan_apn_back_clicked_cb (CcWwanApnDialog *self)
+{
+ GtkWidget *view;
+
+ view = gtk_stack_get_visible_child (self->apn_settings_stack);
+
+ if (view == GTK_WIDGET (self->apn_edit_view))
+ {
+ gtk_widget_hide (GTK_WIDGET (self->save_button));
+ gtk_widget_show (GTK_WIDGET (self->add_button));
+ gtk_stack_set_visible_child (self->apn_settings_stack,
+ GTK_WIDGET (self->apn_list_view));
+ }
+ else
+ {
+ gtk_widget_hide (GTK_WIDGET (self));
+ }
+}
+
+static void
+cc_wwan_apn_add_clicked_cb (CcWwanApnDialog *self)
+{
+ gtk_editable_set_text (GTK_EDITABLE (self->name_entry), "");
+ gtk_editable_set_text (GTK_EDITABLE (self->apn_entry), "");
+ gtk_editable_set_text (GTK_EDITABLE (self->username_entry), "");
+ gtk_editable_set_text (GTK_EDITABLE (self->password_entry), "");
+
+ gtk_widget_hide (GTK_WIDGET (self->add_button));
+ gtk_widget_show (GTK_WIDGET (self->save_button));
+ self->apn_to_save = NULL;
+ gtk_stack_set_visible_child (self->apn_settings_stack,
+ GTK_WIDGET (self->apn_edit_view));
+}
+
+static void
+cc_wwan_apn_save_clicked_cb (CcWwanApnDialog *self)
+{
+ const gchar *name, *apn_name;
+ CcWwanDataApn *apn;
+
+ apn = self->apn_to_save;
+ self->apn_to_save = NULL;
+
+ name = gtk_editable_get_text (GTK_EDITABLE (self->name_entry));
+ apn_name = gtk_editable_get_text (GTK_EDITABLE (self->apn_entry));
+
+ if (!apn)
+ apn = cc_wwan_data_apn_new ();
+
+ cc_wwan_data_apn_set_name (apn, name);
+ cc_wwan_data_apn_set_apn (apn, apn_name);
+ cc_wwan_data_apn_set_username (apn, gtk_editable_get_text (GTK_EDITABLE (self->username_entry)));
+ cc_wwan_data_apn_set_password (apn, gtk_editable_get_text (GTK_EDITABLE (self->password_entry)));
+
+ cc_wwan_data_save_apn (self->wwan_data, apn, NULL, NULL, NULL);
+
+ gtk_widget_hide (GTK_WIDGET (self->save_button));
+ gtk_stack_set_visible_child (self->apn_settings_stack,
+ GTK_WIDGET (self->apn_list_view));
+}
+
+static void
+cc_wwan_apn_entry_changed_cb (CcWwanApnDialog *self)
+{
+ GtkWidget *widget;
+ const gchar *str;
+ gboolean valid_name, valid_apn;
+
+ widget = GTK_WIDGET (self->name_entry);
+ str = gtk_editable_get_text (GTK_EDITABLE (self->name_entry));
+ valid_name = str && *str;
+
+ if (valid_name)
+ gtk_style_context_remove_class (gtk_widget_get_style_context (widget), "error");
+ else
+ gtk_style_context_add_class (gtk_widget_get_style_context (widget), "error");
+
+ widget = GTK_WIDGET (self->apn_entry);
+ str = gtk_editable_get_text (GTK_EDITABLE (self->apn_entry));
+ valid_apn = str && *str;
+
+ if (valid_apn)
+ gtk_style_context_remove_class (gtk_widget_get_style_context (widget), "error");
+ else
+ gtk_style_context_add_class (gtk_widget_get_style_context (widget), "error");
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->save_button), valid_name && valid_apn);
+}
+
+static void
+cc_wwan_apn_activated_cb (CcWwanApnDialog *self,
+ CcWwanApnRow *row)
+{
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (row->radio_button), TRUE);
+}
+
+static void
+cc_wwan_apn_changed_cb (CcWwanApnDialog *self,
+ GtkWidget *widget)
+{
+ CcWwanApnRow *row;
+
+ if (!gtk_check_button_get_active (GTK_CHECK_BUTTON (widget)))
+ return;
+
+ widget = gtk_widget_get_ancestor (widget, CC_TYPE_WWAN_APN_ROW);
+ row = CC_WWAN_APN_ROW (widget);
+
+ if (cc_wwan_data_set_default_apn (self->wwan_data, row->apn))
+ cc_wwan_data_save_settings (self->wwan_data, NULL, NULL, NULL);
+}
+
+static void
+cc_wwan_apn_edit_clicked_cb (CcWwanApnDialog *self,
+ GtkButton *button)
+{
+ CcWwanDataApn *apn;
+ CcWwanApnRow *row;
+ GtkWidget *widget;
+
+ widget = gtk_widget_get_ancestor (GTK_WIDGET (button), CC_TYPE_WWAN_APN_ROW);
+ row = CC_WWAN_APN_ROW (widget);
+ apn = row->apn;
+ self->apn_to_save = apn;
+
+ gtk_widget_show (GTK_WIDGET (self->save_button));
+ gtk_widget_hide (GTK_WIDGET (self->add_button));
+
+ gtk_editable_set_text (GTK_EDITABLE (self->name_entry), cc_wwan_data_apn_get_name (apn));
+ gtk_editable_set_text (GTK_EDITABLE (self->apn_entry), cc_wwan_data_apn_get_apn (apn));
+ gtk_editable_set_text (GTK_EDITABLE (self->username_entry), cc_wwan_data_apn_get_username (apn));
+ gtk_editable_set_text (GTK_EDITABLE (self->password_entry), cc_wwan_data_apn_get_password (apn));
+
+ gtk_stack_set_visible_child (self->apn_settings_stack,
+ GTK_WIDGET (self->apn_edit_view));
+}
+
+static GtkWidget *
+cc_wwan_apn_dialog_row_new (CcWwanDataApn *apn,
+ CcWwanApnDialog *self)
+{
+ CcWwanApnRow *row;
+ GtkWidget *grid, *name_label, *apn_label, *radio, *edit_button;
+ GtkStyleContext *context;
+
+ row = g_object_new (CC_TYPE_WWAN_APN_ROW, NULL);
+
+ grid = g_object_new (GTK_TYPE_GRID,
+ "margin-top", 6,
+ "margin-bottom", 6,
+ "margin-start", 6,
+ "margin-end", 6,
+ NULL);
+
+ radio = gtk_check_button_new ();
+ row->radio_button = GTK_CHECK_BUTTON (radio);
+ gtk_check_button_set_group (row->radio_button, self->apn_radio_button);
+ gtk_widget_set_margin_end (radio, 12);
+ gtk_grid_attach (GTK_GRID (grid), radio, 0, 0, 1, 2);
+ row->apn = g_object_ref (apn);
+
+ if (cc_wwan_data_get_default_apn (self->wwan_data) == apn)
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (radio), TRUE);
+ g_signal_connect_object (radio, "toggled",
+ G_CALLBACK (cc_wwan_apn_changed_cb),
+ self, G_CONNECT_SWAPPED);
+
+ name_label = gtk_label_new (cc_wwan_data_apn_get_name (apn));
+ gtk_label_set_ellipsize (GTK_LABEL (name_label), PANGO_ELLIPSIZE_END);
+ gtk_widget_set_halign (name_label, GTK_ALIGN_START);
+ gtk_widget_set_hexpand (name_label, TRUE);
+ gtk_grid_attach (GTK_GRID (grid), name_label, 1, 0, 1, 1);
+
+ apn_label = gtk_label_new (cc_wwan_data_apn_get_apn (apn));
+ gtk_label_set_ellipsize (GTK_LABEL (apn_label), PANGO_ELLIPSIZE_END);
+ gtk_widget_set_halign (apn_label, GTK_ALIGN_START);
+ context = gtk_widget_get_style_context (apn_label);
+ gtk_style_context_add_class (context, "dim-label");
+ gtk_grid_attach (GTK_GRID (grid), apn_label, 1, 1, 1, 1);
+
+ edit_button = gtk_button_new_from_icon_name ("emblem-system-symbolic");
+ gtk_accessible_update_property (GTK_ACCESSIBLE (edit_button),
+ GTK_ACCESSIBLE_PROPERTY_LABEL, _("Edit"),
+ -1);
+ g_signal_connect_object (edit_button, "clicked",
+ G_CALLBACK (cc_wwan_apn_edit_clicked_cb),
+ self, G_CONNECT_SWAPPED);
+ gtk_grid_attach (GTK_GRID (grid), edit_button, 2, 0, 1, 2);
+
+ gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), grid);
+
+ return GTK_WIDGET (row);
+}
+
+static void
+cc_wwan_apn_dialog_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcWwanApnDialog *self = (CcWwanApnDialog *)object;
+
+ switch (prop_id)
+ {
+ case PROP_DEVICE:
+ self->device = g_value_dup_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_wwan_apn_dialog_constructed (GObject *object)
+{
+ CcWwanApnDialog *self = (CcWwanApnDialog *)object;
+
+ G_OBJECT_CLASS (cc_wwan_apn_dialog_parent_class)->constructed (object);
+
+ self->wwan_data = cc_wwan_device_get_data (self->device);
+
+ gtk_list_box_bind_model (self->apn_list,
+ cc_wwan_data_get_apn_list (self->wwan_data),
+ (GtkListBoxCreateWidgetFunc)cc_wwan_apn_dialog_row_new,
+ self, NULL);
+}
+
+static void
+cc_wwan_apn_dialog_dispose (GObject *object)
+{
+ CcWwanApnDialog *self = (CcWwanApnDialog *)object;
+
+ g_clear_object (&self->device);
+
+ G_OBJECT_CLASS (cc_wwan_apn_dialog_parent_class)->dispose (object);
+}
+
+
+static void
+cc_wwan_apn_dialog_show (GtkWidget *widget)
+{
+ CcWwanApnDialog *self = (CcWwanApnDialog *)widget;
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->save_button), FALSE);
+ gtk_widget_show (GTK_WIDGET (self->add_button));
+ gtk_widget_hide (GTK_WIDGET (self->save_button));
+ gtk_stack_set_visible_child (self->apn_settings_stack,
+ GTK_WIDGET (self->apn_list_view));
+
+ GTK_WIDGET_CLASS (cc_wwan_apn_dialog_parent_class)->show (widget);
+}
+
+static void
+cc_wwan_apn_dialog_class_init (CcWwanApnDialogClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = cc_wwan_apn_dialog_set_property;
+ object_class->constructed = cc_wwan_apn_dialog_constructed;
+ object_class->dispose = cc_wwan_apn_dialog_dispose;
+
+ widget_class->show = cc_wwan_apn_dialog_show;
+
+ properties[PROP_DEVICE] =
+ g_param_spec_object ("device",
+ "Device",
+ "The WWAN Device",
+ CC_TYPE_WWAN_DEVICE,
+ G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/control-center/wwan/cc-wwan-apn-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcWwanApnDialog, add_button);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanApnDialog, apn_edit_view);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanApnDialog, apn_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanApnDialog, apn_list);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanApnDialog, apn_list_view);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanApnDialog, apn_radio_button);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanApnDialog, apn_settings_stack);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanApnDialog, back_button);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanApnDialog, name_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanApnDialog, password_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanApnDialog, save_button);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanApnDialog, username_entry);
+
+ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_apn_back_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_apn_add_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_apn_save_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_apn_entry_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_apn_activated_cb);
+}
+
+static void
+cc_wwan_apn_dialog_init (CcWwanApnDialog *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+CcWwanApnDialog *
+cc_wwan_apn_dialog_new (GtkWindow *parent_window,
+ CcWwanDevice *device)
+{
+ g_return_val_if_fail (GTK_IS_WINDOW (parent_window), NULL);
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (device), NULL);
+
+ return g_object_new (CC_TYPE_WWAN_APN_DIALOG,
+ "transient-for", parent_window,
+ "use-header-bar", 1,
+ "device", device,
+ NULL);
+}
diff --git a/panels/wwan/cc-wwan-apn-dialog.h b/panels/wwan/cc-wwan-apn-dialog.h
new file mode 100644
index 0000000..37e905e
--- /dev/null
+++ b/panels/wwan/cc-wwan-apn-dialog.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-wwan-apn-dialog.h
+ *
+ * Copyright 2019 Purism SPC
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <adwaita.h>
+#include <shell/cc-panel.h>
+
+#include "cc-wwan-device.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_WWAN_APN_DIALOG (cc_wwan_apn_dialog_get_type())
+G_DECLARE_FINAL_TYPE (CcWwanApnDialog, cc_wwan_apn_dialog, CC, WWAN_APN_DIALOG, GtkDialog)
+
+CcWwanApnDialog *cc_wwan_apn_dialog_new (GtkWindow *parent_window,
+ CcWwanDevice *device);
+
+G_END_DECLS
diff --git a/panels/wwan/cc-wwan-apn-dialog.ui b/panels/wwan/cc-wwan-apn-dialog.ui
new file mode 100644
index 0000000..7853756
--- /dev/null
+++ b/panels/wwan/cc-wwan-apn-dialog.ui
@@ -0,0 +1,209 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk" version="4.0"/>
+ <template class="CcWwanApnDialog" parent="GtkDialog">
+ <property name="default-height">480</property>
+ <property name="default-width">360</property>
+ <property name="hide-on-close">True</property>
+ <property name="title" translatable="yes">Access Points</property>
+ <property name="modal">True</property>
+
+ <child type="titlebar">
+ <object class="GtkHeaderBar">
+
+ <!-- Back button -->
+ <child type="start">
+ <object class="GtkButton" id="back_button">
+ <property name="use-underline">True</property>
+ <property name="icon-name">go-previous-symbolic</property>
+ <signal name="clicked" handler="cc_wwan_apn_back_clicked_cb" swapped="yes"/>
+ <accessibility>
+ <property name="label" translatable="yes">Back</property>
+ </accessibility>
+ </object>
+ </child>
+
+ <!-- Add button -->
+ <child type="end">
+ <object class="GtkButton" id="add_button">
+ <property name="use-underline">True</property>
+ <property name="icon-name">list-add-symbolic</property>
+ <signal name="clicked" handler="cc_wwan_apn_add_clicked_cb" swapped="yes"/>
+ <accessibility>
+ <property name="label" translatable="yes">Add</property>
+ </accessibility>
+ </object>
+ </child>
+
+ <!-- Save button -->
+ <child type="end">
+ <object class="GtkButton" id="save_button">
+ <property name="visible">False</property>
+ <property name="use-underline">True</property>
+ <property name="label" translatable="yes">_Save</property>
+ <signal name="clicked" handler="cc_wwan_apn_save_clicked_cb" swapped="yes"/>
+ <style>
+ <class name="default"/>
+ </style>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkStack" id="apn_settings_stack">
+ <property name="transition-type">slide-left-right</property>
+
+ <!-- Access Point List -->
+ <child>
+ <object class="AdwPreferencesPage" id="apn_list_view">
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="GtkListBox" id="apn_list">
+ <property name="valign">start</property>
+ <property name="selection-mode">none</property>
+ <signal name="row-activated" handler="cc_wwan_apn_activated_cb" swapped="yes"/>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesPage" id="apn_edit_view">
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="GtkGrid">
+ <property name="orientation">vertical</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row-spacing">6</property>
+ <property name="column-spacing">12</property>
+
+ <!-- Name -->
+ <child>
+ <object class="GtkLabel">
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <property name="label" translatable="yes">Name</property>
+ <property name="mnemonic_widget">name_entry</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="name_entry">
+ <property name="hexpand">True</property>
+ <signal name="changed" handler="cc_wwan_apn_entry_changed_cb" swapped="yes"/>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- APN -->
+ <child>
+ <object class="GtkLabel">
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <property name="label" translatable="yes">APN</property>
+ <property name="mnemonic_widget">apn_entry</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="apn_entry">
+ <property name="margin-bottom">12</property>
+ <signal name="changed" handler="cc_wwan_apn_entry_changed_cb" swapped="yes"/>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Username -->
+ <child>
+ <object class="GtkLabel">
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <property name="label" translatable="yes">Username</property>
+ <property name="mnemonic_widget">username_entry</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="username_entry">
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Password -->
+ <child>
+ <object class="GtkLabel">
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <property name="label" translatable="yes">Password</property>
+ <property name="mnemonic_widget">password_entry</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="password_entry">
+ <property name="margin-bottom">12</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object> <!-- ./AdwPreferencesGroup -->
+ </child>
+ </object>
+ </child>
+
+ </object> <!-- ./GtkStack apn_settings_stack -->
+ </child>
+ </template>
+
+ <!-- A simple hack to create a radio button group -->
+ <object class="GtkCheckButton" id="apn_radio_button"/>
+</interface>
diff --git a/panels/wwan/cc-wwan-data.c b/panels/wwan/cc-wwan-data.c
new file mode 100644
index 0000000..2608ab2
--- /dev/null
+++ b/panels/wwan/cc-wwan-data.c
@@ -0,0 +1,1502 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-wwan-data.c
+ *
+ * Copyright 2019 Purism SPC
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "cc-wwan-data"
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <glib/gi18n.h>
+#include <nma-mobile-providers.h>
+
+#include "cc-wwan-data.h"
+
+/**
+ * @short_description: Device Internet Data Object
+ * @include: "cc-wwan-device-data.h"
+ *
+ * #CcWwanData represents the data object of the given
+ * #CcWwanDevice. Please note that while #CcWWanDevice
+ * is bound to the hardware device, #CcWwanData may also
+ * depend on the inserted SIM (if supported). So the state
+ * of #CcWwanData changes when SIM is changed.
+ */
+
+/*
+ * Priority for connections. The larger the number, the lower the priority
+ * https://developer.gnome.org/NetworkManager/stable/nm-settings.html:
+ *
+ * A lower value is better (higher priority). Zero selects a globally
+ * configured default value. If the latter is missing or zero too, it
+ * defaults to 50 for VPNs and 100 for other connections.
+ *
+ * Since WiFi and other network connections will likely get the default
+ * setting of 100, set WWAN DNS priorities higher than the default, with
+ * room to allow multiple modems to set priority above/below each other.
+ */
+#define CC_WWAN_DNS_PRIORITY_LOW (120)
+#define CC_WWAN_DNS_PRIORITY_HIGH (115)
+
+/* These are to be set as route metric */
+#define CC_WWAN_ROUTE_PRIORITY_LOW (1050)
+#define CC_WWAN_ROUTE_PRIORITY_HIGH (1040)
+
+struct _CcWwanData
+{
+ GObject parent_instance;
+
+ MMObject *mm_object;
+ MMModem *modem;
+ MMSim *sim;
+ gchar *sim_id;
+
+ gchar *operator_code; /* MCCMNC */
+ GError *error;
+
+ NMClient *nm_client;
+ NMDevice *nm_device;
+ NMAMobileProvidersDatabase *apn_db;
+ NMAMobileProvider *apn_provider;
+ CcWwanDataApn *default_apn;
+ CcWwanDataApn *old_default_apn;
+ GListStore *apn_list;
+ NMActiveConnection *active_connection;
+
+ gint priority;
+ gboolean data_enabled; /* autoconnect enabled */
+ gboolean home_only; /* Data roaming */
+ gboolean apn_list_updated; /* APN list updated from mobile-provider-info */
+};
+
+G_DEFINE_TYPE (CcWwanData, cc_wwan_data, G_TYPE_OBJECT)
+
+/*
+ * Default Access Point Settings Logic:
+ * For a provided SIM, all the APNs available from NetworkManager
+ * that matches the given SIM identifier (ICCID, available via
+ * mm_sim_get_identifier() or similar gdbus API) is loaded for
+ * the Device (In NetworkManager, it is saved as ‘sim-id’, if
+ * present). At a time, only one connection will be bound to
+ * a device. If there are more than one match, the item with
+ * the highest ‘route-metric’ is taken. If more matches are
+ * still available, the first item is chosen.
+ *
+ * Populating All available APNs:
+ * All Possible APNs for the given sim are populated the following
+ * way (A list of all the following avoiding duplicates)
+ * 1. The above mentioned “Default Access Point Settings Logic”
+ * 2. Get All saved Network Manager connections with the
+ * provided MCCMNC of the given SIM
+ * 3. Get All possible APNs for the MCCMNC from mobile-provider-info
+ *
+ * Testing if data is enabled:
+ * Check if any of the items from step 1 have ‘autoconnect’ set
+ *
+ * Checking/Setting current SIM for data (in case of multiple SIM):
+ * Since other networks (like wifi, ethernet) should have higher
+ * priorities we use a negative number for priority.
+ * 1. All APNs by default have priority CC_WWAN_APN_PRIORITY_LOW
+ * 2. APN of selected SIM for active data have priority of
+ * CC_WWAN_APN_PRIORITY_HIGH
+ *
+ * XXX: Since users may create custom APNs via nmtui or like tools
+ * we may have to check if there are some inconsistencies with APNs
+ * available in NetworkManager, and ask user if they have to reset
+ * the APNs that have invalid settings (basically, we care only APNs
+ * that are set to have ‘autoconnect’ enabled, and all we need is to
+ * disable autoconnect). We won’t interfere CDMA/EVDO networks.
+ */
+struct _CcWwanDataApn {
+ GObject parent_instance;
+
+ /* Set if the APN is from the mobile-provider-info database */
+ NMAMobileAccessMethod *access_method;
+
+ /* Set if the APN is saved in NetworkManager */
+ NMConnection *nm_connection;
+ NMRemoteConnection *remote_connection;
+
+ gboolean modified;
+};
+
+G_DEFINE_TYPE (CcWwanDataApn, cc_wwan_data_apn, G_TYPE_OBJECT)
+
+enum {
+ PROP_0,
+ PROP_ERROR,
+ PROP_ENABLED,
+ N_PROPS
+};
+
+static GParamSpec *properties[N_PROPS];
+
+static void
+wwan_data_apn_reset (CcWwanDataApn *apn)
+{
+ if (!apn)
+ return;
+
+ g_clear_object (&apn->nm_connection);
+ g_clear_object (&apn->remote_connection);
+}
+
+static NMConnection *
+wwan_data_get_nm_connection (CcWwanDataApn *apn)
+{
+ NMConnection *connection;
+ NMSetting *setting;
+ g_autofree gchar *uuid = NULL;
+
+ if (apn->nm_connection)
+ return apn->nm_connection;
+
+ if (apn->remote_connection)
+ return NM_CONNECTION (apn->remote_connection);
+
+ connection = nm_simple_connection_new ();
+ apn->nm_connection = connection;
+
+ setting = nm_setting_connection_new ();
+ uuid = nm_utils_uuid_generate ();
+ g_object_set (setting,
+ NM_SETTING_CONNECTION_UUID, uuid,
+ NM_SETTING_CONNECTION_TYPE, NM_SETTING_GSM_SETTING_NAME,
+ NULL);
+ nm_connection_add_setting (connection, setting);
+
+ setting = nm_setting_serial_new ();
+ nm_connection_add_setting (connection, setting);
+
+ setting = nm_setting_ip4_config_new ();
+ g_object_set (setting, NM_SETTING_IP_CONFIG_METHOD, "auto", NULL);
+ nm_connection_add_setting (connection, setting);
+
+ nm_connection_add_setting (connection, nm_setting_gsm_new ());
+ nm_connection_add_setting (connection, nm_setting_ppp_new ());
+
+ return apn->nm_connection;
+}
+
+static gboolean
+wwan_data_apn_are_same (CcWwanDataApn *apn,
+ NMAMobileAccessMethod *access_method)
+{
+ NMConnection *connection;
+ NMSetting *setting;
+
+ if (!apn->remote_connection)
+ return FALSE;
+
+ connection = NM_CONNECTION (apn->remote_connection);
+ setting = NM_SETTING (nm_connection_get_setting_gsm (connection));
+
+ if (g_strcmp0 (nma_mobile_access_method_get_3gpp_apn (access_method),
+ nm_setting_gsm_get_apn (NM_SETTING_GSM (setting))) != 0)
+ return FALSE;
+
+ if (g_strcmp0 (nma_mobile_access_method_get_username (access_method),
+ nm_setting_gsm_get_username (NM_SETTING_GSM (setting))) != 0)
+ return FALSE;
+
+ if (g_strcmp0 (nma_mobile_access_method_get_password (access_method),
+ cc_wwan_data_apn_get_password (apn)) != 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+static CcWwanDataApn *
+wwan_data_find_matching_apn (CcWwanData *self,
+ NMAMobileAccessMethod *access_method)
+{
+ CcWwanDataApn *apn;
+ guint i, n_items;
+
+ n_items = g_list_model_get_n_items (G_LIST_MODEL (self->apn_list));
+
+ for (i = 0; i < n_items; i++)
+ {
+ apn = g_list_model_get_item (G_LIST_MODEL (self->apn_list), i);
+
+ if (apn->access_method == access_method)
+ return apn;
+
+ if (wwan_data_apn_are_same (apn, access_method))
+ return apn;
+
+ g_object_unref (apn);
+ }
+
+ return NULL;
+}
+
+static gboolean
+wwan_data_nma_method_is_mms (NMAMobileAccessMethod *method)
+{
+ const char *str;
+
+ str = nma_mobile_access_method_get_3gpp_apn (method);
+ if (str && strcasestr (str, "mms"))
+ return TRUE;
+
+ str = nma_mobile_access_method_get_name (method);
+ if (str && strcasestr (str, "mms"))
+ return TRUE;
+
+ return FALSE;
+}
+
+static void
+wwan_data_update_apn_list_db (CcWwanData *self)
+{
+ GSList *apn_methods = NULL, *l;
+ g_autoptr(GError) error = NULL;
+ guint i = 0;
+
+ if (!self->sim || !self->operator_code || self->apn_list_updated)
+ return;
+
+ if (!self->apn_list)
+ return;
+
+ if (!self->apn_db)
+ self->apn_db = nma_mobile_providers_database_new_sync (NULL, NULL, NULL, &error);
+
+ if (error)
+ {
+ g_warning ("%s", error->message);
+ return;
+ }
+
+ if (!self->apn_provider)
+ self->apn_provider = nma_mobile_providers_database_lookup_3gpp_mcc_mnc (self->apn_db,
+ self->operator_code);
+
+ if (self->apn_provider)
+ apn_methods = nma_mobile_provider_get_methods (self->apn_provider);
+
+ self->apn_list_updated = TRUE;
+
+ for (l = apn_methods; l; l = l->next, i++)
+ {
+ g_autoptr(CcWwanDataApn) apn = NULL;
+
+ /* We don’t list MMS APNs */
+ if (wwan_data_nma_method_is_mms (l->data))
+ continue;
+
+ apn = wwan_data_find_matching_apn (self, l->data);
+
+ /* Prepend the item in order */
+ if (!apn)
+ {
+ apn = cc_wwan_data_apn_new ();
+ apn->access_method = l->data;
+ g_list_store_insert (self->apn_list, i, apn);
+ }
+
+ apn->access_method = l->data;
+ }
+}
+
+static void
+wwan_data_update_apn_list (CcWwanData *self)
+{
+ const GPtrArray *nm_connections;
+ guint i;
+
+ if (self->apn_list || !self->sim || !self->nm_device ||
+ nm_device_get_state (self->nm_device) <= NM_DEVICE_STATE_UNAVAILABLE)
+ return;
+
+ if (!self->apn_list)
+ self->apn_list = g_list_store_new (CC_TYPE_WWAN_DATA_APN);
+
+ if (self->nm_device)
+ {
+ nm_connections = nm_device_get_available_connections (self->nm_device);
+
+ for (i = 0; i < nm_connections->len; i++)
+ {
+ g_autoptr(CcWwanDataApn) apn = NULL;
+
+ apn = cc_wwan_data_apn_new ();
+ apn->remote_connection = g_object_ref (nm_connections->pdata[i]);
+ g_list_store_append (self->apn_list, apn);
+
+ /* Load the default APN */
+ if (!self->default_apn && self->sim_id)
+ {
+ NMSettingConnection *connection_setting;
+ NMSettingIPConfig *ip_setting;
+ NMSettingGsm *setting;
+ NMConnection *connection;
+ const gchar *sim_id;
+
+ connection = NM_CONNECTION (apn->remote_connection);
+ setting = nm_connection_get_setting_gsm (connection);
+ connection_setting = nm_connection_get_setting_connection (connection);
+ sim_id = nm_setting_gsm_get_sim_id (setting);
+
+ if (sim_id && *sim_id && g_str_equal (sim_id, self->sim_id))
+ {
+ self->default_apn = apn;
+ self->home_only = nm_setting_gsm_get_home_only (setting);
+ self->data_enabled = nm_setting_connection_get_autoconnect (connection_setting);
+
+ /* If any of the APN has a high priority, the device have high priority */
+ ip_setting = nm_connection_get_setting_ip4_config (connection);
+ if (nm_setting_ip_config_get_route_metric (ip_setting) == CC_WWAN_ROUTE_PRIORITY_HIGH)
+ self->priority = CC_WWAN_APN_PRIORITY_HIGH;
+ }
+ }
+ }
+ }
+}
+
+static void
+wwan_device_state_changed_cb (CcWwanData *self)
+{
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ENABLED]);
+}
+
+static void
+wwan_device_3gpp_operator_code_changd_cb (CcWwanData *self)
+{
+ MMModem3gpp *modem_3gpp;
+
+ modem_3gpp = mm_object_peek_modem_3gpp (self->mm_object);
+
+ if (!self->operator_code)
+ {
+ self->operator_code = mm_modem_3gpp_dup_operator_code (modem_3gpp);
+
+ if (self->operator_code)
+ {
+ wwan_data_update_apn_list (self);
+ wwan_data_update_apn_list_db (self);
+ }
+ }
+}
+
+static void
+cc_wwan_data_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcWwanData *self = (CcWwanData *)object;
+
+ switch (prop_id)
+ {
+ case PROP_ERROR:
+ g_value_set_boolean (value, self->error != NULL);
+ break;
+
+ case PROP_ENABLED:
+ g_value_set_boolean (value, cc_wwan_data_get_enabled (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_wwan_data_dispose (GObject *object)
+{
+ CcWwanData *self = (CcWwanData *)object;
+
+ g_clear_pointer (&self->sim_id, g_free);
+ g_clear_pointer (&self->operator_code, g_free);
+ g_clear_error (&self->error);
+ g_clear_object (&self->apn_list);
+ g_clear_object (&self->modem);
+ g_clear_object (&self->mm_object);
+ g_clear_object (&self->nm_client);
+ g_clear_object (&self->active_connection);
+ g_clear_object (&self->apn_db);
+
+ G_OBJECT_CLASS (cc_wwan_data_parent_class)->dispose (object);
+}
+
+static void
+cc_wwan_data_class_init (CcWwanDataClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = cc_wwan_data_get_property;
+ object_class->dispose = cc_wwan_data_dispose;
+
+ properties[PROP_ERROR] =
+ g_param_spec_boolean ("error",
+ "Error",
+ "Set if some Error occurs",
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_ENABLED] =
+ g_param_spec_boolean ("enabled",
+ "Enabled",
+ "Get if the data is enabled",
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+cc_wwan_data_init (CcWwanData *self)
+{
+ self->home_only = TRUE;
+ self->priority = CC_WWAN_APN_PRIORITY_LOW;
+}
+
+/**
+ * cc_wwan_data_new:
+ * @mm_object: An #MMObject
+ * @nm_client: An #NMClient
+ *
+ * Create a new device data representing the given
+ * @mm_object. If @mm_object isn’t a 3G/CDMA/LTE
+ * modem, %NULL will be returned
+ *
+ * Returns: A #CcWwanData or %NULL.
+ */
+CcWwanData *
+cc_wwan_data_new (MMObject *mm_object,
+ NMClient *nm_client)
+{
+ CcWwanData *self;
+ NMDevice *nm_device = NULL;
+ g_autoptr(MMModem) modem = NULL;
+ NMDeviceModemCapabilities capabilities = 0;
+
+ g_return_val_if_fail (MM_IS_OBJECT (mm_object), NULL);
+ g_return_val_if_fail (NM_CLIENT (nm_client), NULL);
+
+ modem = mm_object_get_modem (mm_object);
+
+ if (modem)
+ nm_device = nm_client_get_device_by_iface (nm_client,
+ mm_modem_get_primary_port (modem));
+
+ if (NM_IS_DEVICE_MODEM (nm_device))
+ capabilities = nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (nm_device));
+
+ if (!(capabilities & (NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS
+ | NM_DEVICE_MODEM_CAPABILITY_LTE)))
+ return NULL;
+
+ self = g_object_new (CC_TYPE_WWAN_DATA, NULL);
+
+ self->nm_client = g_object_ref (nm_client);
+ self->mm_object = g_object_ref (mm_object);
+ self->modem = g_steal_pointer (&modem);
+ self->sim = mm_modem_get_sim_sync (self->modem, NULL, NULL);
+ self->sim_id = mm_sim_dup_identifier (self->sim);
+ self->operator_code = mm_sim_dup_operator_identifier (self->sim);
+ self->nm_device = g_object_ref (nm_device);
+ self->active_connection = nm_device_get_active_connection (nm_device);
+
+ if (!self->operator_code)
+ {
+ MMModem3gpp *modem_3gpp;
+
+ modem_3gpp = mm_object_peek_modem_3gpp (mm_object);
+ if (modem_3gpp)
+ {
+ g_signal_connect_object (modem_3gpp, "notify::operator-code",
+ G_CALLBACK (wwan_device_3gpp_operator_code_changd_cb),
+ self, G_CONNECT_SWAPPED);
+ wwan_device_3gpp_operator_code_changd_cb (self);
+ }
+ }
+
+ if (self->active_connection)
+ g_object_ref (self->active_connection);
+
+ g_signal_connect_object (self->nm_device, "notify::state",
+ G_CALLBACK (wwan_device_state_changed_cb),
+ self, G_CONNECT_SWAPPED);
+
+ wwan_data_update_apn_list (self);
+ wwan_data_update_apn_list_db (self);
+
+ return self;
+}
+
+GError *
+cc_wwan_data_get_error (CcWwanData *self)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DATA (self), NULL);
+
+ return self->error;
+}
+
+const gchar *
+cc_wwan_data_get_simple_html_error (CcWwanData *self)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DATA (self), NULL);
+
+ if (!self->error)
+ return NULL;
+
+ if (g_error_matches (self->error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return _("Operation Cancelled");
+
+ if (g_error_matches (self->error, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED))
+ return _("<b>Error:</b> Access denied changing settings");
+
+ if (self->error->domain == MM_MOBILE_EQUIPMENT_ERROR)
+ return _("<b>Error:</b> Mobile Equipment Error");
+
+ return NULL;
+}
+
+GListModel *
+cc_wwan_data_get_apn_list (CcWwanData *self)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DATA (self), NULL);
+
+ if (!self->apn_list)
+ wwan_data_update_apn_list (self);
+
+ return G_LIST_MODEL (self->apn_list);
+}
+
+static gboolean
+wwan_data_apn_is_new (CcWwanDataApn *apn)
+{
+ return apn->remote_connection == NULL;
+}
+
+static void
+wwan_data_update_apn (CcWwanData *self,
+ CcWwanDataApn *apn,
+ NMConnection *connection)
+{
+ NMSetting *setting;
+ const gchar *name, *username, *password, *apn_name;
+ gint dns_priority, route_metric;
+
+ setting = NM_SETTING (nm_connection_get_setting_connection (connection));
+
+ g_object_set (setting,
+ NM_SETTING_CONNECTION_AUTOCONNECT, self->data_enabled,
+ NULL);
+
+ setting = NM_SETTING (nm_connection_get_setting_gsm (connection));
+
+ g_object_set (setting,
+ NM_SETTING_GSM_HOME_ONLY, self->home_only,
+ NULL);
+
+ setting = NM_SETTING (nm_connection_get_setting_ip4_config (connection));
+ if (self->priority == CC_WWAN_APN_PRIORITY_HIGH &&
+ self->default_apn == apn)
+ {
+ dns_priority = CC_WWAN_DNS_PRIORITY_HIGH;
+ route_metric = CC_WWAN_ROUTE_PRIORITY_HIGH;
+ }
+ else
+ {
+ dns_priority = CC_WWAN_DNS_PRIORITY_LOW;
+ route_metric = CC_WWAN_ROUTE_PRIORITY_LOW;
+ }
+
+ g_object_set (setting,
+ NM_SETTING_IP_CONFIG_DNS_PRIORITY, dns_priority,
+ NM_SETTING_IP_CONFIG_ROUTE_METRIC, (gint64)route_metric,
+ NULL);
+
+ if (apn->access_method && !apn->remote_connection)
+ {
+ name = nma_mobile_access_method_get_name (apn->access_method);
+ username = nma_mobile_access_method_get_username (apn->access_method);
+ password = nma_mobile_access_method_get_password (apn->access_method);
+ apn_name = nma_mobile_access_method_get_3gpp_apn (apn->access_method);
+ }
+ else
+ {
+ return;
+ }
+
+ setting = NM_SETTING (nm_connection_get_setting_gsm (connection));
+ g_object_set (setting,
+ NM_SETTING_GSM_USERNAME, username,
+ NM_SETTING_GSM_PASSWORD, password,
+ NM_SETTING_GSM_APN, apn_name,
+ NULL);
+
+ setting = NM_SETTING (nm_connection_get_setting_connection (connection));
+
+ g_object_set (setting,
+ NM_SETTING_CONNECTION_ID, name,
+ NULL);
+}
+
+static gint
+wwan_data_get_apn_index (CcWwanData *self,
+ CcWwanDataApn *apn)
+{
+ GListModel *model;
+ guint i, n_items;
+
+ model = G_LIST_MODEL (self->apn_list);
+ n_items = g_list_model_get_n_items (model);
+
+ for (i = 0; i < n_items; i++)
+ {
+ g_autoptr(CcWwanDataApn) cached_apn = NULL;
+
+ cached_apn = g_list_model_get_item (model, i);
+
+ if (apn == cached_apn)
+ return i;
+ }
+
+ return -1;
+}
+
+static void
+cc_wwan_data_connection_updated_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ CcWwanData *self;
+ CcWwanDataApn *apn;
+ g_autoptr(GTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+
+ self = g_task_get_source_object (G_TASK (task));
+ apn = g_task_get_task_data (G_TASK (task));
+
+ nm_remote_connection_commit_changes_finish (apn->remote_connection,
+ result, &error);
+ if (!error)
+ {
+ guint apn_index;
+ apn_index = wwan_data_get_apn_index (self, apn);
+
+ if (apn_index >= 0)
+ g_list_model_items_changed (G_LIST_MODEL (self->apn_list),
+ apn_index, 1, 1);
+ else
+ g_warning ("APN ‘%s’ not in APN list",
+ cc_wwan_data_apn_get_name (apn));
+
+ apn->modified = FALSE;
+ g_task_return_boolean (task, TRUE);
+ }
+ else
+ {
+ g_task_return_error (task, g_steal_pointer (&error));
+ }
+}
+
+static void
+cc_wwan_data_new_connection_added_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ CcWwanData *self;
+ CcWwanDataApn *apn;
+ g_autoptr(GTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+
+ self = g_task_get_source_object (G_TASK (task));
+ apn = g_task_get_task_data (G_TASK (task));
+ apn->remote_connection = nm_client_add_connection_finish (self->nm_client,
+ result, &error);
+ if (!error)
+ {
+ apn->modified = FALSE;
+
+ /* If APN has access method, it’s already on the list */
+ if (!apn->access_method)
+ {
+ g_list_store_append (self->apn_list, apn);
+ g_object_unref (apn);
+ }
+
+ g_task_return_pointer (task, apn, NULL);
+ }
+ else
+ {
+ g_task_return_error (task, g_steal_pointer (&error));
+ }
+}
+
+void
+cc_wwan_data_save_apn (CcWwanData *self,
+ CcWwanDataApn *apn,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ NMConnection *connection = NULL;
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (CC_IS_WWAN_DATA (self));
+ g_return_if_fail (CC_IS_WWAN_DATA_APN (apn));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_task_data (task, apn, NULL);
+
+ connection = wwan_data_get_nm_connection (apn);
+
+ /* If the item has a remote connection, it should already be saved.
+ * We should save it again only if it got modified */
+ if (apn->remote_connection && !apn->modified)
+ {
+ g_task_return_pointer (task, apn, NULL);
+ return;
+ }
+
+ wwan_data_update_apn (self, apn, connection);
+ if (wwan_data_apn_is_new (apn))
+ {
+ nm_client_add_connection_async (self->nm_client, apn->nm_connection,
+ TRUE, cancellable,
+ cc_wwan_data_new_connection_added_cb,
+ g_steal_pointer (&task));
+ }
+ else
+ {
+ nm_remote_connection_commit_changes_async (apn->remote_connection, TRUE,
+ cancellable,
+ cc_wwan_data_connection_updated_cb,
+ g_steal_pointer (&task));
+ }
+}
+
+CcWwanDataApn *
+cc_wwan_data_save_apn_finish (CcWwanData *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DATA (self), NULL);
+ g_return_val_if_fail (G_IS_TASK (result), NULL);
+
+ return g_task_propagate_pointer (G_TASK (result), error);
+}
+
+static void
+cc_wwan_data_activated_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ CcWwanData *self;
+ NMActiveConnection *connection;
+ g_autoptr(GTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+
+ self = g_task_get_source_object (G_TASK (task));
+ connection = nm_client_activate_connection_finish (self->nm_client,
+ result, &error);
+ if (connection)
+ {
+ g_set_object (&self->active_connection, connection);
+ g_task_return_boolean (task, TRUE);
+ }
+ else
+ {
+ g_task_return_error (task, g_steal_pointer (&error));
+ }
+
+ if (error)
+ g_warning ("Error: %s", error->message);
+}
+
+static void
+cc_wwan_data_disconnect_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ CcWwanData *self;
+ g_autoptr(GTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+
+ self = g_task_get_source_object (G_TASK (task));
+ if (nm_device_disconnect_finish (self->nm_device, result, &error))
+ {
+ g_clear_object (&self->active_connection);
+ g_task_return_boolean (task, TRUE);
+ }
+ else
+ {
+ g_task_return_error (task, g_steal_pointer (&error));
+ }
+
+ if (error)
+ g_warning ("Error: %s", error->message);
+}
+
+static void
+cc_wwan_data_settings_saved_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ CcWwanData *self;
+ GCancellable *cancellable;
+ g_autoptr(GTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+
+ self = g_task_get_source_object (G_TASK (task));
+ cancellable = g_task_get_cancellable (G_TASK (task));
+
+ if (!cc_wwan_data_save_apn_finish (self, result, &error))
+ {
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ self->default_apn->modified = FALSE;
+
+ if (self->data_enabled)
+ {
+ nm_client_activate_connection_async (self->nm_client,
+ NM_CONNECTION (self->default_apn->remote_connection),
+ self->nm_device,
+ NULL, cancellable,
+ cc_wwan_data_activated_cb,
+ g_steal_pointer (&task));
+ }
+ else
+ {
+ nm_device_disconnect_async (self->nm_device,
+ cancellable,
+ cc_wwan_data_disconnect_cb,
+ g_steal_pointer (&task));
+ }
+}
+
+/**
+ * cc_wwan_data_save_settings:
+ * @cancellable: (nullable): a #GCancellable or %NULL
+ * @callback: a #GAsyncReadyCallback, or %NULL
+ * @user_data: closure data for @callback
+ *
+ * Save default settings to disk and apply changes.
+ * If the default APN has data enabled, the data is
+ * activated after the settings are saved.
+ *
+ * It’s a programmer error to call this function without
+ * a default APN set.
+ * Finish with cc_wwan_data_save_settings_finish().
+ */
+void
+cc_wwan_data_save_settings (CcWwanData *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ NMConnection *connection;
+ NMSetting *setting;
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (CC_IS_WWAN_DATA (self));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (self->default_apn != NULL);
+
+ task = g_task_new (self, cancellable, callback, user_data);
+
+ /* Reset old settings to default value */
+ if (self->old_default_apn && self->old_default_apn->remote_connection)
+ {
+ connection = NM_CONNECTION (self->old_default_apn->remote_connection);
+
+ setting = NM_SETTING (nm_connection_get_setting_gsm (connection));
+ g_object_set (G_OBJECT (setting),
+ NM_SETTING_GSM_HOME_ONLY, TRUE,
+ NM_SETTING_GSM_SIM_ID, NULL,
+ NULL);
+
+ setting = NM_SETTING (nm_connection_get_setting_ip4_config (connection));
+ g_object_set (setting,
+ NM_SETTING_IP_CONFIG_DNS_PRIORITY, CC_WWAN_DNS_PRIORITY_LOW,
+ NM_SETTING_IP_CONFIG_ROUTE_METRIC, (gint64)CC_WWAN_ROUTE_PRIORITY_LOW,
+ NULL);
+
+ setting = NM_SETTING (nm_connection_get_setting_connection (connection));
+ g_object_set (G_OBJECT (setting),
+ NM_SETTING_CONNECTION_AUTOCONNECT, FALSE,
+ NULL);
+
+ nm_remote_connection_commit_changes (NM_REMOTE_CONNECTION (connection),
+ TRUE, cancellable, NULL);
+ self->old_default_apn->modified = FALSE;
+ self->old_default_apn = NULL;
+ }
+
+ self->default_apn->modified = TRUE;
+ connection = wwan_data_get_nm_connection (self->default_apn);
+
+ setting = NM_SETTING (nm_connection_get_setting_gsm (connection));
+ g_object_set (G_OBJECT (setting),
+ NM_SETTING_GSM_HOME_ONLY, self->home_only,
+ NM_SETTING_GSM_SIM_ID, self->sim_id,
+ NULL);
+
+ cc_wwan_data_save_apn (self, self->default_apn, cancellable,
+ cc_wwan_data_settings_saved_cb,
+ g_steal_pointer (&task));
+}
+
+gboolean
+cc_wwan_data_save_settings_finish (CcWwanData *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DATA (self), FALSE);
+ g_return_val_if_fail (G_IS_TASK (result), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+gboolean
+cc_wwan_data_delete_apn (CcWwanData *self,
+ CcWwanDataApn *apn,
+ GCancellable *cancellable,
+ GError **error)
+{
+ NMRemoteConnection *connection = NULL;
+ gboolean ret = FALSE;
+ gint apn_index;
+
+ g_return_val_if_fail (CC_IS_WWAN_DATA (self), FALSE);
+ g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (CC_IS_WWAN_DATA_APN (apn), FALSE);
+ g_return_val_if_fail (error != NULL, FALSE);
+
+ apn_index = wwan_data_get_apn_index (self, apn);
+ if (apn_index == -1)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
+ "APN not found for the connection");
+ return FALSE;
+ }
+
+ connection = g_steal_pointer (&apn->remote_connection);
+ wwan_data_apn_reset (apn);
+
+ if (connection)
+ ret = nm_remote_connection_delete (connection, cancellable, error);
+
+ if (!ret)
+ {
+ apn->remote_connection = connection;
+ *error = g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Deleting APN from NetworkManager failed");
+ return ret;
+ }
+
+ g_object_unref (connection);
+
+ /* We remove the item only if it's not in the mobile provider database */
+ if (!apn->access_method)
+ {
+ if (self->default_apn == apn)
+ self->default_apn = NULL;
+
+ g_list_store_remove (self->apn_list, apn_index);
+
+ return TRUE;
+ }
+
+ *error = g_error_new (G_IO_ERROR, G_IO_ERROR_READ_ONLY,
+ "Deleting APN from NetworkManager failed");
+ return FALSE;
+}
+
+CcWwanDataApn *
+cc_wwan_data_get_default_apn (CcWwanData *self)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DATA (self), NULL);
+
+ return self->default_apn;
+}
+
+gboolean
+cc_wwan_data_set_default_apn (CcWwanData *self,
+ CcWwanDataApn *apn)
+{
+ NMConnection *connection;
+ NMSetting *setting;
+
+ g_return_val_if_fail (CC_IS_WWAN_DATA (self), FALSE);
+ g_return_val_if_fail (CC_IS_WWAN_DATA_APN (apn), FALSE);
+
+ if (self->default_apn == apn)
+ return FALSE;
+
+ /*
+ * APNs are bound to the SIM, not the modem device.
+ * This will let the APN work if the same SIM inserted
+ * in a different device, and not enable data if a
+ * different SIM is inserted to the modem.
+ */
+ apn->modified = TRUE;
+ self->old_default_apn = self->default_apn;
+ self->default_apn = apn;
+ connection = wwan_data_get_nm_connection (apn);
+ setting = NM_SETTING (nm_connection_get_setting_gsm (connection));
+
+ if (self->sim_id)
+ g_object_set (G_OBJECT (setting),
+ NM_SETTING_GSM_SIM_ID, self->sim_id, NULL);
+
+ return TRUE;
+}
+
+gboolean
+cc_wwan_data_get_enabled (CcWwanData *self)
+{
+ NMSettingConnection *setting;
+ NMConnection *connection;
+ NMDeviceState state;
+
+ g_return_val_if_fail (CC_IS_WWAN_DATA (self), FALSE);
+
+ state = nm_device_get_state (self->nm_device);
+
+ if (state == NM_DEVICE_STATE_DISCONNECTED ||
+ state == NM_DEVICE_STATE_DEACTIVATING)
+ if (nm_device_get_state_reason (self->nm_device) == NM_DEVICE_STATE_REASON_USER_REQUESTED)
+ return FALSE;
+
+ if (nm_device_get_active_connection (self->nm_device) != NULL)
+ return TRUE;
+
+ if (!self->default_apn || !self->default_apn->remote_connection)
+ return FALSE;
+
+ connection = NM_CONNECTION (self->default_apn->remote_connection);
+ setting = nm_connection_get_setting_connection (connection);
+
+ return nm_setting_connection_get_autoconnect (setting);
+}
+
+/**
+ * cc_wwan_data_set_enabled:
+ * @self: A #CcWwanData
+ * @enable_data: whether to enable data
+ *
+ * Enable data for the device. The settings is
+ * saved to disk only after a default APN is set.
+ *
+ * If the data is enabled, the device will automatically
+ * turn data on everytime the same SIM is available.
+ * The data set is bound to the SIM, not the modem device.
+ *
+ * Use @cc_wwan_data_save_apn() with the default APN
+ * to save the changes and really enable/disable data.
+ */
+void
+cc_wwan_data_set_enabled (CcWwanData *self,
+ gboolean enable_data)
+{
+ g_return_if_fail (CC_IS_WWAN_DATA (self));
+
+ self->data_enabled = !!enable_data;
+
+ if (self->default_apn)
+ self->default_apn->modified = TRUE;
+}
+
+gboolean
+cc_wwan_data_get_roaming_enabled (CcWwanData *self)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DATA (self), FALSE);
+
+ if (!self->default_apn)
+ return FALSE;
+
+ return !self->home_only;
+}
+
+/**
+ * cc_wwan_data_apn_set_roaming_enabled:
+ * @self: A #CcWwanData
+ * @enable_roaming: whether to enable roaming or not
+ *
+ * Enable roaming for the device. The settings is
+ * saved to disk only after a default APN is set.
+ *
+ * Use @cc_wwan_data_save_apn() with the default APN
+ * to save the changes and really enable/disable data.
+ */
+void
+cc_wwan_data_set_roaming_enabled (CcWwanData *self,
+ gboolean enable_roaming)
+{
+ g_return_if_fail (CC_IS_WWAN_DATA (self));
+
+ self->home_only = !enable_roaming;
+
+ if (self->default_apn)
+ self->default_apn->modified = TRUE;
+}
+
+static void
+cc_wwan_data_apn_finalize (GObject *object)
+{
+ CcWwanDataApn *apn = CC_WWAN_DATA_APN (object);
+
+ wwan_data_apn_reset (apn);
+ g_clear_pointer (&apn->access_method,
+ nma_mobile_access_method_unref);
+
+ G_OBJECT_CLASS (cc_wwan_data_parent_class)->finalize (object);
+}
+
+static void
+cc_wwan_data_apn_class_init (CcWwanDataApnClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = cc_wwan_data_apn_finalize;
+}
+
+static void
+cc_wwan_data_apn_init (CcWwanDataApn *apn)
+{
+}
+
+CcWwanDataApn *
+cc_wwan_data_apn_new (void)
+{
+ return g_object_new (CC_TYPE_WWAN_DATA_APN, NULL);
+}
+
+/**
+ * cc_wwan_data_apn_get_name:
+ * @apn: A #CcWwanDataApn
+ *
+ * Get the Name of @apn
+ *
+ * Returns: (transfer none): The Name of @apn
+ */
+const gchar *
+cc_wwan_data_apn_get_name (CcWwanDataApn *apn)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DATA_APN (apn), "");
+
+ if (apn->remote_connection)
+ return nm_connection_get_id (NM_CONNECTION (apn->remote_connection));
+
+ if (apn->access_method)
+ return nma_mobile_access_method_get_name (apn->access_method);
+
+ return "";
+}
+
+/**
+ * cc_wwan_data_apn_set_name:
+ * @apn: A #CcWwanDataApn
+ * @name: The name to be given for APN, should not
+ * be empty
+ *
+ * Set the name of @apn to be @name.
+ *
+ * @apn is only modified, use @cc_wwan_data_save_apn()
+ * to save the changes.
+ */
+void
+cc_wwan_data_apn_set_name (CcWwanDataApn *apn,
+ const gchar *name)
+{
+ NMConnection *connection;
+ NMSettingConnection *setting;
+
+ g_return_if_fail (CC_IS_WWAN_DATA_APN (apn));
+ g_return_if_fail (name != NULL);
+ g_return_if_fail (*name != '\0');
+
+ if (g_str_equal (cc_wwan_data_apn_get_name (apn), name))
+ return;
+
+ apn->modified = TRUE;
+ connection = wwan_data_get_nm_connection (apn);
+ setting = nm_connection_get_setting_connection (connection);
+ g_object_set (G_OBJECT (setting),
+ NM_SETTING_CONNECTION_ID, name,
+ NULL);
+}
+
+/**
+ * cc_wwan_data_apn_get_apn:
+ * @apn: A #CcWwanDataApn
+ *
+ * Get the APN of @apn
+ *
+ * Returns: (transfer none): The APN of @apn
+ */
+const gchar *
+cc_wwan_data_apn_get_apn (CcWwanDataApn *apn)
+{
+ const gchar *apn_name = "";
+
+ g_return_val_if_fail (CC_IS_WWAN_DATA_APN (apn), "");
+
+ if (apn->remote_connection)
+ {
+ NMSettingGsm *setting;
+
+ setting = nm_connection_get_setting_gsm (NM_CONNECTION (apn->remote_connection));
+ apn_name = nm_setting_gsm_get_apn (setting);
+ }
+ else if (apn->access_method)
+ {
+ apn_name = nma_mobile_access_method_get_3gpp_apn (apn->access_method);
+ }
+
+ return apn_name ? apn_name : "";
+}
+
+/**
+ * cc_wwan_data_apn_set_apn:
+ * @apn: A #CcWwanDataApn
+ * @apn_name: The apn to be used, should not be
+ * empty
+ *
+ * Set the APN of @apn to @apn_name. @apn_name is
+ * usually a URL like “example.com” or a simple string
+ * like “internet”
+ *
+ * @apn is only modified, use @cc_wwan_data_save_apn()
+ * to save the changes.
+ */
+void
+cc_wwan_data_apn_set_apn (CcWwanDataApn *apn,
+ const gchar *apn_name)
+{
+ NMConnection *connection;
+ NMSettingGsm *setting;
+
+ g_return_if_fail (CC_IS_WWAN_DATA_APN (apn));
+ g_return_if_fail (apn_name != NULL);
+ g_return_if_fail (*apn_name != '\0');
+
+ if (g_str_equal (cc_wwan_data_apn_get_apn (apn), apn_name))
+ return;
+
+ apn->modified = TRUE;
+ connection = wwan_data_get_nm_connection (apn);
+ setting = nm_connection_get_setting_gsm (connection);
+ g_object_set (G_OBJECT (setting),
+ NM_SETTING_GSM_APN, apn_name,
+ NULL);
+}
+
+/**
+ * cc_wwan_data_apn_get_username:
+ * @apn: A #CcWwanDataApn
+ *
+ * Get the Username of @apn
+ *
+ * Returns: (transfer none): The Username of @apn
+ */
+const gchar *
+cc_wwan_data_apn_get_username (CcWwanDataApn *apn)
+{
+ const gchar *username = "";
+
+ g_return_val_if_fail (CC_IS_WWAN_DATA_APN (apn), "");
+
+ if (apn->remote_connection)
+ {
+ NMSettingGsm *setting;
+
+ setting = nm_connection_get_setting_gsm (NM_CONNECTION (apn->remote_connection));
+ username = nm_setting_gsm_get_username (setting);
+ }
+ else if (apn->access_method)
+ {
+ username = nma_mobile_access_method_get_username (apn->access_method);
+ }
+
+ return username ? username : "";
+}
+
+/**
+ * cc_wwan_data_apn_set_username:
+ * @apn: A #CcWwanDataAPN
+ * @username: The username to be used
+ *
+ * Set the Username of @apn to @username.
+ *
+ * @apn is only modified, use @cc_wwan_data_save_apn()
+ * to save the changes.
+ */
+void
+cc_wwan_data_apn_set_username (CcWwanDataApn *apn,
+ const gchar *username)
+{
+ NMConnection *connection;
+ NMSettingGsm *setting;
+
+ g_return_if_fail (CC_IS_WWAN_DATA_APN (apn));
+
+ if (username && !*username)
+ username = NULL;
+
+ if (g_strcmp0 (cc_wwan_data_apn_get_username (apn), username) == 0)
+ return;
+
+ apn->modified = TRUE;
+ connection = wwan_data_get_nm_connection (apn);
+ setting = nm_connection_get_setting_gsm (connection);
+ g_object_set (G_OBJECT (setting),
+ NM_SETTING_GSM_USERNAME, username,
+ NULL);
+}
+
+/**
+ * cc_wwan_data_apn_get_password:
+ * @apn: A #CcWwanDataApn
+ *
+ * Get the Password of @apn
+ *
+ * Returns: (transfer none): The Password of @apn
+ */
+const gchar *
+cc_wwan_data_apn_get_password (CcWwanDataApn *apn)
+{
+ const gchar *password = "";
+
+ g_return_val_if_fail (CC_IS_WWAN_DATA_APN (apn), "");
+
+ if (NM_IS_REMOTE_CONNECTION (apn->remote_connection))
+ {
+ g_autoptr(GVariant) secrets = NULL;
+ g_autoptr(GError) error = NULL;
+
+ secrets = nm_remote_connection_get_secrets (NM_REMOTE_CONNECTION (apn->remote_connection),
+ "gsm", NULL, &error);
+
+ if (!error)
+ nm_connection_update_secrets (NM_CONNECTION (apn->remote_connection),
+ "gsm", secrets, &error);
+
+ if (error)
+ {
+ g_warning ("Error: %s", error->message);
+ return "";
+ }
+ }
+
+ if (apn->remote_connection)
+ {
+ NMSettingGsm *setting;
+
+ setting = nm_connection_get_setting_gsm (NM_CONNECTION (apn->remote_connection));
+ password = nm_setting_gsm_get_password (setting);
+ }
+ else if (apn->access_method)
+ {
+ password = nma_mobile_access_method_get_password (apn->access_method);
+ }
+
+ return password ? password : "";
+}
+
+/**
+ * cc_wwan_data_apn_set_password:
+ * @apn: A #CcWwanDataApn
+ * @password: The password to be used
+ *
+ * Set the Password of @apn to @password.
+ *
+ * @apn is only modified, use @cc_wwan_data_save_apn()
+ * to save the changes.
+ */
+void
+cc_wwan_data_apn_set_password (CcWwanDataApn *apn,
+ const gchar *password)
+{
+ NMConnection *connection;
+ NMSettingGsm *setting;
+
+ g_return_if_fail (CC_IS_WWAN_DATA_APN (apn));
+
+ if (password && !*password)
+ password = NULL;
+
+ if (g_strcmp0 (cc_wwan_data_apn_get_password (apn), password) == 0)
+ return;
+
+ apn->modified = TRUE;
+ connection = wwan_data_get_nm_connection (apn);
+ setting = nm_connection_get_setting_gsm (connection);
+ g_object_set (G_OBJECT (setting),
+ NM_SETTING_GSM_PASSWORD, password,
+ NULL);
+}
+
+gint
+cc_wwan_data_get_priority (CcWwanData *self)
+{
+ CcWwanDataApn *apn;
+ NMSettingIPConfig *setting;
+
+ g_return_val_if_fail (CC_IS_WWAN_DATA (self),
+ CC_WWAN_APN_PRIORITY_LOW);
+
+ apn = self->default_apn;
+
+ if (!apn || !apn->remote_connection)
+ return CC_WWAN_APN_PRIORITY_LOW;
+
+ setting = nm_connection_get_setting_ip4_config (NM_CONNECTION (apn->remote_connection));
+
+ /* Lower the number, higher the priority */
+ if (nm_setting_ip_config_get_route_metric (setting) <= CC_WWAN_ROUTE_PRIORITY_HIGH)
+ return CC_WWAN_APN_PRIORITY_HIGH;
+ else
+ return CC_WWAN_APN_PRIORITY_LOW;
+}
+
+void
+cc_wwan_data_set_priority (CcWwanData *self,
+ int priority)
+{
+ g_return_if_fail (CC_IS_WWAN_DATA (self));
+ g_return_if_fail (priority == CC_WWAN_APN_PRIORITY_LOW ||
+ priority == CC_WWAN_APN_PRIORITY_HIGH);
+
+ if (self->priority == priority)
+ return;
+
+ self->priority = priority;
+
+ if (self->default_apn)
+ self->default_apn->modified = TRUE;
+}
diff --git a/panels/wwan/cc-wwan-data.h b/panels/wwan/cc-wwan-data.h
new file mode 100644
index 0000000..9572b86
--- /dev/null
+++ b/panels/wwan/cc-wwan-data.h
@@ -0,0 +1,93 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-wwan-data.h
+ *
+ * Copyright 2019 Purism SPC
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <glib-object.h>
+#include <libmm-glib.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+#define CC_WWAN_APN_PRIORITY_LOW (1)
+#define CC_WWAN_APN_PRIORITY_HIGH (2)
+
+#define CC_TYPE_WWAN_DATA_APN (cc_wwan_data_apn_get_type())
+G_DECLARE_FINAL_TYPE (CcWwanDataApn, cc_wwan_data_apn, CC, WWAN_DATA_APN, GObject)
+
+#define CC_TYPE_WWAN_DATA (cc_wwan_data_get_type())
+G_DECLARE_FINAL_TYPE (CcWwanData, cc_wwan_data, CC, WWAN_DATA, GObject)
+
+CcWwanData *cc_wwan_data_new (MMObject *mm_object,
+ NMClient *nm_client);
+GError *cc_wwan_data_get_error (CcWwanData *self);
+const gchar *cc_wwan_data_get_simple_html_error (CcWwanData *self);
+GListModel *cc_wwan_data_get_apn_list (CcWwanData *self);
+void cc_wwan_data_save_apn (CcWwanData *self,
+ CcWwanDataApn *apn,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+CcWwanDataApn *cc_wwan_data_save_apn_finish (CcWwanData *self,
+ GAsyncResult *result,
+ GError **error);
+void cc_wwan_data_save_settings (CcWwanData *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean cc_wwan_data_save_settings_finish (CcWwanData *self,
+ GAsyncResult *result,
+ GError **error);
+gboolean cc_wwan_data_delete_apn (CcWwanData *self,
+ CcWwanDataApn *apn,
+ GCancellable *cancellable,
+ GError **error);
+gboolean cc_wwan_data_set_default_apn (CcWwanData *self,
+ CcWwanDataApn *apn);
+CcWwanDataApn *cc_wwan_data_get_default_apn (CcWwanData *self);
+gboolean cc_wwan_data_get_enabled (CcWwanData *self);
+void cc_wwan_data_set_enabled (CcWwanData *self,
+ gboolean enabled);
+gboolean cc_wwan_data_get_roaming_enabled (CcWwanData *self);
+void cc_wwan_data_set_roaming_enabled (CcWwanData *self,
+ gboolean enable_roaming);
+
+CcWwanDataApn *cc_wwan_data_apn_new (void);
+const gchar *cc_wwan_data_apn_get_name (CcWwanDataApn *apn);
+void cc_wwan_data_apn_set_name (CcWwanDataApn *apn,
+ const gchar *name);
+const gchar *cc_wwan_data_apn_get_apn (CcWwanDataApn *apn);
+void cc_wwan_data_apn_set_apn (CcWwanDataApn *apn,
+ const gchar *apn_name);
+const gchar *cc_wwan_data_apn_get_username (CcWwanDataApn *apn);
+void cc_wwan_data_apn_set_username (CcWwanDataApn *apn,
+ const gchar *username);
+const gchar *cc_wwan_data_apn_get_password (CcWwanDataApn *apn);
+void cc_wwan_data_apn_set_password (CcWwanDataApn *apn,
+ const gchar *password);
+gint cc_wwan_data_get_priority (CcWwanData *self);
+void cc_wwan_data_set_priority (CcWwanData *self,
+ int priority);
+
+G_END_DECLS
diff --git a/panels/wwan/cc-wwan-details-dialog.c b/panels/wwan/cc-wwan-details-dialog.c
new file mode 100644
index 0000000..8f2f27d
--- /dev/null
+++ b/panels/wwan/cc-wwan-details-dialog.c
@@ -0,0 +1,256 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-wwan-network-dialog.c
+ *
+ * Copyright 2019,2022 Purism SPC
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "cc-wwan-details-dialog"
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include <libmm-glib.h>
+
+#include "cc-wwan-details-dialog.h"
+#include "cc-wwan-resources.h"
+
+/**
+ * @short_description: Dialog to Show Device Details
+ */
+
+struct _CcWwanDetailsDialog
+{
+ GtkDialog parent_instance;
+
+ GtkLabel *device_identifier;
+ GtkLabel *device_model;
+ GtkLabel *firmware_version;
+ GtkLabel *identifier_label;
+ GtkLabel *manufacturer;
+ GtkLabel *network_status;
+ GtkLabel *network_type;
+ GtkLabel *operator_name;
+ GtkLabel *own_numbers;
+ GtkLabel *signal_strength;
+
+ CcWwanDevice *device;
+};
+
+G_DEFINE_TYPE (CcWwanDetailsDialog, cc_wwan_details_dialog, GTK_TYPE_DIALOG)
+
+
+enum {
+ PROP_0,
+ PROP_DEVICE,
+ N_PROPS
+};
+
+static GParamSpec *properties[N_PROPS];
+
+static void
+cc_wwan_details_update_network_status (CcWwanDetailsDialog *self)
+{
+ CcWwanState state;
+
+ g_assert (CC_IS_WWAN_DETAILS_DIALOG (self));
+
+ state = cc_wwan_device_get_network_state (self->device);
+
+ switch (state)
+ {
+ case CC_WWAN_REGISTRATION_STATE_IDLE:
+ gtk_label_set_label (self->network_status, _("Not Registered"));
+ break;
+
+ case CC_WWAN_REGISTRATION_STATE_REGISTERED:
+ gtk_label_set_label (self->network_status, _("Registered"));
+ break;
+
+ case CC_WWAN_REGISTRATION_STATE_ROAMING:
+ gtk_label_set_label (self->network_status, _("Roaming"));
+ break;
+
+ case CC_WWAN_REGISTRATION_STATE_SEARCHING:
+ gtk_label_set_label (self->network_status, _("Searching"));
+ break;
+
+ case CC_WWAN_REGISTRATION_STATE_DENIED:
+ gtk_label_set_label (self->network_status, _("Denied"));
+ break;
+
+ default:
+ gtk_label_set_label (self->network_status, _("Unknown"));
+ break;
+ }
+}
+
+static void
+cc_wwan_details_signal_changed_cb (CcWwanDetailsDialog *self)
+{
+ g_autofree gchar *network_type_string = NULL;
+ g_autofree gchar *signal_string = NULL;
+ const gchar *operator_name;
+
+ g_assert (CC_IS_WWAN_DETAILS_DIALOG (self));
+
+ operator_name = cc_wwan_device_get_operator_name (self->device);
+ if (operator_name)
+ gtk_label_set_label (self->operator_name, operator_name);
+
+ network_type_string = cc_wwan_device_dup_network_type_string (self->device);
+ if (network_type_string)
+ gtk_label_set_label (self->network_type, network_type_string);
+
+ signal_string = cc_wwan_device_dup_signal_string (self->device);
+ if (signal_string)
+ gtk_label_set_label (self->signal_strength, signal_string);
+
+ cc_wwan_details_update_network_status (self);
+}
+
+static void
+cc_wwan_details_update_hardware_details (CcWwanDetailsDialog *self)
+{
+ const gchar *str;
+
+ g_assert (CC_IS_WWAN_DETAILS_DIALOG (self));
+
+ str = cc_wwan_device_get_manufacturer (self->device);
+ if (str)
+ gtk_label_set_label (self->manufacturer, str);
+
+ str = cc_wwan_device_get_model (self->device);
+ if (str)
+ gtk_label_set_label (self->device_model, str);
+
+ str = cc_wwan_device_get_firmware_version (self->device);
+ if (str)
+ gtk_label_set_label (self->firmware_version, str);
+
+ str = cc_wwan_device_get_identifier (self->device);
+ if (str)
+ gtk_label_set_label (self->device_identifier, str);
+}
+
+static void
+cc_wwan_details_dialog_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcWwanDetailsDialog *self = CC_WWAN_DETAILS_DIALOG (object);
+
+ switch (prop_id)
+ {
+ case PROP_DEVICE:
+ self->device = g_value_dup_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_wwan_details_dialog_constructed (GObject *object)
+{
+ CcWwanDetailsDialog *self = CC_WWAN_DETAILS_DIALOG (object);
+ g_autofree char *numbers = NULL;
+
+ G_OBJECT_CLASS (cc_wwan_details_dialog_parent_class)->constructed (object);
+
+ g_signal_connect_object (self->device, "notify::signal",
+ G_CALLBACK (cc_wwan_details_signal_changed_cb),
+ self, G_CONNECT_SWAPPED);
+
+ numbers = cc_wwan_device_dup_own_numbers (self->device);
+ gtk_widget_set_visible (GTK_WIDGET (self->own_numbers), !!numbers);
+
+ if (numbers)
+ gtk_label_set_text (self->own_numbers, numbers);
+
+ cc_wwan_details_signal_changed_cb (self);
+ cc_wwan_details_update_hardware_details (self);
+}
+
+static void
+cc_wwan_details_dialog_dispose (GObject *object)
+{
+ CcWwanDetailsDialog *self = CC_WWAN_DETAILS_DIALOG (object);
+
+ g_clear_object (&self->device);
+
+ G_OBJECT_CLASS (cc_wwan_details_dialog_parent_class)->dispose (object);
+}
+
+static void
+cc_wwan_details_dialog_class_init (CcWwanDetailsDialogClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = cc_wwan_details_dialog_set_property;
+ object_class->constructed = cc_wwan_details_dialog_constructed;
+ object_class->dispose = cc_wwan_details_dialog_dispose;
+
+ properties[PROP_DEVICE] =
+ g_param_spec_object ("device",
+ "Device",
+ "The WWAN Device",
+ CC_TYPE_WWAN_DEVICE,
+ G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/control-center/wwan/cc-wwan-details-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcWwanDetailsDialog, device_identifier);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanDetailsDialog, device_model);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanDetailsDialog, firmware_version);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanDetailsDialog, identifier_label);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanDetailsDialog, manufacturer);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanDetailsDialog, network_status);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanDetailsDialog, network_type);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanDetailsDialog, operator_name);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanDetailsDialog, own_numbers);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanDetailsDialog, signal_strength);
+}
+
+static void
+cc_wwan_details_dialog_init (CcWwanDetailsDialog *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+CcWwanDetailsDialog *
+cc_wwan_details_dialog_new (GtkWindow *parent_window,
+ CcWwanDevice *device)
+{
+ g_return_val_if_fail (GTK_IS_WINDOW (parent_window), NULL);
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (device), NULL);
+
+ return g_object_new (CC_TYPE_WWAN_DETAILS_DIALOG,
+ "transient-for", parent_window,
+ "use-header-bar", 1,
+ "device", device,
+ NULL);
+}
diff --git a/panels/wwan/cc-wwan-details-dialog.h b/panels/wwan/cc-wwan-details-dialog.h
new file mode 100644
index 0000000..3144eee
--- /dev/null
+++ b/panels/wwan/cc-wwan-details-dialog.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-wwan-details-dialog.h
+ *
+ * Copyright 2019 Purism SPC
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <adwaita.h>
+#include <shell/cc-panel.h>
+
+#include "cc-wwan-device.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_WWAN_DETAILS_DIALOG (cc_wwan_details_dialog_get_type())
+G_DECLARE_FINAL_TYPE (CcWwanDetailsDialog, cc_wwan_details_dialog, CC, WWAN_DETAILS_DIALOG, GtkDialog)
+
+CcWwanDetailsDialog *cc_wwan_details_dialog_new (GtkWindow *parent_window,
+ CcWwanDevice *device);
+
+G_END_DECLS
diff --git a/panels/wwan/cc-wwan-details-dialog.ui b/panels/wwan/cc-wwan-details-dialog.ui
new file mode 100644
index 0000000..79ae481
--- /dev/null
+++ b/panels/wwan/cc-wwan-details-dialog.ui
@@ -0,0 +1,274 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk" version="4.0"/>
+ <template class="CcWwanDetailsDialog" parent="GtkDialog">
+ <property name="title" translatable="yes">Modem Details</property>
+ <property name="default-height">480</property>
+ <property name="default-width">360</property>
+ <property name="hide-on-close">True</property>
+ <property name="modal">True</property>
+
+ <child>
+ <object class="AdwPreferencesPage">
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Modem Status</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="row-spacing">9</property>
+ <property name="column-spacing">6</property>
+
+ <!-- Carrier -->
+ <child>
+ <object class="GtkLabel" id="carrier_label">
+ <property name="label" translatable="yes">Carrier</property>
+ <property name="xalign">1.0</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="operator_name">
+ <property name="xalign">0.0</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Network Type -->
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Network Type</property>
+ <property name="xalign">1.0</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="network_type">
+ <property name="xalign">0.0</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Signal Strength -->
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Signal Strength</property>
+ <property name="xalign">1.0</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="signal_strength">
+ <property name="xalign">0.0</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Network Status -->
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Network Status</property>
+ <property name="xalign">1.0</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="network_status">
+ <property name="xalign">0.0</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Own Numbers -->
+ <child>
+ <object class="GtkLabel">
+ <property name="visible" bind-source="own_numbers" bind-flags="sync-create"/>
+ <property name="label" translatable="yes">Own Number</property>
+ <property name="xalign">1.0</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">4</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="own_numbers">
+ <property name="xalign">0.0</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">4</property>
+ </layout>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- Device Details Content -->
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Device Details</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="row-spacing">9</property>
+ <property name="column-spacing">6</property>
+
+ <!-- Manufacturer -->
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Manufacturer</property>
+ <property name="xalign">1.0</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="manufacturer">
+ <property name="xalign">0.0</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Model -->
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Model</property>
+ <property name="xalign">1.0</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="device_model">
+ <property name="xalign">0.0</property>
+ <property name="selectable">True</property>
+ <property name="ellipsize">end</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Firmware version -->
+ <child>
+ <object class="GtkLabel" id="firmware_label">
+ <property name="label" translatable="yes">Firmware Version</property>
+ <property name="xalign">1.0</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="firmware_version">
+ <property name="selectable">True</property>
+ <property name="xalign">0.0</property>
+ <property name="ellipsize">end</property>
+ <property name="wrap">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- IMEI/ICCID -->
+ <child>
+ <object class="GtkLabel" id="identifier_label">
+ <property name="label" translatable="yes">IMEI</property>
+ <property name="xalign">1.0</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="device_identifier">
+ <property name="selectable">True</property>
+ <property name="xalign">0.0</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </template>
+ <object class="GtkSizeGroup">
+ <property name="mode">horizontal</property>
+ <widgets>
+ <widget name="carrier_label"/>
+ <widget name="firmware_label"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/panels/wwan/cc-wwan-device-page.c b/panels/wwan/cc-wwan-device-page.c
new file mode 100644
index 0000000..13aa87a
--- /dev/null
+++ b/panels/wwan/cc-wwan-device-page.c
@@ -0,0 +1,650 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-wwan-device-page.c
+ *
+ * Copyright 2019 Purism SPC
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "cc-wwan-device-page"
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include <libmm-glib.h>
+#define GCR_API_SUBJECT_TO_CHANGE
+#include <gcr/gcr-base.h>
+
+#include "cc-list-row.h"
+#include "cc-wwan-data.h"
+#include "cc-wwan-mode-dialog.h"
+#include "cc-wwan-network-dialog.h"
+#include "cc-wwan-details-dialog.h"
+#include "cc-wwan-sim-lock-dialog.h"
+#include "cc-wwan-apn-dialog.h"
+#include "cc-wwan-device-page.h"
+#include "cc-wwan-resources.h"
+
+#include "shell/cc-application.h"
+#include "shell/cc-debug.h"
+#include "shell/cc-object-storage.h"
+
+/**
+ * @short_description: Device settings page
+ * @include: "cc-wwan-device-page.h"
+ *
+ * The Device page allows users to configure device
+ * settings. Please note that there is no one-to-one
+ * maping for a device settings page and a physical
+ * device. Say, if a device have two SIM card slots,
+ * there should be two device pages, one for each SIM.
+ */
+
+struct _CcWwanDevicePage
+{
+ GtkBox parent_instance;
+
+ GtkListBox *advanced_settings_list;
+ CcListRow *apn_settings_row;
+ CcListRow *data_enable_row;
+ CcListRow *data_roaming_row;
+ GtkListBox *data_settings_list;
+ CcListRow *details_row;
+ GtkStack *main_stack;
+ CcListRow *network_mode_row;
+ CcListRow *network_name_row;
+ GtkListBox *network_settings_list;
+ CcListRow *sim_lock_row;
+ GtkButton *unlock_button;
+
+ AdwToastOverlay *toast_overlay;
+
+ CcWwanDevice *device;
+ CcWwanData *wwan_data;
+ GDBusProxy *wwan_proxy;
+
+ CcWwanApnDialog *apn_dialog;
+ CcWwanDetailsDialog *details_dialog;
+ CcWwanModeDialog *network_mode_dialog;
+ CcWwanNetworkDialog *network_dialog;
+ CcWwanSimLockDialog *sim_lock_dialog;
+
+ gint sim_index;
+ /* Set if a change is triggered in a signal’s callback,
+ * to avoid re-triggering of callback. This is used
+ * instead of blocking handlers where the signal may be
+ * emitted async and the block/unblock may not work right
+ */
+ gboolean is_self_change;
+ gboolean is_retry;
+};
+
+G_DEFINE_TYPE (CcWwanDevicePage, cc_wwan_device_page, GTK_TYPE_BOX)
+
+enum {
+ PROP_0,
+ PROP_DEVICE,
+ N_PROPS
+};
+
+static GParamSpec *properties[N_PROPS];
+
+static void
+wwan_device_page_handle_data_row (CcWwanDevicePage *self,
+ CcListRow *data_row)
+{
+ gboolean active;
+
+ /* The user dismissed the dialog for selecting default APN */
+ if (cc_wwan_data_get_default_apn (self->wwan_data) == NULL)
+ {
+ self->is_self_change = TRUE;
+ gtk_widget_activate (GTK_WIDGET (data_row));
+
+ return;
+ }
+
+ active = cc_list_row_get_active (data_row);
+
+ if (data_row == self->data_enable_row)
+ cc_wwan_data_set_enabled (self->wwan_data, active);
+ else
+ cc_wwan_data_set_roaming_enabled (self->wwan_data, active);
+
+ cc_wwan_data_save_settings (self->wwan_data, NULL, NULL, NULL);
+}
+
+static gboolean
+wwan_apn_dialog_closed_cb (CcWwanDevicePage *self)
+{
+ CcListRow *data_row;
+
+ if (gtk_widget_in_destruction (GTK_WIDGET (self)))
+ return FALSE;
+
+ data_row = g_object_get_data (G_OBJECT (self->apn_dialog), "row");
+ g_object_set_data (G_OBJECT (self->apn_dialog), "row", NULL);
+
+ if (data_row)
+ wwan_device_page_handle_data_row (self, data_row);
+
+ return FALSE;
+}
+
+static void
+wwan_data_show_apn_dialog (CcWwanDevicePage *self)
+{
+ GtkWindow *top_level;
+
+ top_level = GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (self)));
+
+ if (!self->apn_dialog)
+ {
+ self->apn_dialog = cc_wwan_apn_dialog_new (top_level, self->device);
+ g_signal_connect_object (self->apn_dialog, "unmap",
+ G_CALLBACK (wwan_apn_dialog_closed_cb),
+ self, G_CONNECT_SWAPPED);
+ }
+
+ gtk_widget_show (GTK_WIDGET (self->apn_dialog));
+}
+
+static GcrPrompt *
+cc_wwan_device_page_new_prompt (CcWwanDevicePage *self,
+ MMModemLock lock)
+{
+ GcrPrompt *prompt;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *description = NULL;
+ g_autofree gchar *warning = NULL;
+ const gchar *message = NULL;
+ guint num;
+
+ prompt = GCR_PROMPT (gcr_system_prompt_open (-1, NULL, &error));
+
+ if (error)
+ {
+ g_warning ("Error opening Prompt: %s", error->message);
+ return NULL;
+ }
+
+ gcr_prompt_set_title (prompt, _("Unlock SIM card"));
+ gcr_prompt_set_continue_label (prompt, _("Unlock"));
+ gcr_prompt_set_cancel_label (prompt, _("Cancel"));
+
+ if (lock == MM_MODEM_LOCK_SIM_PIN)
+ {
+ description = g_strdup_printf (_("Please provide PIN code for SIM %d"), self->sim_index);
+ message = _("Enter PIN to unlock your SIM card");
+ }
+ else if (lock == MM_MODEM_LOCK_SIM_PUK)
+ {
+ description = g_strdup_printf (_("Please provide PUK code for SIM %d"), self->sim_index);
+ message = _("Enter PUK to unlock your SIM card");
+ }
+ else
+ {
+ g_warn_if_reached ();
+ g_object_unref (prompt);
+
+ return NULL;
+ }
+
+ gcr_prompt_set_description (prompt, description);
+ gcr_prompt_set_message (prompt, message);
+
+ num = cc_wwan_device_get_unlock_retries (self->device, lock);
+
+ if (num != MM_UNLOCK_RETRIES_UNKNOWN)
+ {
+ if (self->is_retry)
+ warning = g_strdup_printf (ngettext ("Wrong password entered. You have %1$u try left",
+ "Wrong password entered. You have %1$u tries left", num), num);
+ else
+ warning = g_strdup_printf (ngettext ("You have %u try left",
+ "You have %u tries left", num), num);
+ }
+ else if (self->is_retry)
+ {
+ warning = g_strdup (_("Wrong password entered."));
+ }
+
+ gcr_prompt_set_warning (prompt, warning);
+
+ return prompt;
+}
+
+static void
+wwan_update_unlock_button (CcWwanDevicePage *self)
+{
+ gtk_button_set_label (self->unlock_button, _("Unlock"));
+ gtk_widget_set_sensitive (GTK_WIDGET (self->unlock_button), TRUE);
+}
+
+static void
+cc_wwan_device_page_unlocked_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ CcWwanDevicePage *self = user_data;
+ wwan_update_unlock_button (self);
+}
+
+static void
+wwan_device_unlock_clicked_cb (CcWwanDevicePage *self)
+{
+ g_autoptr(GError) error = NULL;
+ GcrPrompt *prompt;
+ const gchar *password, *warning;
+ const gchar *pin = "";
+ const gchar *puk = "";
+ MMModemLock lock;
+
+ lock = cc_wwan_device_get_lock (self->device);
+ password = "";
+
+ if (lock != MM_MODEM_LOCK_SIM_PIN &&
+ lock != MM_MODEM_LOCK_SIM_PUK)
+ g_return_if_reached ();
+
+ if (lock == MM_MODEM_LOCK_SIM_PUK)
+ {
+ prompt = cc_wwan_device_page_new_prompt (self, lock);
+
+ warning = _("PUK code should be an 8 digit number");
+ while (password && !cc_wwan_device_pin_valid (password, lock))
+ {
+ password = gcr_prompt_password (prompt, NULL, &error);
+ gcr_prompt_set_warning (prompt, warning);
+ }
+
+ puk = g_strdup (password);
+ password = "";
+ gcr_prompt_close (prompt);
+ g_object_unref (prompt);
+
+ if (error)
+ g_warning ("Error: %s", error->message);
+
+ /* Error or User cancelled PUK */
+ if (!puk)
+ return;
+ }
+
+ prompt = cc_wwan_device_page_new_prompt (self, MM_MODEM_LOCK_SIM_PIN);
+ if (lock == MM_MODEM_LOCK_SIM_PUK)
+ {
+ gcr_prompt_set_password_new (prompt, TRUE);
+ gcr_prompt_set_message (prompt, _("Enter New PIN"));
+ gcr_prompt_set_warning (prompt, "");
+ }
+
+ warning = _("PIN code should be a 4-8 digit number");
+ while (password && !cc_wwan_device_pin_valid (password, MM_MODEM_LOCK_SIM_PIN))
+ {
+ password = gcr_prompt_password (prompt, NULL, &error);
+ gcr_prompt_set_warning (prompt, warning);
+ }
+
+ pin = g_strdup (password);
+ gcr_prompt_close (prompt);
+ g_object_unref (prompt);
+
+ if (error)
+ g_warning ("Error: %s", error->message);
+
+ /* Error or User cancelled PIN */
+ if (!pin)
+ return;
+
+ gtk_button_set_label (self->unlock_button, _("Unlocking…"));
+ gtk_widget_set_sensitive (GTK_WIDGET (self->unlock_button), FALSE);
+
+ if (lock == MM_MODEM_LOCK_SIM_PIN)
+ cc_wwan_device_send_pin (self->device, pin,
+ NULL, /* cancellable */
+ cc_wwan_device_page_unlocked_cb,
+ self);
+ else if (lock == MM_MODEM_LOCK_SIM_PUK)
+ {
+ cc_wwan_device_send_puk (self->device, puk, pin,
+ NULL, /* Cancellable */
+ cc_wwan_device_page_unlocked_cb,
+ self);
+ }
+ else
+ {
+ g_warn_if_reached ();
+ }
+}
+
+static void
+wwan_data_settings_changed_cb (CcWwanDevicePage *self,
+ GParamSpec *pspec,
+ CcListRow *data_row)
+{
+ if (self->is_self_change)
+ {
+ self->is_self_change = FALSE;
+ return;
+ }
+
+ if (cc_wwan_data_get_default_apn (self->wwan_data) == NULL)
+ {
+ wwan_data_show_apn_dialog (self);
+ g_object_set_data (G_OBJECT (self->apn_dialog), "row", data_row);
+ }
+ else
+ {
+ wwan_device_page_handle_data_row (self, data_row);
+ }
+}
+
+static void
+wwan_network_settings_activated_cb (CcWwanDevicePage *self,
+ CcListRow *row)
+{
+ GtkWidget *dialog;
+ GtkWindow *top_level;
+
+ top_level = GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (self)));
+
+ if (row == self->network_mode_row)
+ {
+ if (!self->network_mode_dialog)
+ self->network_mode_dialog = cc_wwan_mode_dialog_new (top_level, self->device);
+
+ dialog = GTK_WIDGET (self->network_mode_dialog);
+ }
+ else if (row == self->network_name_row)
+ {
+ if (!self->network_dialog)
+ self->network_dialog = cc_wwan_network_dialog_new (top_level, self->device);
+
+ dialog = GTK_WIDGET (self->network_dialog);
+ }
+ else
+ {
+ return;
+ }
+
+ gtk_widget_show (dialog);
+}
+
+static void
+wwan_advanced_settings_activated_cb (CcWwanDevicePage *self,
+ CcListRow *row)
+{
+ GtkWindow *top_level;
+
+ top_level = GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (self)));
+
+ if (row == self->sim_lock_row)
+ {
+ if (!self->sim_lock_dialog)
+ self->sim_lock_dialog = cc_wwan_sim_lock_dialog_new (top_level, self->device);
+ gtk_widget_show (GTK_WIDGET (self->sim_lock_dialog));
+ }
+ else if (row == self->details_row)
+ {
+ if (!self->details_dialog)
+ self->details_dialog = cc_wwan_details_dialog_new (top_level, self->device);
+ gtk_widget_show (GTK_WIDGET (self->details_dialog));
+ }
+ else if (row == self->apn_settings_row)
+ {
+ wwan_data_show_apn_dialog (self);
+ }
+ else
+ {
+ g_return_if_reached ();
+ }
+}
+
+static void
+cc_wwan_device_page_update_data (CcWwanDevicePage *self)
+{
+ gboolean has_data;
+
+ if (self->wwan_data == cc_wwan_device_get_data (self->device))
+ return;
+
+ self->wwan_data = cc_wwan_device_get_data (self->device);
+ has_data = self->wwan_data != NULL;
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->data_settings_list), has_data);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->apn_settings_row), has_data);
+
+ if (!has_data)
+ return;
+
+ g_signal_handlers_block_by_func (self->data_roaming_row,
+ wwan_data_settings_changed_cb, self);
+ g_signal_handlers_block_by_func (self->data_enable_row,
+ wwan_data_settings_changed_cb, self);
+
+ g_object_set (self->data_roaming_row, "active",
+ cc_wwan_data_get_roaming_enabled (self->wwan_data), NULL);
+
+ g_object_set (self->data_enable_row, "active",
+ cc_wwan_data_get_enabled (self->wwan_data), NULL);
+
+ g_signal_handlers_unblock_by_func (self->data_roaming_row,
+ wwan_data_settings_changed_cb, self);
+ g_signal_handlers_unblock_by_func (self->data_enable_row,
+ wwan_data_settings_changed_cb, self);
+}
+
+static void
+cc_wwan_device_page_update (CcWwanDevicePage *self)
+{
+ GtkStack *main_stack;
+ MMModemLock lock;
+
+ main_stack = self->main_stack;
+ if (!cc_wwan_device_has_sim (self->device))
+ gtk_stack_set_visible_child_name (main_stack, "no-sim-view");
+ else if ((lock = cc_wwan_device_get_lock (self->device)) == MM_MODEM_LOCK_SIM_PIN ||
+ lock == MM_MODEM_LOCK_SIM_PUK)
+ gtk_stack_set_visible_child_name (main_stack, "sim-lock-view");
+ else
+ gtk_stack_set_visible_child_name (main_stack, "settings-view");
+}
+
+static void
+cc_wwan_locks_changed_cb (CcWwanDevicePage *self)
+{
+ const gchar *label;
+
+ if (cc_wwan_device_get_sim_lock (self->device))
+ label = _("Enabled");
+ else
+ label = _("Disabled");
+
+ cc_list_row_set_secondary_label (self->sim_lock_row, label);
+ cc_wwan_device_page_update (self);
+}
+
+static void
+cc_wwan_device_page_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcWwanDevicePage *self = (CcWwanDevicePage *)object;
+
+ switch (prop_id)
+ {
+ case PROP_DEVICE:
+ self->device = g_value_dup_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_wwan_device_page_constructed (GObject *object)
+{
+ CcWwanDevicePage *self = (CcWwanDevicePage *)object;
+
+ G_OBJECT_CLASS (cc_wwan_device_page_parent_class)->constructed (object);
+
+ cc_wwan_device_page_update_data (self);
+
+ g_object_bind_property (self->device, "operator-name",
+ self->network_name_row, "secondary-label",
+ G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
+
+ g_object_bind_property (self->device, "network-mode",
+ self->network_mode_row, "secondary-label",
+ G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
+
+ g_signal_connect_object (self->device, "notify::enabled-locks",
+ (GCallback)cc_wwan_locks_changed_cb,
+ self, G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self->device, "notify::has-data",
+ (GCallback)cc_wwan_device_page_update_data,
+ self, G_CONNECT_SWAPPED);
+
+ cc_wwan_device_page_update (self);
+ cc_wwan_locks_changed_cb (self);
+}
+
+static void
+cc_wwan_device_page_dispose (GObject *object)
+{
+ CcWwanDevicePage *self = (CcWwanDevicePage *)object;
+
+ g_clear_pointer ((GtkWindow **)&self->apn_dialog, gtk_window_destroy);
+ g_clear_pointer ((GtkWindow **)&self->details_dialog, gtk_window_destroy);
+ g_clear_pointer ((GtkWindow **)&self->network_mode_dialog, gtk_window_destroy);
+ g_clear_pointer ((GtkWindow **)&self->network_dialog, gtk_window_destroy);
+ g_clear_pointer ((GtkWindow **)&self->sim_lock_dialog, gtk_window_destroy);
+
+ g_clear_object (&self->wwan_proxy);
+ g_clear_object (&self->device);
+
+ G_OBJECT_CLASS (cc_wwan_device_page_parent_class)->dispose (object);
+}
+
+static void
+cc_wwan_device_page_class_init (CcWwanDevicePageClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = cc_wwan_device_page_set_property;
+ object_class->constructed = cc_wwan_device_page_constructed;
+ object_class->dispose = cc_wwan_device_page_dispose;
+
+ g_type_ensure (CC_TYPE_WWAN_DEVICE);
+
+ properties[PROP_DEVICE] =
+ g_param_spec_object ("device",
+ "Device",
+ "The WWAN Device",
+ CC_TYPE_WWAN_DEVICE,
+ G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/control-center/wwan/cc-wwan-device-page.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcWwanDevicePage, advanced_settings_list);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanDevicePage, apn_settings_row);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanDevicePage, data_enable_row);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanDevicePage, data_roaming_row);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanDevicePage, data_settings_list);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanDevicePage, details_row);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanDevicePage, main_stack);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanDevicePage, network_mode_row);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanDevicePage, network_name_row);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanDevicePage, network_settings_list);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanDevicePage, sim_lock_row);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanDevicePage, unlock_button);
+
+ gtk_widget_class_bind_template_callback (widget_class, wwan_device_unlock_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, wwan_data_settings_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, wwan_network_settings_activated_cb);
+ gtk_widget_class_bind_template_callback (widget_class, wwan_advanced_settings_activated_cb);
+}
+
+static void
+cc_wwan_device_page_init (CcWwanDevicePage *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+cc_wwan_error_changed_cb (CcWwanDevicePage *self)
+{
+ AdwToast *toast;
+ const gchar *message;
+
+ message = cc_wwan_device_get_simple_error (self->device);
+
+ if (!message)
+ return;
+
+ toast = adw_toast_new (message);
+ adw_toast_overlay_add_toast (self->toast_overlay, toast);
+}
+
+CcWwanDevicePage *
+cc_wwan_device_page_new (CcWwanDevice *device,
+ GtkWidget *toast_overlay)
+{
+ CcWwanDevicePage *self;
+
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (device), NULL);
+
+ self = g_object_new (CC_TYPE_WWAN_DEVICE_PAGE,
+ "device", device,
+ NULL);
+
+ self->toast_overlay = ADW_TOAST_OVERLAY (toast_overlay);
+
+ g_signal_connect_object (self->device, "notify::error",
+ G_CALLBACK (cc_wwan_error_changed_cb),
+ self, G_CONNECT_SWAPPED);
+
+ return self;
+}
+
+CcWwanDevice *
+cc_wwan_device_page_get_device (CcWwanDevicePage *self)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE_PAGE (self), NULL);
+
+ return self->device;
+}
+
+void
+cc_wwan_device_page_set_sim_index (CcWwanDevicePage *self,
+ gint sim_index)
+{
+ g_return_if_fail (CC_IS_WWAN_DEVICE_PAGE (self));
+ g_return_if_fail (sim_index >= 1);
+
+ self->sim_index = sim_index;
+}
diff --git a/panels/wwan/cc-wwan-device-page.h b/panels/wwan/cc-wwan-device-page.h
new file mode 100644
index 0000000..0fd03c1
--- /dev/null
+++ b/panels/wwan/cc-wwan-device-page.h
@@ -0,0 +1,42 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-wwan-device-page.h
+ *
+ * Copyright 2019 Purism SPC
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+#include "cc-wwan-device.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_WWAN_DEVICE_PAGE (cc_wwan_device_page_get_type())
+G_DECLARE_FINAL_TYPE (CcWwanDevicePage, cc_wwan_device_page, CC, WWAN_DEVICE_PAGE, GtkBox)
+
+CcWwanDevicePage *cc_wwan_device_page_new (CcWwanDevice *device,
+ GtkWidget *toast_overlay);
+CcWwanDevice *cc_wwan_device_page_get_device (CcWwanDevicePage *self);
+void cc_wwan_device_page_set_sim_index (CcWwanDevicePage *self,
+ gint sim_index);
+
+G_END_DECLS
diff --git a/panels/wwan/cc-wwan-device-page.ui b/panels/wwan/cc-wwan-device-page.ui
new file mode 100644
index 0000000..9899920
--- /dev/null
+++ b/panels/wwan/cc-wwan-device-page.ui
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk" version="4.0"/>
+ <template class="CcWwanDevicePage" parent="GtkBox">
+ <child>
+ <object class="GtkStack" id="main_stack">
+ <property name="vhomogeneous">False</property>
+ <property name="hhomogeneous">False</property>
+
+ <!-- SIM not inserted view -->
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">no-sim-view</property>
+ <property name="child">
+ <object class="AdwStatusPage">
+ <property name="hexpand">True</property>
+ <property name="icon-name">auth-sim-missing</property>
+ <property name="title" translatable="yes">No SIM</property>
+ <property name="description" translatable="yes">Insert a SIM card to use this modem</property>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <!-- SIM locked view -->
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">sim-lock-view</property>
+ <property name="child">
+ <object class="AdwStatusPage">
+ <property name="hexpand">True</property>
+ <property name="icon-name">auth-sim-locked</property>
+ <property name="title" translatable="yes">SIM Locked</property>
+ <child>
+ <object class="GtkButton" id="unlock_button">
+ <property name="halign">center</property>
+ <property name="use-underline">True</property>
+ <property name="label" translatable="yes">_Unlock</property>
+ <signal name="clicked" handler="wwan_device_unlock_clicked_cb" swapped="yes"/>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <!-- Network Settings -->
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">settings-view</property>
+ <property name="child">
+ <object class="GtkBox">
+ <property name="margin-top">18</property>
+ <property name="orientation">vertical</property>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Network</property>
+ <property name="margin-bottom">32</property>
+
+ <!-- Internet settings -->
+ <child>
+ <object class="GtkListBox" id="data_settings_list">
+ <property name="selection-mode">none</property>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+
+ <!-- Enable/Disable Data -->
+ <child>
+ <object class="CcListRow" id="data_enable_row">
+ <property name="use-underline">True</property>
+ <property name="show-switch">True</property>
+ <property name="title" translatable="yes">_Mobile Data</property>
+ <property name="subtitle" translatable="yes">Access data using mobile network</property>
+ <signal name="notify::active" handler="wwan_data_settings_changed_cb" swapped="yes"/>
+ </object>
+ </child>
+
+ <!-- Data Roaming -->
+ <child>
+ <object class="CcListRow" id="data_roaming_row">
+ <property name="use-underline">True</property>
+ <property name="show-switch">True</property>
+ <property name="title" translatable="yes">_Data Roaming</property>
+ <property name="subtitle" translatable="yes">Use mobile data when roaming</property>
+ <signal name="notify::active" handler="wwan_data_settings_changed_cb" swapped="yes"/>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <!-- Network Settings -->
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="margin-bottom">32</property>
+ <child>
+ <object class="GtkListBox" id="network_settings_list">
+ <property name="selection-mode">none</property>
+ <signal name="row-activated" handler="wwan_network_settings_activated_cb" swapped="yes"/>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ <child>
+ <object class="CcListRow" id="network_mode_row">
+ <property name="use-underline">True</property>
+ <property name="show-arrow">True</property>
+ <property name="title" translatable="yes">_Network Mode</property>
+ </object>
+ </child>
+ <child>
+ <object class="CcListRow" id="network_name_row">
+ <property name="use-underline">True</property>
+ <property name="show-arrow">True</property>
+ <property name="title" translatable="yes">N_etwork</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Advanced</property>
+ <child>
+ <object class="GtkListBox" id="advanced_settings_list">
+ <property name="selection-mode">none</property>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ <signal name="row-activated" handler="wwan_advanced_settings_activated_cb" swapped="yes"/>
+
+ <!-- Accesss Point Settings -->
+ <child>
+ <object class="CcListRow" id="apn_settings_row">
+ <property name="use-underline">True</property>
+ <property name="show-arrow">true</property>
+ <property name="title" translatable="yes">_Access Point Names</property>
+ </object>
+ </child>
+
+ <!-- SIM Lock -->
+ <child>
+ <object class="CcListRow" id="sim_lock_row">
+ <property name="use-underline">True</property>
+ <property name="show-arrow">True</property>
+ <property name="title" translatable="yes">_SIM Lock</property>
+ <property name="subtitle" translatable="yes">Lock SIM with PIN</property>
+ </object>
+ </child>
+
+ <!-- Modem Details -->
+ <child>
+ <object class="CcListRow" id="details_row">
+ <property name="use-underline">True</property>
+ <property name="show-arrow">True</property>
+ <property name="title" translatable="yes">M_odem Details</property>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </property>
+ </object>
+ </child>
+
+ </object> <!-- ./GtkStack main_stack -->
+ </child>
+ </template>
+ <object class="GtkSizeGroup">
+ <property name="mode">both</property>
+ <widgets>
+ <widget name="apn_settings_row"/>
+ <widget name="sim_lock_row"/>
+ <widget name="details_row"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/panels/wwan/cc-wwan-device.c b/panels/wwan/cc-wwan-device.c
new file mode 100644
index 0000000..a77715b
--- /dev/null
+++ b/panels/wwan/cc-wwan-device.c
@@ -0,0 +1,1481 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-wwan-device.c
+ *
+ * Copyright 2019-2020 Purism SPC
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "cc-wwan-device"
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib/gi18n.h>
+#include <polkit/polkit.h>
+#if defined(HAVE_NETWORK_MANAGER) && defined(BUILD_NETWORK)
+# include <NetworkManager.h>
+# include <nma-mobile-providers.h>
+#endif
+
+#include "cc-wwan-errors-private.h"
+#include "cc-wwan-device.h"
+
+/**
+ * @short_description: Device Object
+ * @include: "cc-wwan-device.h"
+ */
+
+struct _CcWwanDevice
+{
+ GObject parent_instance;
+
+ MMObject *mm_object;
+ MMModem *modem;
+ MMSim *sim;
+ MMModem3gpp *modem_3gpp;
+
+ const char *operator_code; /* MCCMNC */
+ GError *error;
+
+ /* Building with NetworkManager is optional,
+ * so #NMclient type can’t be used here.
+ */
+ GObject *nm_client; /* An #NMClient */
+ CcWwanData *wwan_data;
+
+ gulong modem_3gpp_id;
+ gulong modem_3gpp_locks_id;
+
+ /* Enabled locks like PIN, PIN2, PUK, etc. */
+ MMModem3gppFacility locks;
+
+ CcWwanState registration_state;
+ gboolean network_is_manual;
+};
+
+G_DEFINE_TYPE (CcWwanDevice, cc_wwan_device, G_TYPE_OBJECT)
+
+
+enum {
+ PROP_0,
+ PROP_OPERATOR_NAME,
+ PROP_ENABLED_LOCKS,
+ PROP_ERROR,
+ PROP_HAS_DATA,
+ PROP_NETWORK_MODE,
+ PROP_REGISTRATION_STATE,
+ PROP_SIGNAL,
+ PROP_UNLOCK_REQUIRED,
+ N_PROPS
+};
+
+static GParamSpec *properties[N_PROPS];
+
+static void
+cc_wwan_device_state_changed_cb (CcWwanDevice *self)
+{
+ MMModem3gppRegistrationState state;
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_OPERATOR_NAME]);
+
+ state = mm_modem_3gpp_get_registration_state (self->modem_3gpp);
+
+ switch (state)
+ {
+ case MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN:
+ self->registration_state = CC_WWAN_REGISTRATION_STATE_UNKNOWN;
+ break;
+
+ case MM_MODEM_3GPP_REGISTRATION_STATE_DENIED:
+ self->registration_state = CC_WWAN_REGISTRATION_STATE_DENIED;
+ break;
+
+ case MM_MODEM_3GPP_REGISTRATION_STATE_IDLE:
+ self->registration_state = CC_WWAN_REGISTRATION_STATE_IDLE;
+ break;
+
+ case MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING:
+ self->registration_state = CC_WWAN_REGISTRATION_STATE_SEARCHING;
+ break;
+
+ case MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING:
+ self->registration_state = CC_WWAN_REGISTRATION_STATE_ROAMING;
+ break;
+
+ default:
+ self->registration_state = CC_WWAN_REGISTRATION_STATE_REGISTERED;
+ break;
+ }
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_REGISTRATION_STATE]);
+}
+
+static void
+cc_wwan_device_locks_changed_cb (CcWwanDevice *self)
+{
+ self->locks = mm_modem_3gpp_get_enabled_facility_locks (self->modem_3gpp);
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ENABLED_LOCKS]);
+}
+
+static void
+cc_wwan_device_3gpp_changed_cb (CcWwanDevice *self)
+{
+ gulong handler_id = 0;
+
+ if (self->modem_3gpp_id)
+ g_signal_handler_disconnect (self->modem_3gpp, self->modem_3gpp_id);
+ self->modem_3gpp_id = 0;
+
+ if (self->modem_3gpp_locks_id)
+ g_signal_handler_disconnect (self->modem_3gpp, self->modem_3gpp_locks_id);
+ self->modem_3gpp_locks_id = 0;
+
+ g_clear_object (&self->modem_3gpp);
+ self->modem_3gpp = mm_object_get_modem_3gpp (self->mm_object);
+
+ if (self->modem_3gpp)
+ {
+ handler_id = g_signal_connect_object (self->modem_3gpp, "notify::registration-state",
+ G_CALLBACK (cc_wwan_device_state_changed_cb),
+ self, G_CONNECT_SWAPPED);
+ self->modem_3gpp_id = handler_id;
+
+ handler_id = g_signal_connect_object (self->modem_3gpp, "notify::enabled-facility-locks",
+ G_CALLBACK (cc_wwan_device_locks_changed_cb),
+ self, G_CONNECT_SWAPPED);
+ self->modem_3gpp_locks_id = handler_id;
+ cc_wwan_device_locks_changed_cb (self);
+ cc_wwan_device_state_changed_cb (self);
+ }
+}
+
+static void
+cc_wwan_device_signal_quality_changed_cb (CcWwanDevice *self)
+{
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SIGNAL]);
+}
+
+static void
+cc_wwan_device_mode_changed_cb (CcWwanDevice *self)
+{
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_NETWORK_MODE]);
+}
+
+static void
+wwan_device_emit_data_changed (CcWwanDevice *self)
+{
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_HAS_DATA]);
+}
+
+static void
+cc_wwan_device_unlock_required_cb (CcWwanDevice *self)
+{
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_UNLOCK_REQUIRED]);
+}
+
+#if defined(HAVE_NETWORK_MANAGER) && defined(BUILD_NETWORK)
+static void
+cc_wwan_device_nm_changed_cb (CcWwanDevice *self,
+ GParamSpec *pspec,
+ NMClient *client)
+{
+ gboolean nm_is_running;
+
+ nm_is_running = nm_client_get_nm_running (client);
+
+ if (!nm_is_running && self->wwan_data != NULL)
+ {
+ g_clear_object (&self->wwan_data);
+ wwan_device_emit_data_changed (self);
+ }
+}
+
+static void
+cc_wwan_device_nm_device_added_cb (CcWwanDevice *self,
+ NMDevice *nm_device)
+{
+ if (!NM_IS_DEVICE_MODEM (nm_device))
+ return;
+
+ if(!self->sim || !cc_wwan_device_is_nm_device (self, G_OBJECT (nm_device)))
+ return;
+
+ self->wwan_data = cc_wwan_data_new (self->mm_object,
+ NM_CLIENT (self->nm_client));
+
+ if (self->wwan_data)
+ {
+ g_signal_connect_object (self->wwan_data, "notify::enabled",
+ G_CALLBACK (wwan_device_emit_data_changed),
+ self, G_CONNECT_SWAPPED);
+ wwan_device_emit_data_changed (self);
+ }
+}
+#endif
+
+static void
+cc_wwan_device_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcWwanDevice *self = (CcWwanDevice *)object;
+ MMModemMode allowed, preferred;
+
+ switch (prop_id)
+ {
+ case PROP_OPERATOR_NAME:
+ g_value_set_string (value, cc_wwan_device_get_operator_name (self));
+ break;
+
+ case PROP_ERROR:
+ g_value_set_boolean (value, self->error != NULL);
+ break;
+
+ case PROP_HAS_DATA:
+ g_value_set_boolean (value, self->wwan_data != NULL);
+ break;
+
+ case PROP_ENABLED_LOCKS:
+ g_value_set_int (value, self->locks);
+ break;
+
+ case PROP_NETWORK_MODE:
+ if (cc_wwan_device_get_current_mode (self, &allowed, &preferred))
+ g_value_take_string (value, cc_wwan_device_get_string_from_mode (self, allowed, preferred));
+ break;
+
+ case PROP_REGISTRATION_STATE:
+ g_value_set_int (value, self->registration_state);
+ break;
+
+ case PROP_UNLOCK_REQUIRED:
+ g_value_set_int (value, cc_wwan_device_get_lock (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_wwan_device_dispose (GObject *object)
+{
+ CcWwanDevice *self = (CcWwanDevice *)object;
+
+ g_clear_error (&self->error);
+ g_clear_object (&self->modem);
+ g_clear_object (&self->mm_object);
+ g_clear_object (&self->sim);
+ g_clear_object (&self->modem_3gpp);
+
+ g_clear_object (&self->nm_client);
+ g_clear_object (&self->wwan_data);
+
+ G_OBJECT_CLASS (cc_wwan_device_parent_class)->dispose (object);
+}
+
+static void
+cc_wwan_device_class_init (CcWwanDeviceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = cc_wwan_device_get_property;
+ object_class->dispose = cc_wwan_device_dispose;
+
+ properties[PROP_OPERATOR_NAME] =
+ g_param_spec_string ("operator-name",
+ "Operator Name",
+ "Operator Name the device is connected to",
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_ENABLED_LOCKS] =
+ g_param_spec_int ("enabled-locks",
+ "Enabled Locks",
+ "Locks Enabled in Modem",
+ MM_MODEM_3GPP_FACILITY_NONE,
+ MM_MODEM_3GPP_FACILITY_CORP_PERS,
+ MM_MODEM_3GPP_FACILITY_NONE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_ERROR] =
+ g_param_spec_boolean ("error",
+ "Error",
+ "Set if some Error occurs",
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_HAS_DATA] =
+ g_param_spec_boolean ("has-data",
+ "has-data",
+ "Data for the device",
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_NETWORK_MODE] =
+ g_param_spec_string ("network-mode",
+ "Network Mode",
+ "A String representing preferred network mode",
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_REGISTRATION_STATE] =
+ g_param_spec_int ("registration-state",
+ "Registration State",
+ "The current network registration state",
+ CC_WWAN_REGISTRATION_STATE_UNKNOWN,
+ CC_WWAN_REGISTRATION_STATE_DENIED,
+ CC_WWAN_REGISTRATION_STATE_UNKNOWN,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_UNLOCK_REQUIRED] =
+ g_param_spec_int ("unlock-required",
+ "Unlock Required",
+ "The Modem lock status changed",
+ MM_MODEM_LOCK_UNKNOWN,
+ MM_MODEM_LOCK_PH_NETSUB_PUK,
+ MM_MODEM_LOCK_UNKNOWN,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_SIGNAL] =
+ g_param_spec_int ("signal",
+ "Signal",
+ "Get Device Signal",
+ 0, 100, 0,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+cc_wwan_device_init (CcWwanDevice *self)
+{
+}
+
+/**
+ * cc_wwan_device_new:
+ * @mm_object: (transfer full): An #MMObject
+ *
+ * Create a new device representing the given
+ * @mm_object.
+ *
+ * Returns: A #CcWwanDevice
+ */
+CcWwanDevice *
+cc_wwan_device_new (MMObject *mm_object,
+ GObject *nm_client)
+{
+ CcWwanDevice *self;
+
+ g_return_val_if_fail (MM_IS_OBJECT (mm_object), NULL);
+#if defined(HAVE_NETWORK_MANAGER) && defined(BUILD_NETWORK)
+ g_return_val_if_fail (NM_IS_CLIENT (nm_client), NULL);
+#else
+ g_return_val_if_fail (!nm_client, NULL);
+#endif
+
+ self = g_object_new (CC_TYPE_WWAN_DEVICE, NULL);
+
+ self->mm_object = g_object_ref (mm_object);
+ self->modem = mm_object_get_modem (mm_object);
+ self->sim = mm_modem_get_sim_sync (self->modem, NULL, NULL);
+ g_set_object (&self->nm_client, nm_client);
+ if (self->sim)
+ {
+ self->operator_code = mm_sim_get_operator_identifier (self->sim);
+#if defined(HAVE_NETWORK_MANAGER) && defined(BUILD_NETWORK)
+ self->wwan_data = cc_wwan_data_new (mm_object,
+ NM_CLIENT (self->nm_client));
+#endif
+ }
+
+ g_signal_connect_object (self->mm_object, "notify::unlock-required",
+ G_CALLBACK (cc_wwan_device_unlock_required_cb),
+ self, G_CONNECT_SWAPPED);
+ if (self->wwan_data)
+ g_signal_connect_object (self->wwan_data, "notify::enabled",
+ G_CALLBACK (wwan_device_emit_data_changed),
+ self, G_CONNECT_SWAPPED);
+
+#if defined(HAVE_NETWORK_MANAGER) && defined(BUILD_NETWORK)
+ g_signal_connect_object (self->nm_client, "notify::nm-running" ,
+ G_CALLBACK (cc_wwan_device_nm_changed_cb), self,
+ G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self->nm_client, "device-added",
+ G_CALLBACK (cc_wwan_device_nm_device_added_cb),
+ self, G_CONNECT_SWAPPED);
+#endif
+
+ g_signal_connect_object (self->mm_object, "notify::modem3gpp",
+ G_CALLBACK (cc_wwan_device_3gpp_changed_cb),
+ self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->modem, "notify::signal-quality",
+ G_CALLBACK (cc_wwan_device_signal_quality_changed_cb),
+ self, G_CONNECT_SWAPPED);
+
+ cc_wwan_device_3gpp_changed_cb (self);
+ g_signal_connect_object (self->modem, "notify::current-modes",
+ G_CALLBACK (cc_wwan_device_mode_changed_cb),
+ self, G_CONNECT_SWAPPED);
+
+ return self;
+}
+
+gboolean
+cc_wwan_device_has_sim (CcWwanDevice *self)
+{
+ MMModemStateFailedReason state_reason;
+
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), FALSE);
+
+ state_reason = mm_modem_get_state_failed_reason (self->modem);
+
+ if (state_reason == MM_MODEM_STATE_FAILED_REASON_SIM_MISSING)
+ return FALSE;
+
+ return TRUE;
+}
+
+/**
+ * cc_wwan_device_get_lock:
+ * @self: a #CcWwanDevice
+ *
+ * Get the active device lock that is required to
+ * be unlocked for accessing device features.
+ *
+ * Returns: %TRUE if PIN enabled, %FALSE otherwise.
+ */
+MMModemLock
+cc_wwan_device_get_lock (CcWwanDevice *self)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), MM_MODEM_LOCK_UNKNOWN);
+
+ return mm_modem_get_unlock_required (self->modem);
+}
+
+
+/**
+ * cc_wwan_device_get_sim_lock:
+ * @self: a #CcWwanDevice
+ *
+ * Get if SIM lock with PIN is enabled. SIM PIN
+ * enabled doesn’t mean that SIM is locked.
+ * See cc_wwan_device_get_lock().
+ *
+ * Returns: %TRUE if PIN enabled, %FALSE otherwise.
+ */
+gboolean
+cc_wwan_device_get_sim_lock (CcWwanDevice *self)
+{
+ gboolean sim_lock;
+
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), FALSE);
+
+ sim_lock = self->locks & MM_MODEM_3GPP_FACILITY_SIM;
+
+ return !!sim_lock;
+}
+
+guint
+cc_wwan_device_get_unlock_retries (CcWwanDevice *self,
+ MMModemLock lock)
+{
+ MMUnlockRetries *retries;
+
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), 0);
+
+ retries = mm_modem_get_unlock_retries (self->modem);
+
+ return mm_unlock_retries_get (retries, lock);
+}
+
+static void
+cc_wwan_device_pin_sent_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ CcWwanDevice *self;
+ MMSim *sim = (MMSim *)object;
+ g_autoptr(GTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+
+ if (!mm_sim_send_pin_finish (sim, result, &error))
+ {
+ self = g_task_get_source_object (G_TASK (task));
+
+ g_clear_error (&self->error);
+ self->error = g_error_copy (error);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ERROR]);
+
+ g_task_return_error (task, g_steal_pointer (&error));
+ }
+ else
+ {
+ g_task_return_boolean (task, TRUE);
+ }
+}
+
+void
+cc_wwan_device_send_pin (CcWwanDevice *self,
+ const gchar *pin,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (CC_IS_WWAN_DEVICE (self));
+ g_return_if_fail (MM_IS_SIM (self->sim));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (pin && *pin);
+
+ task = g_task_new (self, cancellable, callback, user_data);
+
+ mm_sim_send_pin (self->sim, pin, cancellable,
+ cc_wwan_device_pin_sent_cb,
+ g_steal_pointer (&task));
+}
+
+gboolean
+cc_wwan_device_send_pin_finish (CcWwanDevice *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), FALSE);
+ g_return_val_if_fail (G_IS_TASK (result), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+static void
+cc_wwan_device_puk_sent_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ CcWwanDevice *self;
+ MMSim *sim = (MMSim *)object;
+ g_autoptr(GTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+
+ if (!mm_sim_send_puk_finish (sim, result, &error))
+ {
+ self = g_task_get_source_object (G_TASK (task));
+
+ g_clear_error (&self->error);
+ self->error = g_error_copy (error);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ERROR]);
+
+ g_task_return_error (task, g_steal_pointer (&error));
+ }
+ else
+ {
+ g_task_return_boolean (task, TRUE);
+ }
+}
+
+void
+cc_wwan_device_send_puk (CcWwanDevice *self,
+ const gchar *puk,
+ const gchar *pin,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (CC_IS_WWAN_DEVICE (self));
+ g_return_if_fail (MM_IS_SIM (self->sim));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (puk && *puk);
+ g_return_if_fail (pin && *pin);
+
+ task = g_task_new (self, cancellable, callback, user_data);
+
+ mm_sim_send_puk (self->sim, puk, pin, cancellable,
+ cc_wwan_device_puk_sent_cb,
+ g_steal_pointer (&task));
+}
+
+gboolean
+cc_wwan_device_send_puk_finish (CcWwanDevice *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), FALSE);
+ g_return_val_if_fail (G_IS_TASK (result), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+static void
+cc_wwan_device_enable_pin_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ CcWwanDevice *self;
+ MMSim *sim = (MMSim *)object;
+ g_autoptr(GTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+
+ if (!mm_sim_enable_pin_finish (sim, result, &error))
+ {
+ self = g_task_get_source_object (G_TASK (task));
+
+ g_clear_error (&self->error);
+ self->error = g_error_copy (error);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ERROR]);
+
+ g_task_return_error (task, g_steal_pointer (&error));
+ }
+ else
+ {
+ g_task_return_boolean (task, TRUE);
+ }
+}
+
+void
+cc_wwan_device_enable_pin (CcWwanDevice *self,
+ const gchar *pin,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (CC_IS_WWAN_DEVICE (self));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (pin && *pin);
+
+ task = g_task_new (self, cancellable, callback, user_data);
+
+ mm_sim_enable_pin (self->sim, pin, cancellable,
+ cc_wwan_device_enable_pin_cb,
+ g_steal_pointer (&task));
+}
+
+gboolean
+cc_wwan_device_enable_pin_finish (CcWwanDevice *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), FALSE);
+ g_return_val_if_fail (G_IS_TASK (result), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+static void
+cc_wwan_device_disable_pin_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ CcWwanDevice *self;
+ MMSim *sim = (MMSim *)object;
+ g_autoptr(GTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+
+ if (!mm_sim_disable_pin_finish (sim, result, &error))
+ {
+ self = g_task_get_source_object (G_TASK (task));
+
+ g_clear_error (&self->error);
+ self->error = g_error_copy (error);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ERROR]);
+
+ g_task_return_error (task, g_steal_pointer (&error));
+ }
+ else
+ {
+ g_task_return_boolean (task, TRUE);
+ }
+}
+
+void
+cc_wwan_device_disable_pin (CcWwanDevice *self,
+ const gchar *pin,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (CC_IS_WWAN_DEVICE (self));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (pin && *pin);
+
+ task = g_task_new (self, cancellable, callback, user_data);
+
+ mm_sim_disable_pin (self->sim, pin, cancellable,
+ cc_wwan_device_disable_pin_cb,
+ g_steal_pointer (&task));
+}
+
+gboolean
+cc_wwan_device_disable_pin_finish (CcWwanDevice *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), FALSE);
+ g_return_val_if_fail (G_IS_TASK (result), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+static void
+cc_wwan_device_change_pin_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ CcWwanDevice *self;
+ MMSim *sim = (MMSim *)object;
+ g_autoptr(GTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+
+ if (!mm_sim_change_pin_finish (sim, result, &error))
+ {
+ self = g_task_get_source_object (G_TASK (task));
+
+ g_clear_error (&self->error);
+ self->error = g_error_copy (error);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ERROR]);
+
+ g_task_return_error (task, g_steal_pointer (&error));
+ }
+ else
+ {
+ g_task_return_boolean (task, TRUE);
+ }
+}
+
+void
+cc_wwan_device_change_pin (CcWwanDevice *self,
+ const gchar *old_pin,
+ const gchar *new_pin,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (CC_IS_WWAN_DEVICE (self));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (old_pin && *old_pin);
+ g_return_if_fail (new_pin && *new_pin);
+
+ task = g_task_new (self, cancellable, callback, user_data);
+
+ mm_sim_change_pin (self->sim, old_pin, new_pin, cancellable,
+ cc_wwan_device_change_pin_cb,
+ g_steal_pointer (&task));
+}
+
+gboolean
+cc_wwan_device_change_pin_finish (CcWwanDevice *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), FALSE);
+ g_return_val_if_fail (G_IS_TASK (result), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+static void
+cc_wwan_device_network_mode_set_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ CcWwanDevice *self;
+ MMModem *modem = (MMModem *)object;
+ g_autoptr(GTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+
+ if (!mm_modem_set_current_modes_finish (modem, result, &error))
+ {
+ self = g_task_get_source_object (G_TASK (task));
+
+ g_clear_error (&self->error);
+ self->error = g_error_copy (error);
+ g_warning ("Error: %s", error->message);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ERROR]);
+
+ g_task_return_error (task, g_steal_pointer (&error));
+ }
+ else
+ {
+ g_task_return_boolean (task, TRUE);
+ }
+}
+
+/**
+ * cc_wwan_device_set_network_mode:
+ * @self: a #CcWwanDevice
+ * @allowed: The allowed #MMModemModes
+ * @preferred: The preferred #MMModemMode
+ * @cancellable: (nullable): a #GCancellable or %NULL
+ * @callback: (nullable): a #GAsyncReadyCallback or %NULL
+ * @user_data: (nullable): closure data for @callback
+ *
+ * Asynchronously set preferred network mode.
+ *
+ * Call @cc_wwan_device_set_current_mode_finish()
+ * in @callback to get the result of operation.
+ */
+void
+cc_wwan_device_set_current_mode (CcWwanDevice *self,
+ MMModemMode allowed,
+ MMModemMode preferred,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+ GPermission *permission;
+ g_autoptr(GError) error = NULL;
+
+ g_return_if_fail (CC_IS_WWAN_DEVICE (self));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ permission = polkit_permission_new_sync ("org.freedesktop.ModemManager1.Device.Control",
+ NULL, cancellable, &error);
+ if (permission)
+ g_task_set_task_data (task, permission, g_object_unref);
+
+ if (error)
+ g_warning ("error: %s", error->message);
+
+ if (error)
+ {
+ g_task_return_error (task, g_steal_pointer (&error));
+ }
+ else if (!g_permission_get_allowed (permission))
+ {
+ error = g_error_new (G_IO_ERROR,
+ G_IO_ERROR_PERMISSION_DENIED,
+ "Access Denied");
+ g_clear_error (&self->error);
+ self->error = g_error_copy (error);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ERROR]);
+
+ g_task_return_error (task, g_steal_pointer (&error));
+ }
+ else
+ {
+ mm_modem_set_current_modes (self->modem, allowed, preferred,
+ cancellable, cc_wwan_device_network_mode_set_cb,
+ g_steal_pointer (&task));
+ }
+}
+
+/**
+ * cc_wwan_device_set_current_mode_finish:
+ * @self: a #CcWwanDevice
+ * @result: a #GAsyncResult
+ * @error: a location for #GError or %NULL
+ *
+ * Get the status whether setting network mode
+ * succeeded
+ *
+ * Returns: %TRUE if network mode was successfully set,
+ * %FALSE otherwise.
+ */
+gboolean
+cc_wwan_device_set_current_mode_finish (CcWwanDevice *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), FALSE);
+ g_return_val_if_fail (G_IS_TASK (result), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+gboolean
+cc_wwan_device_get_current_mode (CcWwanDevice *self,
+ MMModemMode *allowed,
+ MMModemMode *preferred)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), FALSE);
+
+ return mm_modem_get_current_modes (self->modem, allowed, preferred);
+}
+
+gboolean
+cc_wwan_device_is_auto_network (CcWwanDevice *self)
+{
+ /*
+ * XXX: ModemManager Doesn’t have a true API to check
+ * if registration is automatic or manual. So Let’s
+ * do some guess work.
+ */
+ if (self->registration_state == CC_WWAN_REGISTRATION_STATE_DENIED)
+ return FALSE;
+
+ return !self->network_is_manual;
+}
+
+CcWwanState
+cc_wwan_device_get_network_state (CcWwanDevice *self)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), 0);
+
+ return self->registration_state;
+}
+
+gboolean
+cc_wwan_device_get_supported_modes (CcWwanDevice *self,
+ MMModemMode *allowed,
+ MMModemMode *preferred)
+{
+ g_autofree MMModemModeCombination *modes = NULL;
+ guint n_modes, i;
+
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), FALSE);
+
+ if (!mm_modem_get_supported_modes (self->modem, &modes, &n_modes))
+ return FALSE;
+
+ if (allowed)
+ *allowed = 0;
+ if (preferred)
+ *preferred = 0;
+
+ for (i = 0; i < n_modes; i++)
+ {
+ if (allowed)
+ *allowed = *allowed | modes[i].allowed;
+ if (preferred)
+ *preferred = *preferred | modes[i].preferred;
+ }
+
+ return TRUE;
+}
+
+gchar *
+cc_wwan_device_get_string_from_mode (CcWwanDevice *self,
+ MMModemMode allowed,
+ MMModemMode preferred)
+{
+ GString *str;
+
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), NULL);
+ g_return_val_if_fail (allowed != 0, NULL);
+
+ if (allowed == MM_MODEM_MODE_2G)
+ return g_strdup (_("2G Only"));
+
+ if (allowed == MM_MODEM_MODE_3G)
+ return g_strdup (_("3G Only"));
+
+ if (allowed == MM_MODEM_MODE_4G)
+ return g_strdup (_("4G Only"));
+
+ if (allowed == MM_MODEM_MODE_5G)
+ return g_strdup (_("5G Only"));
+
+ str = g_string_sized_new (10);
+
+ if (allowed & MM_MODEM_MODE_2G &&
+ allowed & MM_MODEM_MODE_3G &&
+ allowed & MM_MODEM_MODE_4G &&
+ allowed & MM_MODEM_MODE_5G)
+ {
+ if (preferred & MM_MODEM_MODE_5G)
+ g_string_append (str, _("2G, 3G, 4G, 5G (Preferred)"));
+ else if (preferred & MM_MODEM_MODE_4G)
+ g_string_append (str, _("2G, 3G, 4G (Preferred), 5G"));
+ else if (preferred & MM_MODEM_MODE_3G)
+ g_string_append (str, _("2G, 3G (Preferred), 4G, 5G"));
+ else if (preferred & MM_MODEM_MODE_2G)
+ g_string_append (str, _("2G (Preferred), 3G, 4G, 5G"));
+ else
+ g_string_append (str, _("2G, 3G, 4G, 5G"));
+ }
+ else if (allowed & MM_MODEM_MODE_2G &&
+ allowed & MM_MODEM_MODE_3G &&
+ allowed & MM_MODEM_MODE_4G)
+ {
+ if (preferred & MM_MODEM_MODE_4G)
+ g_string_append (str, _("2G, 3G, 4G (Preferred)"));
+ else if (preferred & MM_MODEM_MODE_3G)
+ g_string_append (str, _("2G, 3G (Preferred), 4G"));
+ else if (preferred & MM_MODEM_MODE_2G)
+ g_string_append (str, _("2G (Preferred), 3G, 4G"));
+ else
+ g_string_append (str, _("2G, 3G, 4G"));
+ }
+ else if (allowed & MM_MODEM_MODE_3G &&
+ allowed & MM_MODEM_MODE_4G &&
+ allowed & MM_MODEM_MODE_5G)
+ {
+ if (preferred & MM_MODEM_MODE_5G)
+ g_string_append (str, _("3G, 4G, 5G (Preferred)"));
+ else if (preferred & MM_MODEM_MODE_4G)
+ g_string_append (str, _("3G, 4G (Preferred), 5G"));
+ else if (preferred & MM_MODEM_MODE_2G)
+ g_string_append (str, _("3G (Preferred), 4G, 5G"));
+ else
+ g_string_append (str, _("3G, 4G, 5G"));
+ }
+ else if (allowed & MM_MODEM_MODE_2G &&
+ allowed & MM_MODEM_MODE_4G &&
+ allowed & MM_MODEM_MODE_5G)
+ {
+ if (preferred & MM_MODEM_MODE_5G)
+ g_string_append (str, _("2G, 4G, 5G (Preferred)"));
+ else if (preferred & MM_MODEM_MODE_4G)
+ g_string_append (str, _("2G, 4G (Preferred), 5G"));
+ else if (preferred & MM_MODEM_MODE_2G)
+ g_string_append (str, _("2G (Preferred), 4G, 5G"));
+ else
+ g_string_append (str, _("2G, 4G, 5G"));
+ }
+ else if (allowed & MM_MODEM_MODE_2G &&
+ allowed & MM_MODEM_MODE_3G &&
+ allowed & MM_MODEM_MODE_5G)
+ {
+ if (preferred & MM_MODEM_MODE_5G)
+ g_string_append (str, _("2G, 3G, 5G (Preferred)"));
+ else if (preferred & MM_MODEM_MODE_3G)
+ g_string_append (str, _("2G, 3G (Preferred), 5G"));
+ else if (preferred & MM_MODEM_MODE_2G)
+ g_string_append (str, _("2G (Preferred), 3G, 5G"));
+ else
+ g_string_append (str, _("2G, 3G, 5G"));
+ }
+ else if (allowed & MM_MODEM_MODE_3G &&
+ allowed & MM_MODEM_MODE_4G)
+ {
+ if (preferred & MM_MODEM_MODE_4G)
+ g_string_append (str, _("3G, 4G (Preferred)"));
+ else if (preferred & MM_MODEM_MODE_3G)
+ g_string_append (str, _("3G (Preferred), 4G"));
+ else
+ g_string_append (str, _("3G, 4G"));
+ }
+ else if (allowed & MM_MODEM_MODE_2G &&
+ allowed & MM_MODEM_MODE_4G)
+ {
+ if (preferred & MM_MODEM_MODE_4G)
+ g_string_append (str, _("2G, 4G (Preferred)"));
+ else if (preferred & MM_MODEM_MODE_2G)
+ g_string_append (str, _("2G (Preferred), 4G"));
+ else
+ g_string_append (str, _("2G, 4G"));
+ }
+ else if (allowed & MM_MODEM_MODE_2G &&
+ allowed & MM_MODEM_MODE_3G)
+ {
+ if (preferred & MM_MODEM_MODE_3G)
+ g_string_append (str, _("2G, 3G (Preferred)"));
+ else if (preferred & MM_MODEM_MODE_2G)
+ g_string_append (str, _("2G (Preferred), 3G"));
+ else
+ g_string_append (str, _("2G, 3G"));
+ }
+ else if (allowed & MM_MODEM_MODE_2G &&
+ allowed & MM_MODEM_MODE_5G)
+ {
+ if (preferred & MM_MODEM_MODE_5G)
+ g_string_append (str, _("2G, 5G (Preferred)"));
+ else if (preferred & MM_MODEM_MODE_2G)
+ g_string_append (str, _("2G (Preferred), 5G"));
+ else
+ g_string_append (str, _("2G, 5G"));
+ }
+ else if (allowed & MM_MODEM_MODE_3G &&
+ allowed & MM_MODEM_MODE_5G)
+ {
+ if (preferred & MM_MODEM_MODE_5G)
+ g_string_append (str, _("3G, 5G (Preferred)"));
+ else if (preferred & MM_MODEM_MODE_3G)
+ g_string_append (str, _("3G (Preferred), 5G"));
+ else
+ g_string_append (str, _("3G, 5G"));
+ }
+ else if (allowed & MM_MODEM_MODE_4G &&
+ allowed & MM_MODEM_MODE_5G)
+ {
+ if (preferred & MM_MODEM_MODE_5G)
+ g_string_append (str, _("4G, 5G (Preferred)"));
+ else if (preferred & MM_MODEM_MODE_4G)
+ g_string_append (str, _("4G (Preferred), 5G"));
+ else
+ g_string_append (str, _("4G, 5G"));
+ }
+
+ if (!str->len)
+ g_string_append (str, C_("Network mode", "Unknown"));
+
+ return g_string_free (str, FALSE);
+}
+
+static void
+wwan_network_list_free (GList *network_list)
+{
+ g_list_free_full (network_list, (GDestroyNotify)mm_modem_3gpp_network_free);
+}
+
+static void
+cc_wwan_device_scan_complete_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ MMModem3gpp *modem_3gpp = (MMModem3gpp *)object;
+ g_autoptr(GTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+ GList *network_list;
+
+ network_list = mm_modem_3gpp_scan_finish (modem_3gpp, result, &error);
+
+ if (error)
+ g_task_return_error (task, g_steal_pointer (&error));
+ else
+ g_task_return_pointer (task, network_list, (GDestroyNotify)wwan_network_list_free);
+}
+
+void
+cc_wwan_device_scan_networks (CcWwanDevice *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (CC_IS_WWAN_DEVICE (self));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = g_task_new (self, cancellable, callback, user_data);
+
+ mm_modem_3gpp_scan (self->modem_3gpp, cancellable,
+ cc_wwan_device_scan_complete_cb,
+ g_steal_pointer (&task));
+}
+
+GList *
+cc_wwan_device_scan_networks_finish (CcWwanDevice *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), FALSE);
+ g_return_val_if_fail (G_IS_TASK (result), FALSE);
+
+ return g_task_propagate_pointer (G_TASK (result), error);
+}
+
+static void
+cc_wwan_device_register_network_complete_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ CcWwanDevice *self;
+ MMModem3gpp *modem_3gpp = (MMModem3gpp *)object;
+ g_autoptr(GTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+
+ if (!mm_modem_3gpp_register_finish (modem_3gpp, result, &error))
+ {
+ self = g_task_get_source_object (G_TASK (task));
+
+ g_clear_error (&self->error);
+ self->error = g_error_copy (error);
+ g_warning ("Error: %s", error->message);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ERROR]);
+
+ g_task_return_error (task, g_steal_pointer (&error));
+ }
+ else
+ {
+ g_task_return_boolean (task, TRUE);
+ }
+}
+
+void
+cc_wwan_device_register_network (CcWwanDevice *self,
+ const gchar *network_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (CC_IS_WWAN_DEVICE (self));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = g_task_new (self, cancellable, callback, user_data);
+
+ if (network_id && *network_id)
+ self->network_is_manual = TRUE;
+ else
+ self->network_is_manual = FALSE;
+
+ mm_modem_3gpp_register (self->modem_3gpp, network_id, cancellable,
+ cc_wwan_device_register_network_complete_cb,
+ g_steal_pointer (&task));
+}
+
+gboolean
+cc_wwan_device_register_network_finish (CcWwanDevice *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), FALSE);
+ g_return_val_if_fail (G_IS_TASK (result), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+/**
+ * cc_wwan_device_get_operator_name:
+ * @self: a #CcWwanDevice
+ *
+ * Get the human readable network operator name
+ * currently the device is connected to.
+ *
+ * Returns: (nullable): The operator name or %NULL
+ */
+const gchar *
+cc_wwan_device_get_operator_name (CcWwanDevice *self)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), NULL);
+
+ if (!self->modem_3gpp)
+ return NULL;
+
+ return mm_modem_3gpp_get_operator_name (self->modem_3gpp);
+}
+
+gchar *
+cc_wwan_device_dup_own_numbers (CcWwanDevice *self)
+{
+ const char *const *own_numbers;
+
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), NULL);
+
+ own_numbers = mm_modem_get_own_numbers (self->modem);
+
+ if (!own_numbers)
+ return NULL;
+
+ return g_strjoinv ("\n", (char **)own_numbers);
+}
+
+gchar *
+cc_wwan_device_dup_network_type_string (CcWwanDevice *self)
+{
+ MMModemAccessTechnology type;
+
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), NULL);
+
+ type = mm_modem_get_access_technologies (self->modem);
+
+ return mm_modem_access_technology_build_string_from_mask (type);
+}
+
+gchar *
+cc_wwan_device_dup_signal_string (CcWwanDevice *self)
+{
+ MMModemSignal *modem_signal;
+ MMSignal *signal;
+ GString *str;
+ gdouble value;
+ gboolean recent;
+ guint refresh_rate;
+
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), NULL);
+
+ modem_signal = mm_object_peek_modem_signal (self->mm_object);
+
+ if (modem_signal)
+ refresh_rate = mm_modem_signal_get_rate (modem_signal);
+
+ if (!modem_signal || !refresh_rate)
+ return g_strdup_printf ("%d%%", mm_modem_get_signal_quality (self->modem, &recent));
+
+ str = g_string_new ("");
+
+ /* Adapted from ModemManager mmcli-modem-signal.c */
+ signal = mm_modem_signal_peek_cdma (modem_signal);
+ if (signal)
+ {
+ if ((value = mm_signal_get_rssi (signal)) != MM_SIGNAL_UNKNOWN)
+ g_string_append_printf (str, "rssi: %.2g dBm ", value);
+ if ((value = mm_signal_get_ecio (signal)) != MM_SIGNAL_UNKNOWN)
+ g_string_append_printf (str, "ecio: %.2g dBm ", value);
+ }
+
+ signal = mm_modem_signal_peek_evdo (modem_signal);
+ if (signal)
+ {
+ if ((value = mm_signal_get_rssi (signal)) != MM_SIGNAL_UNKNOWN)
+ g_string_append_printf (str, "rssi: %.2g dBm ", value);
+ if ((value = mm_signal_get_ecio (signal)) != MM_SIGNAL_UNKNOWN)
+ g_string_append_printf (str, "ecio: %.2g dBm ", value);
+ if ((value = mm_signal_get_sinr (signal)) != MM_SIGNAL_UNKNOWN)
+ g_string_append_printf (str, "sinr: %.2g dB ", value);
+ if ((value = mm_signal_get_io (signal)) != MM_SIGNAL_UNKNOWN)
+ g_string_append_printf (str, "io: %.2g dBm ", value);
+ }
+
+ signal = mm_modem_signal_peek_gsm (modem_signal);
+ if (signal)
+ if ((value = mm_signal_get_rssi (signal)) != MM_SIGNAL_UNKNOWN)
+ g_string_append_printf (str, "rssi: %.2g dBm ", value);
+
+ signal = mm_modem_signal_peek_umts (modem_signal);
+ if (signal)
+ {
+ if ((value = mm_signal_get_rssi (signal)) != MM_SIGNAL_UNKNOWN)
+ g_string_append_printf (str, "rssi: %.2g dBm ", value);
+ if ((value = mm_signal_get_rscp (signal)) != MM_SIGNAL_UNKNOWN)
+ g_string_append_printf (str, "rscp: %.2g dBm ", value);
+ if ((value = mm_signal_get_ecio (signal)) != MM_SIGNAL_UNKNOWN)
+ g_string_append_printf (str, "ecio: %.2g dBm ", value);
+ }
+
+ signal = mm_modem_signal_peek_lte (modem_signal);
+ if (signal)
+ {
+ if ((value = mm_signal_get_rssi (signal)) != MM_SIGNAL_UNKNOWN)
+ g_string_append_printf (str, "rssi: %.2g dBm ", value);
+ if ((value = mm_signal_get_rsrq (signal)) != MM_SIGNAL_UNKNOWN)
+ g_string_append_printf (str, "rsrq: %.2g dB ", value);
+ if ((value = mm_signal_get_rsrp (signal)) != MM_SIGNAL_UNKNOWN)
+ g_string_append_printf (str, "rsrp: %.2g dBm ", value);
+ if ((value = mm_signal_get_snr (signal)) != MM_SIGNAL_UNKNOWN)
+ g_string_append_printf (str, "snr: %.2g dB ", value);
+ }
+
+ return g_string_free (str, FALSE);
+}
+
+const gchar *
+cc_wwan_device_get_manufacturer (CcWwanDevice *self)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), NULL);
+
+ return mm_modem_get_manufacturer (self->modem);
+}
+
+const gchar *
+cc_wwan_device_get_model (CcWwanDevice *self)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), NULL);
+
+ return mm_modem_get_model (self->modem);
+}
+
+const gchar *
+cc_wwan_device_get_firmware_version (CcWwanDevice *self)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), NULL);
+
+ return mm_modem_get_revision (self->modem);
+}
+
+const gchar *
+cc_wwan_device_get_identifier (CcWwanDevice *self)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), NULL);
+
+ return mm_modem_get_equipment_identifier (self->modem);
+}
+
+const gchar *
+cc_wwan_device_get_simple_error (CcWwanDevice *self)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), NULL);
+
+ if (!self->error)
+ return NULL;
+
+ g_dbus_error_strip_remote_error (self->error);
+
+ return cc_wwan_error_get_message (self->error);
+}
+
+gboolean
+cc_wwan_device_is_nm_device (CcWwanDevice *self,
+ GObject *nm_device)
+{
+#if defined(HAVE_NETWORK_MANAGER) && defined(BUILD_NETWORK)
+ g_return_val_if_fail (NM_IS_DEVICE (nm_device), FALSE);
+
+ return g_str_equal (mm_modem_get_primary_port (self->modem),
+ nm_device_get_iface (NM_DEVICE (nm_device)));
+#else
+ return FALSE;
+#endif
+}
+
+const gchar *
+cc_wwan_device_get_path (CcWwanDevice *self)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), "");
+
+ return mm_object_get_path (self->mm_object);
+}
+
+CcWwanData *
+cc_wwan_device_get_data (CcWwanDevice *self)
+{
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), NULL);
+
+ return self->wwan_data;
+}
+
+gboolean
+cc_wwan_device_pin_valid (const gchar *password,
+ MMModemLock lock)
+{
+ size_t len;
+
+ g_return_val_if_fail (lock == MM_MODEM_LOCK_SIM_PIN ||
+ lock == MM_MODEM_LOCK_SIM_PIN2 ||
+ lock == MM_MODEM_LOCK_SIM_PUK ||
+ lock == MM_MODEM_LOCK_SIM_PUK2, FALSE);
+ if (!password)
+ return FALSE;
+
+ len = strlen (password);
+
+ if (len < 4 || len > 8)
+ return FALSE;
+
+ if (strspn (password, "0123456789") != len)
+ return FALSE;
+
+ /*
+ * XXX: Can PUK code be something other than 8 digits?
+ * 3GPP standard seems mum on this
+ */
+ if (lock == MM_MODEM_LOCK_SIM_PUK ||
+ lock == MM_MODEM_LOCK_SIM_PUK2)
+ if (len != 8)
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/panels/wwan/cc-wwan-device.h b/panels/wwan/cc-wwan-device.h
new file mode 100644
index 0000000..e484bcf
--- /dev/null
+++ b/panels/wwan/cc-wwan-device.h
@@ -0,0 +1,152 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-wwan-device.h
+ *
+ * Copyright 2019-2020 Purism SPC
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <glib-object.h>
+#include <libmm-glib.h>
+
+#if defined(HAVE_NETWORK_MANAGER) && defined(BUILD_NETWORK)
+# include "cc-wwan-data.h"
+#endif
+
+G_BEGIN_DECLS
+
+typedef enum
+{
+ CC_WWAN_REGISTRATION_STATE_UNKNOWN,
+ CC_WWAN_REGISTRATION_STATE_IDLE,
+ CC_WWAN_REGISTRATION_STATE_REGISTERED,
+ CC_WWAN_REGISTRATION_STATE_ROAMING,
+ CC_WWAN_REGISTRATION_STATE_SEARCHING,
+ CC_WWAN_REGISTRATION_STATE_DENIED
+} CcWwanState;
+
+typedef struct _CcWwanData CcWwanData;
+
+#define CC_TYPE_WWAN_DEVICE (cc_wwan_device_get_type())
+G_DECLARE_FINAL_TYPE (CcWwanDevice, cc_wwan_device, CC, WWAN_DEVICE, GObject)
+
+CcWwanDevice *cc_wwan_device_new (MMObject *mm_object,
+ GObject *nm_client);
+gboolean cc_wwan_device_has_sim (CcWwanDevice *self);
+MMModemLock cc_wwan_device_get_lock (CcWwanDevice *self);
+gboolean cc_wwan_device_get_sim_lock (CcWwanDevice *self);
+guint cc_wwan_device_get_unlock_retries (CcWwanDevice *self,
+ MMModemLock lock);
+void cc_wwan_device_enable_pin (CcWwanDevice *self,
+ const gchar *pin,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean cc_wwan_device_enable_pin_finish (CcWwanDevice *self,
+ GAsyncResult *result,
+ GError **error);
+void cc_wwan_device_disable_pin (CcWwanDevice *self,
+ const gchar *pin,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean cc_wwan_device_disable_pin_finish (CcWwanDevice *self,
+ GAsyncResult *result,
+ GError **error);
+void cc_wwan_device_send_pin (CcWwanDevice *self,
+ const gchar *pin,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean cc_wwan_device_send_pin_finish (CcWwanDevice *self,
+ GAsyncResult *result,
+ GError **error);
+void cc_wwan_device_send_puk (CcWwanDevice *self,
+ const gchar *puk,
+ const gchar *pin,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean cc_wwan_device_send_puk_finish (CcWwanDevice *self,
+ GAsyncResult *result,
+ GError **error);
+void cc_wwan_device_change_pin (CcWwanDevice *self,
+ const gchar *old_pin,
+ const gchar *new_pin,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean cc_wwan_device_change_pin_finish (CcWwanDevice *self,
+ GAsyncResult *result,
+ GError **error);
+const gchar *cc_wwan_device_get_operator_name (CcWwanDevice *self);
+gchar *cc_wwan_device_dup_own_numbers (CcWwanDevice *self);
+gchar *cc_wwan_device_dup_network_type_string (CcWwanDevice *self);
+gchar *cc_wwan_device_dup_signal_string (CcWwanDevice *self);
+const gchar *cc_wwan_device_get_manufacturer (CcWwanDevice *self);
+const gchar *cc_wwan_device_get_model (CcWwanDevice *self);
+const gchar *cc_wwan_device_get_firmware_version (CcWwanDevice *self);
+const gchar *cc_wwan_device_get_identifier (CcWwanDevice *self);
+gboolean cc_wwan_device_get_current_mode (CcWwanDevice *self,
+ MMModemMode *allowed,
+ MMModemMode *preferred);
+gboolean cc_wwan_device_is_auto_network (CcWwanDevice *self);
+CcWwanState cc_wwan_device_get_network_state (CcWwanDevice *self);
+gboolean cc_wwan_device_get_supported_modes (CcWwanDevice *self,
+ MMModemMode *allowed,
+ MMModemMode *preferred);
+void cc_wwan_device_set_current_mode (CcWwanDevice *self,
+ MMModemMode allowed,
+ MMModemMode preferred,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean cc_wwan_device_set_current_mode_finish (CcWwanDevice *self,
+ GAsyncResult *result,
+ GError **error);
+gchar *cc_wwan_device_get_string_from_mode (CcWwanDevice *self,
+ MMModemMode allowed,
+ MMModemMode preferred);
+void cc_wwan_device_scan_networks (CcWwanDevice *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GList *cc_wwan_device_scan_networks_finish (CcWwanDevice *self,
+ GAsyncResult *result,
+ GError **error);
+void cc_wwan_device_register_network (CcWwanDevice *self,
+ const gchar *network_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean cc_wwan_device_register_network_finish (CcWwanDevice *self,
+ GAsyncResult *result,
+ GError **error);
+const gchar *cc_wwan_device_get_simple_error (CcWwanDevice *self);
+GSList *cc_wwan_device_get_apn_list (CcWwanDevice *self);
+gboolean cc_wwan_device_is_nm_device (CcWwanDevice *self,
+ GObject *nm_device);
+const gchar *cc_wwan_device_get_path (CcWwanDevice *self);
+CcWwanData *cc_wwan_device_get_data (CcWwanDevice *self);
+gboolean cc_wwan_device_pin_valid (const gchar *password,
+ MMModemLock lock);
+
+G_END_DECLS
diff --git a/panels/wwan/cc-wwan-errors-private.h b/panels/wwan/cc-wwan-errors-private.h
new file mode 100644
index 0000000..15cc76a
--- /dev/null
+++ b/panels/wwan/cc-wwan-errors-private.h
@@ -0,0 +1,107 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-wwan-errors-private.h
+ *
+ * Copyright 2019 Purism SPC
+ *
+ * Modified from mm-error-helpers.c from ModemManager
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <libmm-glib.h>
+
+typedef struct {
+ guint code;
+ const gchar *message;
+} ErrorTable;
+
+
+static ErrorTable me_errors[] = {
+ { MM_MOBILE_EQUIPMENT_ERROR_PHONE_FAILURE, N_("Phone failure") },
+ { MM_MOBILE_EQUIPMENT_ERROR_NO_CONNECTION, N_("No connection to phone") },
+ { MM_MOBILE_EQUIPMENT_ERROR_LINK_RESERVED, "Phone-adaptor link reserved" },
+ { MM_MOBILE_EQUIPMENT_ERROR_NOT_ALLOWED, N_("Operation not allowed") },
+ { MM_MOBILE_EQUIPMENT_ERROR_NOT_SUPPORTED, N_("Operation not supported") },
+ { MM_MOBILE_EQUIPMENT_ERROR_PH_SIM_PIN, "PH-SIM PIN required" },
+ { MM_MOBILE_EQUIPMENT_ERROR_PH_FSIM_PIN, "PH-FSIM PIN required" },
+ { MM_MOBILE_EQUIPMENT_ERROR_PH_FSIM_PUK, "PH-FSIM PUK required" },
+ { MM_MOBILE_EQUIPMENT_ERROR_SIM_NOT_INSERTED, N_("SIM not inserted") },
+ { MM_MOBILE_EQUIPMENT_ERROR_SIM_PIN, N_("SIM PIN required") },
+ { MM_MOBILE_EQUIPMENT_ERROR_SIM_PUK, N_("SIM PUK required") },
+ { MM_MOBILE_EQUIPMENT_ERROR_SIM_FAILURE, N_("SIM failure") },
+ { MM_MOBILE_EQUIPMENT_ERROR_SIM_BUSY, N_("SIM busy") },
+ { MM_MOBILE_EQUIPMENT_ERROR_SIM_WRONG, N_("SIM wrong") },
+ { MM_MOBILE_EQUIPMENT_ERROR_INCORRECT_PASSWORD, N_("Incorrect password") },
+ { MM_MOBILE_EQUIPMENT_ERROR_SIM_PIN2, N_("SIM PIN2 required") },
+ { MM_MOBILE_EQUIPMENT_ERROR_SIM_PUK2, N_("SIM PUK2 required") },
+ { MM_MOBILE_EQUIPMENT_ERROR_MEMORY_FULL, "Memory full" },
+ { MM_MOBILE_EQUIPMENT_ERROR_INVALID_INDEX, "Invalid index" },
+ { MM_MOBILE_EQUIPMENT_ERROR_NOT_FOUND, N_("Not found") },
+ { MM_MOBILE_EQUIPMENT_ERROR_MEMORY_FAILURE, "Memory failure" },
+ { MM_MOBILE_EQUIPMENT_ERROR_NO_NETWORK, N_("No network service") },
+ { MM_MOBILE_EQUIPMENT_ERROR_NETWORK_TIMEOUT, N_("Network timeout") },
+ { MM_MOBILE_EQUIPMENT_ERROR_NETWORK_NOT_ALLOWED, "Network not allowed - emergency calls only" },
+ { MM_MOBILE_EQUIPMENT_ERROR_NETWORK_PIN, "Network personalization PIN required" },
+ { MM_MOBILE_EQUIPMENT_ERROR_NETWORK_PUK, "Network personalization PUK required" },
+ { MM_MOBILE_EQUIPMENT_ERROR_NETWORK_SUBSET_PIN, "Network subset personalization PIN required" },
+ { MM_MOBILE_EQUIPMENT_ERROR_NETWORK_SUBSET_PUK, "Network subset personalization PUK required" },
+ { MM_MOBILE_EQUIPMENT_ERROR_SERVICE_PIN, "Service provider personalization PIN required" },
+ { MM_MOBILE_EQUIPMENT_ERROR_SERVICE_PUK, "Service provider personalization PUK required" },
+ { MM_MOBILE_EQUIPMENT_ERROR_CORP_PIN, "Corporate personalization PIN required" },
+ { MM_MOBILE_EQUIPMENT_ERROR_CORP_PUK, "Corporate personalization PUK required" },
+ { MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN, N_("Unknown error") },
+ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_ILLEGAL_MS, "Illegal MS" },
+ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_ILLEGAL_ME, "Illegal ME" },
+ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_SERVICE_NOT_ALLOWED, N_("GPRS services not allowed") },
+ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_PLMN_NOT_ALLOWED, "PLMN not allowed" },
+ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_LOCATION_NOT_ALLOWED, "Location area not allowed" },
+ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_ROAMING_NOT_ALLOWED, N_("Roaming not allowed in this location area") },
+ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_SERVICE_OPTION_NOT_SUPPORTED, "Service option not supported" },
+ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_SERVICE_OPTION_NOT_SUBSCRIBED, "Requested service option not subscribed" },
+ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_SERVICE_OPTION_OUT_OF_ORDER, "Service option temporarily out of order" },
+ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_UNKNOWN, N_("Unspecified GPRS error") },
+ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_PDP_AUTH_FAILURE, "PDP authentication failure" },
+ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_INVALID_MOBILE_CLASS, "Invalid mobile class" },
+};
+
+static inline const gchar *
+cc_wwan_error_get_message (GError *error)
+{
+ if (!error)
+ return _("No Error");
+
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return _("Action Cancelled");
+
+ if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED))
+ return _("Access denied");
+
+ if (error->domain != MM_MOBILE_EQUIPMENT_ERROR)
+ return error->message;
+
+ for (guint i = 0; i < G_N_ELEMENTS (me_errors); i++)
+ if (me_errors[i].code == error->code)
+ return _(me_errors[i].message);
+
+ return _("Unknown Error");
+}
diff --git a/panels/wwan/cc-wwan-mode-dialog.c b/panels/wwan/cc-wwan-mode-dialog.c
new file mode 100644
index 0000000..dd5a4a1
--- /dev/null
+++ b/panels/wwan/cc-wwan-mode-dialog.c
@@ -0,0 +1,335 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-wwan-mode-dialog.c
+ *
+ * Copyright 2019,2022 Purism SPC
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "cc-network-mode-dialog"
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include <libmm-glib.h>
+
+#include "cc-wwan-mode-dialog.h"
+#include "cc-wwan-resources.h"
+
+/**
+ * @short_description: WWAN network type selection dialog
+ */
+
+#define CC_TYPE_WWAN_MODE_ROW (cc_wwan_mode_row_get_type())
+G_DECLARE_FINAL_TYPE (CcWwanModeRow, cc_wwan_mode_row, CC, WWAN_MODE_ROW, GtkListBoxRow)
+
+struct _CcWwanModeDialog
+{
+ GtkDialog parent_instance;
+
+ CcWwanDevice *device;
+ GtkListBox *network_mode_list;
+ CcWwanModeRow *selected_row;
+
+ MMModemMode preferred;
+ MMModemMode allowed;
+ MMModemMode new_allowed;
+ MMModemMode new_preferred;
+};
+
+G_DEFINE_TYPE (CcWwanModeDialog, cc_wwan_mode_dialog, GTK_TYPE_DIALOG)
+
+
+enum {
+ PROP_0,
+ PROP_DEVICE,
+ N_PROPS
+};
+
+static GParamSpec *properties[N_PROPS];
+
+struct _CcWwanModeRow
+{
+ GtkListBoxRow parent_instance;
+ GtkImage *ok_emblem;
+ MMModemMode allowed;
+ MMModemMode preferred;
+};
+
+G_DEFINE_TYPE (CcWwanModeRow, cc_wwan_mode_row, GTK_TYPE_LIST_BOX_ROW)
+
+static void
+cc_wwan_mode_row_class_init (CcWwanModeRowClass *klass)
+{
+}
+
+static void
+cc_wwan_mode_row_init (CcWwanModeRow *row)
+{
+}
+
+static void
+cc_wwan_mode_changed_cb (CcWwanModeDialog *self,
+ CcWwanModeRow *row)
+{
+ g_assert (CC_IS_WWAN_MODE_DIALOG (self));
+ g_assert (CC_IS_WWAN_MODE_ROW (row));
+
+ if (row == self->selected_row)
+ return;
+
+ gtk_widget_show (GTK_WIDGET (row->ok_emblem));
+
+ if (self->selected_row)
+ gtk_widget_hide (GTK_WIDGET (self->selected_row->ok_emblem));
+
+ self->selected_row = row;
+}
+
+static void
+cc_wwan_mode_dialog_ok_clicked_cb (CcWwanModeDialog *self)
+{
+ g_assert (CC_IS_WWAN_MODE_DIALOG (self));
+
+ if (self->selected_row)
+ {
+ cc_wwan_device_set_current_mode (self->device,
+ self->selected_row->allowed,
+ self->selected_row->preferred,
+ NULL, NULL, NULL);
+ }
+ else
+ {
+ g_return_if_reached ();
+ }
+
+ gtk_widget_hide (GTK_WIDGET (self));
+}
+
+static GtkWidget *
+cc_wwan_mode_dialog_row_new (CcWwanModeDialog *self,
+ MMModemMode allowed,
+ MMModemMode preferred)
+{
+ CcWwanModeRow *row;
+ GtkWidget *box, *label, *image;
+ g_autofree gchar *mode = NULL;
+
+ g_assert (CC_WWAN_MODE_DIALOG (self));
+
+ row = g_object_new (CC_TYPE_WWAN_MODE_ROW, NULL);
+ row->allowed = allowed;
+ row->preferred = preferred;
+
+ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+ gtk_widget_show (box);
+ g_object_set (box,
+ "margin-top", 18,
+ "margin-bottom", 18,
+ "margin-start", 18,
+ "margin-end", 18,
+ NULL);
+ gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), box);
+
+ mode = cc_wwan_device_get_string_from_mode (self->device, allowed, preferred);
+ label = gtk_label_new (mode);
+ gtk_widget_set_hexpand (label, TRUE);
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+ gtk_box_append (GTK_BOX (box), label);
+
+ /* image should be hidden by default */
+ image = gtk_image_new_from_icon_name ("emblem-ok-symbolic");
+ gtk_widget_hide (image);
+ row->ok_emblem = GTK_IMAGE (image);
+ gtk_box_append (GTK_BOX (box), image);
+
+ return GTK_WIDGET (row);
+}
+
+static void
+cc_wwan_mode_dialog_update (CcWwanModeDialog *self)
+{
+ MMModemMode allowed;
+ MMModemMode modes[][2] = {
+ {MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, MM_MODEM_MODE_5G},
+ {MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, 0},
+ {MM_MODEM_MODE_3G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, MM_MODEM_MODE_5G},
+ {MM_MODEM_MODE_3G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, 0},
+ {MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_4G},
+ {MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, 0},
+ {MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_4G},
+ {MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, 0},
+ {MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, MM_MODEM_MODE_3G},
+ {MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, 0},
+ {MM_MODEM_MODE_5G, 0},
+ {MM_MODEM_MODE_4G, 0},
+ {MM_MODEM_MODE_3G, 0},
+ {MM_MODEM_MODE_2G, 0},
+ };
+ size_t i;
+
+ g_assert (CC_IS_WWAN_MODE_DIALOG (self));
+
+ if (!cc_wwan_device_get_supported_modes (self->device, &allowed, NULL))
+ {
+ g_warning ("No modes supported by modem");
+ return;
+ }
+
+ for (i = 0; i < G_N_ELEMENTS (modes); i++)
+ {
+ GtkWidget *row;
+
+ if ((modes[i][0] & allowed) != modes[i][0])
+ continue;
+
+ if (modes[i][1] && !(modes[i][1] & allowed))
+ continue;
+
+ row = cc_wwan_mode_dialog_row_new (self, modes[i][0], modes[i][1]);
+ gtk_list_box_append (GTK_LIST_BOX (self->network_mode_list), row);
+ }
+}
+
+static void
+cc_wwan_mode_dialog_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcWwanModeDialog *self = CC_WWAN_MODE_DIALOG (object);
+
+ switch (prop_id)
+ {
+ case PROP_DEVICE:
+ self->device = g_value_dup_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_wwan_mode_dialog_constructed (GObject *object)
+{
+ CcWwanModeDialog *self = CC_WWAN_MODE_DIALOG (object);
+
+ G_OBJECT_CLASS (cc_wwan_mode_dialog_parent_class)->constructed (object);
+
+ if(!cc_wwan_device_get_current_mode (self->device, &self->allowed, &self->preferred))
+ g_warning ("Can't get allowed and preferred wwan modes");
+
+ cc_wwan_mode_dialog_update (self);
+}
+
+static void
+cc_wwan_mode_dialog_dispose (GObject *object)
+{
+ CcWwanModeDialog *self = CC_WWAN_MODE_DIALOG (object);
+
+ g_clear_object (&self->device);
+
+ G_OBJECT_CLASS (cc_wwan_mode_dialog_parent_class)->dispose (object);
+}
+
+static void
+cc_wwan_mode_dialog_update_mode (CcWwanModeRow *row,
+ CcWwanModeDialog *self)
+{
+ if (self->allowed == row->allowed && self->preferred == row->preferred)
+ {
+ self->selected_row = row;
+ gtk_widget_show (GTK_WIDGET (row->ok_emblem));
+ }
+ else
+ gtk_widget_hide (GTK_WIDGET (row->ok_emblem));
+}
+
+static void
+cc_wwan_mode_dialog_show (GtkWidget *widget)
+{
+ CcWwanModeDialog *self = CC_WWAN_MODE_DIALOG (widget);
+
+ if(!cc_wwan_device_get_current_mode (self->device, &self->allowed, &self->preferred))
+ {
+ g_warning ("Can't get allowed and preferred wwan modes");
+ goto end;
+ }
+
+ self->selected_row = NULL;
+
+ for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (self->network_mode_list));
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ cc_wwan_mode_dialog_update_mode (CC_WWAN_MODE_ROW (child), self);
+
+ end:
+ GTK_WIDGET_CLASS (cc_wwan_mode_dialog_parent_class)->show (widget);
+}
+
+static void
+cc_wwan_mode_dialog_class_init (CcWwanModeDialogClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = cc_wwan_mode_dialog_set_property;
+ object_class->constructed = cc_wwan_mode_dialog_constructed;
+ object_class->dispose = cc_wwan_mode_dialog_dispose;
+
+ widget_class->show = cc_wwan_mode_dialog_show;
+
+ properties[PROP_DEVICE] =
+ g_param_spec_object ("device",
+ "Device",
+ "The WWAN Device",
+ CC_TYPE_WWAN_DEVICE,
+ G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/control-center/wwan/cc-wwan-mode-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcWwanModeDialog, network_mode_list);
+
+ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_mode_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_mode_dialog_ok_clicked_cb);
+}
+
+static void
+cc_wwan_mode_dialog_init (CcWwanModeDialog *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+CcWwanModeDialog *
+cc_wwan_mode_dialog_new (GtkWindow *parent_window,
+ CcWwanDevice *device)
+{
+ g_return_val_if_fail (GTK_IS_WINDOW (parent_window), NULL);
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (device), NULL);
+
+ return g_object_new (CC_TYPE_WWAN_MODE_DIALOG,
+ "transient-for", parent_window,
+ "use-header-bar", 1,
+ "device", device,
+ NULL);
+}
diff --git a/panels/wwan/cc-wwan-mode-dialog.h b/panels/wwan/cc-wwan-mode-dialog.h
new file mode 100644
index 0000000..0916ddf
--- /dev/null
+++ b/panels/wwan/cc-wwan-mode-dialog.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-wwan-mode-dialog.h
+ *
+ * Copyright 2019 Purism SPC
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <adwaita.h>
+#include <shell/cc-panel.h>
+
+#include "cc-wwan-device.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_WWAN_MODE_DIALOG (cc_wwan_mode_dialog_get_type())
+G_DECLARE_FINAL_TYPE (CcWwanModeDialog, cc_wwan_mode_dialog, CC, WWAN_MODE_DIALOG, GtkDialog)
+
+CcWwanModeDialog *cc_wwan_mode_dialog_new (GtkWindow *parent_window,
+ CcWwanDevice *device);
+
+G_END_DECLS
diff --git a/panels/wwan/cc-wwan-mode-dialog.ui b/panels/wwan/cc-wwan-mode-dialog.ui
new file mode 100644
index 0000000..4c350c8
--- /dev/null
+++ b/panels/wwan/cc-wwan-mode-dialog.ui
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk" version="4.0"/>
+ <template class="CcWwanModeDialog" parent="GtkDialog">
+ <property name="title" translatable="yes">Network Mode</property>
+ <property name="default-height">480</property>
+ <property name="default-width">360</property>
+ <property name="hide-on-close">True</property>
+ <property name="modal">True</property>
+
+ <child>
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="GtkListBox" id="network_mode_list">
+ <property name="selection-mode">none</property>
+ <signal name="row-activated" handler="cc_wwan_mode_changed_cb" swapped="yes"/>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child type="action">
+ <object class="GtkButton" id="button_cancel">
+ <property name="use-underline">True</property>
+ <property name="label" translatable="yes">_Cancel</property>
+ <signal name="clicked" handler="gtk_widget_hide" swapped="yes"/>
+ </object>
+ </child>
+ <child type="action">
+ <object class="GtkButton" id="button_ok">
+ <property name="use-underline">True</property>
+ <property name="label" translatable="yes">_Set</property>
+ <signal name="clicked" handler="cc_wwan_mode_dialog_ok_clicked_cb" swapped="yes"/>
+ <style>
+ <class name="suggested-action "/>
+ </style>
+ </object>
+ </child>
+
+ <action-widgets>
+ <action-widget response="cancel">button_cancel</action-widget>
+ <action-widget response="apply" default="True">button_ok</action-widget>
+ </action-widgets>
+ </template>
+</interface>
diff --git a/panels/wwan/cc-wwan-network-dialog.c b/panels/wwan/cc-wwan-network-dialog.c
new file mode 100644
index 0000000..ac00547
--- /dev/null
+++ b/panels/wwan/cc-wwan-network-dialog.c
@@ -0,0 +1,432 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-wwan-network-dialog.c
+ *
+ * Copyright 2019,2022 Purism SPC
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "cc-wwan-network-dialog"
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include <libmm-glib.h>
+
+#include "cc-list-row.h"
+#include "cc-wwan-errors-private.h"
+#include "cc-wwan-network-dialog.h"
+#include "cc-wwan-resources.h"
+
+/**
+ * @short_description: WWAN network operator selection dialog
+ */
+
+#define CC_TYPE_WWAN_NETWORK_ROW (cc_wwan_network_row_get_type())
+G_DECLARE_FINAL_TYPE (CcWwanNetworkRow, cc_wwan_network_row, CC, WWAN_NETWORK_ROW, GtkListBoxRow)
+
+struct _CcWwanNetworkDialog
+{
+ GtkDialog parent_instance;
+
+ AdwToastOverlay *toast_overlay;
+ CcListRow *automatic_row;
+ GtkButton *button_apply;
+ GtkSpinner *loading_spinner;
+ GtkBox *network_search_title;
+ GtkListBox *operator_list_box;
+ GtkButton *refresh_button;
+
+ CcWwanDevice *device;
+ GList *operator_list;
+
+ CcWwanNetworkRow *selected_row;
+
+ GCancellable *search_cancellable;
+
+ gboolean no_update_network;
+};
+
+G_DEFINE_TYPE (CcWwanNetworkDialog, cc_wwan_network_dialog, GTK_TYPE_DIALOG)
+
+
+enum {
+ PROP_0,
+ PROP_DEVICE,
+ N_PROPS
+};
+
+static GParamSpec *properties[N_PROPS];
+
+struct _CcWwanNetworkRow
+{
+ GtkListBoxRow parent_instance;
+ GtkImage *ok_emblem;
+ gchar *operator_code;
+};
+
+G_DEFINE_TYPE (CcWwanNetworkRow, cc_wwan_network_row, GTK_TYPE_LIST_BOX_ROW)
+
+static void
+cc_wwan_network_row_finalize (GObject *object)
+{
+ CcWwanNetworkRow *row = (CcWwanNetworkRow *)object;
+
+ g_free (row->operator_code);
+
+ G_OBJECT_CLASS (cc_wwan_network_row_parent_class)->finalize (object);
+}
+
+static void
+cc_wwan_network_row_class_init (CcWwanNetworkRowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = cc_wwan_network_row_finalize;
+}
+
+static void
+cc_wwan_network_row_init (CcWwanNetworkRow *row)
+{
+}
+
+static void
+cc_wwan_network_changed_cb (CcWwanNetworkDialog *self,
+ CcWwanNetworkRow *row)
+{
+ if (row == self->selected_row)
+ return;
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->button_apply), TRUE);
+ gtk_widget_show (GTK_WIDGET (row->ok_emblem));
+
+ if (self->selected_row)
+ gtk_widget_hide (GTK_WIDGET (self->selected_row->ok_emblem));
+
+ self->selected_row = row;
+}
+
+/*
+ * cc_wwan_network_dialog_row_new:
+ * @self: a #CcWwanNetworkDialog
+ * @operator_name: (transfer full): The long operator name
+ * @operator_id: (transfer full): operator id
+ */
+static CcWwanNetworkRow *
+cc_wwan_network_dialog_row_new (CcWwanNetworkDialog *self,
+ const gchar *operator_name,
+ const gchar *operator_code)
+{
+ CcWwanNetworkRow *row;
+ GtkWidget *box, *label, *image;
+
+ row = g_object_new (CC_TYPE_WWAN_NETWORK_ROW, NULL);
+
+ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+ gtk_widget_show (box);
+ g_object_set (box,
+ "margin-top", 18,
+ "margin-bottom", 18,
+ "margin-start", 18,
+ "margin-end", 18,
+ NULL);
+ gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), box);
+
+ label = gtk_label_new (operator_name);
+ gtk_widget_set_hexpand (label, TRUE);
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+ gtk_box_append (GTK_BOX (box), label);
+
+ image = gtk_image_new_from_icon_name ("emblem-ok-symbolic");
+ gtk_widget_hide (image);
+ row->ok_emblem = GTK_IMAGE (image);
+ gtk_box_append (GTK_BOX (box), image);
+
+ row->operator_code = g_strdup (operator_code);
+
+ return row;
+}
+
+static void
+cc_wwan_network_dialog_update_current_network (CcWwanNetworkDialog *self)
+{
+ CcWwanNetworkRow *row;
+ GtkWidget *child;
+ const gchar *operator_name;
+
+ operator_name = cc_wwan_device_get_operator_name (self->device);
+
+ if (!operator_name || operator_name[0] == '\0')
+ return;
+
+ child = gtk_widget_get_first_child (GTK_WIDGET (self->operator_list_box));
+
+ while (child)
+ {
+ GtkWidget *next;
+
+ next = gtk_widget_get_next_sibling (child);
+ gtk_list_box_remove (GTK_LIST_BOX (self->operator_list_box), child);
+
+ child = next;
+ }
+
+ row = cc_wwan_network_dialog_row_new (self, operator_name, "");
+ self->selected_row = row;
+ gtk_widget_show (GTK_WIDGET (row->ok_emblem));
+ gtk_list_box_append (GTK_LIST_BOX (self->operator_list_box), GTK_WIDGET (row));
+}
+
+static void
+cc_wwan_network_dialog_update (CcWwanNetworkDialog *self)
+{
+ CcWwanNetworkRow *row;
+ GtkWidget *child;
+ GList *item;
+ const gchar *operator_code, *operator_name;
+
+ child = gtk_widget_get_first_child (GTK_WIDGET (self->operator_list_box));
+
+ while (child)
+ {
+ GtkWidget *next;
+
+ next = gtk_widget_get_next_sibling (child);
+ gtk_list_box_remove (GTK_LIST_BOX (self->operator_list_box), child);
+
+ child = next;
+ }
+
+ for (item = self->operator_list; item; item = item->next)
+ {
+ operator_code = mm_modem_3gpp_network_get_operator_code (item->data);
+ operator_name = mm_modem_3gpp_network_get_operator_long (item->data);
+
+ row = cc_wwan_network_dialog_row_new (self, operator_name, operator_code);
+ gtk_list_box_append (GTK_LIST_BOX (self->operator_list_box), GTK_WIDGET (row));
+ }
+}
+
+static void
+cc_wwan_network_scan_complete_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(CcWwanNetworkDialog) self = user_data;
+ g_autoptr(GError) error = NULL;
+
+ if (self->operator_list)
+ g_list_free_full (self->operator_list, (GDestroyNotify)mm_modem_3gpp_network_free);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->refresh_button), TRUE);
+ gtk_spinner_stop (self->loading_spinner);
+ self->operator_list = cc_wwan_device_scan_networks_finish (self->device, result, &error);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->operator_list_box), !error);
+
+ if (!error)
+ {
+ cc_wwan_network_dialog_update (self);
+ gtk_widget_show (GTK_WIDGET (self->operator_list_box));
+ }
+ else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ AdwToast *toast;
+
+ self->no_update_network = TRUE;
+ gtk_widget_activate (GTK_WIDGET (self->automatic_row));
+ gtk_widget_set_sensitive (GTK_WIDGET (self->operator_list_box), FALSE);
+
+ toast = adw_toast_new (cc_wwan_error_get_message (error));
+ adw_toast_overlay_add_toast (self->toast_overlay, toast);
+
+ gtk_widget_show (GTK_WIDGET (self->operator_list_box));
+ g_warning ("Error: scanning networks failed: %s", error->message);
+ }
+}
+
+static void
+cc_wwan_network_dialog_refresh_networks (CcWwanNetworkDialog *self)
+{
+ gtk_widget_set_sensitive (GTK_WIDGET (self->refresh_button), FALSE);
+ gtk_spinner_start (self->loading_spinner);
+ cc_wwan_device_scan_networks (self->device, self->search_cancellable,
+ (GAsyncReadyCallback)cc_wwan_network_scan_complete_cb,
+ g_object_ref (self));
+}
+
+static void
+cc_wwan_network_dialog_apply_clicked_cb (CcWwanNetworkDialog *self)
+{
+ gboolean is_auto;
+
+ g_assert (CC_IS_WWAN_NETWORK_DIALOG (self));
+
+ is_auto = cc_list_row_get_active (self->automatic_row);
+
+ if (is_auto)
+ cc_wwan_device_register_network (self->device, "", NULL, NULL, NULL);
+ else if (self->selected_row)
+ cc_wwan_device_register_network (self->device, self->selected_row->operator_code, NULL, NULL, self);
+ else
+ g_warn_if_reached ();
+
+ gtk_widget_hide (GTK_WIDGET (self));
+}
+
+static void
+cc_wwan_auto_network_changed_cb (CcWwanNetworkDialog *self,
+ GParamSpec *pspec,
+ CcListRow *auto_network_row)
+{
+ gboolean is_auto;
+
+ g_assert (CC_IS_WWAN_NETWORK_DIALOG (self));
+ g_assert (CC_IS_LIST_ROW (auto_network_row));
+
+ is_auto = cc_list_row_get_active (auto_network_row);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->button_apply), is_auto);
+
+ if (self->no_update_network)
+ {
+ self->no_update_network = FALSE;
+ return;
+ }
+
+ self->selected_row = NULL;
+ gtk_widget_set_visible (GTK_WIDGET (self->network_search_title), !is_auto);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->operator_list_box), !is_auto);
+ gtk_widget_hide (GTK_WIDGET (self->operator_list_box));
+
+ if (is_auto)
+ {
+ g_cancellable_cancel (self->search_cancellable);
+ g_cancellable_reset (self->search_cancellable);
+ }
+ else
+ {
+ cc_wwan_network_dialog_refresh_networks (self);
+ }
+}
+
+static void
+cc_wwan_network_dialog_show (GtkWidget *widget)
+{
+ CcWwanNetworkDialog *self = (CcWwanNetworkDialog *)widget;
+ gboolean is_auto;
+
+ is_auto = cc_wwan_device_is_auto_network (self->device);
+
+ self->no_update_network = TRUE;
+ g_object_set (self->automatic_row, "active", is_auto, NULL);
+
+ cc_wwan_network_dialog_update_current_network (self);
+
+ GTK_WIDGET_CLASS (cc_wwan_network_dialog_parent_class)->show (widget);
+}
+
+static void
+cc_wwan_network_dialog_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcWwanNetworkDialog *self = (CcWwanNetworkDialog *)object;
+
+ switch (prop_id)
+ {
+ case PROP_DEVICE:
+ self->device = g_value_dup_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_wwan_network_dialog_dispose (GObject *object)
+{
+ CcWwanNetworkDialog *self = (CcWwanNetworkDialog *)object;
+
+ g_cancellable_cancel (self->search_cancellable);
+
+ g_clear_object (&self->search_cancellable);
+ g_clear_object (&self->device);
+
+ G_OBJECT_CLASS (cc_wwan_network_dialog_parent_class)->dispose (object);
+}
+
+static void
+cc_wwan_network_dialog_class_init (CcWwanNetworkDialogClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = cc_wwan_network_dialog_set_property;
+ object_class->dispose = cc_wwan_network_dialog_dispose;
+
+ widget_class->show = cc_wwan_network_dialog_show;
+
+ properties[PROP_DEVICE] =
+ g_param_spec_object ("device",
+ "Device",
+ "The WWAN Device",
+ CC_TYPE_WWAN_DEVICE,
+ G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/control-center/wwan/cc-wwan-network-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcWwanNetworkDialog, toast_overlay);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanNetworkDialog, automatic_row);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanNetworkDialog, button_apply);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanNetworkDialog, loading_spinner);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanNetworkDialog, network_search_title);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanNetworkDialog, operator_list_box);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanNetworkDialog, refresh_button);
+
+ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_network_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_auto_network_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_network_dialog_refresh_networks);
+ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_network_dialog_apply_clicked_cb);
+}
+
+static void
+cc_wwan_network_dialog_init (CcWwanNetworkDialog *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->search_cancellable = g_cancellable_new ();
+}
+
+CcWwanNetworkDialog *
+cc_wwan_network_dialog_new (GtkWindow *parent_window,
+ CcWwanDevice *device)
+{
+ g_return_val_if_fail (GTK_IS_WINDOW (parent_window), NULL);
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (device), NULL);
+
+ return g_object_new (CC_TYPE_WWAN_NETWORK_DIALOG,
+ "transient-for", parent_window,
+ "use-header-bar", 1,
+ "device", device,
+ NULL);
+}
diff --git a/panels/wwan/cc-wwan-network-dialog.h b/panels/wwan/cc-wwan-network-dialog.h
new file mode 100644
index 0000000..bd7091e
--- /dev/null
+++ b/panels/wwan/cc-wwan-network-dialog.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-wwan-network-dialog.h
+ *
+ * Copyright 2019 Purism SPC
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <adwaita.h>
+#include <shell/cc-panel.h>
+
+#include "cc-wwan-device.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_WWAN_NETWORK_DIALOG (cc_wwan_network_dialog_get_type())
+G_DECLARE_FINAL_TYPE (CcWwanNetworkDialog, cc_wwan_network_dialog, CC, WWAN_NETWORK_DIALOG, GtkDialog)
+
+CcWwanNetworkDialog *cc_wwan_network_dialog_new (GtkWindow *parent_window,
+ CcWwanDevice *device);
+
+G_END_DECLS
diff --git a/panels/wwan/cc-wwan-network-dialog.ui b/panels/wwan/cc-wwan-network-dialog.ui
new file mode 100644
index 0000000..1ffc4e5
--- /dev/null
+++ b/panels/wwan/cc-wwan-network-dialog.ui
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk" version="4.0"/>
+ <template class="CcWwanNetworkDialog" parent="GtkDialog">
+ <property name="title" translatable="yes">Network</property>
+ <property name="default-height">480</property>
+ <property name="default-width">360</property>
+ <property name="hide-on-close">True</property>
+ <property name="modal">True</property>
+
+ <child>
+ <object class="GtkBox">
+ <property name="width-request">340</property>
+ <property name="height-request">360</property>
+ <child>
+ <object class="AdwToastOverlay" id="toast_overlay">
+ <property name="hexpand">True</property>
+ <property name="child">
+ <object class="GtkBox">
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="margin-top">18</property>
+ <property name="margin-bottom">18</property>
+ <property name="orientation">vertical</property>
+
+ <!-- Automatic Network Selection Switch -->
+ <child>
+ <object class="GtkListBox">
+ <property name="selection-mode">none</property>
+ <property name="margin-bottom">18</property>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ <child>
+ <object class="CcListRow" id="automatic_row">
+ <property name="show-switch">True</property>
+ <property name="use-underline">True</property>
+ <property name="title" translatable="yes">_Automatic</property>
+ <signal name="notify::active" handler="cc_wwan_auto_network_changed_cb" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- Network Selection List Title and Spinner -->
+ <child>
+ <object class="GtkBox" id="network_search_title">
+ <property name="visible" bind-source="automatic_row" bind-property="active" bind-flags="sync-create|invert-boolean"/>
+ <property name="margin-bottom">9</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Choose Network</property>
+ <property name="xalign">0.0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSpinner" id="loading_spinner"/>
+ </child>
+ <child>
+ <object class="GtkButton" id="refresh_button">
+ <property name="icon-name">view-refresh-symbolic</property>
+ <signal name="clicked" handler="cc_wwan_network_dialog_refresh_networks" swapped="yes"/>
+ <accessibility>
+ <property name="label" translatable="yes">Refresh Network Providers</property>
+ </accessibility>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- Network Selection List -->
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="hscrollbar-policy">never</property>
+ <property name="propagate-natural-height">True</property>
+ <property name="visible" bind-source="operator_list_box" bind-flags="sync-create"/>
+ <style>
+ <class name="frame"/>
+ </style>
+ <property name="child">
+ <object class="GtkListBox" id="operator_list_box">
+ <property name="visible">False</property>
+ <property name="sensitive">False</property>
+ <property name="selection-mode">none</property>
+ <signal name="row-activated" handler="cc_wwan_network_changed_cb" swapped="yes"/>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child type="action">
+ <object class="GtkButton" id="button_cancel">
+ <property name="use-underline">True</property>
+ <property name="label" translatable="yes">_Cancel</property>
+ <signal name="clicked" handler="gtk_widget_hide" swapped="yes"/>
+ </object>
+ </child>
+ <child type="action">
+ <object class="GtkButton" id="button_apply">
+ <property name="use-underline">True</property>
+ <property name="label" translatable="yes">_Set</property>
+ <signal name="clicked" handler="cc_wwan_network_dialog_apply_clicked_cb" swapped="yes"/>
+ <style>
+ <class name="suggested-action "/>
+ </style>
+ </object>
+ </child>
+
+ <action-widgets>
+ <action-widget response="cancel">button_cancel</action-widget>
+ <action-widget response="apply" default="True">button_apply</action-widget>
+ </action-widgets>
+ </template>
+</interface>
diff --git a/panels/wwan/cc-wwan-panel.c b/panels/wwan/cc-wwan-panel.c
new file mode 100644
index 0000000..066a615
--- /dev/null
+++ b/panels/wwan/cc-wwan-panel.c
@@ -0,0 +1,836 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-wwan-panel.c
+ *
+ * Copyright 2019,2022 Purism SPC
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "cc-wwan-panel"
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include <libmm-glib.h>
+
+#include "cc-wwan-device.h"
+#include "cc-wwan-data.h"
+#include "cc-wwan-device-page.h"
+#include "cc-wwan-panel.h"
+#include "cc-wwan-resources.h"
+
+#include "shell/cc-application.h"
+#include "shell/cc-debug.h"
+#include "shell/cc-object-storage.h"
+
+typedef enum {
+ OPERATION_NULL,
+ OPERATION_SHOW_DEVICE,
+} CmdlineOperation;
+
+struct _CcWwanPanel
+{
+ CcPanel parent_instance;
+
+ AdwToastOverlay *toast_overlay;
+ AdwComboRow *data_list_row;
+ GtkListBox *data_sim_select_listbox;
+ GtkStack *devices_stack;
+ GtkStackSwitcher *devices_switcher;
+ GtkSwitch *enable_switch;
+ GtkStack *main_stack;
+ GtkRevealer *multi_device_revealer;
+
+ GDBusProxy *rfkill_proxy;
+ MMManager *mm_manager;
+ NMClient *nm_client;
+
+ /* The default device that will be used for data */
+ CcWwanDevice *data_device;
+ GListStore *devices;
+ GListStore *data_devices;
+ GListStore *data_devices_name_list;
+ GCancellable *cancellable;
+
+ CmdlineOperation arg_operation;
+ char *arg_device;
+};
+
+enum {
+ PROP_0,
+ PROP_PARAMETERS
+};
+
+G_DEFINE_TYPE (CcWwanPanel, cc_wwan_panel, CC_TYPE_PANEL)
+
+
+#define CC_TYPE_DATA_DEVICE_ROW (cc_data_device_row_get_type())
+G_DECLARE_FINAL_TYPE (CcDataDeviceRow, cc_data_device_row, CC, DATA_DEVICE_ROW, GtkListBoxRow)
+
+struct _CcDataDeviceRow
+{
+ GtkListBoxRow parent_instance;
+
+ GtkImage *ok_emblem;
+ CcWwanDevice *device;
+};
+
+G_DEFINE_TYPE (CcDataDeviceRow, cc_data_device_row, GTK_TYPE_LIST_BOX_ROW)
+
+static void
+cc_data_device_row_class_init (CcDataDeviceRowClass *klass)
+{
+}
+
+static void
+cc_data_device_row_init (CcDataDeviceRow *row)
+{
+}
+
+static CmdlineOperation
+cmdline_operation_from_string (const gchar *str)
+{
+ if (g_strcmp0 (str, "show-device") == 0)
+ return OPERATION_SHOW_DEVICE;
+
+ g_warning ("Invalid additional argument %s", str);
+ return OPERATION_NULL;
+}
+
+static void
+reset_command_line_args (CcWwanPanel *self)
+{
+ self->arg_operation = OPERATION_NULL;
+ g_clear_pointer (&self->arg_device, g_free);
+}
+
+static gboolean
+verify_argv (CcWwanPanel *self,
+ const char **args)
+{
+ switch (self->arg_operation)
+ {
+ case OPERATION_SHOW_DEVICE:
+ if (self->arg_device == NULL)
+ {
+ g_warning ("Operation %s requires an object path", args[0]);
+ return FALSE;
+ }
+ default:
+ return TRUE;
+ }
+}
+
+static void
+handle_argv (CcWwanPanel *self)
+{
+ if (self->arg_operation == OPERATION_SHOW_DEVICE &&
+ self->arg_operation)
+ {
+ for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (self->devices_stack));
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ {
+ CcWwanDevice *device;
+
+ device = cc_wwan_device_page_get_device (CC_WWAN_DEVICE_PAGE (child));
+
+ if (g_strcmp0 (cc_wwan_device_get_path (device), self->arg_device) == 0)
+ {
+ gtk_stack_set_visible_child (GTK_STACK (self->devices_stack), child);
+ g_debug ("Opening device %s", self->arg_device);
+ reset_command_line_args (self);
+ return;
+ }
+ }
+ }
+}
+
+static gboolean
+wwan_panel_device_is_supported (GDBusObject *object)
+{
+ MMObject *mm_object;
+ MMModem *modem;
+ MMModemCapability capability;
+
+ g_assert (G_IS_DBUS_OBJECT (object));
+
+ mm_object = MM_OBJECT (object);
+ modem = mm_object_get_modem (mm_object);
+ capability = mm_modem_get_current_capabilities (modem);
+
+ /* We Support only GSM/3G/LTE devices */
+ if (capability & (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_LTE_ADVANCED))
+ return TRUE;
+
+ return FALSE;
+}
+
+static gint
+wwan_model_get_item_index (GListModel *model,
+ gpointer item)
+{
+ guint i, n_items;
+
+ g_assert (G_IS_LIST_MODEL (model));
+ g_assert (G_IS_OBJECT (item));
+
+ n_items = g_list_model_get_n_items (model);
+
+ for (i = 0; i < n_items; i++)
+ {
+ g_autoptr(GObject) object = NULL;
+
+ object = g_list_model_get_item (model, i);
+
+ if (object == item)
+ return i;
+ }
+
+ return -1;
+}
+
+static CcWwanDevice *
+wwan_model_get_item_from_mm_object (GListModel *model,
+ MMObject *mm_object)
+{
+ const gchar *modem_path, *device_path;
+ guint i, n_items;
+
+ n_items = g_list_model_get_n_items (model);
+ modem_path = mm_object_get_path (mm_object);
+
+ for (i = 0; i < n_items; i++)
+ {
+ g_autoptr(CcWwanDevice) device = NULL;
+
+ device = g_list_model_get_item (model, i);
+ device_path = cc_wwan_device_get_path (device);
+
+ if (g_str_equal (modem_path, device_path))
+ return g_steal_pointer (&device);
+ }
+
+ return NULL;
+}
+
+static void
+cc_wwan_panel_update_data_selection (CcWwanPanel *self)
+{
+ int i;
+
+ if (!self->data_device)
+ return;
+
+ i = wwan_model_get_item_index (G_LIST_MODEL (self->data_devices), self->data_device);
+
+ if (i != -1)
+ adw_combo_row_set_selected (self->data_list_row, i);
+}
+
+static void
+cc_wwan_data_item_activate_cb (CcWwanPanel *self,
+ CcWwanDevice *device)
+{
+ CcWwanData *data;
+
+ if (device == self->data_device)
+ return;
+
+ if (!self->data_device)
+ return;
+
+ /* Set lower priority for previously selected APN */
+ data = cc_wwan_device_get_data (self->data_device);
+ cc_wwan_data_set_priority (data, CC_WWAN_APN_PRIORITY_LOW);
+ cc_wwan_data_save_settings (data, NULL, NULL, NULL);
+
+ /* Set high priority for currently selected APN */
+ data = cc_wwan_device_get_data (device);
+ cc_wwan_data_set_priority (data, CC_WWAN_APN_PRIORITY_HIGH);
+ cc_wwan_data_save_settings (data, NULL, NULL, NULL);
+
+ self->data_device = device;
+ cc_wwan_panel_update_data_selection (self);
+}
+
+static void
+wwan_on_airplane_off_clicked_cb (CcWwanPanel *self)
+{
+ g_debug ("Airplane Mode Off clicked, disabling airplane mode");
+ g_dbus_proxy_call (self->rfkill_proxy,
+ "org.freedesktop.DBus.Properties.Set",
+ g_variant_new_parsed ("('org.gnome.SettingsDaemon.Rfkill',"
+ "'AirplaneMode', %v)",
+ g_variant_new_boolean (FALSE)),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ self->cancellable,
+ NULL,
+ NULL);
+}
+
+static void
+wwan_data_list_selected_sim_changed_cb (CcWwanPanel *self)
+{
+ CcWwanDevice *device;
+ GObject *selected;
+
+ g_assert (CC_IS_WWAN_PANEL (self));
+
+ selected = adw_combo_row_get_selected_item (self->data_list_row);
+ if (!selected)
+ return;
+
+ device = g_object_get_data (selected, "device");
+ cc_wwan_data_item_activate_cb (self, device);
+}
+
+static gboolean
+cc_wwan_panel_get_cached_dbus_property (GDBusProxy *proxy,
+ const gchar *property)
+{
+ g_autoptr(GVariant) result = NULL;
+
+ g_assert (G_IS_DBUS_PROXY (proxy));
+ g_assert (property && *property);
+
+ result = g_dbus_proxy_get_cached_property (proxy, property);
+ g_assert (!result || g_variant_is_of_type (result, G_VARIANT_TYPE_BOOLEAN));
+
+ return result ? g_variant_get_boolean (result) : FALSE;
+}
+
+static void
+cc_wwan_panel_update_view (CcWwanPanel *self)
+{
+ gboolean has_airplane, is_airplane = FALSE, enabled = FALSE;
+
+ has_airplane = cc_wwan_panel_get_cached_dbus_property (self->rfkill_proxy, "HasAirplaneMode");
+ has_airplane &= cc_wwan_panel_get_cached_dbus_property (self->rfkill_proxy, "ShouldShowAirplaneMode");
+
+ if (has_airplane)
+ {
+ is_airplane = cc_wwan_panel_get_cached_dbus_property (self->rfkill_proxy, "AirplaneMode");
+ is_airplane |= cc_wwan_panel_get_cached_dbus_property (self->rfkill_proxy, "HardwareAirplaneMode");
+ }
+
+ if (self->nm_client)
+ enabled = nm_client_wwan_get_enabled (self->nm_client);
+
+ if (has_airplane && is_airplane)
+ gtk_stack_set_visible_child_name (self->main_stack, "airplane-mode");
+ else if (enabled && g_list_model_get_n_items (G_LIST_MODEL (self->devices)) > 0)
+ gtk_stack_set_visible_child_name (self->main_stack, "device-settings");
+ else
+ gtk_stack_set_visible_child_name (self->main_stack, "no-wwan-devices");
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->enable_switch), !is_airplane);
+
+ if (enabled)
+ gtk_revealer_set_reveal_child (self->multi_device_revealer,
+ g_list_model_get_n_items (G_LIST_MODEL (self->devices)) > 1);
+}
+
+static void
+cc_wwan_panel_add_device (CcWwanPanel *self,
+ CcWwanDevice *device)
+{
+ CcWwanDevicePage *device_page;
+ g_autofree gchar *operator_name = NULL;
+ g_autofree gchar *stack_name = NULL;
+ guint n_items;
+
+ g_list_store_append (self->devices, device);
+
+ n_items = g_list_model_get_n_items (G_LIST_MODEL (self->devices));
+ operator_name = g_strdup_printf (_("SIM %d"), n_items);
+ stack_name = g_strdup_printf ("sim-%d", n_items);
+
+ device_page = cc_wwan_device_page_new (device, GTK_WIDGET (self->toast_overlay));
+ cc_wwan_device_page_set_sim_index (device_page, n_items);
+ gtk_stack_add_titled (self->devices_stack,
+ GTK_WIDGET (device_page), stack_name, operator_name);
+}
+
+static void
+cc_wwan_panel_update_page_title (CcWwanDevicePage *device_page,
+ CcWwanPanel *self)
+{
+ g_autofree gchar *title = NULL;
+ g_autofree gchar *name = NULL;
+ CcWwanDevice *device;
+ GtkStackPage *page;
+ gint index;
+
+ g_assert (CC_IS_WWAN_DEVICE_PAGE (device_page));
+
+ device = cc_wwan_device_page_get_device (device_page);
+
+ page = gtk_stack_get_page (GTK_STACK (self->devices_stack), GTK_WIDGET (device_page));
+ index = wwan_model_get_item_index (G_LIST_MODEL (self->devices), device);
+
+ if (index == -1)
+ g_return_if_reached ();
+
+ /* index starts with 0, but we need human readable index to be 1+ */
+ cc_wwan_device_page_set_sim_index (device_page, index + 1);
+ title = g_strdup_printf (_("SIM %d"), index + 1);
+ name = g_strdup_printf ("sim-%d", index + 1);
+ gtk_stack_page_set_title (page, title);
+ gtk_stack_page_set_name (page, name);
+}
+
+static void
+cc_wwan_panel_remove_mm_object (CcWwanPanel *self,
+ MMObject *mm_object)
+{
+ g_autoptr(CcWwanDevice) device = NULL;
+ GtkWidget *device_page;
+ g_autofree gchar *stack_name = NULL;
+ guint n_items;
+ gint index;
+
+ device = wwan_model_get_item_from_mm_object (G_LIST_MODEL (self->devices), mm_object);
+
+ if (!device)
+ return;
+
+ index = wwan_model_get_item_index (G_LIST_MODEL (self->data_devices), device);
+ if (index != -1) {
+ g_list_store_remove (self->data_devices, index);
+ g_list_store_remove (self->data_devices_name_list, index);
+ }
+
+ index = wwan_model_get_item_index (G_LIST_MODEL (self->devices), device);
+ if (index == -1)
+ return;
+
+ g_list_store_remove (self->devices, index);
+ stack_name = g_strdup_printf ("sim-%d", index + 1);
+ device_page = gtk_stack_get_child_by_name (self->devices_stack, stack_name);
+ gtk_stack_remove (GTK_STACK (self->devices_stack), device_page);
+
+ n_items = g_list_model_get_n_items (G_LIST_MODEL (self->data_devices));
+ g_list_model_items_changed (G_LIST_MODEL (self->data_devices), 0, n_items, n_items);
+
+ for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (self->devices_stack));
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ cc_wwan_panel_update_page_title (CC_WWAN_DEVICE_PAGE (child), self);
+}
+
+static void
+wwan_panel_add_data_device_to_list (CcWwanPanel *self,
+ CcWwanDevice *device)
+{
+ g_autoptr(GtkStringObject) str = NULL;
+ g_autofree char *operator = NULL;
+ int index;
+
+ index = wwan_model_get_item_index (G_LIST_MODEL (self->data_devices), device);
+ if (index != -1)
+ return;
+
+ g_list_store_append (self->data_devices, device);
+
+ index = wwan_model_get_item_index (G_LIST_MODEL (self->devices), device);
+ operator = g_strdup_printf ("SIM %d", index + 1);
+ str = gtk_string_object_new (operator);
+ g_object_set_data_full (G_OBJECT (str), "device", g_object_ref (device), g_object_unref);
+ g_list_store_append (self->data_devices_name_list, str);
+}
+
+static void
+cc_wwan_panel_update_data_connections (CcWwanPanel *self)
+{
+ CcWwanData *device_data, *active_data = NULL;
+ guint n_items;
+ gint i;
+
+ /*
+ * We can’t predict the order in which the data of device is enabled.
+ * But we have to keep data store in the same order as device store.
+ * So let’s remove every data device and re-add.
+ */
+ g_list_store_remove_all (self->data_devices);
+ g_list_store_remove_all (self->data_devices_name_list);
+ n_items = g_list_model_get_n_items (G_LIST_MODEL (self->devices));
+
+ for (i = 0; i < n_items; i++)
+ {
+ g_autoptr(CcWwanDevice) device = NULL;
+
+ device = g_list_model_get_item (G_LIST_MODEL (self->devices), i);
+ device_data = cc_wwan_device_get_data (device);
+
+ if (!device_data)
+ continue;
+
+ if ((!active_data ||
+ cc_wwan_data_get_priority (device_data) > cc_wwan_data_get_priority (active_data)) &&
+ cc_wwan_data_get_enabled (device_data))
+ {
+ active_data = device_data;
+ self->data_device = device;
+ }
+
+ if (cc_wwan_data_get_enabled (device_data))
+ wwan_panel_add_data_device_to_list (self, device);
+ }
+
+ if (active_data)
+ cc_wwan_panel_update_data_selection (self);
+}
+
+static void
+cc_wwan_panel_update_devices (CcWwanPanel *self)
+{
+ GList *devices, *iter;
+
+ devices = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (self->mm_manager));
+
+ for (iter = devices; iter; iter = iter->next)
+ {
+ MMObject *mm_object = iter->data;
+ CcWwanDevice *device;
+
+ if(!wwan_panel_device_is_supported (iter->data))
+ continue;
+
+ device = cc_wwan_device_new (mm_object, G_OBJECT (self->nm_client));
+ cc_wwan_panel_add_device (self, device);
+ g_signal_connect_object (device, "notify::has-data",
+ G_CALLBACK (cc_wwan_panel_update_data_connections),
+ self, G_CONNECT_SWAPPED);
+
+ if (cc_wwan_device_get_data (device))
+ wwan_panel_add_data_device_to_list (self, device);
+ }
+
+ cc_wwan_panel_update_data_connections (self);
+ handle_argv (self);
+}
+
+static void
+wwan_panel_device_added_cb (CcWwanPanel *self,
+ GDBusObject *object)
+{
+ CcWwanDevice *device;
+
+ if(!wwan_panel_device_is_supported (object))
+ return;
+
+ device = cc_wwan_device_new (MM_OBJECT (object), G_OBJECT (self->nm_client));
+ cc_wwan_panel_add_device (self, device);
+ g_signal_connect_object (device, "notify::has-data",
+ G_CALLBACK (cc_wwan_panel_update_data_connections),
+ self, G_CONNECT_SWAPPED);
+ cc_wwan_panel_update_view (self);
+ handle_argv (self);
+}
+
+static void
+wwan_panel_device_removed_cb (CcWwanPanel *self,
+ GDBusObject *object)
+{
+ if (!wwan_panel_device_is_supported (object))
+ return;
+
+ cc_wwan_panel_remove_mm_object (self, MM_OBJECT (object));
+
+ gtk_revealer_set_reveal_child (self->multi_device_revealer,
+ g_list_model_get_n_items (G_LIST_MODEL (self->devices)) > 1);
+}
+
+static GPtrArray *
+variant_av_to_string_array (GVariant *array)
+{
+ GVariant *v;
+ GPtrArray *strv;
+ GVariantIter iter;
+ gsize count;
+
+ count = g_variant_iter_init (&iter, array);
+ strv = g_ptr_array_sized_new (count + 1);
+
+ while (g_variant_iter_next (&iter, "v", &v))
+ {
+ g_ptr_array_add (strv, (gpointer)g_variant_get_string (v, NULL));
+ g_variant_unref (v);
+ }
+ g_ptr_array_add (strv, NULL); /* NULL-terminate the strv data array */
+
+ return strv;
+}
+
+static void
+cc_wwan_panel_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcWwanPanel *self = CC_WWAN_PANEL (object);
+
+ switch (property_id)
+ {
+ case PROP_PARAMETERS:
+ {
+ GVariant *parameters;
+
+ reset_command_line_args (self);
+
+ parameters = g_value_get_variant (value);
+ if (parameters)
+ {
+ g_autoptr(GPtrArray) array = NULL;
+ const gchar **args;
+
+ array = variant_av_to_string_array (parameters);
+ args = (const gchar **) array->pdata;
+
+ g_debug ("Invoked with operation %s", args[0]);
+
+ if (args[0])
+ self->arg_operation = cmdline_operation_from_string (args[0]);
+ if (args[0] && args[1])
+ self->arg_device = g_strdup (args[1]);
+
+ if (!verify_argv (self, (const char **) args))
+ {
+ reset_command_line_args (self);
+ return;
+ }
+ g_debug ("Calling handle_argv() after setting property");
+ handle_argv (self);
+ }
+ break;
+ }
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+cc_wwan_panel_dispose (GObject *object)
+{
+ CcWwanPanel *self = (CcWwanPanel *)object;
+
+ g_cancellable_cancel (self->cancellable);
+
+ g_clear_object (&self->devices);
+ g_clear_object (&self->data_devices);
+ g_clear_object (&self->data_devices_name_list);
+ g_clear_object (&self->mm_manager);
+ g_clear_object (&self->nm_client);
+ g_clear_object (&self->cancellable);
+ g_clear_object (&self->rfkill_proxy);
+ g_clear_pointer (&self->arg_device, g_free);
+
+ G_OBJECT_CLASS (cc_wwan_panel_parent_class)->dispose (object);
+}
+
+static void
+cc_wwan_panel_class_init (CcWwanPanelClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = cc_wwan_panel_set_property;
+ object_class->dispose = cc_wwan_panel_dispose;
+
+ g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters");
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/control-center/wwan/cc-wwan-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcWwanPanel, toast_overlay);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanPanel, data_list_row);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanPanel, data_sim_select_listbox);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanPanel, devices_stack);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanPanel, devices_switcher);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanPanel, enable_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanPanel, main_stack);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanPanel, multi_device_revealer);
+
+ gtk_widget_class_bind_template_callback (widget_class, wwan_data_list_selected_sim_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, wwan_on_airplane_off_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_data_item_activate_cb);
+}
+
+static void
+cc_wwan_panel_init (CcWwanPanel *self)
+{
+ g_autoptr(GError) error = NULL;
+
+ g_resources_register (cc_wwan_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->cancellable = g_cancellable_new ();
+ self->devices = g_list_store_new (CC_TYPE_WWAN_DEVICE);
+ self->data_devices = g_list_store_new (CC_TYPE_WWAN_DEVICE);
+ self->data_devices_name_list = g_list_store_new (GTK_TYPE_STRING_OBJECT);
+ adw_combo_row_set_model (ADW_COMBO_ROW (self->data_list_row),
+ G_LIST_MODEL (self->data_devices_name_list));
+
+ if (cc_object_storage_has_object (CC_OBJECT_NMCLIENT))
+ {
+ self->nm_client = cc_object_storage_get_object (CC_OBJECT_NMCLIENT);
+ g_signal_connect_object (self->nm_client,
+ "notify::wwan-enabled",
+ G_CALLBACK (cc_wwan_panel_update_view),
+ self, G_CONNECT_SWAPPED);
+
+ }
+ else
+ {
+ g_warn_if_reached ();
+ }
+
+ if (self->nm_client)
+ {
+ g_object_bind_property (self->nm_client, "wwan-enabled",
+ self->enable_switch, "active",
+ G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+ }
+
+ if (cc_object_storage_has_object ("CcObjectStorage::mm-manager"))
+ {
+ self->mm_manager = cc_object_storage_get_object ("CcObjectStorage::mm-manager");
+
+ g_signal_connect_object (self->mm_manager, "object-added",
+ G_CALLBACK (wwan_panel_device_added_cb),
+ self, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->mm_manager, "object-removed",
+ G_CALLBACK (wwan_panel_device_removed_cb),
+ self, G_CONNECT_SWAPPED);
+
+ cc_wwan_panel_update_devices (self);
+ }
+ else
+ {
+ g_warn_if_reached ();
+ }
+
+ /* Acquire Airplane Mode proxy */
+ self->rfkill_proxy = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "org.gnome.SettingsDaemon.Rfkill",
+ "/org/gnome/SettingsDaemon/Rfkill",
+ "org.gnome.SettingsDaemon.Rfkill",
+ self->cancellable,
+ &error);
+
+ if (error)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_printerr ("Error creating rfkill proxy: %s\n", error->message);
+ }
+ else
+ {
+ g_signal_connect_object (self->rfkill_proxy,
+ "g-properties-changed",
+ G_CALLBACK (cc_wwan_panel_update_view),
+ self, G_CONNECT_SWAPPED);
+
+ cc_wwan_panel_update_view (self);
+ }
+}
+
+static void
+wwan_update_panel_visibility (MMManager *mm_manager)
+{
+ CcApplication *application;
+ GList *devices;
+ gboolean has_wwan;
+
+ g_assert (MM_IS_MANAGER (mm_manager));
+
+ CC_TRACE_MSG ("Updating WWAN panel visibility");
+
+ has_wwan = FALSE;
+ devices = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (mm_manager));
+
+ for (GList *item = devices; item != NULL; item = item->next)
+ {
+ if(wwan_panel_device_is_supported (item->data))
+ {
+ has_wwan = TRUE;
+ break;
+ }
+ }
+
+ /* Set the new visibility */
+ application = CC_APPLICATION (g_application_get_default ());
+ cc_shell_model_set_panel_visibility (cc_application_get_model (application),
+ "wwan",
+ has_wwan ? CC_PANEL_VISIBLE : CC_PANEL_VISIBLE_IN_SEARCH);
+
+ g_debug ("WWAN panel visible: %s", has_wwan ? "yes" : "no");
+
+ g_list_free_full (devices, (GDestroyNotify)g_object_unref);
+}
+
+void
+cc_wwan_panel_static_init_func (void)
+{
+ g_autoptr(GDBusConnection) system_bus = NULL;
+ g_autoptr(MMManager) mm_manager = NULL;
+ g_autoptr(GError) error = NULL;
+
+ /*
+ * There could be other modems that are only handled by rfkill,
+ * and not available via ModemManager. But as this panel
+ * makes use of ModemManager APIs, we only care devices
+ * supported by ModemManager.
+ */
+ system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (system_bus == NULL)
+ g_warning ("Error connecting to system D-Bus: %s", error->message);
+ else
+ mm_manager = mm_manager_new_sync (system_bus,
+ G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
+ NULL, &error);
+
+ if (mm_manager == NULL)
+ {
+ CcApplication *application;
+
+ g_warning ("Error connecting to ModemManager: %s", error->message);
+
+ application = CC_APPLICATION (g_application_get_default ());
+ cc_shell_model_set_panel_visibility (cc_application_get_model (application),
+ "wwan", FALSE);
+ return;
+ }
+ else
+ {
+ cc_object_storage_add_object ("CcObjectStorage::mm-manager", mm_manager);
+ }
+
+ g_debug ("Monitoring ModemManager for WWAN devices");
+
+ g_signal_connect (mm_manager, "object-added", G_CALLBACK (wwan_update_panel_visibility), NULL);
+ g_signal_connect (mm_manager, "object-removed", G_CALLBACK (wwan_update_panel_visibility), NULL);
+
+ wwan_update_panel_visibility (mm_manager);
+}
diff --git a/panels/wwan/cc-wwan-panel.h b/panels/wwan/cc-wwan-panel.h
new file mode 100644
index 0000000..57d2dae
--- /dev/null
+++ b/panels/wwan/cc-wwan-panel.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-wwan-panel.h
+ *
+ * Copyright 2019 Purism SPC
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_WWAN_PANEL (cc_wwan_panel_get_type())
+G_DECLARE_FINAL_TYPE (CcWwanPanel, cc_wwan_panel, CC, WWAN_PANEL, CcPanel)
+
+void cc_wwan_panel_static_init_func (void);
+
+G_END_DECLS
diff --git a/panels/wwan/cc-wwan-panel.ui b/panels/wwan/cc-wwan-panel.ui
new file mode 100644
index 0000000..a984022
--- /dev/null
+++ b/panels/wwan/cc-wwan-panel.ui
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk" version="4.0"/>
+ <template class="CcWwanPanel" parent="CcPanel">
+
+ <!-- Cellular panel on/off switch -->
+ <child type="titlebar-end">
+ <object class="GtkSwitch" id="enable_switch">
+ <accessibility>
+ <property name="label" translatable="yes">Enable Mobile Network</property>
+ </accessibility>
+ </object>
+ </child>
+
+ <child type="content">
+ <object class="AdwToastOverlay" id="toast_overlay">
+ <property name="child">
+ <object class="GtkScrolledWindow">
+ <property name="hscrollbar-policy">never</property>
+ <property name="min-content-height">500</property>
+ <child>
+ <object class="AdwClamp">
+ <property name="margin-top">0</property>
+ <property name="margin-bottom">32</property>
+ <property name="margin-start">18</property>
+ <property name="margin-end">18</property>
+
+ <child>
+ <object class="GtkBox">
+ <property name="hexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkStack" id="main_stack">
+ <property name="vhomogeneous">False</property>
+ <property name="hhomogeneous">False</property>
+ <property name="transition-type">crossfade</property>
+
+ <!-- "No WWAN Adapter" page -->
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">no-wwan-devices</property>
+ <property name="child">
+ <object class="GtkBox">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="valign">center</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">network-cellular-offline-symbolic</property>
+ <property name="pixel-size">192</property>
+ <property name="margin-bottom">18</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="wrap">True</property>
+ <property name="label" translatable="yes">No WWAN Adapter Found</property>
+ <attributes>
+ <attribute name="weight" value="bold"></attribute>
+ <attribute name="scale" value="1.2"></attribute>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="wrap">True</property>
+ <property name="label" translatable="yes">Make sure you have a Wireless Wan/Cellular device</property>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <!-- "Airplane Mode" page -->
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">airplane-mode</property>
+ <property name="child">
+ <object class="GtkBox">
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="valign">center</property>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">airplane-mode-symbolic</property>
+ <property name="pixel-size">192</property>
+ <property name="margin-bottom">18</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="wrap">True</property>
+ <property name="label" translatable="yes">Airplane Mode On</property>
+ <attributes>
+ <attribute name="weight" value="bold"></attribute>
+ <attribute name="scale" value="1.2"></attribute>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="wrap">True</property>
+ <property name="label" translatable="yes">Wireless Wan is disabled when airplane mode is on</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="halign">center</property>
+ <property name="use-underline">True</property>
+ <property name="margin-top">24</property>
+ <property name="label" translatable="yes">_Turn off Airplane Mode</property>
+ <signal name="clicked" handler="wwan_on_airplane_off_clicked_cb" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">device-settings</property>
+ <property name="child">
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+
+ <child>
+ <object class="GtkRevealer" id="multi_device_revealer">
+ <property name="margin-top">18</property>
+ <property name="child">
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+
+ <!-- Data SIM selector -->
+ <child>
+ <object class="GtkListBox" id="data_sim_select_listbox">
+ <property name="margin-bottom">32</property>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ <child>
+ <object class="AdwComboRow" id="data_list_row">
+ <property name="title" translatable="yes">Data Connection</property>
+ <property name="subtitle" translatable="yes">SIM card used for internet</property>
+ <signal name="notify::selected-item" handler="wwan_data_list_selected_sim_changed_cb" swapped="1"/>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <!-- Device (SIM) Name -->
+ <child>
+ <object class="GtkStackSwitcher" id="devices_switcher">
+ <property name="stack">devices_stack</property>
+ <property name="hexpand">True</property>
+ <property name="halign">center</property>
+ </object>
+ </child>
+
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <!-- Device (SIM) settings page -->
+ <child>
+ <object class="GtkStack" id="devices_stack">
+ <property name="vhomogeneous">False</property>
+ <property name="hhomogeneous">False</property>
+ </object>
+ </child>
+
+ </object>
+ </property>
+ </object>
+ </child>
+ </object> <!-- ./GtkStack main_stack -->
+ </child>
+ </object>
+ </child>
+
+ </object> <!-- ./AdwClamp -->
+ </child>
+ </object> <!-- ./GtkScrolledWindow -->
+ </property>
+ </object>
+ </child>
+
+ </template>
+</interface>
diff --git a/panels/wwan/cc-wwan-sim-lock-dialog.c b/panels/wwan/cc-wwan-sim-lock-dialog.c
new file mode 100644
index 0000000..09c6773
--- /dev/null
+++ b/panels/wwan/cc-wwan-sim-lock-dialog.c
@@ -0,0 +1,309 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-wwan-network-dialog.c
+ *
+ * Copyright 2019,2022 Purism SPC
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "cc-wwan-sim-lock-dialog"
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include <libmm-glib.h>
+
+#include "cc-list-row.h"
+#include "cc-wwan-sim-lock-dialog.h"
+#include "cc-wwan-resources.h"
+
+/**
+ * @short_description: Dialog to manage SIM Locks like PIN
+ */
+
+#define PIN_MINIMUM_LENGTH 4
+#define PIN_MAXIMUM_LENGTH 8
+
+struct _CcWwanSimLockDialog
+{
+ GtkDialog parent_instance;
+
+ CcWwanDevice *device;
+
+ GtkButton *apply_button;
+ GtkStack *button_stack;
+ GtkGrid *lock_change_grid;
+ CcListRow *lock_row;
+ GtkEntry *new_pin_entry;
+ GtkButton *next_button;
+ GtkEntry *pin_confirm_entry;
+ GtkEntry *pin_entry;
+ GtkStack *pin_settings_stack;
+};
+
+G_DEFINE_TYPE (CcWwanSimLockDialog, cc_wwan_sim_lock_dialog, GTK_TYPE_DIALOG)
+
+
+enum {
+ PROP_0,
+ PROP_DEVICE,
+ N_PROPS
+};
+
+static GParamSpec *properties[N_PROPS];
+
+static void
+cc_wwan_sim_lock_changed_cb (CcWwanSimLockDialog *self)
+{
+ gboolean row_enabled, lock_enabled;
+
+ lock_enabled = cc_wwan_device_get_sim_lock (self->device);
+ row_enabled = cc_list_row_get_active (self->lock_row);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->next_button), lock_enabled != row_enabled);
+ gtk_widget_set_visible (GTK_WIDGET (self->lock_change_grid), row_enabled && lock_enabled);
+}
+
+static void
+cc_wwan_pin_next_clicked_cb (CcWwanSimLockDialog *self)
+{
+ gtk_stack_set_visible_child_name (self->pin_settings_stack, "pin-entry");
+ gtk_editable_set_text (GTK_EDITABLE (self->pin_entry), "");
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->apply_button), FALSE);
+ gtk_stack_set_visible_child (self->button_stack,
+ GTK_WIDGET (self->apply_button));
+}
+
+static void
+cc_wwan_pin_apply_clicked_cb (CcWwanSimLockDialog *self)
+{
+ const gchar *pin, *new_pin;
+ gboolean row_enabled, lock_enabled;
+
+ gtk_widget_hide (GTK_WIDGET (self));
+
+ lock_enabled = cc_wwan_device_get_sim_lock (self->device);
+ row_enabled = cc_list_row_get_active (self->lock_row);
+ pin = gtk_editable_get_text (GTK_EDITABLE (self->pin_entry));
+ new_pin = gtk_editable_get_text (GTK_EDITABLE (self->new_pin_entry));
+
+ if (lock_enabled != row_enabled)
+ {
+ if (row_enabled)
+ cc_wwan_device_enable_pin (self->device, pin, NULL, NULL, NULL);
+ else
+ cc_wwan_device_disable_pin (self->device, pin, NULL, NULL, NULL);
+
+ return;
+ }
+
+ cc_wwan_device_change_pin (self->device, pin, new_pin, NULL, NULL, NULL);
+}
+
+static void
+cc_wwan_pin_entry_text_inserted_cb (CcWwanSimLockDialog *self,
+ gchar *new_text,
+ gint new_text_length,
+ gpointer position,
+ GtkEditable *editable)
+{
+ size_t digit_end;
+ size_t len;
+
+ if (!new_text || !*new_text)
+ return;
+
+ if (new_text_length == 1 && g_ascii_isdigit (*new_text))
+ return;
+
+ if (new_text_length == -1)
+ len = strlen (new_text);
+ else
+ len = new_text_length;
+
+ if (len == 1 && g_ascii_isdigit (*new_text))
+ return;
+
+ digit_end = strspn (new_text, "1234567890");
+
+ /* The maximum length possible for PIN is 8 */
+ if (len <= 8 && digit_end == len)
+ return;
+
+ g_signal_stop_emission_by_name (editable, "insert-text");
+ gtk_widget_error_bell (GTK_WIDGET (editable));
+}
+
+static void
+cc_wwan_pin_entry_changed_cb (CcWwanSimLockDialog *self)
+{
+ const gchar *new_pin, *confirm_pin;
+
+ new_pin = gtk_editable_get_text (GTK_EDITABLE (self->new_pin_entry));
+ confirm_pin = gtk_editable_get_text (GTK_EDITABLE (self->pin_confirm_entry));
+ gtk_widget_set_sensitive (GTK_WIDGET (self->next_button), FALSE);
+
+ /* A PIN should have a minimum length of 4 */
+ if (!new_pin || !confirm_pin || strlen (new_pin) < 4)
+ return;
+
+ if (g_str_equal (new_pin, confirm_pin))
+ gtk_widget_set_sensitive (GTK_WIDGET (self->next_button), TRUE);
+}
+
+
+static void
+cc_wwan_pin_entered_cb (CcWwanSimLockDialog *self)
+{
+ const gchar *pin;
+ gsize len;
+ gboolean enable_apply;
+
+ pin = gtk_editable_get_text (GTK_EDITABLE (self->pin_entry));
+
+ if (!pin || !*pin)
+ {
+ gtk_widget_set_sensitive (GTK_WIDGET (self->apply_button), FALSE);
+ return;
+ }
+
+ len = strlen (pin);
+ enable_apply = len >= PIN_MINIMUM_LENGTH && len <= PIN_MAXIMUM_LENGTH;
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->apply_button), enable_apply);
+}
+
+static void
+cc_wwan_sim_lock_dialog_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcWwanSimLockDialog *self = (CcWwanSimLockDialog *)object;
+
+ switch (prop_id)
+ {
+ case PROP_DEVICE:
+ self->device = g_value_dup_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cc_wwan_sim_lock_dialog_show (GtkWidget *widget)
+{
+ CcWwanSimLockDialog *self = (CcWwanSimLockDialog *)widget;
+ gboolean lock_enabled;
+
+ gtk_editable_set_text (GTK_EDITABLE (self->pin_entry), "");
+ gtk_widget_set_sensitive (GTK_WIDGET (self->next_button), FALSE);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->apply_button), FALSE);
+
+ lock_enabled = cc_wwan_device_get_sim_lock (self->device);
+ g_object_set (self->lock_row, "active", lock_enabled, NULL);
+ gtk_widget_set_visible (GTK_WIDGET (self->lock_change_grid), lock_enabled);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->next_button), FALSE);
+ gtk_stack_set_visible_child (self->button_stack,
+ GTK_WIDGET (self->next_button));
+ gtk_button_set_label (self->apply_button, _("_Set"));
+
+ gtk_stack_set_visible_child_name (self->pin_settings_stack, "pin-settings");
+
+ gtk_editable_set_text (GTK_EDITABLE (self->pin_entry), "");
+ gtk_editable_set_text (GTK_EDITABLE (self->new_pin_entry), "");
+ gtk_editable_set_text (GTK_EDITABLE (self->pin_confirm_entry), "");
+
+ GTK_WIDGET_CLASS (cc_wwan_sim_lock_dialog_parent_class)->show (widget);
+}
+
+static void
+cc_wwan_sim_lock_dialog_dispose (GObject *object)
+{
+ CcWwanSimLockDialog *self = (CcWwanSimLockDialog *)object;
+
+ g_clear_object (&self->device);
+
+ G_OBJECT_CLASS (cc_wwan_sim_lock_dialog_parent_class)->dispose (object);
+}
+
+static void
+cc_wwan_sim_lock_dialog_class_init (CcWwanSimLockDialogClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = cc_wwan_sim_lock_dialog_set_property;
+ object_class->dispose = cc_wwan_sim_lock_dialog_dispose;
+
+ widget_class->show = cc_wwan_sim_lock_dialog_show;
+
+ properties[PROP_DEVICE] =
+ g_param_spec_object ("device",
+ "Device",
+ "The WWAN Device",
+ CC_TYPE_WWAN_DEVICE,
+ G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/control-center/wwan/cc-wwan-sim-lock-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, apply_button);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, button_stack);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, lock_change_grid);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, lock_row);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, new_pin_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, next_button);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, pin_confirm_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, pin_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, pin_settings_stack);
+
+ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_sim_lock_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_pin_next_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_pin_apply_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_pin_entry_text_inserted_cb);
+ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_pin_entry_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_pin_entered_cb);
+}
+
+static void
+cc_wwan_sim_lock_dialog_init (CcWwanSimLockDialog *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+CcWwanSimLockDialog *
+cc_wwan_sim_lock_dialog_new (GtkWindow *parent_window,
+ CcWwanDevice *device)
+{
+ g_return_val_if_fail (GTK_IS_WINDOW (parent_window), NULL);
+ g_return_val_if_fail (CC_IS_WWAN_DEVICE (device), NULL);
+
+ return g_object_new (CC_TYPE_WWAN_SIM_LOCK_DIALOG,
+ "transient-for", parent_window,
+ "use-header-bar", 1,
+ "device", device,
+ NULL);
+}
diff --git a/panels/wwan/cc-wwan-sim-lock-dialog.h b/panels/wwan/cc-wwan-sim-lock-dialog.h
new file mode 100644
index 0000000..f59d048
--- /dev/null
+++ b/panels/wwan/cc-wwan-sim-lock-dialog.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* cc-wwan-sim-lock-dialog.h
+ *
+ * Copyright 2019 Purism SPC
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s):
+ * Mohammed Sadiq <sadiq@sadiqpk.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <adwaita.h>
+#include <shell/cc-panel.h>
+
+#include "cc-wwan-device.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_WWAN_SIM_LOCK_DIALOG (cc_wwan_sim_lock_dialog_get_type())
+G_DECLARE_FINAL_TYPE (CcWwanSimLockDialog, cc_wwan_sim_lock_dialog, CC, WWAN_SIM_LOCK_DIALOG, GtkDialog)
+
+CcWwanSimLockDialog *cc_wwan_sim_lock_dialog_new (GtkWindow *parent_window,
+ CcWwanDevice *device);
+
+G_END_DECLS
diff --git a/panels/wwan/cc-wwan-sim-lock-dialog.ui b/panels/wwan/cc-wwan-sim-lock-dialog.ui
new file mode 100644
index 0000000..5c7f736
--- /dev/null
+++ b/panels/wwan/cc-wwan-sim-lock-dialog.ui
@@ -0,0 +1,249 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk" version="4.0"/>
+ <template class="CcWwanSimLockDialog" parent="GtkDialog">
+ <property name="default-height">480</property>
+ <property name="default-width">360</property>
+ <property name="hide-on-close">True</property>
+ <property name="modal">True</property>
+ <property name="title" translatable="yes">SIM Lock</property>
+
+ <child type="titlebar">
+ <object class="GtkHeaderBar">
+ <child type="end">
+ <object class="GtkStack" id="button_stack">
+
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">next</property>
+ <!-- Next Button -->
+ <property name="child">
+ <object class="GtkButton" id="next_button">
+ <property name="sensitive">False</property>
+ <property name="use-underline">True</property>
+ <property name="label" translatable="yes">_Next</property>
+ <signal name="clicked" handler="cc_wwan_pin_next_clicked_cb" swapped="yes"/>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">apply</property>
+ <!-- Apply button -->
+ <property name="child">
+ <object class="GtkButton" id="apply_button">
+ <property name="use-underline">True</property>
+ <signal name="clicked" handler="cc_wwan_pin_apply_clicked_cb" swapped="yes"/>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkBox">
+ <property name="width-request">340</property>
+ <property name="height-request">360</property>
+
+ <child>
+ <object class="AdwClamp">
+ <property name="margin-top">32</property>
+ <property name="margin-bottom">32</property>
+ <property name="margin-start">18</property>
+ <property name="margin-end">18</property>
+ <child>
+ <object class="AdwToastOverlay" id="toast_overlay">
+ <property name="child">
+ <object class="GtkStack" id="pin_settings_stack">
+ <property name="transition-type">slide-left</property>
+
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">pin-settings</property>
+ <property name="child">
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+
+ <!-- SIM Lock Switch -->
+ <child>
+ <object class="GtkListBox">
+ <property name="selection-mode">none</property>
+ <property name="margin-bottom">18</property>
+ <style>
+ <class name="frame"/>
+ </style>
+ <child>
+ <object class="CcListRow" id="lock_row">
+ <property name="show-switch">True</property>
+ <property name="use-underline">True</property>
+ <property name="title" translatable="yes">_Lock SIM with PIN</property>
+ <signal name="notify::active" handler="cc_wwan_sim_lock_changed_cb" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkGrid" id="lock_change_grid">
+ <property name="visible">False</property>
+ <property name="row-spacing">18</property>
+ <property name="column-spacing">12</property>
+
+ <!-- SIM Lock Change Title -->
+ <child>
+ <object class="GtkLabel" id="lock_change_title">
+ <property name="label" translatable="yes">Change PIN</property>
+ <property name="margin-bottom">9</property>
+ <property name="xalign">0.0</property>
+ <attributes>
+ <attribute name="weight" value="bold"></attribute>
+ </attributes>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ <property name="column-span">2</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- PIN Entry -->
+ <child>
+ <object class="GtkLabel">
+ <property name="label">New PIN</property>
+ <property name="halign">end</property>
+ <property name="mnemonic_widget">new_pin_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="new_pin_entry">
+ <property name="visibility">False</property>
+ <property name="input-purpose">password</property>
+ <property name="input-hints">no-emoji</property>
+ <property name="max-length">8</property>
+ <property name="max-width-chars">32</property>
+ <signal name="notify::text" handler="cc_wwan_pin_entry_changed_cb" swapped="yes"/>
+ <signal name="insert-text" handler="cc_wwan_pin_entry_text_inserted_cb" swapped="yes"/>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label">Confirm</property>
+ <property name="halign">end</property>
+ <property name="mnemonic_widget">pin_confirm_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Confirm PIN Entry -->
+ <child>
+ <object class="GtkEntry" id="pin_confirm_entry">
+ <property name="visibility">False</property>
+ <property name="input-purpose">password</property>
+ <property name="input-hints">no-emoji</property>
+ <property name="max-length">8</property>
+ <property name="max-width-chars">32</property>
+ <signal name="notify::text" handler="cc_wwan_pin_entry_changed_cb" swapped="yes"/>
+ <signal name="insert-text" handler="cc_wwan_pin_entry_changed_cb" swapped="yes"/>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">pin-entry</property>
+ <property name="child">
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="valign">center</property>
+ <property name="halign">center</property>
+ <child>
+ <object class="GtkImage">
+ <property name="pixel-size">128</property>
+ <property name="icon-name">dialog-password-symbolic</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="">
+ <property name="label" translatable="yes">Enter current PIN to change SIM lock settings</property>
+ <property name="margin-bottom">24</property>
+ <property name="halign">center</property>
+ <property name="mnemonic_widget">pin_entry</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="pin_entry">
+ <property name="visibility">False</property>
+ <property name="input-purpose">password</property>
+ <property name="input-hints">no-emoji</property>
+ <property name="max-length">8</property>
+ <property name="max-width-chars">32</property>
+ <signal name="notify::text" handler="cc_wwan_pin_entered_cb" swapped="yes"/>
+ <signal name="insert-text" handler="cc_wwan_pin_entry_text_inserted_cb" swapped="yes"/>
+ <signal name="activate" handler="cc_wwan_pin_apply_clicked_cb" swapped="yes"/>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </property>
+
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child> <!-- ./internal-child -->
+
+ <child type="action">
+ <object class="GtkButton" id="cancel_button">
+ <property name="use-underline">True</property>
+ <property name="label" translatable="yes">_Cancel</property>
+ <signal name="clicked" handler="gtk_widget_hide" swapped="yes"/>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="cancel">cancel_button</action-widget>
+ </action-widgets>
+
+ </template>
+</interface>
diff --git a/panels/wwan/gnome-wwan-panel.desktop.in.in b/panels/wwan/gnome-wwan-panel.desktop.in.in
new file mode 100644
index 0000000..dfe9409
--- /dev/null
+++ b/panels/wwan/gnome-wwan-panel.desktop.in.in
@@ -0,0 +1,15 @@
+[Desktop Entry]
+Name=Mobile Network
+Comment=Configure Telephony and mobile data connections
+Exec=gnome-control-center wwan
+# FIXME
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=org.gnome.Settings-mobile-network-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;X-GNOME-NetworkSettings;HardwareSettings;X-GNOME-Settings-Panel;X-GNOME-ConnectivitySettings;
+OnlyShowIn=GNOME;Unity;
+# Translators: Search terms to find the WWAN panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=cellular;wwan;telephony;sim;mobile;
diff --git a/panels/wwan/icons/meson.build b/panels/wwan/icons/meson.build
new file mode 100644
index 0000000..88d015a
--- /dev/null
+++ b/panels/wwan/icons/meson.build
@@ -0,0 +1,4 @@
+install_data(
+ 'scalable/org.gnome.Settings-mobile-network-symbolic.svg',
+ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps')
+)
diff --git a/panels/wwan/icons/scalable/org.gnome.Settings-mobile-network-symbolic.svg b/panels/wwan/icons/scalable/org.gnome.Settings-mobile-network-symbolic.svg
new file mode 100644
index 0000000..fe949f0
--- /dev/null
+++ b/panels/wwan/icons/scalable/org.gnome.Settings-mobile-network-symbolic.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+ <path d="m 14 1 c -0.554688 0 -1 0.445312 -1 1 v 12 c 0 0.554688 0.445312 1 1 1 h 1 c 0.554688 0 1 -0.445312 1 -1 v -12 c 0 -0.554688 -0.445312 -1 -1 -1 z m -4 3 c -0.554688 0 -1 0.445312 -1 1 v 9 c 0 0.554688 0.445312 1 1 1 h 1 c 0.554688 0 1 -0.445312 1 -1 v -9 c 0 -0.554688 -0.445312 -1 -1 -1 z m -4 3 c -0.554688 0 -1 0.445312 -1 1 v 6 c 0 0.554688 0.445312 1 1 1 h 1 c 0.554688 0 1 -0.445312 1 -1 v -6 c 0 -0.554688 -0.445312 -1 -1 -1 z m -4 3 c -0.554688 0 -1 0.445312 -1 1 v 3 c 0 0.554688 0.445312 1 1 1 h 1 c 0.554688 0 1 -0.445312 1 -1 v -3 c 0 -0.554688 -0.445312 -1 -1 -1 z m 0 0" fill="#2e3436"/>
+</svg>
diff --git a/panels/wwan/meson.build b/panels/wwan/meson.build
new file mode 100644
index 0000000..9b73b5b
--- /dev/null
+++ b/panels/wwan/meson.build
@@ -0,0 +1,61 @@
+
+deps = common_deps + network_manager_deps + [gcr_dep, polkit_gobject_dep]
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input : desktop + '.in.in',
+ output : desktop + '.in',
+ configuration : desktop_conf
+)
+
+i18n.merge_file(
+ type : 'desktop',
+ input : desktop_in,
+ output : desktop,
+ po_dir : po_dir,
+ install : true,
+ install_dir : control_center_desktopdir
+)
+
+sources = files(
+ 'cc-wwan-panel.c',
+ 'cc-wwan-device.c',
+ 'cc-wwan-data.c',
+ 'cc-wwan-device-page.c',
+ 'cc-wwan-mode-dialog.c',
+ 'cc-wwan-network-dialog.c',
+ 'cc-wwan-details-dialog.c',
+ 'cc-wwan-sim-lock-dialog.c',
+ 'cc-wwan-apn-dialog.c',
+)
+
+resource_data = files(
+ 'cc-wwan-panel.ui',
+ 'cc-wwan-device-page.ui',
+ 'cc-wwan-mode-dialog.ui',
+ 'cc-wwan-network-dialog.ui',
+ 'cc-wwan-details-dialog.ui',
+ 'cc-wwan-sim-lock-dialog.ui',
+ 'cc-wwan-apn-dialog.ui',
+)
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name : 'cc_' + cappletname,
+ dependencies : resource_data,
+ export : true
+)
+
+cflags += '-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir)
+
+panels_libs += static_library(
+ cappletname,
+ sources : sources,
+ include_directories : [ top_inc, common_inc ],
+ dependencies : deps,
+ c_args : cflags
+)
+
+subdir('icons')
diff --git a/panels/wwan/wwan.gresource.xml b/panels/wwan/wwan.gresource.xml
new file mode 100644
index 0000000..f128a16
--- /dev/null
+++ b/panels/wwan/wwan.gresource.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/wwan">
+ <file preprocess="xml-stripblanks">cc-wwan-panel.ui</file>
+ <file preprocess="xml-stripblanks">cc-wwan-device-page.ui</file>
+ <file preprocess="xml-stripblanks">cc-wwan-mode-dialog.ui</file>
+ <file preprocess="xml-stripblanks">cc-wwan-network-dialog.ui</file>
+ <file preprocess="xml-stripblanks">cc-wwan-details-dialog.ui</file>
+ <file preprocess="xml-stripblanks">cc-wwan-sim-lock-dialog.ui</file>
+ <file preprocess="xml-stripblanks">cc-wwan-apn-dialog.ui</file>
+ </gresource>
+</gresources>